heapRegionSet.cpp 15.7 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/g1CollectedHeap.inline.hpp"
27
#include "gc_implementation/g1/heapRegionRemSet.hpp"
28 29
#include "gc_implementation/g1/heapRegionSet.inline.hpp"

30 31
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC

32
uint FreeRegionList::_unrealistically_long_length = 0;
33

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

40 41
#ifndef PRODUCT
void HeapRegionSetBase::verify_region(HeapRegion* hr) {
42 43 44
  assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrm_index()));
  assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrm_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->hrm_index(), name()));
45 46 47
  assert(hr->is_free() == regions_free(), err_msg("Wrong free state for region %u and set %s", hr->hrm_index(), name()));
  assert(!hr->is_free() || hr->is_empty(), err_msg("Free region %u is not empty for set %s", hr->hrm_index(), name()));
  assert(!hr->is_empty() || hr->is_free(), err_msg("Empty region %u is not free for set %s", hr->hrm_index(), name()));
48
  assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrm_index()));
49
}
50
#endif
51 52 53 54 55 56

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.
57
  check_mt_safety();
58

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

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

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

73
  _verify_in_progress = true;
74 75 76 77
}

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

  _verify_in_progress = false;
}

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

97
HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool free, HRSMtSafeChecker* mt_safety_checker)
98
  : _name(name), _verify_in_progress(false),
99
    _is_humongous(humongous), _is_free(free), _mt_safety_checker(mt_safety_checker),
100 101
    _count()
{ }
102

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

108
void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
109
  msg->append(" hd: " PTR_FORMAT " tl: " PTR_FORMAT, _head, _tail);
110 111
}

112 113
void FreeRegionList::remove_all() {
  check_mt_safety();
114 115 116 117
  verify_optional();

  HeapRegion* curr = _head;
  while (curr != NULL) {
118
    verify_region(curr);
119 120 121

    HeapRegion* next = curr->next();
    curr->set_next(NULL);
122
    curr->set_prev(NULL);
123 124 125 126 127 128 129 130
    curr->set_containing_set(NULL);
    curr = next;
  }
  clear();

  verify_optional();
}

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
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;
  }

  #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

154 155 156 157 158 159 160
  if (is_empty()) {
    assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
    _head = from_list->_head;
    _tail = from_list->_tail;
  } else {
    HeapRegion* curr_to = _head;
    HeapRegion* curr_from = from_list->_head;
161

162
    while (curr_from != NULL) {
163
      while (curr_to != NULL && curr_to->hrm_index() < curr_from->hrm_index()) {
164 165
        curr_to = curr_to->next();
      }
166

167 168 169 170 171
      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;
172
      } else {
173 174 175 176 177 178 179 180 181 182 183 184
        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;
185 186 187
      }
    }

188
    if (_tail->hrm_index() < from_list->_tail->hrm_index()) {
189 190
      _tail = from_list->_tail;
    }
191 192 193 194 195 196 197 198 199
  }

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

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

200
void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
201
  check_mt_safety();
202
  assert(num_regions >= 1, hrs_ext_msg(this, "pre-condition"));
T
tonyp 已提交
203
  assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
204 205

  verify_optional();
206
  DEBUG_ONLY(uint old_length = length();)
207

208
  HeapRegion* curr = first;
209
  uint count = 0;
210
  while (count < num_regions) {
211
    verify_region(curr);
212
    HeapRegion* next = curr->next();
213
    HeapRegion* prev = curr->prev();
214

215 216 217 218
    assert(count < num_regions,
           hrs_err_msg("[%s] should not come across more regions "
                       "pending for removal than num_regions: %u",
                       name(), num_regions));
219

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
    if (prev == NULL) {
      assert(_head == curr, hrs_ext_msg(this, "invariant"));
      _head = next;
    } else {
      assert(_head != curr, hrs_ext_msg(this, "invariant"));
      prev->set_next(next);
    }
    if (next == NULL) {
      assert(_tail == curr, hrs_ext_msg(this, "invariant"));
      _tail = prev;
    } else {
      assert(_tail != curr, hrs_ext_msg(this, "invariant"));
      next->set_prev(prev);
    }
    if (_last = curr) {
      _last = NULL;
    }
237

238 239 240
    curr->set_next(NULL);
    curr->set_prev(NULL);
    remove(curr);
241

242
    count++;
243 244 245
    curr = next;
  }

