heapRegionSet.cpp 15.6 KB
Newer Older
1
/*
2
 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * 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"
26
#include "gc_implementation/g1/heapRegionRemSet.hpp"
27 28
#include "gc_implementation/g1/heapRegionSet.inline.hpp"

29 30
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC

31
uint FreeRegionList::_unrealistically_long_length = 0;
32

T
tonyp 已提交
33
void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
34 35
  msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
              name(), message, length(), total_capacity_bytes());
36 37 38
  fill_in_ext_msg_extra(msg);
}

39 40 41 42 43 44 45
#ifndef PRODUCT
void HeapRegionSetBase::verify_region(HeapRegion* hr) {
  assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index()));
  assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions
  assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name()));
  assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name()));
  assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index()));
46
}
47
#endif
48 49 50 51 52 53

void HeapRegionSetBase::verify() {
  // It's important that we also observe the MT safety protocol even
  // for the verification calls. If we do verification without the
  // appropriate locks and the set changes underneath our feet
  // verification might fail and send us on a wild goose chase.
54
  check_mt_safety();
55

56 57
  guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) ||
            (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0),
T
tonyp 已提交
58
            hrs_ext_msg(this, "invariant"));
59 60 61 62
}

void HeapRegionSetBase::verify_start() {
  // See comment in verify() about MT safety and verification.
63
  check_mt_safety();
64
  assert(!_verify_in_progress,
T
tonyp 已提交
65
         hrs_ext_msg(this, "verification should not be in progress"));
66 67 68 69 70 71 72 73 74

  // Do the basic verification first before we do the checks over the regions.
  HeapRegionSetBase::verify();

  _verify_in_progress        = true;
}

void HeapRegionSetBase::verify_end() {
  // See comment in verify() about MT safety and verification.
75
  check_mt_safety();
76
  assert(_verify_in_progress,
T
tonyp 已提交
77
         hrs_ext_msg(this, "verification should be in progress"));
78 79 80 81 82 83 84 85 86 87 88

  _verify_in_progress = false;
}

void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
  out->cr();
  out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
  out->print_cr("  Region Assumptions");
  out->print_cr("    humongous         : %s", BOOL_TO_STR(regions_humongous()));
  out->print_cr("    empty             : %s", BOOL_TO_STR(regions_empty()));
  out->print_cr("  Attributes");
89
  out->print_cr("    length            : %14u", length());
90 91 92 93
  out->print_cr("    total capacity    : "SIZE_FORMAT_W(14)" bytes",
                total_capacity_bytes());
}

94
HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker)
95
  : _name(name), _verify_in_progress(false),
96 97 98
    _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker),
    _count()
{ }
99

100 101 102
void FreeRegionList::set_unrealistically_long_length(uint len) {
  guarantee(_unrealistically_long_length == 0, "should only be set once");
  _unrealistically_long_length = len;
103 104
}

105
void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
106 107 108
  msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
}

109 110 111
void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) {
  check_mt_safety();
  from_list->check_mt_safety();
112 113 114 115

  verify_optional();
  from_list->verify_optional();

116 117 118
  if (from_list->is_empty()) {
    return;
  }
119 120

#ifdef ASSERT
121
  FreeRegionListIterator iter(from_list);
122 123 124 125 126 127 128 129 130 131
  while (iter.more_available()) {
    HeapRegion* hr = iter.get_next();
    // In set_containing_set() we check that we either set the value
    // from NULL to non-NULL or vice versa to catch bugs. So, we have
    // to NULL it first before setting it to the value.
    hr->set_containing_set(NULL);
    hr->set_containing_set(this);
  }
#endif // ASSERT

132
  if (_head == NULL) {
133
    assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
134
    _head = from_list->_head;
135
    _tail = from_list->_tail;
136 137 138 139
  } else {
    assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
    if (as_head) {
      from_list->_tail->set_next(_head);
140
      _head->set_prev(from_list->_tail);
141 142 143
      _head = from_list->_head;
    } else {
      _tail->set_next(from_list->_head);
144
      from_list->_head->set_prev(_tail);
145 146
      _tail = from_list->_tail;
    }
147 148
  }

149
  _count.increment(from_list->length(), from_list->total_capacity_bytes());
150 151 152 153 154 155
  from_list->clear();

  verify_optional();
  from_list->verify_optional();
}

156 157 158
void FreeRegionList::add_as_head(FreeRegionList* from_list) {
  add_as_head_or_tail(from_list, true /* as_head */);
}
159

160 161
void FreeRegionList::add_as_tail(FreeRegionList* from_list) {
  add_as_head_or_tail(from_list, false /* as_head */);
162 163
}

