Skip to content

Commit 5d196c9

Browse files
committed
moved blocktree tree logic to intrusive rbtree
1 parent e16c510 commit 5d196c9

File tree

3 files changed

+91
-346
lines changed

3 files changed

+91
-346
lines changed

src/hotspot/share/memory/metaspace/blockTree.cpp

Lines changed: 43 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,14 @@ const size_t BlockTree::MinWordSize;
3939
#define NODE_FORMAT \
4040
"@" PTR_FORMAT \
4141
": canary " INTPTR_FORMAT \
42-
", parent " PTR_FORMAT \
43-
", left " PTR_FORMAT \
44-
", right " PTR_FORMAT \
42+
", tree " PTR_FORMAT \
4543
", next " PTR_FORMAT \
4644
", size %zu"
4745

4846
#define NODE_FORMAT_ARGS(n) \
4947
p2i(n), \
5048
(n)->_canary, \
51-
p2i((n)->_parent), \
52-
p2i((n)->_left), \
53-
p2i((n)->_right), \
49+
p2i(&(n)->_tree_node), \
5450
p2i((n)->_next), \
5551
(n)->_word_size
5652

@@ -74,15 +70,6 @@ const size_t BlockTree::MinWordSize;
7470
#define tree_assert_invalid_node(cond, failure_node) \
7571
tree_assert(cond, "Invalid node: " NODE_FORMAT, NODE_FORMAT_ARGS(failure_node))
7672

