1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2020 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 
  28 #include "memory/metaspace/blocktree.hpp"
  29 #include "utilities/debug.hpp"
  30 #include "utilities/globalDefinitions.hpp"
  31 #include "utilities/ostream.hpp"
  32 
  33 namespace metaspace {
  34 
  35 
  36 #ifdef ASSERT
  37 
  38 // Tree verification
  39 
  40 // These asserts prints the tree, then asserts
  41 #define assrt(cond, format, ...) \
  42   if (!(cond)) { \
  43     print_tree(tty); \
  44     assert(cond, format, __VA_ARGS__); \
  45   }
  46 
  47   // This assert prints the tree, then stops (generic message)
  48 #define assrt0(cond) \
  49           if (!(cond)) { \
  50             print_tree(tty); \
  51             assert(cond, "sanity"); \
  52           }
  53 
  54 struct BlockTree::veri_data_t {
  55   MemRangeCounter counter;
  56   int max_edge;
  57   size_t largest;
  58 };
  59 
  60 // Given a node, check that all siblings have the same size and that we have no
  61 // (direct) circularities.
  62 void BlockTree::verify_node_siblings(node_t* n, veri_data_t* vd) const {
  63   const size_t size = n->size;
  64   node_t* n2 = n->next;
  65   node_t* prev_sib = NULL;
  66   while (n2 != NULL) {
  67     assrt0(n2->size == size);
  68     vd->counter.add(n2->size);
  69     if (prev_sib != NULL) {
  70       assrt0(prev_sib->next == n2);
  71       assrt0(prev_sib != n2);
  72     }
  73     prev_sib = n2;
  74     n2 = n2->next;
  75   }
  76 }
  77 
  78 // Given a node and outer bounds applying to it and all children, check it and all children recursively.
  79 void BlockTree::verify_node(node_t* n, size_t left_limit, size_t right_limit,
  80     veri_data_t* vd, int lvl) const {
  81 
  82   if (lvl > vd->max_edge) {
  83     vd->max_edge = lvl;
  84   }
  85 
  86   if (n->size > vd->largest) {
  87     vd->largest = n->size;
  88   }
  89 
  90   assrt0((n == _root && n->parent == NULL) || (n != _root && n->parent != NULL));
  91 
  92   // check all siblings
  93   if (n->next != NULL) {
  94     verify_node_siblings(n, vd);
  95   }
  96 
  97   // check order
  98   assrt(n->size >= minimal_word_size && n->size <= maximal_word_size,
  99       "bad node size " SIZE_FORMAT, n->size);
 100   assrt0(n->size < right_limit);
 101   assrt0(n->size > left_limit);
 102 
 103   vd->counter.add(n->size);
 104 
 105   if (n->left != NULL) {
 106     assrt0(n != n->left);
 107     assrt0(n->left->parent == n);
 108     assrt0(n->left->size < n->size);
 109     assrt0(n->left->size > left_limit);
 110     verify_node(n->left, left_limit, n->size, vd, lvl + 1);
 111   }
 112 
 113   if (n->right != NULL) {
 114     assrt0(n != n->right);
 115     assrt0(n->right->parent == n);
 116     assrt0(n->right->size < right_limit);
 117     assrt0(n->right->size > n->size);
 118     verify_node(n->right, n->size, right_limit, vd, lvl + 1);
 119   }
 120 
 121 }
 122 
 123 void BlockTree::verify_tree() const {
 124   int num = 0;
 125   size_t size = 0;
 126   veri_data_t vd;
 127   vd.max_edge = 0;
 128   vd.largest = 0;
 129   if (_root != NULL) {
 130     assrt0(_root->parent == NULL);
 131     verify_node(_root, 0, maximal_word_size + 1, &vd, 0);
 132     assrt0(vd.largest == _largest_size_added);
 133     vd.counter.check(_counter);
 134     assrt0(vd.counter.count() > 0);
 135   }
 136 }
 137 
 138 void BlockTree::zap_range(MetaWord* p, size_t word_size) {
 139   memset(p, 0xF3, word_size * sizeof(MetaWord));
 140 }
 141 
 142 #undef assrt
 143 #undef assrt0
 144 
 145 #endif // ASSERT
 146 
 147 
 148 void BlockTree::print_node(outputStream* st, node_t* n, int lvl) {
 149   for (int i = 0; i < lvl; i ++) {
 150     st->print("---");
 151   }
 152   st->print_cr("<" PTR_FORMAT " (size " SIZE_FORMAT ")", p2i(n), n->size);
 153   if (n->left) {
 154     print_node(st, n->left, lvl + 1);
 155   }
 156   if (n->right) {
 157     print_node(st, n->right, lvl + 1);
 158   }
 159 }
 160 
 161 void BlockTree::print_tree(outputStream* st) const {
 162   if (_root != NULL) {
 163     print_node(st, _root, 0);
 164   } else {
 165     st->print_cr("<no nodes>");
 166   }
 167 }
 168 
 169 } // namespace metaspace