197
198 // Perform concurrent class unloading before any regions get recycled. Class unloading may
199 // need to inspect unmarked objects in trashed regions.
200 if (heap->unload_classes()) {
201 entry_class_unloading();
202 }
203
204 // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
205 // the space. This would be the last action if there is nothing to evacuate. Note that
206 // we will not age young-gen objects in the case that we skip evacuation.
207 entry_cleanup_early();
208
209 // Processing strong roots
210 // This may be skipped if there is nothing to update/evacuate.
211 // If so, strong_root_in_progress would be unset.
212 if (heap->is_concurrent_strong_root_in_progress()) {
213 entry_strong_roots();
214 }
215
216 // Roots processing is complete, put the weak roots flag down.
217 entry_final_roots();
218
219 // Continue the cycle with evacuation and optional update-refs.
220 // This may be skipped if there is nothing to evacuate.
221 // If so, evac_in_progress would be unset by collection set preparation code.
222 if (heap->is_evacuation_in_progress()) {
223 // Concurrently evacuate
224 entry_evacuate();
225 if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) {
226 return false;
227 }
228
229 // Perform update-refs phase.
230 entry_concurrent_update_refs_prepare(heap);
231
232 if (ShenandoahHeap::heap()->mode()->is_generational()) {
233 entry_update_card_table();
234 }
235
236 if (ShenandoahVerify) {
237 vmop_entry_init_update_refs();
346 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
347 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_update_refs_gross);
348
349 heap->try_inject_alloc_failure();
350 heap->try_inject_pin();
351 VM_ShenandoahInitUpdateRefs op(this);
352 VMThread::execute(&op);
353 }
354
355 void ShenandoahConcurrentGC::vmop_entry_final_update_refs() {
356 ShenandoahHeap* const heap = ShenandoahHeap::heap();
357 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
358 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_gross);
359
360 heap->try_inject_alloc_failure();
361 heap->try_inject_pin();
362 VM_ShenandoahFinalUpdateRefs op(this);
363 VMThread::execute(&op);
364 }
365
366 void ShenandoahConcurrentGC::vmop_entry_final_verify() {
367 ShenandoahHeap* const heap = ShenandoahHeap::heap();
368 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
369 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_verify_gross);
370
371 // This phase does not use workers, no need for setup
372 heap->try_inject_alloc_failure();
373 heap->try_inject_pin();
374 VM_ShenandoahFinalVerify op(this);
375 VMThread::execute(&op);
376 }
377
378 void ShenandoahConcurrentGC::entry_init_mark() {
379 const char* msg = init_mark_event_message();
380 ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::init_mark);
381 EventMark em("%s", msg);
382
383 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
384 ShenandoahWorkerPolicy::calc_workers_for_init_marking(),
385 "init marking");
750 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
751 ShenandoahInitMarkUpdateRegionStateClosure cl;
752 heap->parallel_heap_region_iterate(&cl);
753 heap->old_generation()->ref_processor()->reset_thread_locals();
754 } else {
755 // Update region state for only young regions
756 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
757 ShenandoahInitMarkUpdateRegionStateClosure cl;
758 _generation->parallel_heap_region_iterate(&cl);
759 }
760
761 // Weak reference processing
762 ShenandoahReferenceProcessor* rp = _generation->ref_processor();
763 rp->reset_thread_locals();
764
765 // Make above changes visible to worker threads
766 OrderAccess::fence();
767
768 // Arm nmethods/stack for concurrent processing
769 ShenandoahCodeRoots::arm_nmethods();
770 ShenandoahStackWatermark::change_epoch_id();
771
772 {
773 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_propagate_gc_state);
774 heap->propagate_gc_state_to_all_threads();
775 }
776 }
777
778 void ShenandoahConcurrentGC::op_mark_roots() {
779 _mark.mark_concurrent_roots();
780 }
781
782 void ShenandoahConcurrentGC::op_mark() {
783 _mark.concurrent_mark();
784 }
785
786 void ShenandoahConcurrentGC::op_final_mark() {
787 ShenandoahHeap* const heap = ShenandoahHeap::heap();
788 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should be at safepoint");
789 assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
790
806
807 // Has to be done after cset selection
808 heap->prepare_concurrent_roots();
809
810 if (!heap->collection_set()->is_empty()) {
811 LogTarget(Debug, gc, cset) lt;
812 if (lt.is_enabled()) {
813 ResourceMark rm;
814 LogStream ls(lt);
815 heap->collection_set()->print_on(&ls);
816 }
817
818 if (ShenandoahVerify) {
819 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
820 heap->verifier()->verify_before_evacuation(_generation);
821 }
822
823 heap->set_evacuation_in_progress(true);
824 // From here on, we need to update references.
825 heap->set_has_forwarded_objects(true);
826
827 // Arm nmethods/stack for concurrent processing
828 ShenandoahCodeRoots::arm_nmethods();
829 ShenandoahStackWatermark::change_epoch_id();
830
831 } else {
832 if (ShenandoahVerify) {
833 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
834 if (has_in_place_promotions(heap)) {
835 heap->verifier()->verify_after_concmark_with_promotions(_generation);
836 } else {
837 heap->verifier()->verify_after_concmark(_generation);
838 }
839 }
840 }
841 }
842
843 {
844 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state);
845 heap->propagate_gc_state_to_all_threads();
846 }
847 }
848
849 bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) {
850 return heap->mode()->is_generational() && heap->old_generation()->has_in_place_promotions();
851 }
852
853 class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure {
854 private:
855 OopClosure* const _oops;
856 public:
857 explicit ShenandoahConcurrentEvacThreadClosure(OopClosure* oops) : _oops(oops) {}
858
859 void do_thread(Thread* thread) override {
860 JavaThread* const jt = JavaThread::cast(thread);
861 StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc);
862 }
1043
1044 void ShenandoahConcurrentGC::op_class_unloading() {
1045 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1046 assert (heap->is_concurrent_weak_root_in_progress() &&
1047 heap->unload_classes(),
1048 "Checked by caller");
1049 heap->do_class_unloading();
1050 }
1051
1052 class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure {
1053 private:
1054 ShenandoahEvacuateUpdateMetadataClosure _cl;
1055
1056 public:
1057 ShenandoahEvacUpdateCodeCacheClosure() : _cl() {}
1058
1059 void do_nmethod(nmethod* n) {
1060 ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
1061 ShenandoahNMethodLocker locker(data->lock());
1062 data->oops_do(&_cl, /* fix_relocations = */ true);
1063 ShenandoahNMethod::disarm_nmethod(n);
1064 }
1065 };
1066
1067 class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
1068 private:
1069 ShenandoahPhaseTimings::Phase _phase;
1070 ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
1071 ShenandoahClassLoaderDataRoots<true /*concurrent*/>
1072 _cld_roots;
1073 ShenandoahConcurrentNMethodIterator _nmethod_itr;
1074
1075 public:
1076 ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
1077 WorkerTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
1078 _phase(phase),
1079 _vm_roots(phase),
1080 _cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
1081 _nmethod_itr(ShenandoahCodeRoots::table()) {}
1082
1083 void work(uint worker_id) {
1224
1225 // If we are running in generational mode, this will also age active regions that
1226 // haven't been used for allocation.
1227 heap->update_heap_region_states(true /*concurrent*/);
1228
1229 heap->set_update_refs_in_progress(false);
1230 heap->set_has_forwarded_objects(false);
1231
1232 if (ShenandoahVerify) {
1233 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify);
1234 heap->verifier()->verify_after_update_refs(_generation);
1235 }
1236
1237 if (VerifyAfterGC) {
1238 Universe::verify();
1239 }
1240
1241 heap->rebuild_free_set(true /*concurrent*/);
1242 _generation->heuristics()->start_idle_span();
1243
1244 {
1245 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
1246 heap->propagate_gc_state_to_all_threads();
1247 }
1248 }
1249
1250 void ShenandoahConcurrentGC::entry_final_roots() {
1251 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1252 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
1253 const char* msg = conc_final_roots_event_message();
1254 ShenandoahConcurrentPhase gc_phase(msg, ShenandoahPhaseTimings::conc_final_roots);
1255 EventMark em("%s", msg);
1256
1257 heap->concurrent_final_roots();
1258 }
1259
1260 void ShenandoahConcurrentGC::op_verify_final() {
1261 assert(ShenandoahVerify, "Should have been checked before");
1262 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1263 heap->verifier()->verify_after_gc(_generation);
1264 }
1265
1266 void ShenandoahConcurrentGC::op_cleanup_complete() {
1267 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1268 ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
1269 "cleanup complete.");
1270 ShenandoahHeap::heap()->recycle_trash();
1271 }
1272
1273 void ShenandoahConcurrentGC::op_reset_after_collect() {
1274 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1275 ShenandoahWorkerPolicy::calc_workers_for_conc_reset(),
1276 "reset after collection.");
1277
1336 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset", "");
1337 }
1338 }
1339
1340 const char* ShenandoahConcurrentGC::conc_reset_after_collect_event_message() const {
1341 if (ShenandoahHeap::heap()->unload_classes()) {
1342 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", " (unload classes)");
1343 } else {
1344 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", "");
1345 }
1346 }
1347
1348 const char* ShenandoahConcurrentGC::verify_final_event_message() const {
1349 if (ShenandoahHeap::heap()->unload_classes()) {
1350 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", " (unload classes)");
1351 } else {
1352 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", "");
1353 }
1354 }
1355
1356 const char* ShenandoahConcurrentGC::conc_final_roots_event_message() const {
1357 if (ShenandoahHeap::heap()->unload_classes()) {
1358 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent Final Roots", " (unload classes)");
1359 } else {
1360 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent Final Roots", "");
1361 }
1362 }
1363
1364 const char* ShenandoahConcurrentGC::conc_weak_refs_event_message() const {
1365 if (ShenandoahHeap::heap()->unload_classes()) {
1366 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak references", " (unload classes)");
1367 } else {
1368 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak references", "");
1369 }
1370 }
1371
1372 const char* ShenandoahConcurrentGC::conc_weak_roots_event_message() const {
1373 if (ShenandoahHeap::heap()->unload_classes()) {
1374 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak roots", " (unload classes)");
1375 } else {
1376 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak roots", "");
1377 }
1378 }
1379
1380 const char* ShenandoahConcurrentGC::conc_cleanup_event_message() const {
|
197
198 // Perform concurrent class unloading before any regions get recycled. Class unloading may
199 // need to inspect unmarked objects in trashed regions.
200 if (heap->unload_classes()) {
201 entry_class_unloading();
202 }
203
204 // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
205 // the space. This would be the last action if there is nothing to evacuate. Note that
206 // we will not age young-gen objects in the case that we skip evacuation.
207 entry_cleanup_early();
208
209 // Processing strong roots
210 // This may be skipped if there is nothing to update/evacuate.
211 // If so, strong_root_in_progress would be unset.
212 if (heap->is_concurrent_strong_root_in_progress()) {
213 entry_strong_roots();
214 }
215
216 // Roots processing is complete, put the weak roots flag down.
217 vmop_entry_final_roots();
218
219 // Continue the cycle with evacuation and optional update-refs.
220 // This may be skipped if there is nothing to evacuate.
221 // If so, evac_in_progress would be unset by collection set preparation code.
222 if (heap->is_evacuation_in_progress()) {
223 // Concurrently evacuate
224 entry_evacuate();
225 if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) {
226 return false;
227 }
228
229 // Perform update-refs phase.
230 entry_concurrent_update_refs_prepare(heap);
231
232 if (ShenandoahHeap::heap()->mode()->is_generational()) {
233 entry_update_card_table();
234 }
235
236 if (ShenandoahVerify) {
237 vmop_entry_init_update_refs();
346 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
347 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_update_refs_gross);
348
349 heap->try_inject_alloc_failure();
350 heap->try_inject_pin();
351 VM_ShenandoahInitUpdateRefs op(this);
352 VMThread::execute(&op);
353 }
354
355 void ShenandoahConcurrentGC::vmop_entry_final_update_refs() {
356 ShenandoahHeap* const heap = ShenandoahHeap::heap();
357 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
358 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_gross);
359
360 heap->try_inject_alloc_failure();
361 heap->try_inject_pin();
362 VM_ShenandoahFinalUpdateRefs op(this);
363 VMThread::execute(&op);
364 }
365
366 void ShenandoahConcurrentGC::vmop_entry_final_roots() {
367 ShenandoahHeap* const heap = ShenandoahHeap::heap();
368 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
369 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_roots_gross);
370
371 // This phase does not use workers, no need for setup
372 heap->try_inject_alloc_failure();
373 VM_ShenandoahFinalRoots op(this);
374 VMThread::execute(&op);
375 }
376
377 void ShenandoahConcurrentGC::vmop_entry_final_verify() {
378 ShenandoahHeap* const heap = ShenandoahHeap::heap();
379 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
380 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_verify_gross);
381
382 // This phase does not use workers, no need for setup
383 heap->try_inject_alloc_failure();
384 heap->try_inject_pin();
385 VM_ShenandoahFinalVerify op(this);
386 VMThread::execute(&op);
387 }
388
389 void ShenandoahConcurrentGC::entry_init_mark() {
390 const char* msg = init_mark_event_message();
391 ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::init_mark);
392 EventMark em("%s", msg);
393
394 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
395 ShenandoahWorkerPolicy::calc_workers_for_init_marking(),
396 "init marking");
761 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
762 ShenandoahInitMarkUpdateRegionStateClosure cl;
763 heap->parallel_heap_region_iterate(&cl);
764 heap->old_generation()->ref_processor()->reset_thread_locals();
765 } else {
766 // Update region state for only young regions
767 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
768 ShenandoahInitMarkUpdateRegionStateClosure cl;
769 _generation->parallel_heap_region_iterate(&cl);
770 }
771
772 // Weak reference processing
773 ShenandoahReferenceProcessor* rp = _generation->ref_processor();
774 rp->reset_thread_locals();
775
776 // Make above changes visible to worker threads
777 OrderAccess::fence();
778
779 // Arm nmethods/stack for concurrent processing
780 ShenandoahCodeRoots::arm_nmethods();
781
782 {
783 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_propagate_gc_state);
784 heap->propagate_gc_state_to_all_threads();
785 }
786 }
787
788 void ShenandoahConcurrentGC::op_mark_roots() {
789 _mark.mark_concurrent_roots();
790 }
791
792 void ShenandoahConcurrentGC::op_mark() {
793 _mark.concurrent_mark();
794 }
795
796 void ShenandoahConcurrentGC::op_final_mark() {
797 ShenandoahHeap* const heap = ShenandoahHeap::heap();
798 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should be at safepoint");
799 assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
800
816
817 // Has to be done after cset selection
818 heap->prepare_concurrent_roots();
819
820 if (!heap->collection_set()->is_empty()) {
821 LogTarget(Debug, gc, cset) lt;
822 if (lt.is_enabled()) {
823 ResourceMark rm;
824 LogStream ls(lt);
825 heap->collection_set()->print_on(&ls);
826 }
827
828 if (ShenandoahVerify) {
829 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
830 heap->verifier()->verify_before_evacuation(_generation);
831 }
832
833 heap->set_evacuation_in_progress(true);
834 // From here on, we need to update references.
835 heap->set_has_forwarded_objects(true);
836 } else {
837 if (ShenandoahVerify) {
838 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
839 if (has_in_place_promotions(heap)) {
840 heap->verifier()->verify_after_concmark_with_promotions(_generation);
841 } else {
842 heap->verifier()->verify_after_concmark(_generation);
843 }
844 }
845 }
846 }
847
848 // Arm nmethods/stack for concurrent processing
849 ShenandoahCodeRoots::arm_nmethods();
850
851 {
852 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state);
853 heap->propagate_gc_state_to_all_threads();
854 }
855 }
856
857 bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) {
858 return heap->mode()->is_generational() && heap->old_generation()->has_in_place_promotions();
859 }
860
861 class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure {
862 private:
863 OopClosure* const _oops;
864 public:
865 explicit ShenandoahConcurrentEvacThreadClosure(OopClosure* oops) : _oops(oops) {}
866
867 void do_thread(Thread* thread) override {
868 JavaThread* const jt = JavaThread::cast(thread);
869 StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc);
870 }
1051
1052 void ShenandoahConcurrentGC::op_class_unloading() {
1053 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1054 assert (heap->is_concurrent_weak_root_in_progress() &&
1055 heap->unload_classes(),
1056 "Checked by caller");
1057 heap->do_class_unloading();
1058 }
1059
1060 class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure {
1061 private:
1062 ShenandoahEvacuateUpdateMetadataClosure _cl;
1063
1064 public:
1065 ShenandoahEvacUpdateCodeCacheClosure() : _cl() {}
1066
1067 void do_nmethod(nmethod* n) {
1068 ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
1069 ShenandoahNMethodLocker locker(data->lock());
1070 data->oops_do(&_cl, /* fix_relocations = */ true);
1071 }
1072 };
1073
1074 class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
1075 private:
1076 ShenandoahPhaseTimings::Phase _phase;
1077 ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
1078 ShenandoahClassLoaderDataRoots<true /*concurrent*/>
1079 _cld_roots;
1080 ShenandoahConcurrentNMethodIterator _nmethod_itr;
1081
1082 public:
1083 ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
1084 WorkerTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
1085 _phase(phase),
1086 _vm_roots(phase),
1087 _cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
1088 _nmethod_itr(ShenandoahCodeRoots::table()) {}
1089
1090 void work(uint worker_id) {
1231
1232 // If we are running in generational mode, this will also age active regions that
1233 // haven't been used for allocation.
1234 heap->update_heap_region_states(true /*concurrent*/);
1235
1236 heap->set_update_refs_in_progress(false);
1237 heap->set_has_forwarded_objects(false);
1238
1239 if (ShenandoahVerify) {
1240 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify);
1241 heap->verifier()->verify_after_update_refs(_generation);
1242 }
1243
1244 if (VerifyAfterGC) {
1245 Universe::verify();
1246 }
1247
1248 heap->rebuild_free_set(true /*concurrent*/);
1249 _generation->heuristics()->start_idle_span();
1250
1251 // Final pause: update GC barriers to idle state.
1252 ShenandoahCodeRoots::arm_nmethods();
1253
1254 {
1255 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
1256 heap->propagate_gc_state_to_all_threads();
1257 }
1258 }
1259
1260 void ShenandoahConcurrentGC::entry_final_roots() {
1261 const char* msg = final_roots_event_message();
1262 ShenandoahPausePhase gc_phase(msg, ShenandoahPhaseTimings::final_roots);
1263 EventMark em("%s", msg);
1264
1265 ShenandoahHeap::heap()->op_final_roots();
1266 }
1267
1268 void ShenandoahConcurrentGC::op_verify_final() {
1269 assert(ShenandoahVerify, "Should have been checked before");
1270 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1271 heap->verifier()->verify_after_gc(_generation);
1272 }
1273
1274 void ShenandoahConcurrentGC::op_cleanup_complete() {
1275 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1276 ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
1277 "cleanup complete.");
1278 ShenandoahHeap::heap()->recycle_trash();
1279 }
1280
1281 void ShenandoahConcurrentGC::op_reset_after_collect() {
1282 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1283 ShenandoahWorkerPolicy::calc_workers_for_conc_reset(),
1284 "reset after collection.");
1285
1344 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset", "");
1345 }
1346 }
1347
1348 const char* ShenandoahConcurrentGC::conc_reset_after_collect_event_message() const {
1349 if (ShenandoahHeap::heap()->unload_classes()) {
1350 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", " (unload classes)");
1351 } else {
1352 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent reset after collect", "");
1353 }
1354 }
1355
1356 const char* ShenandoahConcurrentGC::verify_final_event_message() const {
1357 if (ShenandoahHeap::heap()->unload_classes()) {
1358 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", " (unload classes)");
1359 } else {
1360 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Verify Final", "");
1361 }
1362 }
1363
1364 const char* ShenandoahConcurrentGC::final_roots_event_message() const {
1365 if (ShenandoahHeap::heap()->unload_classes()) {
1366 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Final Roots", " (unload classes)");
1367 } else {
1368 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Pause Final Roots", "");
1369 }
1370 }
1371
1372 const char* ShenandoahConcurrentGC::conc_weak_refs_event_message() const {
1373 if (ShenandoahHeap::heap()->unload_classes()) {
1374 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak references", " (unload classes)");
1375 } else {
1376 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak references", "");
1377 }
1378 }
1379
1380 const char* ShenandoahConcurrentGC::conc_weak_roots_event_message() const {
1381 if (ShenandoahHeap::heap()->unload_classes()) {
1382 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak roots", " (unload classes)");
1383 } else {
1384 SHENANDOAH_RETURN_EVENT_MESSAGE(_generation->type(), "Concurrent weak roots", "");
1385 }
1386 }
1387
1388 const char* ShenandoahConcurrentGC::conc_cleanup_event_message() const {
|