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