src/share/vm/gc_implementation/g1/heapRegionSet.cpp

Mon, 17 Mar 2014 13:42:16 +0100

author
brutisso
date
Mon, 17 Mar 2014 13:42:16 +0100
changeset 6386
0d2ce7411240
parent 6385
58fc1b1523dc
child 6422
8ee855b4e667
permissions
-rw-r--r--

8037407: G1: Remove heapRegionSets.cpp
Reviewed-by: tschatzl, pliden

tonyp@2472 1 /*
tonyp@3713 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
tonyp@2472 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tonyp@2472 4 *
tonyp@2472 5 * This code is free software; you can redistribute it and/or modify it
tonyp@2472 6 * under the terms of the GNU General Public License version 2 only, as
tonyp@2472 7 * published by the Free Software Foundation.
tonyp@2472 8 *
tonyp@2472 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tonyp@2472 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tonyp@2472 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tonyp@2472 12 * version 2 for more details (a copy is included in the LICENSE file that
tonyp@2472 13 * accompanied this code).
tonyp@2472 14 *
tonyp@2472 15 * You should have received a copy of the GNU General Public License version
tonyp@2472 16 * 2 along with this work; if not, write to the Free Software Foundation,
tonyp@2472 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tonyp@2472 18 *
tonyp@2472 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tonyp@2472 20 * or visit www.oracle.com if you need additional information or have any
tonyp@2472 21 * questions.
tonyp@2472 22 *
tonyp@2472 23 */
tonyp@2472 24
tonyp@2472 25 #include "precompiled.hpp"
brutisso@6385 26 #include "gc_implementation/g1/heapRegionRemSet.hpp"
tonyp@2472 27 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
tonyp@2472 28
brutisso@6385 29 uint FreeRegionList::_unrealistically_long_length = 0;
tonyp@2472 30
tonyp@2643 31 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
brutisso@6385 32 msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
brutisso@6385 33 name(), message, length(), total_capacity_bytes());
tonyp@2472 34 fill_in_ext_msg_extra(msg);
tonyp@2472 35 }
tonyp@2472 36
brutisso@6385 37 #ifndef PRODUCT
brutisso@6385 38 void HeapRegionSetBase::verify_region(HeapRegion* hr) {
brutisso@6385 39 assert(hr->containing_set() == this, err_msg("Inconsistent containing set for %u", hr->hrs_index()));
brutisso@6385 40 assert(!hr->is_young(), err_msg("Adding young region %u", hr->hrs_index())); // currently we don't use these sets for young regions
brutisso@6385 41 assert(hr->isHumongous() == regions_humongous(), err_msg("Wrong humongous state for region %u and set %s", hr->hrs_index(), name()));
brutisso@6385 42 assert(hr->is_empty() == regions_empty(), err_msg("Wrong empty state for region %u and set %s", hr->hrs_index(), name()));
brutisso@6385 43 assert(hr->rem_set()->verify_ready_for_par_iteration(), err_msg("Wrong iteration state %u", hr->hrs_index()));
tonyp@2472 44 }
brutisso@6385 45 #endif
tonyp@2472 46
tonyp@2472 47 void HeapRegionSetBase::verify() {
tonyp@2472 48 // It's important that we also observe the MT safety protocol even
tonyp@2472 49 // for the verification calls. If we do verification without the
tonyp@2472 50 // appropriate locks and the set changes underneath our feet
tonyp@2472 51 // verification might fail and send us on a wild goose chase.
brutisso@6385 52 check_mt_safety();
tonyp@2472 53
brutisso@6385 54 guarantee(( is_empty() && length() == 0 && total_capacity_bytes() == 0) ||
brutisso@6385 55 (!is_empty() && length() >= 0 && total_capacity_bytes() >= 0),
tonyp@2643 56 hrs_ext_msg(this, "invariant"));
tonyp@2472 57 }
tonyp@2472 58
tonyp@2472 59 void HeapRegionSetBase::verify_start() {
tonyp@2472 60 // See comment in verify() about MT safety and verification.
brutisso@6385 61 check_mt_safety();
tonyp@2472 62 assert(!_verify_in_progress,
tonyp@2643 63 hrs_ext_msg(this, "verification should not be in progress"));
tonyp@2472 64
tonyp@2472 65 // Do the basic verification first before we do the checks over the regions.
tonyp@2472 66 HeapRegionSetBase::verify();
tonyp@2472 67
tonyp@2472 68 _verify_in_progress = true;
tonyp@2472 69 }
tonyp@2472 70
tonyp@2472 71 void HeapRegionSetBase::verify_end() {
tonyp@2472 72 // See comment in verify() about MT safety and verification.
brutisso@6385 73 check_mt_safety();
tonyp@2472 74 assert(_verify_in_progress,
tonyp@2643 75 hrs_ext_msg(this, "verification should be in progress"));
tonyp@2472 76
tonyp@2472 77 _verify_in_progress = false;
tonyp@2472 78 }
tonyp@2472 79
tonyp@2472 80 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
tonyp@2472 81 out->cr();
tonyp@2472 82 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
tonyp@2472 83 out->print_cr(" Region Assumptions");
tonyp@2472 84 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
tonyp@2472 85 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty()));
tonyp@2472 86 out->print_cr(" Attributes");
tonyp@3713 87 out->print_cr(" length : %14u", length());
tonyp@2472 88 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
tonyp@2472 89 total_capacity_bytes());
tonyp@2472 90 }
tonyp@2472 91
brutisso@6385 92 HeapRegionSetBase::HeapRegionSetBase(const char* name, bool humongous, bool empty, HRSMtSafeChecker* mt_safety_checker)
brutisso@6385 93 : _name(name), _verify_in_progress(false),
brutisso@6385 94 _is_humongous(humongous), _is_empty(empty), _mt_safety_checker(mt_safety_checker),
brutisso@6385 95 _count()
brutisso@6385 96 { }
brutisso@6385 97
brutisso@6385 98 void FreeRegionList::set_unrealistically_long_length(uint len) {
brutisso@6385 99 guarantee(_unrealistically_long_length == 0, "should only be set once");
brutisso@6385 100 _unrealistically_long_length = len;
tonyp@2472 101 }
tonyp@2472 102
brutisso@6385 103 void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
tonyp@2472 104 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
tonyp@2472 105 }
tonyp@2472 106
brutisso@6385 107 void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) {
brutisso@6385 108 check_mt_safety();
brutisso@6385 109 from_list->check_mt_safety();
tonyp@2714 110
tonyp@2714 111 verify_optional();
tonyp@2714 112 from_list->verify_optional();
tonyp@2714 113
brutisso@6385 114 if (from_list->is_empty()) {
brutisso@6385 115 return;
brutisso@6385 116 }
tonyp@2714 117
tonyp@2714 118 #ifdef ASSERT
brutisso@6385 119 FreeRegionListIterator iter(from_list);
tonyp@2714 120 while (iter.more_available()) {
tonyp@2714 121 HeapRegion* hr = iter.get_next();
tonyp@2714 122 // In set_containing_set() we check that we either set the value
tonyp@2714 123 // from NULL to non-NULL or vice versa to catch bugs. So, we have
tonyp@2714 124 // to NULL it first before setting it to the value.
tonyp@2714 125 hr->set_containing_set(NULL);
tonyp@2714 126 hr->set_containing_set(this);
tonyp@2714 127 }
tonyp@2714 128 #endif // ASSERT
tonyp@2714 129
brutisso@6385 130 if (_head == NULL) {
brutisso@6385 131 assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
brutisso@6385 132 _head = from_list->_head;
brutisso@6385 133 _tail = from_list->_tail;
tonyp@2714 134 } else {
brutisso@6385 135 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
brutisso@6385 136 if (as_head) {
brutisso@6385 137 from_list->_tail->set_next(_head);
brutisso@6385 138 _head = from_list->_head;
brutisso@6385 139 } else {
brutisso@6385 140 _tail->set_next(from_list->_head);
brutisso@6385 141 _tail = from_list->_tail;
brutisso@6385 142 }
tonyp@2714 143 }
tonyp@2714 144
brutisso@6385 145 _count.increment(from_list->length(), from_list->total_capacity_bytes());
tonyp@2714 146 from_list->clear();
tonyp@2714 147
tonyp@2714 148 verify_optional();
tonyp@2714 149 from_list->verify_optional();
tonyp@2714 150 }
tonyp@2714 151
brutisso@6385 152 void FreeRegionList::add_as_head(FreeRegionList* from_list) {
brutisso@6385 153 add_as_head_or_tail(from_list, true /* as_head */);
tonyp@2472 154 }
tonyp@2472 155
brutisso@6385 156 void FreeRegionList::add_as_tail(FreeRegionList* from_list) {
brutisso@6385 157 add_as_head_or_tail(from_list, false /* as_head */);
brutisso@6385 158 }
brutisso@6385 159
brutisso@6385 160 void FreeRegionList::remove_all() {
brutisso@6385 161 check_mt_safety();
tonyp@2472 162 verify_optional();
tonyp@2472 163
tonyp@2472 164 HeapRegion* curr = _head;
tonyp@2472 165 while (curr != NULL) {
brutisso@6385 166 verify_region(curr);
tonyp@2472 167
tonyp@2472 168 HeapRegion* next = curr->next();
tonyp@2472 169 curr->set_next(NULL);
tonyp@2472 170 curr->set_containing_set(NULL);
tonyp@2472 171 curr = next;
tonyp@2472 172 }
tonyp@2472 173 clear();
tonyp@2472 174
tonyp@2472 175 verify_optional();
tonyp@2472 176 }
tonyp@2472 177
brutisso@6385 178 void FreeRegionList::remove_all_pending(uint target_count) {
brutisso@6385 179 check_mt_safety();
tonyp@2643 180 assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
tonyp@2643 181 assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
tonyp@2472 182
tonyp@2472 183 verify_optional();
tonyp@3713 184 DEBUG_ONLY(uint old_length = length();)
tonyp@2472 185
tonyp@2472 186 HeapRegion* curr = _head;
tonyp@2472 187 HeapRegion* prev = NULL;
tonyp@3713 188 uint count = 0;
tonyp@2472 189 while (curr != NULL) {
brutisso@6385 190 verify_region(curr);
tonyp@2472 191 HeapRegion* next = curr->next();
tonyp@2472 192
tonyp@2472 193 if (curr->pending_removal()) {
tonyp@2472 194 assert(count < target_count,
tonyp@2643 195 hrs_err_msg("[%s] should not come across more regions "
tonyp@3713 196 "pending for removal than target_count: %u",
tonyp@2472 197 name(), target_count));
tonyp@2472 198
tonyp@2472 199 if (prev == NULL) {
tonyp@2643 200 assert(_head == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 201 _head = next;
tonyp@2472 202 } else {
tonyp@2643 203 assert(_head != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 204 prev->set_next(next);
tonyp@2472 205 }
tonyp@2472 206 if (next == NULL) {
tonyp@2643 207 assert(_tail == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 208 _tail = prev;
tonyp@2472 209 } else {
tonyp@2643 210 assert(_tail != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 211 }
tonyp@2472 212
tonyp@2472 213 curr->set_next(NULL);
brutisso@6385 214 remove(curr);
tonyp@2472 215 curr->set_pending_removal(false);
tonyp@2472 216
tonyp@2472 217 count += 1;
tonyp@2472 218
tonyp@2472 219 // If we have come across the target number of regions we can
tonyp@2472 220 // just bail out. However, for debugging purposes, we can just
tonyp@2472 221 // carry on iterating to make sure there are not more regions
tonyp@2472 222 // tagged with pending removal.
tonyp@2472 223 DEBUG_ONLY(if (count == target_count) break;)
tonyp@2472 224 } else {
tonyp@2472 225 prev = curr;
tonyp@2472 226 }
tonyp@2472 227 curr = next;
tonyp@2472 228 }
tonyp@2472 229
tonyp@2472 230 assert(count == target_count,
tonyp@3713 231 hrs_err_msg("[%s] count: %u should be == target_count: %u",
tonyp@3713 232 name(), count, target_count));
tonyp@2472 233 assert(length() + target_count == old_length,
tonyp@2643 234 hrs_err_msg("[%s] new length should be consistent "
tonyp@3713 235 "new length: %u old length: %u target_count: %u",
tonyp@2472 236 name(), length(), old_length, target_count));
tonyp@2472 237
tonyp@2472 238 verify_optional();
tonyp@2472 239 }
tonyp@2472 240
brutisso@6385 241 void FreeRegionList::verify() {
tonyp@2472 242 // See comment in HeapRegionSetBase::verify() about MT safety and
tonyp@2472 243 // verification.
brutisso@6385 244 check_mt_safety();
tonyp@2472 245
tonyp@2472 246 // This will also do the basic verification too.
tonyp@2472 247 verify_start();
tonyp@2472 248
brutisso@6385 249 verify_list();
tonyp@2472 250
tonyp@2472 251 verify_end();
tonyp@2472 252 }
tonyp@2472 253
brutisso@6385 254 void FreeRegionList::clear() {
brutisso@6385 255 _count = HeapRegionSetCount();
tonyp@2472 256 _head = NULL;
tonyp@2472 257 _tail = NULL;
tonyp@2472 258 }
tonyp@2472 259
brutisso@6385 260 void FreeRegionList::print_on(outputStream* out, bool print_contents) {
tonyp@2472 261 HeapRegionSetBase::print_on(out, print_contents);
tonyp@2472 262 out->print_cr(" Linking");
tonyp@2472 263 out->print_cr(" head : "PTR_FORMAT, _head);
tonyp@2472 264 out->print_cr(" tail : "PTR_FORMAT, _tail);
tonyp@2472 265
tonyp@2472 266 if (print_contents) {
tonyp@2472 267 out->print_cr(" Contents");
brutisso@6385 268 FreeRegionListIterator iter(this);
tonyp@2472 269 while (iter.more_available()) {
tonyp@2472 270 HeapRegion* hr = iter.get_next();
tonyp@2472 271 hr->print_on(out);
tonyp@2472 272 }
tonyp@2472 273 }
tonyp@2472 274 }
brutisso@6386 275
brutisso@6386 276 void FreeRegionList::verify_list() {
brutisso@6386 277 HeapRegion* curr = head();
brutisso@6386 278 HeapRegion* prev1 = NULL;
brutisso@6386 279 HeapRegion* prev0 = NULL;
brutisso@6386 280 uint count = 0;
brutisso@6386 281 size_t capacity = 0;
brutisso@6386 282 while (curr != NULL) {
brutisso@6386 283 verify_region(curr);
brutisso@6386 284
brutisso@6386 285 count++;
brutisso@6386 286 guarantee(count < _unrealistically_long_length,
brutisso@6386 287 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()));
brutisso@6386 288
brutisso@6386 289 capacity += curr->capacity();
brutisso@6386 290
brutisso@6386 291 prev1 = prev0;
brutisso@6386 292 prev0 = curr;
brutisso@6386 293 curr = curr->next();
brutisso@6386 294 }
brutisso@6386 295
brutisso@6386 296 guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index()));
brutisso@6386 297
brutisso@6386 298 guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count));
brutisso@6386 299 guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
brutisso@6386 300 name(), total_capacity_bytes(), capacity));
brutisso@6386 301 }
brutisso@6386 302
brutisso@6386 303 // Note on the check_mt_safety() methods below:
brutisso@6386 304 //
brutisso@6386 305 // Verification of the "master" heap region sets / lists that are
brutisso@6386 306 // maintained by G1CollectedHeap is always done during a STW pause and
brutisso@6386 307 // by the VM thread at the start / end of the pause. The standard
brutisso@6386 308 // verification methods all assert check_mt_safety(). This is
brutisso@6386 309 // important as it ensures that verification is done without
brutisso@6386 310 // concurrent updates taking place at the same time. It follows, that,
brutisso@6386 311 // for the "master" heap region sets / lists, the check_mt_safety()
brutisso@6386 312 // method should include the VM thread / STW case.
brutisso@6386 313
brutisso@6386 314 void MasterFreeRegionListMtSafeChecker::check() {
brutisso@6386 315 // Master Free List MT safety protocol:
brutisso@6386 316 // (a) If we're at a safepoint, operations on the master free list
brutisso@6386 317 // should be invoked by either the VM thread (which will serialize
brutisso@6386 318 // them) or by the GC workers while holding the
brutisso@6386 319 // FreeList_lock.
brutisso@6386 320 // (b) If we're not at a safepoint, operations on the master free
brutisso@6386 321 // list should be invoked while holding the Heap_lock.
brutisso@6386 322
brutisso@6386 323 if (SafepointSynchronize::is_at_safepoint()) {
brutisso@6386 324 guarantee(Thread::current()->is_VM_thread() ||
brutisso@6386 325 FreeList_lock->owned_by_self(), "master free list MT safety protocol at a safepoint");
brutisso@6386 326 } else {
brutisso@6386 327 guarantee(Heap_lock->owned_by_self(), "master free list MT safety protocol outside a safepoint");
brutisso@6386 328 }
brutisso@6386 329 }
brutisso@6386 330
brutisso@6386 331 void SecondaryFreeRegionListMtSafeChecker::check() {
brutisso@6386 332 // Secondary Free List MT safety protocol:
brutisso@6386 333 // Operations on the secondary free list should always be invoked
brutisso@6386 334 // while holding the SecondaryFreeList_lock.
brutisso@6386 335
brutisso@6386 336 guarantee(SecondaryFreeList_lock->owned_by_self(), "secondary free list MT safety protocol");
brutisso@6386 337 }
brutisso@6386 338
brutisso@6386 339 void OldRegionSetMtSafeChecker::check() {
brutisso@6386 340 // Master Old Set MT safety protocol:
brutisso@6386 341 // (a) If we're at a safepoint, operations on the master old set
brutisso@6386 342 // should be invoked:
brutisso@6386 343 // - by the VM thread (which will serialize them), or
brutisso@6386 344 // - by the GC workers while holding the FreeList_lock, if we're
brutisso@6386 345 // at a safepoint for an evacuation pause (this lock is taken
brutisso@6386 346 // anyway when an GC alloc region is retired so that a new one
brutisso@6386 347 // is allocated from the free list), or
brutisso@6386 348 // - by the GC workers while holding the OldSets_lock, if we're at a
brutisso@6386 349 // safepoint for a cleanup pause.
brutisso@6386 350 // (b) If we're not at a safepoint, operations on the master old set
brutisso@6386 351 // should be invoked while holding the Heap_lock.
brutisso@6386 352
brutisso@6386 353 if (SafepointSynchronize::is_at_safepoint()) {
brutisso@6386 354 guarantee(Thread::current()->is_VM_thread()
brutisso@6386 355 || FreeList_lock->owned_by_self() || OldSets_lock->owned_by_self(),
brutisso@6386 356 "master old set MT safety protocol at a safepoint");
brutisso@6386 357 } else {
brutisso@6386 358 guarantee(Heap_lock->owned_by_self(), "master old set MT safety protocol outside a safepoint");
brutisso@6386 359 }
brutisso@6386 360 }
brutisso@6386 361
brutisso@6386 362 void HumongousRegionSetMtSafeChecker::check() {
brutisso@6386 363 // Humongous Set MT safety protocol:
brutisso@6386 364 // (a) If we're at a safepoint, operations on the master humongous
brutisso@6386 365 // set should be invoked by either the VM thread (which will
brutisso@6386 366 // serialize them) or by the GC workers while holding the
brutisso@6386 367 // OldSets_lock.
brutisso@6386 368 // (b) If we're not at a safepoint, operations on the master
brutisso@6386 369 // humongous set should be invoked while holding the Heap_lock.
brutisso@6386 370
brutisso@6386 371 if (SafepointSynchronize::is_at_safepoint()) {
brutisso@6386 372 guarantee(Thread::current()->is_VM_thread() ||
brutisso@6386 373 OldSets_lock->owned_by_self(),
brutisso@6386 374 "master humongous set MT safety protocol at a safepoint");
brutisso@6386 375 } else {
brutisso@6386 376 guarantee(Heap_lock->owned_by_self(),
brutisso@6386 377 "master humongous set MT safety protocol outside a safepoint");
brutisso@6386 378 }
brutisso@6386 379 }

mercurial