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

Wed, 19 Jan 2011 19:30:42 -0500

author
tonyp
date
Wed, 19 Jan 2011 19:30:42 -0500
changeset 2472
0fa27f37d4d4
child 2643
1216415d8e35
permissions
-rw-r--r--

6977804: G1: remove the zero-filling thread
Summary: This changeset removes the zero-filling thread from G1 and collapses the two free region lists we had before (the "free" and "unclean" lists) into one. The new free list uses the new heap region sets / lists abstractions that we'll ultimately use it to keep track of all regions in the heap. A heap region set was also introduced for the humongous regions. Finally, this change increases the concurrency between the thread that completes freeing regions (after a cleanup pause) and the rest of the system (before we'd have to wait for said thread to complete before allocating a new region). The changest also includes a lot of refactoring and code simplification.
Reviewed-by: jcoomes, johnc

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

mercurial