164 165
void FreeRegionList::remove_all() {
  check_mt_safety();
166 167 168 169
  verify_optional();

  HeapRegion* curr = _head;
  while (curr != NULL) {
170
    verify_region(curr);
171 172 173

    HeapRegion* next = curr->next();
    curr->set_next(NULL);
174
    curr->set_prev(NULL);
175 176 177 178 179 180 181 182
    curr->set_containing_set(NULL);
    curr = next;
  }
  clear();

  verify_optional();
}

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
void FreeRegionList::add_ordered(FreeRegionList* from_list) {
  check_mt_safety();
  from_list->check_mt_safety();

  verify_optional();
  from_list->verify_optional();

  if (from_list->is_empty()) {
    return;
  }

  if (is_empty()) {
    add_as_head(from_list);
    return;
  }

  #ifdef ASSERT
  FreeRegionListIterator iter(from_list);
  while (iter.more_available()) {
    HeapRegion* hr = iter.get_next();
    // In set_containing_set() we check that we either set the value
    // from NULL to non-NULL or vice versa to catch bugs. So, we have
    // to NULL it first before setting it to the value.
    hr->set_containing_set(NULL);
    hr->set_containing_set(this);
  }
  #endif // ASSERT

  HeapRegion* curr_to = _head;
  HeapRegion* curr_from = from_list->_head;

  while (curr_from != NULL) {
    while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) {
      curr_to = curr_to->next();
    }

    if (curr_to == NULL) {
      // The rest of the from list should be added as tail
      _tail->set_next(curr_from);
      curr_from->set_prev(_tail);
      curr_from = NULL;
    } else {
      HeapRegion* next_from = curr_from->next();

      curr_from->set_next(curr_to);
      curr_from->set_prev(curr_to->prev());
      if (curr_to->prev() == NULL) {
        _head = curr_from;
      } else {
        curr_to->prev()->set_next(curr_from);
      }
      curr_to->set_prev(curr_from);

      curr_from = next_from;
    }
  }

  if (_tail->hrs_index() < from_list->_tail->hrs_index()) {
    _tail = from_list->_tail;
  }

  _count.increment(from_list->length(), from_list->total_capacity_bytes());
  from_list->clear();

  verify_optional();
  from_list->verify_optional();
}

251 252
void FreeRegionList::remove_all_pending(uint target_count) {
  check_mt_safety();
T
tonyp 已提交
253 254
  assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
  assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
255 256

  verify_optional();
257
  DEBUG_ONLY(uint old_length = length();)
258 259

  HeapRegion* curr = _head;
260
  uint count = 0;
261
  while (curr != NULL) {
262
    verify_region(curr);
263
    HeapRegion* next = curr->next();
264
    HeapRegion* prev = curr->prev();
265 266 267

    if (curr->pending_removal()) {
      assert(count < target_count,
T
tonyp 已提交
268
             hrs_err_msg("[%s] should not come across more regions "
269
                         "pending for removal than target_count: %u",
270 271 272
                         name(), target_count));

      if (prev == NULL) {
T
tonyp 已提交
273
        assert(_head == curr, hrs_ext_msg(this, "invariant"));
274 275
        _head = next;
      } else {
T
tonyp 已提交
276
        assert(_head != curr, hrs_ext_msg(this, "invariant"));
277 278 279
        prev->set_next(next);
      }
      if (next == NULL) {
T
tonyp 已提交
280
        assert(_tail == curr, hrs_ext_msg(this, "invariant"));
281 282
        _tail = prev;
      } else {
T
tonyp 已提交
283
        assert(_tail != curr, hrs_ext_msg(this, "invariant"));
284 285 286 287
        next->set_prev(prev);
      }
      if (_last = curr) {
        _last = NULL;
288 289 290
      }

      curr->set_next(NULL);
291
      curr->set_prev(NULL);
292
      remove(curr);
293 294 295 296 297 298 299 300 301 302 303 304 305 306
      curr->set_pending_removal(false);

      count += 1;

      // If we have come across the target number of regions we can
      // just bail out. However, for debugging purposes, we can just
      // carry on iterating to make sure there are not more regions
      // tagged with pending removal.
      DEBUG_ONLY(if (count == target_count) break;)
    }
    curr = next;
  }

  assert(count == target_count,
307 308
         hrs_err_msg("[%s] count: %u should be == target_count: %u",
                     name(), count, target_count));
309
  assert(length() + target_count == old_length,
T
tonyp 已提交
310
         hrs_err_msg("[%s] new length should be consistent "
311
                     "new length: %u old length: %u target_count: %u",
312 313 314 315 316
                     name(), length(), old_length, target_count));

  verify_optional();
}

317
void FreeRegionList::verify() {
318 319
  // See comment in HeapRegionSetBase::verify() about MT safety and
  // verification.
320
  check_mt_safety();
321 322 323 324

  // This will also do the basic verification too.
  verify_start();

325
  verify_list();
326 327 328 329

  verify_end();
}