246 247 248 249
  assert(count == num_regions,
         hrs_err_msg("[%s] count: %u should be == num_regions: %u",
                     name(), count, num_regions));
  assert(length() + num_regions == old_length,
T
tonyp 已提交
250
         hrs_err_msg("[%s] new length should be consistent "
251 252
                     "new length: %u old length: %u num_regions: %u",
                     name(), length(), old_length, num_regions));
253 254 255 256

  verify_optional();
}

257
void FreeRegionList::verify() {
258 259
  // See comment in HeapRegionSetBase::verify() about MT safety and
  // verification.
260
  check_mt_safety();
261 262 263 264

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

265
  verify_list();
266 267 268 269

  verify_end();
}

270 271
void FreeRegionList::clear() {
  _count = HeapRegionSetCount();
272 273
  _head = NULL;
  _tail = NULL;
274
  _last = NULL;
275 276
}

277
void FreeRegionList::print_on(outputStream* out, bool print_contents) {
278 279
  HeapRegionSetBase::print_on(out, print_contents);
  out->print_cr("  Linking");
280 281
  out->print_cr("    head              : " PTR_FORMAT, _head);
  out->print_cr("    tail              : " PTR_FORMAT, _tail);
282 283 284

  if (print_contents) {
    out->print_cr("  Contents");
285
    FreeRegionListIterator iter(this);
286 287 288 289 290
    while (iter.more_available()) {
      HeapRegion* hr = iter.get_next();
      hr->print_on(out);
    }
  }
291 292

  out->cr();
293
}
294 295

void FreeRegionList::verify_list() {
296
  HeapRegion* curr = _head;
297 298 299 300
  HeapRegion* prev1 = NULL;
  HeapRegion* prev0 = NULL;
  uint count = 0;
  size_t capacity = 0;
301 302 303
  uint last_index = 0;

  guarantee(_head == NULL || _head->prev() == NULL, "_head should not have a prev");
304 305 306 307 308
  while (curr != NULL) {
    verify_region(curr);

    count++;
    guarantee(count < _unrealistically_long_length,
309
        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()));
310

311 312 313
    if (curr->next() != NULL) {
      guarantee(curr->next()->prev() == curr, "Next or prev pointers messed up");
    }
314 315
    guarantee(curr->hrm_index() == 0 || curr->hrm_index() > last_index, "List should be sorted");
    last_index = curr->hrm_index();
316

317 318 319 320 321 322 323
    capacity += curr->capacity();

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

324
  guarantee(_tail == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), _tail->hrm_index(), prev0->hrm_index()));
325
  guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
  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");
  }
}
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422

void FreeRegionList_test() {
  FreeRegionList l("test");

  const uint num_regions_in_test = 5;
  // Create a fake heap. It does not need to be valid, as the HeapRegion constructor
  // does not access it.
  MemRegion heap(NULL, num_regions_in_test * HeapRegion::GrainWords);
  // Allocate a fake BOT because the HeapRegion constructor initializes
  // the BOT.
  size_t bot_size = G1BlockOffsetSharedArray::compute_size(heap.word_size());
  HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC);
  ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(heap.word_size()));
  G1RegionToSpaceMapper* bot_storage =
    G1RegionToSpaceMapper::create_mapper(bot_rs,
423
                                         bot_rs.size(),
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
                                         os::vm_page_size(),
                                         HeapRegion::GrainBytes,
                                         G1BlockOffsetSharedArray::N_bytes,
                                         mtGC);
  G1BlockOffsetSharedArray oa(heap, bot_storage);
  bot_storage->commit_regions(0, num_regions_in_test);
  HeapRegion hr0(0, &oa, heap);
  HeapRegion hr1(1, &oa, heap);
  HeapRegion hr2(2, &oa, heap);
  HeapRegion hr3(3, &oa, heap);
  HeapRegion hr4(4, &oa, heap);
  l.add_ordered(&hr1);
  l.add_ordered(&hr0);
  l.add_ordered(&hr3);
  l.add_ordered(&hr4);
  l.add_ordered(&hr2);
  assert(l.length() == num_regions_in_test, "wrong length");
  l.verify_list();

  bot_storage->uncommit_regions(0, num_regions_in_test);
  delete bot_storage;
  FREE_C_HEAP_ARRAY(HeapWord, bot_data, mtGC);
}