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