@@ -235,12 +235,8 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) {
235235 phase3_update_references ();
236236
237237 phase4_compact_objects (worker_slices);
238- }
239238
240- {
241- // Epilogue
242- _preserved_marks->restore (heap->workers ());
243- _preserved_marks->reclaim ();
239+ phase5_epilog ();
244240 }
245241
246242 // Resize metaspace
@@ -280,6 +276,8 @@ class ShenandoahPrepareForMarkClosure: public ShenandoahHeapRegionClosure {
280276 _ctx->capture_top_at_mark_start (r);
281277 r->clear_live_data ();
282278 }
279+
280+ bool is_thread_safe () { return true ; }
283281};
284282
285283void ShenandoahFullGC::phase1_mark_heap () {
@@ -289,7 +287,7 @@ void ShenandoahFullGC::phase1_mark_heap() {
289287 ShenandoahHeap* heap = ShenandoahHeap::heap ();
290288
291289 ShenandoahPrepareForMarkClosure cl;
292- heap->heap_region_iterate (&cl);
290+ heap->parallel_heap_region_iterate (&cl);
293291
294292 heap->set_unload_classes (heap->heuristics ()->can_unload_classes ());
295293
@@ -328,7 +326,7 @@ class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
328326 _from_region = from_region;
329327 }
330328
331- void finish_region () {
329+ void finish () {
332330 assert (_to_region != nullptr , " should not happen" );
333331 _to_region->set_new_top (_compact_point);
334332 }
@@ -348,7 +346,7 @@ class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
348346
349347 size_t obj_size = p->size ();
350348 if (_compact_point + obj_size > _to_region->end ()) {
351- finish_region ();
349+ finish ();
352350
353351 // Object doesn't fit. Pick next empty region and start compacting there.
354352 ShenandoahHeapRegion* new_to_region;
@@ -400,47 +398,61 @@ class ShenandoahPrepareForCompactionTask : public WorkerTask {
400398 return r->is_stw_move_allowed () && !r->is_humongous ();
401399 }
402400
403- void work (uint worker_id) {
404- ShenandoahParallelWorkerSession worker_session (worker_id);
405- ShenandoahHeapRegionSet* slice = _worker_slices[worker_id];
406- ShenandoahHeapRegionSetIterator it (slice);
407- ShenandoahHeapRegion* from_region = it.next ();
408- // No work?
409- if (from_region == nullptr ) {
410- return ;
411- }
412-
413- // Sliding compaction. Walk all regions in the slice, and compact them.
414- // Remember empty regions and reuse them as needed.
415- ResourceMark rm;
401+ void work (uint worker_id) override ;
402+ private:
403+ template <typename ClosureType>
404+ void prepare_for_compaction (ClosureType& cl,
405+ GrowableArray<ShenandoahHeapRegion*>& empty_regions,
406+ ShenandoahHeapRegionSetIterator& it,
407+ ShenandoahHeapRegion* from_region);
408+ };
416409
417- GrowableArray<ShenandoahHeapRegion*> empty_regions ((int )_heap->num_regions ());
410+ void ShenandoahPrepareForCompactionTask::work (uint worker_id) {
411+ ShenandoahParallelWorkerSession worker_session (worker_id);
412+ ShenandoahHeapRegionSet* slice = _worker_slices[worker_id];
413+ ShenandoahHeapRegionSetIterator it (slice);
414+ ShenandoahHeapRegion* from_region = it.next ();
415+ // No work?
416+ if (from_region == nullptr ) {
417+ return ;
418+ }
418419
419- ShenandoahPrepareForCompactionObjectClosure cl (_preserved_marks->get (worker_id), empty_regions, from_region);
420+ // Sliding compaction. Walk all regions in the slice, and compact them.
421+ // Remember empty regions and reuse them as needed.
422+ ResourceMark rm;
420423
421- while (from_region != nullptr ) {
422- assert (is_candidate_region (from_region), " Sanity" );
424+ GrowableArray<ShenandoahHeapRegion*> empty_regions ((int )_heap->num_regions ());
423425
424- cl.set_from_region (from_region);
425- if (from_region->has_live ()) {
426- _heap->marked_object_iterate (from_region, &cl);
427- }
426+ ShenandoahPrepareForCompactionObjectClosure cl (_preserved_marks->get (worker_id), empty_regions, from_region);
427+ prepare_for_compaction (cl, empty_regions, it, from_region);
428+ }
428429
429- // Compacted the region to somewhere else? From-region is empty then.
430- if (!cl.is_compact_same_region ()) {
431- empty_regions.append (from_region);
432- }
433- from_region = it.next ();
430+ template <typename ClosureType>
431+ void ShenandoahPrepareForCompactionTask::prepare_for_compaction (ClosureType& cl,
432+ GrowableArray<ShenandoahHeapRegion*>& empty_regions,
433+ ShenandoahHeapRegionSetIterator& it,
434+ ShenandoahHeapRegion* from_region) {
435+ while (from_region != nullptr ) {
436+ assert (is_candidate_region (from_region), " Sanity" );
437+ cl.set_from_region (from_region);
438+ if (from_region->has_live ()) {
439+ _heap->marked_object_iterate (from_region, &cl);
434440 }
435- cl.finish_region ();
436441
437- // Mark all remaining regions as empty
438- for (int pos = cl.empty_regions_pos (); pos < empty_regions.length (); ++pos) {
439- ShenandoahHeapRegion* r = empty_regions.at (pos);
440- r->set_new_top (r->bottom ());
442+ // Compacted the region to somewhere else? From-region is empty then.
443+ if (!cl.is_compact_same_region ()) {
444+ empty_regions.append (from_region);
441445 }
446+ from_region = it.next ();
442447 }
443- };
448+ cl.finish ();
449+
450+ // Mark all remaining regions as empty
451+ for (int pos = cl.empty_regions_pos (); pos < empty_regions.length (); ++pos) {
452+ ShenandoahHeapRegion* r = empty_regions.at (pos);
453+ r->set_new_top (r->bottom ());
454+ }
455+ }
444456
445457void ShenandoahFullGC::calculate_target_humongous_objects () {
446458 ShenandoahHeap* heap = ShenandoahHeap::heap ();
@@ -948,7 +960,7 @@ void ShenandoahFullGC::compact_humongous_objects() {
948960 //
949961 // This code is serial, because doing the in-slice parallel sliding is tricky. In most cases,
950962 // humongous regions are already compacted, and do not require further moves, which alleviates
951- // sliding costs. We may consider doing this in parallel in future.
963+ // sliding costs. We may consider doing this in parallel in the future.
952964
953965 ShenandoahHeap* heap = ShenandoahHeap::heap ();
954966
@@ -1054,6 +1066,11 @@ void ShenandoahFullGC::phase4_compact_objects(ShenandoahHeapRegionSet** worker_s
10541066 ShenandoahGCPhase phase (ShenandoahPhaseTimings::full_gc_copy_objects_humong);
10551067 compact_humongous_objects ();
10561068 }
1069+ }
1070+
1071+ void ShenandoahFullGC::phase5_epilog () {
1072+ GCTraceTime (Info, gc, phases) time (" Phase 5: Full GC epilog" , _gc_timer);
1073+ ShenandoahHeap* heap = ShenandoahHeap::heap ();
10571074
10581075 // Reset complete bitmap. We're about to reset the complete-top-at-mark-start pointer
10591076 // and must ensure the bitmap is in sync.
@@ -1066,14 +1083,15 @@ void ShenandoahFullGC::phase4_compact_objects(ShenandoahHeapRegionSet** worker_s
10661083 // Bring regions in proper states after the collection, and set heap properties.
10671084 {
10681085 ShenandoahGCPhase phase (ShenandoahPhaseTimings::full_gc_copy_objects_rebuild);
1069-
10701086 ShenandoahPostCompactClosure post_compact;
10711087 heap->heap_region_iterate (&post_compact);
10721088 heap->set_used (post_compact.get_live ());
10731089
10741090 heap->collection_set ()->clear ();
10751091 heap->free_set ()->rebuild ();
1092+ heap->clear_cancelled_gc ();
10761093 }
10771094
1078- heap->clear_cancelled_gc ();
1095+ _preserved_marks->restore (heap->workers ());
1096+ _preserved_marks->reclaim ();
10791097}
0 commit comments