1 /* 2 * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "precompiled.hpp" 25 26 #include "memory/allocation.hpp" 27 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp" 28 #include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp" 29 #include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp" 30 #include "memory/space.inline.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "memory/universe.hpp" 33 #include "oops/oop.inline.hpp" 34 #include "runtime/java.hpp" 35 #include "runtime/mutexLocker.hpp" 36 #include "runtime/os.hpp" 37 #include "runtime/safepoint.hpp" 38 39 size_t ShenandoahHeapRegion::RegionCount = 0; 40 size_t ShenandoahHeapRegion::RegionSizeBytes = 0; 41 size_t ShenandoahHeapRegion::RegionSizeWords = 0; 42 size_t ShenandoahHeapRegion::RegionSizeBytesShift = 0; 43 size_t ShenandoahHeapRegion::RegionSizeWordsShift = 0; 44 size_t ShenandoahHeapRegion::RegionSizeBytesMask = 0; 45 size_t ShenandoahHeapRegion::RegionSizeWordsMask = 0; 46 size_t ShenandoahHeapRegion::HumongousThresholdBytes = 0; 47 size_t ShenandoahHeapRegion::HumongousThresholdWords = 0; 48 size_t ShenandoahHeapRegion::MaxTLABSizeBytes = 0; 49 size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0; 50 51 ShenandoahHeapRegion::PaddedAllocSeqNum ShenandoahHeapRegion::_alloc_seq_num; 52 53 ShenandoahHeapRegion::ShenandoahHeapRegion(ShenandoahHeap* heap, HeapWord* start, 54 size_t size_words, size_t index, bool committed) : 55 _heap(heap), 56 _reserved(MemRegion(start, size_words)), 57 _region_number(index), 58 _new_top(NULL), 59 _empty_time(os::elapsedTime()), 60 _state(committed ? _empty_committed : _empty_uncommitted), 61 _tlab_allocs(0), 62 _gclab_allocs(0), 63 _shared_allocs(0), 64 _seqnum_first_alloc_mutator(0), 65 _seqnum_first_alloc_gc(0), 66 _seqnum_last_alloc_mutator(0), 67 _seqnum_last_alloc_gc(0), 68 _live_data(0), 69 _critical_pins(0) { 70 71 ContiguousSpace::initialize(_reserved, true, committed); 72 } 73 74 size_t ShenandoahHeapRegion::region_number() const { 75 return _region_number; 76 } 77 78 void ShenandoahHeapRegion::report_illegal_transition(const char *method) { 79 ResourceMark rm; 80 stringStream ss; 81 ss.print("Illegal region state transition from \"%s\", at %s\n ", region_state_to_string(_state), method); 82 print_on(&ss); 83 fatal(ss.as_string()); 84 } 85 86 void ShenandoahHeapRegion::make_regular_allocation() { 87 _heap->assert_heaplock_owned_by_current_thread(); 88 switch (_state) { 89 case _empty_uncommitted: 90 do_commit(); 91 case _empty_committed: 92 _state = _regular; 93 case _regular: 94 case _pinned: 95 return; 96 default: 97 report_illegal_transition("regular allocation"); 98 } 99 } 100 101 void ShenandoahHeapRegion::make_regular_bypass() { 102 _heap->assert_heaplock_owned_by_current_thread(); 103 assert (_heap->is_full_gc_in_progress() || _heap->is_degenerated_gc_in_progress(), 104 "only for full or degen GC"); 105 106 switch (_state) { 107 case _empty_uncommitted: 108 do_commit(); 109 case _empty_committed: 110 case _cset: 111 case _humongous_start: 112 case _humongous_cont: 113 _state = _regular; 114 return; 115 case _pinned_cset: 116 _state = _pinned; 117 return; 118 case _regular: 119 case _pinned: 120 return; 121 default: 122 report_illegal_transition("regular bypass"); 123 } 124 } 125 126 void ShenandoahHeapRegion::make_humongous_start() { 127 _heap->assert_heaplock_owned_by_current_thread(); 128 switch (_state) { 129 case _empty_uncommitted: 130 do_commit(); 131 case _empty_committed: 132 _state = _humongous_start; 133 return; 134 default: 135 report_illegal_transition("humongous start allocation"); 136 } 137 } 138 139 void ShenandoahHeapRegion::make_humongous_start_bypass() { 140 _heap->assert_heaplock_owned_by_current_thread(); 141 assert (_heap->is_full_gc_in_progress(), "only for full GC"); 142 143 switch (_state) { 144 case _empty_committed: 145 case _regular: 146 case _humongous_start: 147 case _humongous_cont: 148 _state = _humongous_start; 149 return; 150 default: 151 report_illegal_transition("humongous start bypass"); 152 } 153 } 154 155 void ShenandoahHeapRegion::make_humongous_cont() { 156 _heap->assert_heaplock_owned_by_current_thread(); 157 switch (_state) { 158 case _empty_uncommitted: 159 do_commit(); 160 case _empty_committed: 161 _state = _humongous_cont; 162 return; 163 default: 164 report_illegal_transition("humongous continuation allocation"); 165 } 166 } 167 168 void ShenandoahHeapRegion::make_humongous_cont_bypass() { 169 _heap->assert_heaplock_owned_by_current_thread(); 170 assert (_heap->is_full_gc_in_progress(), "only for full GC"); 171 172 switch (_state) { 173 case _empty_committed: 174 case _regular: 175 case _humongous_start: 176 case _humongous_cont: 177 _state = _humongous_cont; 178 return; 179 default: 180 report_illegal_transition("humongous continuation bypass"); 181 } 182 } 183 184 void ShenandoahHeapRegion::make_pinned() { 185 _heap->assert_heaplock_owned_by_current_thread(); 186 assert(pin_count() > 0, err_msg("Should have pins: " SIZE_FORMAT, pin_count())); 187 188 switch (_state) { 189 case _regular: 190 _state = _pinned; 191 case _pinned_cset: 192 case _pinned: 193 return; 194 case _humongous_start: 195 _state = _pinned_humongous_start; 196 case _pinned_humongous_start: 197 return; 198 case _cset: 199 _state = _pinned_cset; 200 return; 201 default: 202 report_illegal_transition("pinning"); 203 } 204 } 205 206 void ShenandoahHeapRegion::make_unpinned() { 207 _heap->assert_heaplock_owned_by_current_thread(); 208 assert(pin_count() == 0, err_msg("Should not have pins: " SIZE_FORMAT, pin_count())); 209 210 switch (_state) { 211 case _pinned: 212 _state = _regular; 213 return; 214 case _regular: 215 case _humongous_start: 216 return; 217 case _pinned_cset: 218 _state = _cset; 219 return; 220 case _pinned_humongous_start: 221 _state = _humongous_start; 222 return; 223 default: 224 report_illegal_transition("unpinning"); 225 } 226 } 227 228 void ShenandoahHeapRegion::make_cset() { 229 _heap->assert_heaplock_owned_by_current_thread(); 230 switch (_state) { 231 case _regular: 232 _state = _cset; 233 case _cset: 234 return; 235 default: 236 report_illegal_transition("cset"); 237 } 238 } 239 240 void ShenandoahHeapRegion::make_trash() { 241 _heap->assert_heaplock_owned_by_current_thread(); 242 switch (_state) { 243 case _cset: 244 // Reclaiming cset regions 245 case _humongous_start: 246 case _humongous_cont: 247 // Reclaiming humongous regions 248 case _regular: 249 // Immediate region reclaim 250 _state = _trash; 251 return; 252 default: 253 report_illegal_transition("trashing"); 254 } 255 } 256 257 void ShenandoahHeapRegion::make_trash_immediate() { 258 make_trash(); 259 260 // On this path, we know there are no marked objects in the region, 261 // tell marking context about it to bypass bitmap resets. 262 _heap->complete_marking_context()->reset_top_bitmap(this); 263 } 264 265 void ShenandoahHeapRegion::make_empty() { 266 _heap->assert_heaplock_owned_by_current_thread(); 267 switch (_state) { 268 case _trash: 269 _state = _empty_committed; 270 _empty_time = os::elapsedTime(); 271 return; 272 default: 273 report_illegal_transition("emptying"); 274 } 275 } 276 277 void ShenandoahHeapRegion::make_uncommitted() { 278 _heap->assert_heaplock_owned_by_current_thread(); 279 switch (_state) { 280 case _empty_committed: 281 do_uncommit(); 282 _state = _empty_uncommitted; 283 return; 284 default: 285 report_illegal_transition("uncommiting"); 286 } 287 } 288 289 void ShenandoahHeapRegion::make_committed_bypass() { 290 _heap->assert_heaplock_owned_by_current_thread(); 291 assert (_heap->is_full_gc_in_progress(), "only for full GC"); 292 293 switch (_state) { 294 case _empty_uncommitted: 295 do_commit(); 296 _state = _empty_committed; 297 return; 298 default: 299 report_illegal_transition("commit bypass"); 300 } 301 } 302 303 void ShenandoahHeapRegion::clear_live_data() { 304 OrderAccess::release_store_fence((volatile jint*)&_live_data, 0); 305 } 306 307 void ShenandoahHeapRegion::reset_alloc_metadata() { 308 _tlab_allocs = 0; 309 _gclab_allocs = 0; 310 _shared_allocs = 0; 311 _seqnum_first_alloc_mutator = 0; 312 _seqnum_last_alloc_mutator = 0; 313 _seqnum_first_alloc_gc = 0; 314 _seqnum_last_alloc_gc = 0; 315 } 316 317 void ShenandoahHeapRegion::reset_alloc_metadata_to_shared() { 318 if (used() > 0) { 319 _tlab_allocs = 0; 320 _gclab_allocs = 0; 321 _shared_allocs = used() >> LogHeapWordSize; 322 uint64_t next = _alloc_seq_num.value++; 323 _seqnum_first_alloc_mutator = next; 324 _seqnum_last_alloc_mutator = next; 325 _seqnum_first_alloc_gc = 0; 326 _seqnum_last_alloc_gc = 0; 327 } else { 328 reset_alloc_metadata(); 329 } 330 } 331 332 size_t ShenandoahHeapRegion::get_shared_allocs() const { 333 return _shared_allocs * HeapWordSize; 334 } 335 336 size_t ShenandoahHeapRegion::get_tlab_allocs() const { 337 return _tlab_allocs * HeapWordSize; 338 } 339 340 size_t ShenandoahHeapRegion::get_gclab_allocs() const { 341 return _gclab_allocs * HeapWordSize; 342 } 343 344 void ShenandoahHeapRegion::set_live_data(size_t s) { 345 assert(Thread::current()->is_VM_thread(), "by VM thread"); 346 size_t v = s >> LogHeapWordSize; 347 assert(v < (size_t)max_jint, "sanity"); 348 _live_data = (jint)v; 349 } 350 351 size_t ShenandoahHeapRegion::get_live_data_words() const { 352 jint v = OrderAccess::load_acquire((volatile jint*)&_live_data); 353 assert(v >= 0, "sanity"); 354 return (size_t)v; 355 } 356 357 size_t ShenandoahHeapRegion::get_live_data_bytes() const { 358 return get_live_data_words() * HeapWordSize; 359 } 360 361 bool ShenandoahHeapRegion::has_live() const { 362 return get_live_data_words() != 0; 363 } 364 365 size_t ShenandoahHeapRegion::garbage() const { 366 assert(used() >= get_live_data_bytes(), err_msg("Live Data must be a subset of used() live: " SIZE_FORMAT " used: " SIZE_FORMAT, 367 get_live_data_bytes(), used())); 368 size_t result = used() - get_live_data_bytes(); 369 return result; 370 } 371 372 void ShenandoahHeapRegion::print_on(outputStream* st) const { 373 st->print("|"); 374 st->print(SIZE_FORMAT_W(5), this->_region_number); 375 376 switch (_state) { 377 case _empty_uncommitted: 378 st->print("|EU "); 379 break; 380 case _empty_committed: 381 st->print("|EC "); 382 break; 383 case _regular: 384 st->print("|R "); 385 break; 386 case _humongous_start: 387 st->print("|H "); 388 break; 389 case _pinned_humongous_start: 390 st->print("|HP "); 391 break; 392 case _humongous_cont: 393 st->print("|HC "); 394 break; 395 case _cset: 396 st->print("|CS "); 397 break; 398 case _trash: 399 st->print("|T "); 400 break; 401 case _pinned: 402 st->print("|P "); 403 break; 404 case _pinned_cset: 405 st->print("|CSP"); 406 break; 407 default: 408 ShouldNotReachHere(); 409 } 410 st->print("|BTE " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12), 411 p2i(bottom()), p2i(top()), p2i(end())); 412 st->print("|TAMS " INTPTR_FORMAT_W(12), 413 p2i(_heap->marking_context()->top_at_mark_start(const_cast<ShenandoahHeapRegion*>(this)))); 414 st->print("|U " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used())); 415 st->print("|T " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_tlab_allocs()), proper_unit_for_byte_size(get_tlab_allocs())); 416 st->print("|G " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_gclab_allocs()), proper_unit_for_byte_size(get_gclab_allocs())); 417 st->print("|S " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_shared_allocs()), proper_unit_for_byte_size(get_shared_allocs())); 418 st->print("|L " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_live_data_bytes()), proper_unit_for_byte_size(get_live_data_bytes())); 419 st->print("|CP " SIZE_FORMAT_W(3), pin_count()); 420 st->print("|SN " UINT64_FORMAT_X_W(12) ", " UINT64_FORMAT_X_W(8) ", " UINT64_FORMAT_X_W(8) ", " UINT64_FORMAT_X_W(8), 421 seqnum_first_alloc_mutator(), seqnum_last_alloc_mutator(), 422 seqnum_first_alloc_gc(), seqnum_last_alloc_gc()); 423 st->cr(); 424 } 425 426 ShenandoahHeapRegion* ShenandoahHeapRegion::humongous_start_region() const { 427 assert(is_humongous(), "Must be a part of the humongous region"); 428 size_t reg_num = region_number(); 429 ShenandoahHeapRegion* r = const_cast<ShenandoahHeapRegion*>(this); 430 while (!r->is_humongous_start()) { 431 assert(reg_num > 0, "Sanity"); 432 reg_num --; 433 r = _heap->get_region(reg_num); 434 assert(r->is_humongous(), "Must be a part of the humongous region"); 435 } 436 assert(r->is_humongous_start(), "Must be"); 437 return r; 438 } 439 440 void ShenandoahHeapRegion::recycle() { 441 ContiguousSpace::clear(false); 442 if (ZapUnusedHeapArea) { 443 ContiguousSpace::mangle_unused_area_complete(); 444 } 445 clear_live_data(); 446 reset_alloc_metadata(); 447 448 _heap->marking_context()->reset_top_at_mark_start(this); 449 450 make_empty(); 451 } 452 453 HeapWord* ShenandoahHeapRegion::block_start_const(const void* p) const { 454 assert(MemRegion(bottom(), end()).contains(p), 455 err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")", 456 p2i(p), p2i(bottom()), p2i(end()))); 457 if (p >= top()) { 458 return top(); 459 } else { 460 HeapWord* last = bottom(); 461 HeapWord* cur = last; 462 while (cur <= p) { 463 last = cur; 464 cur += oop(cur)->size(); 465 } 466 shenandoah_assert_correct(NULL, oop(last)); 467 return last; 468 } 469 } 470 471 void ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) { 472 // Absolute minimums we should not ever break: 473 static const size_t MIN_REGION_SIZE = 256*K; 474 475 size_t region_size; 476 if (FLAG_IS_DEFAULT(ShenandoahHeapRegionSize)) { 477 if (ShenandoahMinRegionSize > max_heap_size / MIN_NUM_REGIONS) { 478 err_msg message("Max heap size (" SIZE_FORMAT "%s) is too low to afford the minimum number " 479 "of regions (" SIZE_FORMAT ") of minimum region size (" SIZE_FORMAT "%s).", 480 byte_size_in_proper_unit(max_heap_size), proper_unit_for_byte_size(max_heap_size), 481 MIN_NUM_REGIONS, 482 byte_size_in_proper_unit(ShenandoahMinRegionSize), proper_unit_for_byte_size(ShenandoahMinRegionSize)); 483 vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message); 484 } 485 if (ShenandoahMinRegionSize < MIN_REGION_SIZE) { 486 err_msg message("" SIZE_FORMAT "%s should not be lower than minimum region size (" SIZE_FORMAT "%s).", 487 byte_size_in_proper_unit(ShenandoahMinRegionSize), proper_unit_for_byte_size(ShenandoahMinRegionSize), 488 byte_size_in_proper_unit(MIN_REGION_SIZE), proper_unit_for_byte_size(MIN_REGION_SIZE)); 489 vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message); 490 } 491 if (ShenandoahMinRegionSize < MinTLABSize) { 492 err_msg message("" SIZE_FORMAT "%s should not be lower than TLAB size size (" SIZE_FORMAT "%s).", 493 byte_size_in_proper_unit(ShenandoahMinRegionSize), proper_unit_for_byte_size(ShenandoahMinRegionSize), 494 byte_size_in_proper_unit(MinTLABSize), proper_unit_for_byte_size(MinTLABSize)); 495 vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message); 496 } 497 if (ShenandoahMaxRegionSize < MIN_REGION_SIZE) { 498 err_msg message("" SIZE_FORMAT "%s should not be lower than min region size (" SIZE_FORMAT "%s).", 499 byte_size_in_proper_unit(ShenandoahMaxRegionSize), proper_unit_for_byte_size(ShenandoahMaxRegionSize), 500 byte_size_in_proper_unit(MIN_REGION_SIZE), proper_unit_for_byte_size(MIN_REGION_SIZE)); 501 vm_exit_during_initialization("Invalid -XX:ShenandoahMaxRegionSize option", message); 502 } 503 if (ShenandoahMinRegionSize > ShenandoahMaxRegionSize) { 504 err_msg message("Minimum (" SIZE_FORMAT "%s) should be larger than maximum (" SIZE_FORMAT "%s).", 505 byte_size_in_proper_unit(ShenandoahMinRegionSize), proper_unit_for_byte_size(ShenandoahMinRegionSize), 506 byte_size_in_proper_unit(ShenandoahMaxRegionSize), proper_unit_for_byte_size(ShenandoahMaxRegionSize)); 507 vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize or -XX:ShenandoahMaxRegionSize", message); 508 } 509 510 // We rapidly expand to max_heap_size in most scenarios, so that is the measure 511 // for usual heap sizes. Do not depend on initial_heap_size here. 512 region_size = max_heap_size / ShenandoahTargetNumRegions; 513 514 // Now make sure that we don't go over or under our limits. 515 region_size = MAX2<size_t>(ShenandoahMinRegionSize, region_size); 516 region_size = MIN2<size_t>(ShenandoahMaxRegionSize, region_size); 517 518 } else { 519 if (ShenandoahHeapRegionSize > max_heap_size / MIN_NUM_REGIONS) { 520 err_msg message("Max heap size (" SIZE_FORMAT "%s) is too low to afford the minimum number " 521 "of regions (" SIZE_FORMAT ") of requested size (" SIZE_FORMAT "%s).", 522 byte_size_in_proper_unit(max_heap_size), proper_unit_for_byte_size(max_heap_size), 523 MIN_NUM_REGIONS, 524 byte_size_in_proper_unit(ShenandoahHeapRegionSize), proper_unit_for_byte_size(ShenandoahHeapRegionSize)); 525 vm_exit_during_initialization("Invalid -XX:ShenandoahHeapRegionSize option", message); 526 } 527 if (ShenandoahHeapRegionSize < ShenandoahMinRegionSize) { 528 err_msg message("Heap region size (" SIZE_FORMAT "%s) should be larger than min region size (" SIZE_FORMAT "%s).", 529 byte_size_in_proper_unit(ShenandoahHeapRegionSize), proper_unit_for_byte_size(ShenandoahHeapRegionSize), 530 byte_size_in_proper_unit(ShenandoahMinRegionSize), proper_unit_for_byte_size(ShenandoahMinRegionSize)); 531 vm_exit_during_initialization("Invalid -XX:ShenandoahHeapRegionSize option", message); 532 } 533 if (ShenandoahHeapRegionSize > ShenandoahMaxRegionSize) { 534 err_msg message("Heap region size (" SIZE_FORMAT "%s) should be lower than max region size (" SIZE_FORMAT "%s).", 535 byte_size_in_proper_unit(ShenandoahHeapRegionSize), proper_unit_for_byte_size(ShenandoahHeapRegionSize), 536 byte_size_in_proper_unit(ShenandoahMaxRegionSize), proper_unit_for_byte_size(ShenandoahMaxRegionSize)); 537 vm_exit_during_initialization("Invalid -XX:ShenandoahHeapRegionSize option", message); 538 } 539 region_size = ShenandoahHeapRegionSize; 540 } 541 542 if (1 > ShenandoahHumongousThreshold || ShenandoahHumongousThreshold > 100) { 543 vm_exit_during_initialization("Invalid -XX:ShenandoahHumongousThreshold option, should be within [1..100]"); 544 } 545 546 // Make sure region size is at least one large page, if enabled. 547 // Otherwise, uncommitting one region may falsely uncommit the adjacent 548 // regions too. 549 // Also see shenandoahArguments.cpp, where it handles UseLargePages. 550 if (UseLargePages && ShenandoahUncommit) { 551 region_size = MAX2(region_size, os::large_page_size()); 552 } 553 554 int region_size_log = log2_long((jlong) region_size); 555 // Recalculate the region size to make sure it's a power of 556 // 2. This means that region_size is the largest power of 2 that's 557 // <= what we've calculated so far. 558 region_size = size_t(1) << region_size_log; 559 560 // Now, set up the globals. 561 guarantee(RegionSizeBytesShift == 0, "we should only set it once"); 562 RegionSizeBytesShift = (size_t)region_size_log; 563 564 guarantee(RegionSizeWordsShift == 0, "we should only set it once"); 565 RegionSizeWordsShift = RegionSizeBytesShift - LogHeapWordSize; 566 567 guarantee(RegionSizeBytes == 0, "we should only set it once"); 568 RegionSizeBytes = region_size; 569 RegionSizeWords = RegionSizeBytes >> LogHeapWordSize; 570 assert (RegionSizeWords*HeapWordSize == RegionSizeBytes, "sanity"); 571 572 guarantee(RegionSizeWordsMask == 0, "we should only set it once"); 573 RegionSizeWordsMask = RegionSizeWords - 1; 574 575 guarantee(RegionSizeBytesMask == 0, "we should only set it once"); 576 RegionSizeBytesMask = RegionSizeBytes - 1; 577 578 guarantee(RegionCount == 0, "we should only set it once"); 579 RegionCount = max_heap_size / RegionSizeBytes; 580 581 guarantee(HumongousThresholdWords == 0, "we should only set it once"); 582 HumongousThresholdWords = RegionSizeWords * ShenandoahHumongousThreshold / 100; 583 HumongousThresholdWords = (size_t)align_size_down(HumongousThresholdWords, MinObjAlignment); 584 assert (HumongousThresholdWords <= RegionSizeWords, "sanity"); 585 586 guarantee(HumongousThresholdBytes == 0, "we should only set it once"); 587 HumongousThresholdBytes = HumongousThresholdWords * HeapWordSize; 588 assert (HumongousThresholdBytes <= RegionSizeBytes, "sanity"); 589 590 // The rationale for trimming the TLAB sizes has to do with the raciness in 591 // TLAB allocation machinery. It may happen that TLAB sizing policy polls Shenandoah 592 // about next free size, gets the answer for region #N, goes away for a while, then 593 // tries to allocate in region #N, and fail because some other thread have claimed part 594 // of the region #N, and then the freeset allocation code has to retire the region #N, 595 // before moving the allocation to region #N+1. 596 // 597 // The worst case realizes when "answer" is "region size", which means it could 598 // prematurely retire an entire region. Having smaller TLABs does not fix that 599 // completely, but reduces the probability of too wasteful region retirement. 600 // With current divisor, we will waste no more than 1/8 of region size in the worst 601 // case. This also has a secondary effect on collection set selection: even under 602 // the race, the regions would be at least 7/8 used, which allows relying on 603 // "used" - "live" for cset selection. Otherwise, we can get the fragmented region 604 // below the garbage threshold that would never be considered for collection. 605 // 606 // The whole thing would be mitigated if Elastic TLABs were enabled, but there 607 // is no support in this JDK. 608 // 609 guarantee(MaxTLABSizeWords == 0, "we should only set it once"); 610 MaxTLABSizeWords = MIN2(RegionSizeWords / 8, HumongousThresholdWords); 611 MaxTLABSizeWords = (size_t)align_size_down(MaxTLABSizeWords, MinObjAlignment); 612 613 guarantee(MaxTLABSizeBytes == 0, "we should only set it once"); 614 MaxTLABSizeBytes = MaxTLABSizeWords * HeapWordSize; 615 assert (MaxTLABSizeBytes > MinTLABSize, "should be larger"); 616 617 log_info(gc, init)("Regions: " SIZE_FORMAT " x " SIZE_FORMAT "%s", 618 RegionCount, byte_size_in_proper_unit(RegionSizeBytes), proper_unit_for_byte_size(RegionSizeBytes)); 619 log_info(gc, init)("Humongous object threshold: " SIZE_FORMAT "%s", 620 byte_size_in_proper_unit(HumongousThresholdBytes), proper_unit_for_byte_size(HumongousThresholdBytes)); 621 log_info(gc, init)("Max TLAB size: " SIZE_FORMAT "%s", 622 byte_size_in_proper_unit(MaxTLABSizeBytes), proper_unit_for_byte_size(MaxTLABSizeBytes)); 623 } 624 625 void ShenandoahHeapRegion::do_commit() { 626 if (!_heap->is_heap_region_special() && !os::commit_memory((char *) _reserved.start(), _reserved.byte_size(), false)) { 627 report_java_out_of_memory("Unable to commit region"); 628 } 629 if (!_heap->commit_bitmap_slice(this)) { 630 report_java_out_of_memory("Unable to commit bitmaps for region"); 631 } 632 _heap->increase_committed(ShenandoahHeapRegion::region_size_bytes()); 633 } 634 635 void ShenandoahHeapRegion::do_uncommit() { 636 if (!_heap->is_heap_region_special() && !os::uncommit_memory((char *) _reserved.start(), _reserved.byte_size())) { 637 report_java_out_of_memory("Unable to uncommit region"); 638 } 639 if (!_heap->uncommit_bitmap_slice(this)) { 640 report_java_out_of_memory("Unable to uncommit bitmaps for region"); 641 } 642 _heap->decrease_committed(ShenandoahHeapRegion::region_size_bytes()); 643 } 644 645 void ShenandoahHeapRegion::record_pin() { 646 Atomic::add(1, &_critical_pins); 647 } 648 649 void ShenandoahHeapRegion::record_unpin() { 650 assert(pin_count() > 0, err_msg("Region " SIZE_FORMAT " should have non-zero pins", region_number())); 651 Atomic::add(-1, &_critical_pins); 652 } 653 654 size_t ShenandoahHeapRegion::pin_count() const { 655 jint v = OrderAccess::load_acquire((volatile jint*)&_critical_pins); 656 assert(v >= 0, "sanity"); 657 return (size_t)v; 658 }