Skip to content

Commit f386a71

Browse files
committed
rbtree better cmp and verify/print user functions
1 parent 3641c32 commit f386a71

File tree

7 files changed

+250
-99
lines changed

7 files changed

+250
-99
lines changed

src/hotspot/share/gc/z/zMappedCache.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,20 +118,20 @@ static ZMappedCacheEntry* create_entry(const ZVirtualMemory& vmem) {
118118
return entry;
119119
}
120120

121-
bool ZMappedCache::EntryCompare::cmp(const IntrusiveRBNode* a, const IntrusiveRBNode* b) {
121+
bool ZMappedCache::EntryCompare::less(const IntrusiveRBNode* a, const IntrusiveRBNode* b) {
122122
const ZVirtualMemory vmem_a = ZMappedCacheEntry::cast_to_entry(a)->vmem();
123123
const ZVirtualMemory vmem_b = ZMappedCacheEntry::cast_to_entry(b)->vmem();
124124

125125
return vmem_a.end() < vmem_b.start();
126126
}
127127

128-
int ZMappedCache::EntryCompare::cmp(zoffset key, const IntrusiveRBNode* node) {
128+
RBTreeOrdering ZMappedCache::EntryCompare::cmp(zoffset key, const IntrusiveRBNode* node) {
129129
const ZVirtualMemory vmem = ZMappedCacheEntry::cast_to_entry(node)->vmem();
130130

131-
if (key < vmem.start()) { return -1; }
132-
if (key > vmem.end()) { return 1; }
131+
if (key < vmem.start()) { return RBTreeOrdering::less; }
132+
if (key > vmem.end()) { return RBTreeOrdering::greater; }
133133

134-
return 0; // Containing
134+
return RBTreeOrdering::equal; // Containing
135135
}
136136

137137
void ZMappedCache::Tree::verify() const {
@@ -168,12 +168,12 @@ void ZMappedCache::Tree::insert(TreeNode* node, const TreeCursor& cursor) {
168168
// Insert in tree
169169
TreeImpl::insert_at_cursor(node, cursor);
170170

171-
if (_left_most == nullptr || EntryCompare::cmp(node, _left_most)) {
171+
if (_left_most == nullptr || EntryCompare::less(node, _left_most)) {
172172
// Keep track of left most node
173173
_left_most = node;
174174
}
175175

176-
if (_right_most == nullptr || EntryCompare::cmp(_right_most, node)) {
176+
if (_right_most == nullptr || EntryCompare::less(_right_most, node)) {
177177
// Keep track of right most node
178178
_right_most = node;
179179
}

src/hotspot/share/gc/z/zMappedCache.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class ZMappedCache {
4040

4141
private:
4242
struct EntryCompare {
43-
static int cmp(zoffset a, const IntrusiveRBNode* b);
44-
static bool cmp(const IntrusiveRBNode* a, const IntrusiveRBNode* b);
43+
static RBTreeOrdering cmp(zoffset a, const IntrusiveRBNode* b);
44+
static bool less(const IntrusiveRBNode* a, const IntrusiveRBNode* b);
4545
};
4646

4747
struct ZSizeClassListNode {

src/hotspot/share/nmt/vmatree.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@ class VMATree {
5050

5151
class PositionComparator {
5252
public:
53-
static int cmp(position a, position b) {
54-
if (a < b) return -1;
55-
if (a == b) return 0;
56-
if (a > b) return 1;
53+
static RBTreeOrdering cmp(position a, position b) {
54+
if (a < b) return RBTreeOrdering::less;
55+
if (a == b) return RBTreeOrdering::equal;
56+
if (a > b) return RBTreeOrdering::greater;
5757
ShouldNotReachHere();
5858
}
5959
};

src/hotspot/share/opto/printinlining.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ class InlinePrinter {
6767
};
6868

6969
struct Cmp {
70-
static int cmp(int a, int b) {
71-
return a - b;
70+
static RBTreeOrdering cmp(int a, int b) {
71+
if (a < b) return RBTreeOrdering::less;
72+
if (a > b) return RBTreeOrdering::greater;
73+
return RBTreeOrdering::equal;
7274
}
7375
};
7476

src/hotspot/share/utilities/rbTree.hpp

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,13 @@
3535
// An intrusive red-black tree is constructed with two template parameters:
3636
// K is the key type used.
3737
// COMPARATOR must have a static function `cmp(K a, const IntrusiveRBNode* b)` which returns:
38-
// - an int < 0 when a < b
39-
// - an int == 0 when a == b
40-
// - an int > 0 when a > b
41-
// Additional static functions used for extra validation can optionally be provided:
42-
// `cmp(K a, K b)` which returns:
43-
// - an int < 0 when a < b
44-
// - an int == 0 when a == b
45-
// - an int > 0 when a > b
46-
// `cmp(const IntrusiveRBNode* a, const IntrusiveRBNode* b)` which returns:
47-
// - true if a < b
48-
// - false otherwise
38+
// - RBTreeOrdering::less when a < b
39+
// - RBTreeOrdering::equal when a == b
40+
// - RBTreeOrdering::greater when a > b
41+
// A second static function `less(const IntrusiveRBNode* a, const IntrusiveRBNode* b)`
42+
// used for extra validation can optionally be provided. This should return:
43+
// - true if a < b
44+
// - false otherwise
4945
// K needs to be of a type that is trivially destructible.
5046
// K needs to be stored by the user and is not stored inside the tree.
5147
// Nodes are address stable and will not change during its lifetime.
@@ -54,10 +50,10 @@
5450
// K is the key type stored in the tree nodes.
5551
// V is the value type stored in the tree nodes.
5652
// COMPARATOR must have a static function `cmp(K a, K b)` which returns:
57-
// - an int < 0 when a < b
58-
// - an int == 0 when a == b
59-
// - an int > 0 when a > b
60-
// A second static function `cmp(const RBNode<K, V>* a, const RBNode<K, V>* b)`
53+
// - RBTreeOrdering::less when a < b
54+
// - RBTreeOrdering::equal when a == b
55+
// - RBTreeOrdering::greater when a > b
56+
// A second static function `less(const RBNode<K, V>* a, const RBNode<K, V>* b)`
6157
// used for extra validation can optionally be provided. This should return:
6258
// - true if a < b
6359
// - false otherwise
@@ -66,6 +62,8 @@
6662
// The tree will call a value's destructor when its node is removed.
6763
// Nodes are address stable and will not change during its lifetime.
6864

65+
enum class RBTreeOrdering : int { less = -1, equal = 0, greater = 1 };
66+
6967
template <typename K, typename NodeType, typename COMPARATOR>
7068
class AbstractRBTree;
7169

@@ -127,10 +125,11 @@ class IntrusiveRBNode {
127125
// Returns left child (now parent)
128126
IntrusiveRBNode* rotate_right();
129127

130-
template <typename NodeType, typename NodeVerifier>
128+
template <typename NodeType, typename NodeVerifier, typename USER_VERIFIER>
131129
void verify(size_t& num_nodes, size_t& black_nodes_until_leaf,
132130
size_t& shortest_leaf_path, size_t& longest_leaf_path,
133-
size_t& tree_depth, bool expect_visited, NodeVerifier verifier) const;
131+
size_t& tree_depth, bool expect_visited, NodeVerifier verifier,
132+
const USER_VERIFIER& extra_verifier) const;
134133

135134
};
136135

@@ -204,32 +203,37 @@ class AbstractRBTree {
204203
struct has_cmp_type<CMP, RET, ARG1, ARG2, decltype(static_cast<RET(*)(ARG1, ARG2)>(CMP::cmp), void())> : std::true_type {};
205204

206205
template <typename CMP>
207-
static constexpr bool HasKeyComparator = has_cmp_type<CMP, int, K, K>::value;
206+
static constexpr bool HasKeyComparator = has_cmp_type<CMP, RBTreeOrdering, K, K>::value;
208207

209208
template <typename CMP>
210-
static constexpr bool HasNodeComparator = has_cmp_type<CMP, int, K, const NodeType*>::value;
209+
static constexpr bool HasNodeComparator = has_cmp_type<CMP, RBTreeOrdering, K, const NodeType*>::value;
210+
211+
template <typename CMP, typename RET, typename ARG1, typename ARG2, typename = void>
212+
struct has_less_type : std::false_type {};
213+
template <typename CMP, typename RET, typename ARG1, typename ARG2>
214+
struct has_less_type<CMP, RET, ARG1, ARG2, decltype(static_cast<RET(*)(ARG1, ARG2)>(CMP::less), void())> : std::true_type {};
211215

212216
template <typename CMP>
213-
static constexpr bool HasNodeVerifier = has_cmp_type<CMP, bool, const NodeType*, const NodeType*>::value;
217+
static constexpr bool HasNodeVerifier = has_less_type<CMP, bool, const NodeType*, const NodeType*>::value;
214218

215219
template <typename CMP = COMPARATOR, ENABLE_IF(HasKeyComparator<CMP> && !HasNodeComparator<CMP>)>
216-
int cmp(const K& a, const NodeType* b) const {
220+
RBTreeOrdering cmp(const K& a, const NodeType* b) const {
217221
return COMPARATOR::cmp(a, b->key());
218222
}
219223

220224
template <typename CMP = COMPARATOR, ENABLE_IF(HasNodeComparator<CMP>)>
221-
int cmp(const K& a, const NodeType* b) const {
225+
RBTreeOrdering cmp(const K& a, const NodeType* b) const {
222226
return COMPARATOR::cmp(a, b);
223227
}
224228

225229
template <typename CMP = COMPARATOR, ENABLE_IF(!HasNodeVerifier<CMP>)>
226-
bool cmp(const NodeType* a, const NodeType* b) const {
230+
bool less(const NodeType* a, const NodeType* b) const {
227231
return true;
228232
}
229233

230234
template <typename CMP = COMPARATOR, ENABLE_IF(HasNodeVerifier<CMP>)>
231-
bool cmp(const NodeType* a, const NodeType* b) const {
232-
return COMPARATOR::cmp(a, b);
235+
bool less(const NodeType* a, const NodeType* b) const {
236+
return COMPARATOR::less(a, b);
233237
}
234238

235239
// Cannot assert if no key comparator exist.
@@ -238,7 +242,7 @@ class AbstractRBTree {
238242

239243
template <typename CMP = COMPARATOR, ENABLE_IF(HasKeyComparator<CMP>)>
240244
void assert_key_leq(K a, K b) const {
241-
assert(COMPARATOR::cmp(a, b) <= 0, "key a must be less or equal to key b");
245+
assert(COMPARATOR::cmp(a, b) != RBTreeOrdering::greater, "key a must be less or equal to key b");
242246
}
243247

244248
// True if node is black (nil nodes count as black)
@@ -257,10 +261,23 @@ class AbstractRBTree {
257261
// Assumption: node has at most one child. Two children is handled in `remove_at_cursor()`
258262
void remove_from_tree(IntrusiveRBNode* node);
259263

260-
template <typename NodeVerifier>
261-
void verify_self(NodeVerifier verifier) const;
264+
struct empty_verifier {
265+
bool operator()(const NodeType* n) const {
266+
return true;
267+
}
268+
};
262269

263-
void print_node_on(outputStream* st, int depth, const NodeType* n) const;
270+
template <typename NodeVerifier, typename USER_VERIFIER>
271+
void verify_self(NodeVerifier verifier, const USER_VERIFIER& extra_verifier) const;
272+
273+
struct default_printer {
274+
void operator()(outputStream* st, const NodeType* n, int depth) const {
275+
n->print_on(st, depth);
276+
}
277+
};
278+
279+
template <typename PRINTER>
280+
void print_node_on(outputStream* st, int depth, const NodeType* n, const PRINTER& node_printer) const;
264281

265282
public:
266283
NONCOPYABLE(AbstractRBTree);
@@ -423,22 +440,30 @@ class AbstractRBTree {
423440
// Verifies that the tree is correct and holds rb-properties
424441
// If not using a key comparator (when using IntrusiveRBTree for example),
425442
// A second `cmp` must exist in COMPARATOR (see top of file).
426-
template <typename CMP = COMPARATOR, ENABLE_IF(HasNodeVerifier<CMP>)>
427-
void verify_self() const {
428-
verify_self([](const NodeType* a, const NodeType* b){ return COMPARATOR::cmp(a, b);});
443+
// Accepts an optional callable `bool extra_verifier(const Node* n)`.
444+
// This should return true if the node is valid.
445+
// If provided, each node is also verified through this callable.
446+
template <typename USER_VERIFIER = empty_verifier, typename CMP = COMPARATOR, ENABLE_IF(HasNodeVerifier<CMP>)>
447+
void verify_self(const USER_VERIFIER& extra_verifier = USER_VERIFIER()) const {
448+
verify_self([](const NodeType* a, const NodeType* b){ return COMPARATOR::less(a, b);}, extra_verifier);
429449
}
430450

431-
template <typename CMP = COMPARATOR, ENABLE_IF(HasKeyComparator<CMP> && !HasNodeVerifier<CMP>)>
432-
void verify_self() const {
433-
verify_self([](const NodeType* a, const NodeType* b){ return COMPARATOR::cmp(a->key(), b->key()) < 0; });
451+
template <typename USER_VERIFIER = empty_verifier, typename CMP = COMPARATOR,
452+
ENABLE_IF(HasKeyComparator<CMP> && !HasNodeVerifier<CMP>)>
453+
void verify_self(const USER_VERIFIER& extra_verifier = USER_VERIFIER()) const {
454+
verify_self([](const NodeType* a, const NodeType* b){ return COMPARATOR::cmp(a->key(), b->key()) == RBTreeOrdering::less; }, extra_verifier);
434455
}
435456

436-
template <typename CMP = COMPARATOR, ENABLE_IF(HasNodeComparator<CMP> && !HasKeyComparator<CMP> && !HasNodeVerifier<CMP>)>
437-
void verify_self() const {
438-
verify_self([](const NodeType*, const NodeType*){ return true;});
457+
template <typename USER_VERIFIER = empty_verifier, typename CMP = COMPARATOR,
458+
ENABLE_IF(HasNodeComparator<CMP> && !HasKeyComparator<CMP> && !HasNodeVerifier<CMP>)>
459+
void verify_self(const USER_VERIFIER& extra_verifier = USER_VERIFIER()) const {
460+
verify_self([](const NodeType*, const NodeType*){ return true;}, extra_verifier);
439461
}
440462

441-
void print_on(outputStream* st) const;
463+
// Accepts an optional printing callable `void node_printer(outputStream* st, const Node* n, int depth)`.
464+
// If provided, each node is printed through this callable rather than the default `print_on`.
465+
template <typename PRINTER = default_printer>
466+
void print_on(outputStream* st, const PRINTER& node_printer = PRINTER()) const;
442467

443468
};
444469

0 commit comments

Comments
 (0)