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

Mon, 12 Mar 2012 14:59:00 -0700

author
johnc
date
Mon, 12 Mar 2012 14:59:00 -0700
changeset 3666
64bf7c8270cb
parent 3268
8aae2050e83e
child 3713
720b6a76dd9d
permissions
-rw-r--r--

7147724: G1: hang in SurrogateLockerThread::manipulatePLL
Summary: Attempting to initiate a marking cycle when allocating a humongous object can, if a marking cycle is successfully initiated by another thread, result in the allocating thread spinning until the marking cycle is complete. Eliminate a deadlock between the main ConcurrentMarkThread, the SurrogateLocker thread, the VM thread, and a mutator thread waiting on the SecondaryFreeList_lock (while free regions are going to become available) by not manipulating the pending list lock during the prologue and epilogue of the cleanup pause.
Reviewed-by: brutisso, jcoomes, tonyp

tonyp@2472 1 /*
tonyp@2472 2 * Copyright (c) 2011, 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"
tonyp@2472 26 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
tonyp@2472 27
tonyp@2472 28 size_t HeapRegionSetBase::_unrealistically_long_length = 0;
tonyp@3268 29 HRSPhase HeapRegionSetBase::_phase = HRSPhaseNone;
tonyp@2472 30
tonyp@2472 31 //////////////////// HeapRegionSetBase ////////////////////
tonyp@2472 32
tonyp@2472 33 void HeapRegionSetBase::set_unrealistically_long_length(size_t len) {
tonyp@2472 34 guarantee(_unrealistically_long_length == 0, "should only be set once");
tonyp@2472 35 _unrealistically_long_length = len;
tonyp@2472 36 }
tonyp@2472 37
tonyp@2472 38 size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
tonyp@2472 39 assert(hr->startsHumongous(), "pre-condition");
tonyp@2472 40 assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant");
tonyp@2472 41 size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes;
tonyp@2472 42 assert(region_num > 0, "sanity");
tonyp@2472 43 return region_num;
tonyp@2472 44 }
tonyp@2472 45
tonyp@2643 46 void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
tonyp@2472 47 msg->append("[%s] %s "
tonyp@2472 48 "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" "
tonyp@2472 49 "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
tonyp@2472 50 name(), message, length(), region_num(),
tonyp@2472 51 total_capacity_bytes(), total_used_bytes());
tonyp@2472 52 fill_in_ext_msg_extra(msg);
tonyp@2472 53 }
tonyp@2472 54
tonyp@2472 55 bool HeapRegionSetBase::verify_region(HeapRegion* hr,
tonyp@2472 56 HeapRegionSetBase* expected_containing_set) {
tonyp@2472 57 const char* error_message = NULL;
tonyp@2472 58
tonyp@2472 59 if (!regions_humongous()) {
tonyp@2472 60 if (hr->isHumongous()) {
tonyp@2472 61 error_message = "the region should not be humongous";
tonyp@2472 62 }
tonyp@2472 63 } else {
tonyp@2472 64 if (!hr->isHumongous() || !hr->startsHumongous()) {
tonyp@2472 65 error_message = "the region should be 'starts humongous'";
tonyp@2472 66 }
tonyp@2472 67 }
tonyp@2472 68
tonyp@2472 69 if (!regions_empty()) {
tonyp@2472 70 if (hr->is_empty()) {
tonyp@2472 71 error_message = "the region should not be empty";
tonyp@2472 72 }
tonyp@2472 73 } else {
tonyp@2472 74 if (!hr->is_empty()) {
tonyp@2472 75 error_message = "the region should be empty";
tonyp@2472 76 }
tonyp@2472 77 }
tonyp@2472 78
tonyp@2472 79 #ifdef ASSERT
tonyp@2472 80 // The _containing_set field is only available when ASSERT is defined.
tonyp@2472 81 if (hr->containing_set() != expected_containing_set) {
tonyp@2472 82 error_message = "inconsistent containing set found";
tonyp@2472 83 }
tonyp@2472 84 #endif // ASSERT
tonyp@2472 85
tonyp@2472 86 const char* extra_error_message = verify_region_extra(hr);
tonyp@2472 87 if (extra_error_message != NULL) {
tonyp@2472 88 error_message = extra_error_message;
tonyp@2472 89 }
tonyp@2472 90
tonyp@2472 91 if (error_message != NULL) {
tonyp@2472 92 outputStream* out = tty;
tonyp@2472 93 out->cr();
tonyp@2472 94 out->print_cr("## [%s] %s", name(), error_message);
tonyp@2472 95 out->print_cr("## Offending Region: "PTR_FORMAT, hr);
tonyp@2472 96 out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr));
tonyp@2472 97 #ifdef ASSERT
tonyp@2472 98 out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set());
tonyp@2472 99 #endif // ASSERT
tonyp@2472 100 out->print_cr("## Offending Region Set: "PTR_FORMAT, this);
tonyp@2472 101 print_on(out);
tonyp@2472 102 return false;
tonyp@2472 103 } else {
tonyp@2472 104 return true;
tonyp@2472 105 }
tonyp@2472 106 }
tonyp@2472 107
tonyp@2472 108 void HeapRegionSetBase::verify() {
tonyp@2472 109 // It's important that we also observe the MT safety protocol even
tonyp@2472 110 // for the verification calls. If we do verification without the
tonyp@2472 111 // appropriate locks and the set changes underneath our feet
tonyp@2472 112 // verification might fail and send us on a wild goose chase.
tonyp@2643 113 hrs_assert_mt_safety_ok(this);
tonyp@2472 114
tonyp@2472 115 guarantee(( is_empty() && length() == 0 && region_num() == 0 &&
tonyp@2472 116 total_used_bytes() == 0 && total_capacity_bytes() == 0) ||
tonyp@2472 117 (!is_empty() && length() >= 0 && region_num() >= 0 &&
tonyp@2472 118 total_used_bytes() >= 0 && total_capacity_bytes() >= 0),
tonyp@2643 119 hrs_ext_msg(this, "invariant"));
tonyp@2472 120
tonyp@2472 121 guarantee((!regions_humongous() && region_num() == length()) ||
tonyp@2472 122 ( regions_humongous() && region_num() >= length()),
tonyp@2643 123 hrs_ext_msg(this, "invariant"));
tonyp@2472 124
tonyp@2472 125 guarantee(!regions_empty() || total_used_bytes() == 0,
tonyp@2643 126 hrs_ext_msg(this, "invariant"));
tonyp@2472 127
tonyp@2472 128 guarantee(total_used_bytes() <= total_capacity_bytes(),
tonyp@2643 129 hrs_ext_msg(this, "invariant"));
tonyp@2472 130 }
tonyp@2472 131
tonyp@2472 132 void HeapRegionSetBase::verify_start() {
tonyp@2472 133 // See comment in verify() about MT safety and verification.
tonyp@2643 134 hrs_assert_mt_safety_ok(this);
tonyp@2472 135 assert(!_verify_in_progress,
tonyp@2643 136 hrs_ext_msg(this, "verification should not be in progress"));
tonyp@2472 137
tonyp@2472 138 // Do the basic verification first before we do the checks over the regions.
tonyp@2472 139 HeapRegionSetBase::verify();
tonyp@2472 140
tonyp@2472 141 _calc_length = 0;
tonyp@2472 142 _calc_region_num = 0;
tonyp@2472 143 _calc_total_capacity_bytes = 0;
tonyp@2472 144 _calc_total_used_bytes = 0;
tonyp@2472 145 _verify_in_progress = true;
tonyp@2472 146 }
tonyp@2472 147
tonyp@2472 148 void HeapRegionSetBase::verify_next_region(HeapRegion* hr) {
tonyp@2472 149 // See comment in verify() about MT safety and verification.
tonyp@2643 150 hrs_assert_mt_safety_ok(this);
tonyp@2472 151 assert(_verify_in_progress,
tonyp@2643 152 hrs_ext_msg(this, "verification should be in progress"));
tonyp@2472 153
tonyp@2643 154 guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification"));
tonyp@2472 155
tonyp@2472 156 _calc_length += 1;
tonyp@2472 157 if (!hr->isHumongous()) {
tonyp@2472 158 _calc_region_num += 1;
tonyp@2472 159 } else {
tonyp@2472 160 _calc_region_num += calculate_region_num(hr);
tonyp@2472 161 }
tonyp@2472 162 _calc_total_capacity_bytes += hr->capacity();
tonyp@2472 163 _calc_total_used_bytes += hr->used();
tonyp@2472 164 }
tonyp@2472 165
tonyp@2472 166 void HeapRegionSetBase::verify_end() {
tonyp@2472 167 // See comment in verify() about MT safety and verification.
tonyp@2643 168 hrs_assert_mt_safety_ok(this);
tonyp@2472 169 assert(_verify_in_progress,
tonyp@2643 170 hrs_ext_msg(this, "verification should be in progress"));
tonyp@2472 171
tonyp@2472 172 guarantee(length() == _calc_length,
tonyp@2643 173 hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == "
tonyp@2472 174 "calc length: "SIZE_FORMAT,
tonyp@2472 175 name(), length(), _calc_length));
tonyp@2472 176
tonyp@2472 177 guarantee(region_num() == _calc_region_num,
tonyp@2643 178 hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == "
tonyp@2472 179 "calc region num: "SIZE_FORMAT,
tonyp@2472 180 name(), region_num(), _calc_region_num));
tonyp@2472 181
tonyp@2472 182 guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
tonyp@2643 183 hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == "
tonyp@2472 184 "calc capacity bytes: "SIZE_FORMAT,
tonyp@2472 185 name(),
tonyp@2472 186 total_capacity_bytes(), _calc_total_capacity_bytes));
tonyp@2472 187
tonyp@2472 188 guarantee(total_used_bytes() == _calc_total_used_bytes,
tonyp@2643 189 hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == "
tonyp@2472 190 "calc used bytes: "SIZE_FORMAT,
tonyp@2472 191 name(), total_used_bytes(), _calc_total_used_bytes));
tonyp@2472 192
tonyp@2472 193 _verify_in_progress = false;
tonyp@2472 194 }
tonyp@2472 195
tonyp@3268 196 void HeapRegionSetBase::clear_phase() {
tonyp@3268 197 assert(_phase != HRSPhaseNone, "pre-condition");
tonyp@3268 198 _phase = HRSPhaseNone;
tonyp@3268 199 }
tonyp@3268 200
tonyp@3268 201 void HeapRegionSetBase::set_phase(HRSPhase phase) {
tonyp@3268 202 assert(_phase == HRSPhaseNone, "pre-condition");
tonyp@3268 203 assert(phase != HRSPhaseNone, "pre-condition");
tonyp@3268 204 _phase = phase;
tonyp@3268 205 }
tonyp@3268 206
tonyp@2472 207 void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
tonyp@2472 208 out->cr();
tonyp@2472 209 out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
tonyp@2472 210 out->print_cr(" Region Assumptions");
tonyp@2472 211 out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
tonyp@2472 212 out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty()));
tonyp@2472 213 out->print_cr(" Attributes");
tonyp@2472 214 out->print_cr(" length : "SIZE_FORMAT_W(14), length());
tonyp@2472 215 out->print_cr(" region num : "SIZE_FORMAT_W(14), region_num());
tonyp@2472 216 out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
tonyp@2472 217 total_capacity_bytes());
tonyp@2472 218 out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes",
tonyp@2472 219 total_used_bytes());
tonyp@2472 220 }
tonyp@2472 221
tonyp@2472 222 void HeapRegionSetBase::clear() {
tonyp@2472 223 _length = 0;
tonyp@2472 224 _region_num = 0;
tonyp@2472 225 _total_used_bytes = 0;
tonyp@2472 226 }
tonyp@2472 227
tonyp@2472 228 HeapRegionSetBase::HeapRegionSetBase(const char* name)
tonyp@2472 229 : _name(name), _verify_in_progress(false),
tonyp@2472 230 _calc_length(0), _calc_region_num(0),
tonyp@2472 231 _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { }
tonyp@2472 232
tonyp@2472 233 //////////////////// HeapRegionSet ////////////////////
tonyp@2472 234
tonyp@2472 235 void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
tonyp@2643 236 hrs_assert_mt_safety_ok(this);
tonyp@2643 237 hrs_assert_mt_safety_ok(proxy_set);
tonyp@2643 238 hrs_assert_sets_match(this, proxy_set);
tonyp@2472 239
tonyp@2472 240 verify_optional();
tonyp@2472 241 proxy_set->verify_optional();
tonyp@2472 242
tonyp@2472 243 if (proxy_set->is_empty()) return;
tonyp@2472 244
tonyp@2472 245 assert(proxy_set->length() <= _length,
tonyp@2643 246 hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" "
tonyp@2472 247 "should be <= length: "SIZE_FORMAT,
tonyp@2472 248 name(), proxy_set->length(), _length));
tonyp@2472 249 _length -= proxy_set->length();
tonyp@2472 250
tonyp@2472 251 assert(proxy_set->region_num() <= _region_num,
tonyp@2643 252 hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" "
tonyp@2472 253 "should be <= region num: "SIZE_FORMAT,
tonyp@2472 254 name(), proxy_set->region_num(), _region_num));
tonyp@2472 255 _region_num -= proxy_set->region_num();
tonyp@2472 256
tonyp@2472 257 assert(proxy_set->total_used_bytes() <= _total_used_bytes,
tonyp@2643 258 hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" "
tonyp@2472 259 "should be <= used bytes: "SIZE_FORMAT,
tonyp@2472 260 name(), proxy_set->total_used_bytes(),
tonyp@2472 261 _total_used_bytes));
tonyp@2472 262 _total_used_bytes -= proxy_set->total_used_bytes();
tonyp@2472 263
tonyp@2472 264 proxy_set->clear();
tonyp@2472 265
tonyp@2472 266 verify_optional();
tonyp@2472 267 proxy_set->verify_optional();
tonyp@2472 268 }
tonyp@2472 269
tonyp@2472 270 //////////////////// HeapRegionLinkedList ////////////////////
tonyp@2472 271
tonyp@2643 272 void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
tonyp@2472 273 msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
tonyp@2472 274 }
tonyp@2472 275
tonyp@2714 276 void HeapRegionLinkedList::add_as_head(HeapRegionLinkedList* from_list) {
tonyp@2714 277 hrs_assert_mt_safety_ok(this);
tonyp@2714 278 hrs_assert_mt_safety_ok(from_list);
tonyp@2714 279
tonyp@2714 280 verify_optional();
tonyp@2714 281 from_list->verify_optional();
tonyp@2714 282
tonyp@2714 283 if (from_list->is_empty()) return;
tonyp@2714 284
tonyp@2714 285 #ifdef ASSERT
tonyp@2714 286 HeapRegionLinkedListIterator iter(from_list);
tonyp@2714 287 while (iter.more_available()) {
tonyp@2714 288 HeapRegion* hr = iter.get_next();
tonyp@2714 289 // In set_containing_set() we check that we either set the value
tonyp@2714 290 // from NULL to non-NULL or vice versa to catch bugs. So, we have
tonyp@2714 291 // to NULL it first before setting it to the value.
tonyp@2714 292 hr->set_containing_set(NULL);
tonyp@2714 293 hr->set_containing_set(this);
tonyp@2714 294 }
tonyp@2714 295 #endif // ASSERT
tonyp@2714 296
tonyp@2714 297 if (_head != NULL) {
tonyp@2714 298 assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
tonyp@2714 299 from_list->_tail->set_next(_head);
tonyp@2714 300 } else {
tonyp@2714 301 assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant"));
tonyp@2714 302 _tail = from_list->_tail;
tonyp@2714 303 }
tonyp@2714 304 _head = from_list->_head;
tonyp@2714 305
tonyp@2714 306 _length += from_list->length();
tonyp@2714 307 _region_num += from_list->region_num();
tonyp@2714 308 _total_used_bytes += from_list->total_used_bytes();
tonyp@2714 309 from_list->clear();
tonyp@2714 310
tonyp@2714 311 verify_optional();
tonyp@2714 312 from_list->verify_optional();
tonyp@2714 313 }
tonyp@2714 314
tonyp@2472 315 void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
tonyp@2643 316 hrs_assert_mt_safety_ok(this);
tonyp@2643 317 hrs_assert_mt_safety_ok(from_list);
tonyp@2472 318
tonyp@2472 319 verify_optional();
tonyp@2472 320 from_list->verify_optional();
tonyp@2472 321
tonyp@2472 322 if (from_list->is_empty()) return;
tonyp@2472 323
tonyp@2472 324 #ifdef ASSERT
tonyp@2472 325 HeapRegionLinkedListIterator iter(from_list);
tonyp@2472 326 while (iter.more_available()) {
tonyp@2472 327 HeapRegion* hr = iter.get_next();
tonyp@2472 328 // In set_containing_set() we check that we either set the value
tonyp@2472 329 // from NULL to non-NULL or vice versa to catch bugs. So, we have
tonyp@2472 330 // to NULL it first before setting it to the value.
tonyp@2472 331 hr->set_containing_set(NULL);
tonyp@2472 332 hr->set_containing_set(this);
tonyp@2472 333 }
tonyp@2472 334 #endif // ASSERT
tonyp@2472 335
tonyp@2472 336 if (_tail != NULL) {
tonyp@2643 337 assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant"));
tonyp@2472 338 _tail->set_next(from_list->_head);
tonyp@2472 339 } else {
tonyp@2643 340 assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant"));
tonyp@2472 341 _head = from_list->_head;
tonyp@2472 342 }
tonyp@2472 343 _tail = from_list->_tail;
tonyp@2472 344
tonyp@2472 345 _length += from_list->length();
tonyp@2472 346 _region_num += from_list->region_num();
tonyp@2472 347 _total_used_bytes += from_list->total_used_bytes();
tonyp@2472 348 from_list->clear();
tonyp@2472 349
tonyp@2472 350 verify_optional();
tonyp@2472 351 from_list->verify_optional();
tonyp@2472 352 }
tonyp@2472 353
tonyp@2472 354 void HeapRegionLinkedList::remove_all() {
tonyp@2643 355 hrs_assert_mt_safety_ok(this);
tonyp@2472 356 verify_optional();
tonyp@2472 357
tonyp@2472 358 HeapRegion* curr = _head;
tonyp@2472 359 while (curr != NULL) {
tonyp@2643 360 hrs_assert_region_ok(this, curr, this);
tonyp@2472 361
tonyp@2472 362 HeapRegion* next = curr->next();
tonyp@2472 363 curr->set_next(NULL);
tonyp@2472 364 curr->set_containing_set(NULL);
tonyp@2472 365 curr = next;
tonyp@2472 366 }
tonyp@2472 367 clear();
tonyp@2472 368
tonyp@2472 369 verify_optional();
tonyp@2472 370 }
tonyp@2472 371
tonyp@2472 372 void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
tonyp@2643 373 hrs_assert_mt_safety_ok(this);
tonyp@2643 374 assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
tonyp@2643 375 assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
tonyp@2472 376
tonyp@2472 377 verify_optional();
tonyp@2472 378 DEBUG_ONLY(size_t old_length = length();)
tonyp@2472 379
tonyp@2472 380 HeapRegion* curr = _head;
tonyp@2472 381 HeapRegion* prev = NULL;
tonyp@2472 382 size_t count = 0;
tonyp@2472 383 while (curr != NULL) {
tonyp@2643 384 hrs_assert_region_ok(this, curr, this);
tonyp@2472 385 HeapRegion* next = curr->next();
tonyp@2472 386
tonyp@2472 387 if (curr->pending_removal()) {
tonyp@2472 388 assert(count < target_count,
tonyp@2643 389 hrs_err_msg("[%s] should not come across more regions "
tonyp@2472 390 "pending for removal than target_count: "SIZE_FORMAT,
tonyp@2472 391 name(), target_count));
tonyp@2472 392
tonyp@2472 393 if (prev == NULL) {
tonyp@2643 394 assert(_head == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 395 _head = next;
tonyp@2472 396 } else {
tonyp@2643 397 assert(_head != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 398 prev->set_next(next);
tonyp@2472 399 }
tonyp@2472 400 if (next == NULL) {
tonyp@2643 401 assert(_tail == curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 402 _tail = prev;
tonyp@2472 403 } else {
tonyp@2643 404 assert(_tail != curr, hrs_ext_msg(this, "invariant"));
tonyp@2472 405 }
tonyp@2472 406
tonyp@2472 407 curr->set_next(NULL);
tonyp@2472 408 remove_internal(curr);
tonyp@2472 409 curr->set_pending_removal(false);
tonyp@2472 410
tonyp@2472 411 count += 1;
tonyp@2472 412
tonyp@2472 413 // If we have come across the target number of regions we can
tonyp@2472 414 // just bail out. However, for debugging purposes, we can just
tonyp@2472 415 // carry on iterating to make sure there are not more regions
tonyp@2472 416 // tagged with pending removal.
tonyp@2472 417 DEBUG_ONLY(if (count == target_count) break;)
tonyp@2472 418 } else {
tonyp@2472 419 prev = curr;
tonyp@2472 420 }
tonyp@2472 421 curr = next;
tonyp@2472 422 }
tonyp@2472 423
tonyp@2472 424 assert(count == target_count,
tonyp@2643 425 hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == "
tonyp@2472 426 "target_count: "SIZE_FORMAT, name(), count, target_count));
tonyp@2472 427 assert(length() + target_count == old_length,
tonyp@2643 428 hrs_err_msg("[%s] new length should be consistent "
tonyp@2472 429 "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" "
tonyp@2472 430 "target_count: "SIZE_FORMAT,
tonyp@2472 431 name(), length(), old_length, target_count));
tonyp@2472 432
tonyp@2472 433 verify_optional();
tonyp@2472 434 }
tonyp@2472 435
tonyp@2472 436 void HeapRegionLinkedList::verify() {
tonyp@2472 437 // See comment in HeapRegionSetBase::verify() about MT safety and
tonyp@2472 438 // verification.
tonyp@2643 439 hrs_assert_mt_safety_ok(this);
tonyp@2472 440
tonyp@2472 441 // This will also do the basic verification too.
tonyp@2472 442 verify_start();
tonyp@2472 443
tonyp@2472 444 HeapRegion* curr = _head;
tonyp@2472 445 HeapRegion* prev1 = NULL;
tonyp@2472 446 HeapRegion* prev0 = NULL;
tonyp@2472 447 size_t count = 0;
tonyp@2472 448 while (curr != NULL) {
tonyp@2472 449 verify_next_region(curr);
tonyp@2472 450
tonyp@2472 451 count += 1;
tonyp@2472 452 guarantee(count < _unrealistically_long_length,
tonyp@2643 453 hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" "
tonyp@2472 454 "seems very long, is there maybe a cycle? "
tonyp@2472 455 "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
tonyp@2472 456 "prev1: "PTR_FORMAT" length: "SIZE_FORMAT,
tonyp@2472 457 name(), count, curr, prev0, prev1, length()));
tonyp@2472 458
tonyp@2472 459 prev1 = prev0;
tonyp@2472 460 prev0 = curr;
tonyp@2472 461 curr = curr->next();
tonyp@2472 462 }
tonyp@2472 463
tonyp@2643 464 guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition"));
tonyp@2472 465
tonyp@2472 466 verify_end();
tonyp@2472 467 }
tonyp@2472 468
tonyp@2472 469 void HeapRegionLinkedList::clear() {
tonyp@2472 470 HeapRegionSetBase::clear();
tonyp@2472 471 _head = NULL;
tonyp@2472 472 _tail = NULL;
tonyp@2472 473 }
tonyp@2472 474
tonyp@2472 475 void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) {
tonyp@2472 476 HeapRegionSetBase::print_on(out, print_contents);
tonyp@2472 477 out->print_cr(" Linking");
tonyp@2472 478 out->print_cr(" head : "PTR_FORMAT, _head);
tonyp@2472 479 out->print_cr(" tail : "PTR_FORMAT, _tail);
tonyp@2472 480
tonyp@2472 481 if (print_contents) {
tonyp@2472 482 out->print_cr(" Contents");
tonyp@2472 483 HeapRegionLinkedListIterator iter(this);
tonyp@2472 484 while (iter.more_available()) {
tonyp@2472 485 HeapRegion* hr = iter.get_next();
tonyp@2472 486 hr->print_on(out);
tonyp@2472 487 }
tonyp@2472 488 }
tonyp@2472 489 }

mercurial