/* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// This assert prints the tree too #define tree_assert(cond, format, ...) \ do { \ if (!(cond)) { \
tty->print("Error in tree @" PTR_FORMAT ": ", p2i(this)); \
tty->print_cr(format, __VA_ARGS__); \
tty->print_cr("Tree:"); \
print_tree(tty); \
assert(cond, format, __VA_ARGS__); \
} \
} while (0)
// Assert, prints tree and specific given node #define tree_assert_invalid_node(cond, failure_node) \
tree_assert(cond, "Invalid node: " NODE_FORMAT, NODE_FORMAT_ARGS(failure_node))
// walkinfo keeps a node plus the size corridor it and its children // are supposed to be in. struct BlockTree::walkinfo {
BlockTree::Node* n; int depth;
size_t lim1; // (
size_t lim2; // )
};
// Helper for verify() void BlockTree::verify_node_pointer(const Node* n) const {
tree_assert(os::is_readable_pointer(n), "Invalid node: @" PTR_FORMAT " is unreadable.", p2i(n)); // If the canary is broken, this is either an invalid node pointer or // the node has been overwritten. Either way, print a hex dump, then // assert away. if (n->_canary != Node::_canary_value) {
os::print_hex_dump(tty, (address)n, (address)n + sizeof(Node), 1);
tree_assert(false, "Invalid node: @" PTR_FORMAT " canary broken or pointer invalid", p2i(n));
}
}
void BlockTree::verify() const { // Traverse the tree and test that all nodes are in the correct order.
while (stack.length() > 0) {
info = stack.pop(); const Node* n = info.n;
verify_node_pointer(n);
// Assume a (ridiculously large) edge limit to catch cases // of badly degenerated or circular trees.
tree_assert(info.depth < 10000, "too deep (%d)", info.depth);
counter.add(n->_word_size);
// If node has same-sized siblings check those too. const Node* n2 = n->_next; while (n2 != NULL) {
verify_node_pointer(n2);
tree_assert_invalid_node(n2 != n, n2); // catch simple circles
tree_assert_invalid_node(n2->_word_size == n->_word_size, n2);
counter.add(n2->_word_size);
n2 = n2->_next;
}
}
}
// At the end, check that counters match // (which also verifies that we visited every node, or at least // as many nodes as are in this tree)
_counter.check(counter);
// Note: we do not print the tree indented, since I found that printing it // as a quasi list is much clearer to the eye. // We print the tree depth-first, with stacked nodes below normal ones // (normal "real" nodes are marked with a leading '+') if (_root != NULL) {
ResourceMark rm;
GrowableArray<walkinfo> stack;
walkinfo info;
info.n = _root;
info.depth = 0;
stack.push(info); while (stack.length() > 0) {
info = stack.pop(); const Node* n = info.n;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.