330 331
void FreeRegionList::clear() {
  _count = HeapRegionSetCount();
332 333
  _head = NULL;
  _tail = NULL;
334
  _last = NULL;
335 336
}

337
void FreeRegionList::print_on(outputStream* out, bool print_contents) {
338 339 340 341 342 343 344
  HeapRegionSetBase::print_on(out, print_contents);
  out->print_cr("  Linking");
  out->print_cr("    head              : "PTR_FORMAT, _head);
  out->print_cr("    tail              : "PTR_FORMAT, _tail);

  if (print_contents) {
    out->print_cr("  Contents");
345
    FreeRegionListIterator iter(this);
346 347 348 349 350 351
    while (iter.more_available()) {
      HeapRegion* hr = iter.get_next();
      hr->print_on(out);
    }
  }
}
352 353 354 355 356 357 358

void FreeRegionList::verify_list() {
  HeapRegion* curr = head();
  HeapRegion* prev1 = NULL;
  HeapRegion* prev0 = NULL;
  uint count = 0;
  size_t capacity = 0;
359 360 361
  uint last_index = 0;

  guarantee(_head == NULL || _head->prev() == NULL, "_head should not have a prev");
362 363 364 365 366 367 368
  while (curr != NULL) {
    verify_region(curr);

    count++;
    guarantee(count < _unrealistically_long_length,
        hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u", name(), count, curr, prev0, prev1, length()));

369 370 371 372 373 374
    if (curr->next() != NULL) {
      guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up");
    }
    guarantee(curr->hrs_index() == 0 || curr->hrs_index() > last_index, "List should be sorted");
    last_index = curr->hrs_index();

375 376 377 378 379 380 381 382
    capacity += curr->capacity();

    prev1 = prev0;
    prev0 = curr;
    curr = curr->next();
  }

  guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index()));
383
  guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count));
  guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
      name(), total_capacity_bytes(), capacity));
}

// Note on the check_mt_safety() methods below:
//
// Verification of the "master" heap region sets / lists that are
// maintained by G1CollectedHeap is always done during a STW pause and
// by the VM thread at the start / end of the pause. The standard
// verification methods all assert check_mt_safety(). This is
// important as it ensures that verification is done without
// concurrent updates taking place at the same time. It follows, that,
// for the "master" heap region sets / lists, the check_mt_safety()
// method should include the VM thread / STW case.

void MasterFreeRegionListMtSafeChecker::check() {
  // Master Free List MT safety protocol:
  // (a) If we're at a safepoint, operations on the master free list
  // should be invoked by either the VM thread (which will serialize
  // them) or by the GC workers while holding the
  // FreeList_lock.
  // (b) If we're not at a safepoint, operations on the master free
  // list should be invoked while holding the Heap_lock.

  if (SafepointSynchronize::is_at_safepoint()) {
    guarantee(Thread::current()->is_VM_thread() ||
              FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
  } else {
    guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
  }
}

void SecondaryFreeRegionListMtSafeChecker::check() {
  // Secondary Free List MT safety protocol:
  // Operations on the secondary free list should always be invoked
  // while holding the SecondaryFreeList_lock.

  guarantee(SecondaryFreeList_lock->owned_by_self(), "secondary free list MT safety protocol");
}

void OldRegionSetMtSafeChecker::check() {
  // Master Old Set MT safety protocol:
  // (a) If we're at a safepoint, operations on the master old set
  // should be invoked:
  // - by the VM thread (which will serialize them), or
  // - by the GC workers while holding the FreeList_lock, if we're
  //   at a safepoint for an evacuation pause (this lock is taken
  //   anyway when an GC alloc region is retired so that a new one
  //   is allocated from the free list), or
  // - by the GC workers while holding the OldSets_lock, if we're at a
  //   safepoint for a cleanup pause.
  // (b) If we're not at a safepoint, operations on the master old set
  // should be invoked while holding the Heap_lock.

  if (SafepointSynchronize::is_at_safepoint()) {
    guarantee(Thread::current()->is_VM_thread()
        || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
        "master old set MT safety protocol at a safepoint");
  } else {
    guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
  }
}

void HumongousRegionSetMtSafeChecker::check() {
  // Humongous Set MT safety protocol:
  // (a) If we're at a safepoint, operations on the master humongous
  // set should be invoked by either the VM thread (which will
  // serialize them) or by the GC workers while holding the
  // OldSets_lock.
  // (b) If we're not at a safepoint, operations on the master
  // humongous set should be invoked while holding the Heap_lock.

  if (SafepointSynchronize::is_at_safepoint()) {
    guarantee(Thread::current()->is_VM_thread() ||
              OldSets_lock->owned_by_self(),
              "master humongous set MT safety protocol at a safepoint");
  } else {
    guarantee(Heap_lock->owned_by_self(),
              "master humongous set MT safety protocol outside a safepoint");
  }
}