@@ -88,19 +88,20 @@ ShenandoahHeapRegion::ShenandoahHeapRegion(HeapWord* start, size_t index, bool c
88
88
if (ZapUnusedHeapArea && committed) {
89
89
SpaceMangler::mangle_region (MemRegion (_bottom, _end));
90
90
}
91
+ _recycling.unset ();
91
92
}
92
93
93
94
void ShenandoahHeapRegion::report_illegal_transition (const char *method) {
94
95
stringStream ss;
95
- ss.print (" Illegal region state transition from \" %s\" , at %s\n " , region_state_to_string (_state ), method);
96
+ ss.print (" Illegal region state transition from \" %s\" , at %s\n " , region_state_to_string (state () ), method);
96
97
print_on (&ss);
97
98
fatal (" %s" , ss.freeze ());
98
99
}
99
100
100
101
void ShenandoahHeapRegion::make_regular_allocation (ShenandoahAffiliation affiliation) {
101
102
shenandoah_assert_heaplocked ();
102
103
reset_age ();
103
- switch (_state ) {
104
+ switch (state () ) {
104
105
case _empty_uncommitted:
105
106
do_commit ();
106
107
case _empty_committed:
@@ -120,7 +121,7 @@ void ShenandoahHeapRegion::make_regular_allocation(ShenandoahAffiliation affilia
120
121
void ShenandoahHeapRegion::make_affiliated_maybe () {
121
122
shenandoah_assert_heaplocked ();
122
123
assert (!ShenandoahHeap::heap ()->mode ()->is_generational (), " Only call if non-generational" );
123
- switch (_state ) {
124
+ switch (state () ) {
124
125
case _empty_uncommitted:
125
126
case _empty_committed:
126
127
case _cset:
@@ -146,14 +147,15 @@ void ShenandoahHeapRegion::make_regular_bypass() {
146
147
ShenandoahHeap::heap ()->is_degenerated_gc_in_progress (),
147
148
" Only for STW GC or when Universe is initializing (CDS)" );
148
149
reset_age ();
149
- switch (_state) {
150
+ auto cur_state = state ();
151
+ switch (cur_state) {
150
152
case _empty_uncommitted:
151
153
do_commit ();
152
154
case _empty_committed:
153
155
case _cset:
154
156
case _humongous_start:
155
157
case _humongous_cont:
156
- if (_state == _humongous_start || _state == _humongous_cont) {
158
+ if (cur_state == _humongous_start || cur_state == _humongous_cont) {
157
159
// CDS allocates chunks of the heap to fill with regular objects. The allocator
158
160
// will dutifully track any waste in the unused portion of the last region. Once
159
161
// CDS has finished initializing the objects, it will convert these regions to
@@ -177,7 +179,7 @@ void ShenandoahHeapRegion::make_regular_bypass() {
177
179
void ShenandoahHeapRegion::make_humongous_start () {
178
180
shenandoah_assert_heaplocked ();
179
181
reset_age ();
180
- switch (_state ) {
182
+ switch (state () ) {
181
183
case _empty_uncommitted:
182
184
do_commit ();
183
185
case _empty_committed:
@@ -194,7 +196,7 @@ void ShenandoahHeapRegion::make_humongous_start_bypass(ShenandoahAffiliation aff
194
196
// Don't bother to account for affiliated regions during Full GC. We recompute totals at end.
195
197
set_affiliation (affiliation);
196
198
reset_age ();
197
- switch (_state ) {
199
+ switch (state () ) {
198
200
case _empty_committed:
199
201
case _regular:
200
202
case _humongous_start:
@@ -209,7 +211,7 @@ void ShenandoahHeapRegion::make_humongous_start_bypass(ShenandoahAffiliation aff
209
211
void ShenandoahHeapRegion::make_humongous_cont () {
210
212
shenandoah_assert_heaplocked ();
211
213
reset_age ();
212
- switch (_state ) {
214
+ switch (state () ) {
213
215
case _empty_uncommitted:
214
216
do_commit ();
215
217
case _empty_committed:
@@ -226,7 +228,7 @@ void ShenandoahHeapRegion::make_humongous_cont_bypass(ShenandoahAffiliation affi
226
228
set_affiliation (affiliation);
227
229
// Don't bother to account for affiliated regions during Full GC. We recompute totals at end.
228
230
reset_age ();
229
- switch (_state ) {
231
+ switch (state () ) {
230
232
case _empty_committed:
231
233
case _regular:
232
234
case _humongous_start:
@@ -242,7 +244,7 @@ void ShenandoahHeapRegion::make_pinned() {
242
244
shenandoah_assert_heaplocked ();
243
245
assert (pin_count () > 0 , " Should have pins: " SIZE_FORMAT, pin_count ());
244
246
245
- switch (_state ) {
247
+ switch (state () ) {
246
248
case _regular:
247
249
set_state (_pinned);
248
250
case _pinned_cset:
@@ -253,7 +255,7 @@ void ShenandoahHeapRegion::make_pinned() {
253
255
case _pinned_humongous_start:
254
256
return ;
255
257
case _cset:
256
- _state = _pinned_cset;
258
+ set_state ( _pinned_cset) ;
257
259
return ;
258
260
default :
259
261
report_illegal_transition (" pinning" );
@@ -264,7 +266,7 @@ void ShenandoahHeapRegion::make_unpinned() {
264
266
shenandoah_assert_heaplocked ();
265
267
assert (pin_count () == 0 , " Should not have pins: " SIZE_FORMAT, pin_count ());
266
268
267
- switch (_state ) {
269
+ switch (state () ) {
268
270
case _pinned:
269
271
assert (is_affiliated (), " Pinned region should be affiliated" );
270
272
set_state (_regular);
@@ -286,7 +288,7 @@ void ShenandoahHeapRegion::make_unpinned() {
286
288
void ShenandoahHeapRegion::make_cset () {
287
289
shenandoah_assert_heaplocked ();
288
290
// Leave age untouched. We need to consult the age when we are deciding whether to promote evacuated objects.
289
- switch (_state ) {
291
+ switch (state () ) {
290
292
case _regular:
291
293
set_state (_cset);
292
294
case _cset:
@@ -299,7 +301,7 @@ void ShenandoahHeapRegion::make_cset() {
299
301
void ShenandoahHeapRegion::make_trash () {
300
302
shenandoah_assert_heaplocked ();
301
303
reset_age ();
302
- switch (_state ) {
304
+ switch (state () ) {
303
305
case _humongous_start:
304
306
case _humongous_cont:
305
307
{
@@ -329,10 +331,9 @@ void ShenandoahHeapRegion::make_trash_immediate() {
329
331
}
330
332
331
333
void ShenandoahHeapRegion::make_empty () {
332
- shenandoah_assert_heaplocked ();
333
334
reset_age ();
334
335
CENSUS_NOISE (clear_youth ();)
335
- switch (_state ) {
336
+ switch (state () ) {
336
337
case _trash:
337
338
set_state (_empty_committed);
338
339
_empty_time = os::elapsedTime ();
@@ -344,7 +345,7 @@ void ShenandoahHeapRegion::make_empty() {
344
345
345
346
void ShenandoahHeapRegion::make_uncommitted () {
346
347
shenandoah_assert_heaplocked ();
347
- switch (_state ) {
348
+ switch (state () ) {
348
349
case _empty_committed:
349
350
do_uncommit ();
350
351
set_state (_empty_uncommitted);
@@ -358,7 +359,7 @@ void ShenandoahHeapRegion::make_committed_bypass() {
358
359
shenandoah_assert_heaplocked ();
359
360
assert (ShenandoahHeap::heap ()->is_full_gc_in_progress (), " only for full GC" );
360
361
361
- switch (_state ) {
362
+ switch (state () ) {
362
363
case _empty_uncommitted:
363
364
do_commit ();
364
365
set_state (_empty_committed);
@@ -399,7 +400,7 @@ void ShenandoahHeapRegion::print_on(outputStream* st) const {
399
400
st->print (" |" );
400
401
st->print (SIZE_FORMAT_W (5 ), this ->_index );
401
402
402
- switch (_state ) {
403
+ switch (state () ) {
403
404
case _empty_uncommitted:
404
405
st->print (" |EU " );
405
406
break ;
@@ -569,27 +570,62 @@ ShenandoahHeapRegion* ShenandoahHeapRegion::humongous_start_region() const {
569
570
return r;
570
571
}
571
572
572
- void ShenandoahHeapRegion::recycle () {
573
- shenandoah_assert_heaplocked ();
574
- ShenandoahHeap* heap = ShenandoahHeap::heap ();
575
- ShenandoahGeneration* generation = heap->generation_for (affiliation ());
576
573
577
- heap->decrease_used (generation, used ());
578
- generation->decrement_affiliated_region_count ();
574
+ void ShenandoahHeapRegion::recycle_internal () {
575
+ assert (_recycling.is_set () && is_trash (), " Wrong state" );
576
+ ShenandoahHeap* heap = ShenandoahHeap::heap ();
579
577
580
578
set_top (bottom ());
581
579
clear_live_data ();
582
580
reset_alloc_metadata ();
583
-
584
581
heap->marking_context ()->reset_top_at_mark_start (this );
585
-
586
582
set_update_watermark (bottom ());
583
+ if (ZapUnusedHeapArea) {
584
+ SpaceMangler::mangle_region (MemRegion (bottom (), end ()));
585
+ }
587
586
588
587
make_empty ();
589
-
590
588
set_affiliation (FREE);
591
- if (ZapUnusedHeapArea) {
592
- SpaceMangler::mangle_region (MemRegion (bottom (), end ()));
589
+ }
590
+
591
+ void ShenandoahHeapRegion::try_recycle_under_lock () {
592
+ shenandoah_assert_heaplocked ();
593
+ if (is_trash () && _recycling.try_set ()) {
594
+ if (is_trash ()) {
595
+ ShenandoahHeap* heap = ShenandoahHeap::heap ();
596
+ ShenandoahGeneration* generation = heap->generation_for (affiliation ());
597
+
598
+ heap->decrease_used (generation, used ());
599
+ generation->decrement_affiliated_region_count ();
600
+
601
+ recycle_internal ();
602
+ }
603
+ _recycling.unset ();
604
+ } else {
605
+ // Ensure recycling is unset before returning to mutator to continue memory allocation.
606
+ while (_recycling.is_set ()) {
607
+ if (os::is_MP ()) {
608
+ SpinPause ();
609
+ } else {
610
+ os::naked_yield ();
611
+ }
612
+ }
613
+ }
614
+ }
615
+
616
+ void ShenandoahHeapRegion::try_recycle () {
617
+ shenandoah_assert_not_heaplocked ();
618
+ if (is_trash () && _recycling.try_set ()) {
619
+ // Double check region state after win the race to set recycling flag
620
+ if (is_trash ()) {
621
+ ShenandoahHeap* heap = ShenandoahHeap::heap ();
622
+ ShenandoahGeneration* generation = heap->generation_for (affiliation ());
623
+ heap->decrease_used (generation, used ());
624
+ generation->decrement_affiliated_region_count_without_lock ();
625
+
626
+ recycle_internal ();
627
+ }
628
+ _recycling.unset ();
593
629
}
594
630
}
595
631
@@ -795,11 +831,11 @@ void ShenandoahHeapRegion::set_state(RegionState to) {
795
831
evt.set_index ((unsigned ) index ());
796
832
evt.set_start ((uintptr_t )bottom ());
797
833
evt.set_used (used ());
798
- evt.set_from (_state );
834
+ evt.set_from (state () );
799
835
evt.set_to (to);
800
836
evt.commit ();
801
837
}
802
- _state = to ;
838
+ Atomic::store (& _state, to) ;
803
839
}
804
840
805
841
void ShenandoahHeapRegion::record_pin () {
0 commit comments