1 /*
   2  * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/g1/g1CollectedHeap.inline.hpp"
  27 #include "gc/g1/g1NUMA.hpp"
  28 #include "gc/g1/heapRegionRemSet.hpp"
  29 #include "gc/g1/heapRegionSet.inline.hpp"
  30 
  31 uint FreeRegionList::_unrealistically_long_length = 0;
  32 
  33 #ifndef PRODUCT
  34 void HeapRegionSetBase::verify_region(HeapRegion* hr) {
  35   assert(hr->containing_set() == this, "Inconsistent containing set for %u", hr->hrm_index());
  36   assert(!hr->is_young(), "Adding young region %u", hr->hrm_index()); // currently we don't use these sets for young regions
  37   assert(_checker == NULL || _checker->is_correct_type(hr), "Wrong type of region %u (%s) and set %s",
  38          hr->hrm_index(), hr->get_type_str(), name());
  39   assert(!hr->is_free() || hr->is_empty(), "Free region %u is not empty for set %s", hr->hrm_index(), name());
  40   assert(!hr->is_empty() || hr->is_free() || hr->is_archive(),
  41          "Empty region %u is not free or archive for set %s", hr->hrm_index(), name());
  42 }
  43 #endif
  44 
  45 void HeapRegionSetBase::verify() {
  46   // It's important that we also observe the MT safety protocol even
  47   // for the verification calls. If we do verification without the
  48   // appropriate locks and the set changes underneath our feet
  49   // verification might fail and send us on a wild goose chase.
  50   check_mt_safety();
  51 
  52   guarantee_heap_region_set(( is_empty() && length() == 0) ||
  53                             (!is_empty() && length() > 0),
  54                             "invariant");
  55 }
  56 
  57 void HeapRegionSetBase::verify_start() {
  58   // See comment in verify() about MT safety and verification.
  59   check_mt_safety();
  60   assert_heap_region_set(!_verify_in_progress, "verification should not be in progress");
  61 
  62   // Do the basic verification first before we do the checks over the regions.
  63   HeapRegionSetBase::verify();
  64 
  65   _verify_in_progress = true;
  66 }
  67 
  68 void HeapRegionSetBase::verify_end() {
  69   // See comment in verify() about MT safety and verification.
  70   check_mt_safety();
  71   assert_heap_region_set(_verify_in_progress, "verification should be in progress");
  72 
  73   _verify_in_progress = false;
  74 }
  75 
  76 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
  77   out->cr();
  78   out->print_cr("Set: %s (" PTR_FORMAT ")", name(), p2i(this));
  79   out->print_cr("  Region Type         : %s", _checker->get_description());
  80   out->print_cr("  Length              : %14u", length());
  81 }
  82 
  83 HeapRegionSetBase::HeapRegionSetBase(const char* name, HeapRegionSetChecker* checker)
  84   : _checker(checker), _length(0), _name(name), _verify_in_progress(false)
  85 {
  86 }
  87 
  88 void FreeRegionList::set_unrealistically_long_length(uint len) {
  89   guarantee(_unrealistically_long_length == 0, "should only be set once");
  90   _unrealistically_long_length = len;
  91 }
  92 
  93 void FreeRegionList::remove_all() {
  94   check_mt_safety();
  95   verify_optional();
  96 
  97   HeapRegion* curr = _head;
  98   while (curr != NULL) {
  99     verify_region(curr);
 100 
 101     HeapRegion* next = curr->next();
 102     curr->set_next(NULL);
 103     curr->set_prev(NULL);
 104     curr->set_containing_set(NULL);
 105 
 106     decrease_length(curr->node_index());
 107 
 108     curr = next;
 109   }
 110   clear();
 111 
 112   verify_optional();
 113 }
 114 
 115 void FreeRegionList::add_ordered(FreeRegionList* from_list) {
 116   check_mt_safety();
 117   from_list->check_mt_safety();
 118 
 119   verify_optional();
 120   from_list->verify_optional();
 121 
 122   if (from_list->is_empty()) {
 123     return;
 124   }
 125 
 126   if (_node_info != NULL && from_list->_node_info != NULL) {
 127     _node_info->add(from_list->_node_info);
 128   }
 129 
 130   #ifdef ASSERT
 131   FreeRegionListIterator iter(from_list);
 132   while (iter.more_available()) {
 133     HeapRegion* hr = iter.get_next();
 134     // In set_containing_set() we check that we either set the value
 135     // from NULL to non-NULL or vice versa to catch bugs. So, we have
 136     // to NULL it first before setting it to the value.
 137     hr->set_containing_set(NULL);
 138     hr->set_containing_set(this);
 139   }
 140   #endif // ASSERT
 141 
 142   if (is_empty()) {
 143     assert_free_region_list(length() == 0 && _tail == NULL, "invariant");
 144     _head = from_list->_head;
 145     _tail = from_list->_tail;
 146   } else {
 147     HeapRegion* curr_to = _head;
 148     HeapRegion* curr_from = from_list->_head;
 149 
 150     while (curr_from != NULL) {
 151       while (curr_to != NULL && curr_to->hrm_index() < curr_from->hrm_index()) {
 152         curr_to = curr_to->next();
 153       }
 154 
 155       if (curr_to == NULL) {
 156         // The rest of the from list should be added as tail
 157         _tail->set_next(curr_from);
 158         curr_from->set_prev(_tail);
 159         curr_from = NULL;
 160       } else {
 161         HeapRegion* next_from = curr_from->next();
 162 
 163         curr_from->set_next(curr_to);
 164         curr_from->set_prev(curr_to->prev());
 165         if (curr_to->prev() == NULL) {
 166           _head = curr_from;
 167         } else {
 168           curr_to->prev()->set_next(curr_from);
 169         }
 170         curr_to->set_prev(curr_from);
 171 
 172         curr_from = next_from;
 173       }
 174     }
 175 
 176     if (_tail->hrm_index() < from_list->_tail->hrm_index()) {
 177       _tail = from_list->_tail;
 178     }
 179   }
 180 
 181   _length += from_list->length();
 182   from_list->clear();
 183 
 184   verify_optional();
 185   from_list->verify_optional();
 186 }
 187 
 188 void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
 189   check_mt_safety();
 190   assert_free_region_list(num_regions >= 1, "pre-condition");
 191   assert_free_region_list(!is_empty(), "pre-condition");
 192 
 193   verify_optional();
 194   DEBUG_ONLY(uint old_length = length();)
 195 
 196   HeapRegion* curr = first;
 197   uint count = 0;
 198   while (count < num_regions) {
 199     verify_region(curr);
 200     HeapRegion* next = curr->next();
 201     HeapRegion* prev = curr->prev();
 202 
 203     assert(count < num_regions,
 204            "[%s] should not come across more regions "
 205            "pending for removal than num_regions: %u",
 206            name(), num_regions);
 207 
 208     if (prev == NULL) {
 209       assert_free_region_list(_head == curr, "invariant");
 210       _head = next;
 211     } else {
 212       assert_free_region_list(_head != curr, "invariant");
 213       prev->set_next(next);
 214     }
 215     if (next == NULL) {
 216       assert_free_region_list(_tail == curr, "invariant");
 217       _tail = prev;
 218     } else {
 219       assert_free_region_list(_tail != curr, "invariant");
 220       next->set_prev(prev);
 221     }
 222     if (_last == curr) {
 223       _last = NULL;
 224     }
 225 
 226     curr->set_next(NULL);
 227     curr->set_prev(NULL);
 228     remove(curr);
 229 
 230     count++;
 231 
 232     decrease_length(curr->node_index());
 233 
 234     curr = next;
 235   }
 236 
 237   assert(count == num_regions,
 238          "[%s] count: %u should be == num_regions: %u",
 239          name(), count, num_regions);
 240   assert(length() + num_regions == old_length,
 241          "[%s] new length should be consistent "
 242          "new length: %u old length: %u num_regions: %u",
 243          name(), length(), old_length, num_regions);
 244 
 245   verify_optional();
 246 }
 247 
 248 uint FreeRegionList::num_of_regions_in_range(uint start, uint end) const {
 249   HeapRegion* cur = _head;
 250   uint num = 0;
 251   while (cur != NULL) {
 252     uint index = cur->hrm_index();
 253     if (index > end) {
 254       break;
 255     } else if (index >= start) {
 256       num++;
 257     }
 258     cur = cur->next();
 259   }
 260   return num;
 261 }
 262 
 263 void FreeRegionList::verify() {
 264   // See comment in HeapRegionSetBase::verify() about MT safety and
 265   // verification.
 266   check_mt_safety();
 267 
 268   // This will also do the basic verification too.
 269   verify_start();
 270 
 271   verify_list();
 272 
 273   verify_end();
 274 }
 275 
 276 void FreeRegionList::clear() {
 277   _length = 0;
 278   _head = NULL;
 279   _tail = NULL;
 280   _last = NULL;
 281 
 282   if (_node_info!= NULL) {
 283     _node_info->clear();
 284   }
 285 }
 286 
 287 void FreeRegionList::verify_list() {
 288   HeapRegion* curr = _head;
 289   HeapRegion* prev1 = NULL;
 290   HeapRegion* prev0 = NULL;
 291   uint count = 0;
 292   size_t capacity = 0;
 293   uint last_index = 0;
 294 
 295   guarantee(_head == NULL || _head->prev() == NULL, "_head should not have a prev");
 296   while (curr != NULL) {
 297     verify_region(curr);
 298 
 299     count++;
 300     guarantee(count < _unrealistically_long_length,
 301               "[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " "prev1: " PTR_FORMAT " length: %u",
 302               name(), count, p2i(curr), p2i(prev0), p2i(prev1), length());
 303 
 304     if (curr->next() != NULL) {
 305       guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up");
 306     }
 307     guarantee(curr->hrm_index() == 0 || curr->hrm_index() > last_index, "List should be sorted");
 308     last_index = curr->hrm_index();
 309 
 310     capacity += curr->capacity();
 311 
 312     prev1 = prev0;
 313     prev0 = curr;
 314     curr = curr->next();
 315   }
 316 
 317   guarantee(_tail == prev0, "Expected %s to end with %u but it ended with %u.", name(), _tail->hrm_index(), prev0->hrm_index());
 318   guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
 319   guarantee(length() == count, "%s count mismatch. Expected %u, actual %u.", name(), length(), count);
 320 }
 321 
 322 
 323 FreeRegionList::FreeRegionList(const char* name, HeapRegionSetChecker* checker):
 324   HeapRegionSetBase(name, checker),
 325   _node_info(G1NUMA::numa()->is_enabled() ? new NodeInfo() : NULL) {
 326 
 327   clear();
 328 }
 329 
 330 FreeRegionList::~FreeRegionList() {
 331   if (_node_info != NULL) {
 332     delete _node_info;
 333   }
 334 }
 335 
 336 FreeRegionList::NodeInfo::NodeInfo() : _numa(G1NUMA::numa()), _length_of_node(NULL),
 337                                        _num_nodes(_numa->num_active_nodes()) {
 338   assert(UseNUMA, "Invariant");
 339 
 340   _length_of_node = NEW_C_HEAP_ARRAY(uint, _num_nodes, mtGC);
 341 }
 342 
 343 FreeRegionList::NodeInfo::~NodeInfo() {
 344   FREE_C_HEAP_ARRAY(uint, _length_of_node);
 345 }
 346 
 347 void FreeRegionList::NodeInfo::clear() {
 348   for (uint i = 0; i < _num_nodes; ++i) {
 349     _length_of_node[i] = 0;
 350   }
 351 }
 352 
 353 void FreeRegionList::NodeInfo::add(NodeInfo* info) {
 354   for (uint i = 0; i < _num_nodes; ++i) {
 355     _length_of_node[i] += info->_length_of_node[i];
 356   }
 357 }
 358