@@ -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()
8774void 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
9986void 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