77-
// walkinfo keeps a node plus the size corridor it and its children
78-
// are supposed to be in.
79-
struct BlockTree::walkinfo {
80-
BlockTree::Node* n;
81-
int depth;
82-
size_t lim1; // (
83-
size_t lim2; // )
84-
};
85-
8673
// Helper for verify()
8774
void BlockTree::verify_node_pointer(const Node* n) const {
8875
tree_assert(os::is_readable_pointer(n),
@@ -98,80 +85,32 @@ void BlockTree::verify_node_pointer(const Node* n) const {
9885

9986
void BlockTree::verify() const {
10087
// Traverse the tree and test that all nodes are in the correct order.
101-
10288
MemRangeCounter counter;
103-
if (_root != nullptr) {
104-
105-
ResourceMark rm;
106-
GrowableArray<walkinfo> stack;
107-
108-
walkinfo info;
109-
info.n = _root;
110-
info.lim1 = 0;
111-
info.lim2 = SIZE_MAX;
112-
info.depth = 0;
11389

114-
stack.push(info);
90+
// Verifies node ordering (n1 < n2 => word_size1 < word_size2),
91+
// node vadility, and that the tree is balanced and not ill-formed.
92+
_tree.verify_self([&](const TreeNode* tree_node) {
93+
const Node* n = Node::cast_to_node(tree_node);
11594

116-
while (stack.length() > 0) {
117-
info = stack.pop();
118-
const Node* n = info.n;
95+
verify_node_pointer(n);
11996

120-
verify_node_pointer(n);
97+
counter.add(n->_word_size);
12198

122-
// Assume a (ridiculously large) edge limit to catch cases
123-
// of badly degenerated or circular trees.
124-
tree_assert(info.depth < 10000, "too deep (%d)", info.depth);
125-
counter.add(n->_word_size);
99+
tree_assert_invalid_node(n->_word_size >= MinWordSize, n);
100+
tree_assert_invalid_node(n->_word_size <= chunklevel::MAX_CHUNK_WORD_SIZE, n);
126101

127-
if (n == _root) {
128-
tree_assert_invalid_node(n->_parent == nullptr, n);
129-
} else {
130-
tree_assert_invalid_node(n->_parent != nullptr, n);
131-
}
132-
133-
// check size and ordering
134-
tree_assert_invalid_node(n->_word_size >= MinWordSize, n);
135-
tree_assert_invalid_node(n->_word_size <= chunklevel::MAX_CHUNK_WORD_SIZE, n);
136-
tree_assert_invalid_node(n->_word_size > info.lim1, n);
137-
tree_assert_invalid_node(n->_word_size < info.lim2, n);
138-
139-
// Check children
140-
if (n->_left != nullptr) {
141-
tree_assert_invalid_node(n->_left != n, n);
142-
tree_assert_invalid_node(n->_left->_parent == n, n);
143-
144-
walkinfo info2;
145-
info2.n = n->_left;
146-
info2.lim1 = info.lim1;
147-
info2.lim2 = n->_word_size;
148-
info2.depth = info.depth + 1;
149-
stack.push(info2);
150-
}
151-
152-
if (n->_right != nullptr) {
153-
tree_assert_invalid_node(n->_right != n, n);
154-
tree_assert_invalid_node(n->_right->_parent == n, n);
155-
156-
walkinfo info2;
157-
info2.n = n->_right;
158-
info2.lim1 = n->_word_size;
159-
info2.lim2 = info.lim2;
160-
info2.depth = info.depth + 1;
161-
stack.push(info2);
162-
}
163-
164-
// If node has same-sized siblings check those too.
165-
const Node* n2 = n->_next;
166-
while (n2 != nullptr) {
167-
verify_node_pointer(n2);
168-
tree_assert_invalid_node(n2 != n, n2); // catch simple circles
169-
tree_assert_invalid_node(n2->_word_size == n->_word_size, n2);
170-
counter.add(n2->_word_size);
171-
n2 = n2->_next;
172-
}
102+
// If node has same-sized siblings check those too.
103+
const Node* n2 = n->_next;
104+
while (n2 != nullptr) {
105+
verify_node_pointer(n2);
106+
tree_assert_invalid_node(n2 != n, n2); // catch simple circles
107+
tree_assert_invalid_node(n2->_word_size == n->_word_size, n2);
108+
counter.add(n2->_word_size);
109+
n2 = n2->_next;
173110
}
174-
}
111+
112+
return true;
113+
});
175114

176115
// At the end, check that counters match
177116
// (which also verifies that we visited every node, or at least
@@ -189,64 +128,34 @@ void BlockTree::print_tree(outputStream* st) const {
189128
// as a quasi list is much clearer to the eye.
190129
// We print the tree depth-first, with stacked nodes below normal ones
191130
// (normal "real" nodes are marked with a leading '+')
192-
if (_root != nullptr) {
193-
194-
ResourceMark rm;
195-
GrowableArray<walkinfo> stack;
131+
if (is_empty()) {
132+
st->print_cr("<no nodes>");
133+
return;
134+
}
196135

197-
walkinfo info;
198-
info.n = _root;
199-
info.depth = 0;
136+
_tree.print_on(st, [&](outputStream *st, const TreeNode *tree_node, int depth) {
137+
const Node* n = Node::cast_to_node(tree_node);
200138

201-
stack.push(info);
202-
while (stack.length() > 0) {
203-
info = stack.pop();
204-
const Node* n = info.n;
139+
// Print node.
140+
st->print("%4d + ", depth);
141+
if (os::is_readable_pointer(n)) {
142+
st->print_cr(NODE_FORMAT, NODE_FORMAT_ARGS(n));
143+
} else {
144+
st->print_cr("@" PTR_FORMAT ": unreadable", p2i(n));
145+
return;
146+
}
205147

206-
// Print node.
207-
st->print("%4d + ", info.depth);
208-
if (os::is_readable_pointer(n)) {
209-
st->print_cr(NODE_FORMAT, NODE_FORMAT_ARGS(n));
148+
// Print same-sized-nodes stacked under this node
149+
for (Node* n2 = n->_next; n2 != nullptr; n2 = n2->_next) {
150+
st->print_raw(" ");
151+
if (os::is_readable_pointer(n2)) {
152+
st->print_cr(NODE_FORMAT, NODE_FORMAT_ARGS(n2));
210153
} else {
211-
st->print_cr("@" PTR_FORMAT ": unreadable (skipping subtree)", p2i(n));
212-
continue; // don't print this subtree
213-
}
214-
215-
// Print same-sized-nodes stacked under this node
216-
for (Node* n2 = n->_next; n2 != nullptr; n2 = n2->_next) {
217-
st->print_raw(" ");
218-
if (os::is_readable_pointer(n2)) {
219-
st->print_cr(NODE_FORMAT, NODE_FORMAT_ARGS(n2));
220-
} else {
221-
st->print_cr("@" PTR_FORMAT ": unreadable (skipping rest of chain).", p2i(n2));
222-
break; // stop printing this chain.
223-
}
224-
}
225-
226-
// Handle simple circularities
227-
if (n == n->_right || n == n->_left || n == n->_next) {
228-
st->print_cr("@" PTR_FORMAT ": circularity detected.", p2i(n));
229-
return; // stop printing
230-
}
231-
232-
// Handle children.
233-
if (n->_right != nullptr) {
234-
walkinfo info2;
235-
info2.n = n->_right;
236-
info2.depth = info.depth + 1;
237-
stack.push(info2);
238-
}
239-
if (n->_left != nullptr) {
240-
walkinfo info2;
241-
info2.n = n->_left;
242-
info2.depth = info.depth + 1;
243-
stack.push(info2);
154+
st->print_cr("@" PTR_FORMAT ": unreadable (skipping rest of chain).", p2i(n2));
155+
break; // stop printing this chain.
244156
}
245157
}
246-
247-
} else {
248-
st->print_cr("<no nodes>");
249-
}
158+
});
250159
}
251160

252161
#endif // ASSERT

0 commit comments

Comments
 (0)