--- /dev/null 2020-09-04 12:37:41.765504620 +0200 +++ new/src/hotspot/share/memory/metaspace/msBlockTree.cpp 2020-09-04 13:57:41.961294776 +0200 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020 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. + * + */ + +#include "precompiled.hpp" + +#include "memory/metaspace/msBlockTree.hpp" +#include "memory/resourceArea.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/ostream.hpp" + +namespace metaspace { + +#ifdef ASSERT + +// Tree verification + +// These asserts prints the tree, then asserts +#define assrt(cond, format, ...) \ + do { \ + if (!(cond)) { \ + print_tree(tty); \ + assert(cond, format, __VA_ARGS__); \ + } \ + } while(0) + + // This assert prints the tree, then stops (generic message) +#define assrt0(cond) \ + do { \ + if (!(cond)) { \ + print_tree(tty); \ + assert(cond, "sanity"); \ + } \ + } while(0) + + + +// 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; // ) +}; + +void BlockTree::verify() const { + + // Traverse the tree and test that all nodes are in the correct order. + + MemRangeCounter counter; + int longest_edge = 0; + + if (_root != NULL) { + + ResourceMark rm; + + GrowableArray stack; + + walkinfo info; + info.n = _root; + info.lim1 = 0; + info.lim2 = SIZE_MAX; + info.depth = 0; + + stack.push(info); + + while (stack.length() > 0) { + + info = stack.pop(); + const Node* n = info.n; + + // Assume a (ridiculously large) edge limit to catch cases + // of badly degenerated or circular trees. + assrt0(info.depth < 10000); + + counter.add(n->_word_size); + + // Verify node. + if (n == _root) { + assrt0(n->_parent == NULL); + } else { + assrt0(n->_parent != NULL); + } + + // check size and ordering + assrt(n->_word_size >= MinWordSize, "bad node size " SIZE_FORMAT, n->_word_size); + assrt0(n->_word_size > info.lim1); + assrt0(n->_word_size < info.lim2); + + // Check children + if (n->_left != NULL) { + assrt0(n->_left != n); + assrt0(n->_left->_parent == n); + + walkinfo info2; + info2.n = n->_left; + info2.lim1 = info.lim1; + info2.lim2 = n->_word_size; + info2.depth = info.depth + 1; + stack.push(info2); + } + + if (n->_right != NULL) { + assrt0(n->_right != n); + assrt0(n->_right->_parent == n); + + walkinfo info2; + info2.n = n->_right; + info2.lim1 = n->_word_size; + info2.lim2 = info.lim2; + info2.depth = info.depth + 1; + stack.push(info2); + } + + // If node has same-sized siblings check those too. + const Node* n2 = n->_next; + while (n2 != NULL) { + assrt0(n2 != n); + assrt0(n2->_word_size == n->_word_size); + counter.add(n2->_word_size); + n2 = n2->_next; + } + } + } + + // At the end, check that counters match + _counter.check(counter); + +} + +void BlockTree::zap_range(MetaWord* p, size_t word_size) { + memset(p, 0xF3, word_size * sizeof(MetaWord)); +} + +#undef assrt +#undef assrt0 + +void BlockTree::print_tree(outputStream* st) const { + + if (_root != NULL) { + + ResourceMark rm; + + GrowableArray stack; + + walkinfo info; + info.n = _root; + info.depth = 0; + + stack.push(info); + while (stack.length() > 0) { + info = stack.pop(); + const Node* n = info.n; + // Print node. + for (int i = 0; i < info.depth; i++) { + st->print("---"); + } + st->print_cr("<" PTR_FORMAT " (size " SIZE_FORMAT ")", p2i(n), n->_word_size); + // Handle children. + if (n->_right != NULL) { + walkinfo info2; + info2.n = n->_right; + info2.depth = info.depth + 1; + stack.push(info2); + } + if (n->_left != NULL) { + walkinfo info2; + info2.n = n->_left; + info2.depth = info.depth + 1; + stack.push(info2); + } + } + + } else { + st->print_cr(""); + } +} + +#endif // ASSERT + +} // namespace metaspace