35 #include "gc/shenandoah/shenandoahForwarding.inline.hpp"
36 #include "gc/shenandoah/shenandoahFreeSet.hpp"
37 #include "gc/shenandoah/shenandoahGeneration.hpp"
38 #include "gc/shenandoah/shenandoahGenerationalHeap.hpp"
39 #include "gc/shenandoah/shenandoahLock.hpp"
40 #include "gc/shenandoah/shenandoahMark.inline.hpp"
41 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
42 #include "gc/shenandoah/shenandoahOldGeneration.hpp"
43 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
44 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
45 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
46 #include "gc/shenandoah/shenandoahStackWatermark.hpp"
47 #include "gc/shenandoah/shenandoahUtils.hpp"
48 #include "gc/shenandoah/shenandoahVerifier.hpp"
49 #include "gc/shenandoah/shenandoahVMOperations.hpp"
50 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
51 #include "gc/shenandoah/shenandoahWorkGroup.hpp"
52 #include "gc/shenandoah/shenandoahYoungGeneration.hpp"
53 #include "memory/allocation.hpp"
54 #include "prims/jvmtiTagMap.hpp"
55 #include "runtime/vmThread.hpp"
56 #include "utilities/events.hpp"
57
58 // Breakpoint support
59 class ShenandoahBreakpointGCScope : public StackObj {
60 private:
61 const GCCause::Cause _cause;
62 public:
63 ShenandoahBreakpointGCScope(GCCause::Cause cause) : _cause(cause) {
64 if (cause == GCCause::_wb_breakpoint) {
65 ShenandoahBreakpoint::start_gc();
66 ShenandoahBreakpoint::at_before_gc();
67 }
68 }
69
70 ~ShenandoahBreakpointGCScope() {
71 if (_cause == GCCause::_wb_breakpoint) {
72 ShenandoahBreakpoint::at_after_gc();
73 }
74 }
199
200 // Perform concurrent class unloading before any regions get recycled. Class unloading may
201 // need to inspect unmarked objects in trashed regions.
202 if (heap->unload_classes()) {
203 entry_class_unloading();
204 }
205
206 // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
207 // the space. This would be the last action if there is nothing to evacuate. Note that
208 // we will not age young-gen objects in the case that we skip evacuation.
209 entry_cleanup_early();
210
211 // Processing strong roots
212 // This may be skipped if there is nothing to update/evacuate.
213 // If so, strong_root_in_progress would be unset.
214 if (heap->is_concurrent_strong_root_in_progress()) {
215 entry_strong_roots();
216 }
217
218 // Roots processing is complete, put the weak roots flag down.
219 entry_final_roots();
220
221 // Continue the cycle with evacuation and optional update-refs.
222 // This may be skipped if there is nothing to evacuate.
223 // If so, evac_in_progress would be unset by collection set preparation code.
224 if (heap->is_evacuation_in_progress()) {
225 // Concurrently evacuate
226 entry_evacuate();
227 if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) {
228 return false;
229 }
230
231 // Perform update-refs phase.
232 entry_concurrent_update_refs_prepare(heap);
233
234 if (ShenandoahHeap::heap()->mode()->is_generational()) {
235 entry_update_card_table();
236 }
237
238 if (ShenandoahVerify) {
239 vmop_entry_init_update_refs();
348 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
349 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_update_refs_gross);
350
351 heap->try_inject_alloc_failure();
352 heap->try_inject_pin();
353 VM_ShenandoahInitUpdateRefs op(this);
354 VMThread::execute(&op);
355 }
356
357 void ShenandoahConcurrentGC::vmop_entry_final_update_refs() {
358 ShenandoahHeap* const heap = ShenandoahHeap::heap();
359 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
360 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_gross);
361
362 heap->try_inject_alloc_failure();
363 heap->try_inject_pin();
364 VM_ShenandoahFinalUpdateRefs op(this);
365 VMThread::execute(&op);
366 }
367
368 void ShenandoahConcurrentGC::vmop_entry_final_verify() {
369 ShenandoahHeap* const heap = ShenandoahHeap::heap();
370 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
371 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_verify_gross);
372
373 // This phase does not use workers, no need for setup
374 heap->try_inject_alloc_failure();
375 heap->try_inject_pin();
376 VM_ShenandoahFinalVerify op(this);
377 VMThread::execute(&op);
378 }
379
380 void ShenandoahConcurrentGC::entry_init_mark() {
381 ShenandoahHeap* const heap = ShenandoahHeap::heap();
382 assert(!heap->has_forwarded_objects(), "Should not have forwarded objects here");
383
384 SHENANDOAH_EVENT_MESSAGE(msg, _generation->type(), "Pause Init Mark", "");
385 ShenandoahPauseSubphase gc_phase(msg, ShenandoahPhaseTimings::init_mark);
386 EventMark em("%s", msg);
387
760 // Update region state for both young and old regions
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 ShenandoahStackWatermark::change_epoch_id();
782
783 {
784 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_propagate_gc_state);
785 heap->propagate_gc_state_to_all_threads();
786 }
787 }
788
789 void ShenandoahConcurrentGC::op_mark_roots() {
790 _mark.mark_concurrent_roots();
791 }
792
793 void ShenandoahConcurrentGC::op_mark() {
794 _mark.concurrent_mark();
795 }
796
797 void ShenandoahConcurrentGC::op_final_mark() {
798 ShenandoahHeap* const heap = ShenandoahHeap::heap();
799 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should be at safepoint");
800 assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
801
817
818 // Has to be done after cset selection
819 heap->prepare_concurrent_roots();
820
821 if (!heap->collection_set()->is_empty()) {
822 LogTarget(Debug, gc, cset) lt;
823 if (lt.is_enabled()) {
824 ResourceMark rm;
825 LogStream ls(lt);
826 heap->collection_set()->print_on(&ls);
827 }
828
829 if (ShenandoahVerify) {
830 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
831 heap->verifier()->verify_before_evacuation(_generation);
832 }
833
834 heap->set_evacuation_in_progress(true);
835 // From here on, we need to update references.
836 heap->set_has_forwarded_objects(true);
837
838 // Arm nmethods/stack for concurrent processing
839 ShenandoahCodeRoots::arm_nmethods();
840 ShenandoahStackWatermark::change_epoch_id();
841
842 } else {
843 if (ShenandoahVerify) {
844 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
845 if (has_in_place_promotions(heap)) {
846 heap->verifier()->verify_after_concmark_with_promotions(_generation);
847 } else {
848 heap->verifier()->verify_after_concmark(_generation);
849 }
850 }
851 }
852 }
853
854 {
855 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state);
856 heap->propagate_gc_state_to_all_threads();
857 }
858 }
859
860 bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) {
861 return heap->mode()->is_generational() && heap->old_generation()->has_in_place_promotions();
862 }
863
864 class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure {
865 private:
866 OopClosure* const _oops;
867 public:
868 explicit ShenandoahConcurrentEvacThreadClosure(OopClosure* oops) : _oops(oops) {}
869
870 void do_thread(Thread* thread) override {
871 JavaThread* const jt = JavaThread::cast(thread);
872 StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc);
873 }
1053 }
1054
1055 void ShenandoahConcurrentGC::op_class_unloading() {
1056 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1057 assert (heap->is_concurrent_weak_root_in_progress() &&
1058 heap->unload_classes(),
1059 "Checked by caller");
1060 heap->do_class_unloading();
1061 }
1062
1063 class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure {
1064 private:
1065 ShenandoahEvacuateUpdateMetadataClosure _cl;
1066
1067 public:
1068 ShenandoahEvacUpdateCodeCacheClosure() : _cl() {}
1069
1070 void do_nmethod(nmethod* n) {
1071 ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
1072 ShenandoahNMethodLocker locker(data->lock());
1073 data->oops_do(&_cl, /* fix_relocations = */ true);
1074 ShenandoahNMethod::disarm_nmethod(n);
1075 }
1076 };
1077
1078 class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
1079 private:
1080 ShenandoahPhaseTimings::Phase _phase;
1081 ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
1082 ShenandoahClassLoaderDataRoots<true /*concurrent*/>
1083 _cld_roots;
1084 ShenandoahConcurrentNMethodIterator _nmethod_itr;
1085
1086 public:
1087 ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
1088 WorkerTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
1089 _phase(phase),
1090 _vm_roots(phase),
1091 _cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
1092 _nmethod_itr(ShenandoahCodeRoots::table()) {}
1093
1094 void work(uint worker_id) {
1235
1236 // If we are running in generational mode, this will also age active regions that
1237 // haven't been used for allocation.
1238 heap->update_heap_region_states(true /*concurrent*/);
1239
1240 heap->set_update_refs_in_progress(false);
1241 heap->set_has_forwarded_objects(false);
1242
1243 if (ShenandoahVerify) {
1244 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify);
1245 heap->verifier()->verify_after_update_refs(_generation);
1246 }
1247
1248 if (VerifyAfterGC) {
1249 Universe::verify();
1250 }
1251
1252 heap->rebuild_free_set(true /*concurrent*/);
1253 _generation->heuristics()->start_idle_span();
1254
1255 {
1256 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
1257 heap->propagate_gc_state_to_all_threads();
1258 }
1259 }
1260
1261 void ShenandoahConcurrentGC::entry_final_roots() {
1262 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1263 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
1264 SHENANDOAH_EVENT_MESSAGE(msg, _generation->type(), "Concurrent final roots", "");
1265 ShenandoahConcurrentSubphase gc_phase(msg, ShenandoahPhaseTimings::conc_final_roots);
1266 EventMark em("%s", msg);
1267
1268 heap->concurrent_final_roots();
1269 }
1270
1271 void ShenandoahConcurrentGC::op_verify_final() {
1272 assert(ShenandoahVerify, "Should have been checked before");
1273 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1274 heap->verifier()->verify_after_gc(_generation);
1275 }
1276
1277 void ShenandoahConcurrentGC::op_cleanup_complete() {
1278 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1279 ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
1280 "cleanup complete.");
1281 ShenandoahHeap::heap()->recycle_trash();
1282 }
1283
1284 void ShenandoahConcurrentGC::op_reset_after_collect() {
1285 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1286 ShenandoahWorkerPolicy::calc_workers_for_conc_reset(),
1287 "reset after collection.");
1288
|
35 #include "gc/shenandoah/shenandoahForwarding.inline.hpp"
36 #include "gc/shenandoah/shenandoahFreeSet.hpp"
37 #include "gc/shenandoah/shenandoahGeneration.hpp"
38 #include "gc/shenandoah/shenandoahGenerationalHeap.hpp"
39 #include "gc/shenandoah/shenandoahLock.hpp"
40 #include "gc/shenandoah/shenandoahMark.inline.hpp"
41 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
42 #include "gc/shenandoah/shenandoahOldGeneration.hpp"
43 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
44 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
45 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
46 #include "gc/shenandoah/shenandoahStackWatermark.hpp"
47 #include "gc/shenandoah/shenandoahUtils.hpp"
48 #include "gc/shenandoah/shenandoahVerifier.hpp"
49 #include "gc/shenandoah/shenandoahVMOperations.hpp"
50 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
51 #include "gc/shenandoah/shenandoahWorkGroup.hpp"
52 #include "gc/shenandoah/shenandoahYoungGeneration.hpp"
53 #include "memory/allocation.hpp"
54 #include "prims/jvmtiTagMap.hpp"
55 #include "runtime/icache.hpp"
56 #include "runtime/vmThread.hpp"
57 #include "utilities/events.hpp"
58
59 // Breakpoint support
60 class ShenandoahBreakpointGCScope : public StackObj {
61 private:
62 const GCCause::Cause _cause;
63 public:
64 ShenandoahBreakpointGCScope(GCCause::Cause cause) : _cause(cause) {
65 if (cause == GCCause::_wb_breakpoint) {
66 ShenandoahBreakpoint::start_gc();
67 ShenandoahBreakpoint::at_before_gc();
68 }
69 }
70
71 ~ShenandoahBreakpointGCScope() {
72 if (_cause == GCCause::_wb_breakpoint) {
73 ShenandoahBreakpoint::at_after_gc();
74 }
75 }
200
201 // Perform concurrent class unloading before any regions get recycled. Class unloading may
202 // need to inspect unmarked objects in trashed regions.
203 if (heap->unload_classes()) {
204 entry_class_unloading();
205 }
206
207 // Final mark might have reclaimed some immediate garbage, kick cleanup to reclaim
208 // the space. This would be the last action if there is nothing to evacuate. Note that
209 // we will not age young-gen objects in the case that we skip evacuation.
210 entry_cleanup_early();
211
212 // Processing strong roots
213 // This may be skipped if there is nothing to update/evacuate.
214 // If so, strong_root_in_progress would be unset.
215 if (heap->is_concurrent_strong_root_in_progress()) {
216 entry_strong_roots();
217 }
218
219 // Roots processing is complete, put the weak roots flag down.
220 vmop_entry_final_roots();
221
222 // Continue the cycle with evacuation and optional update-refs.
223 // This may be skipped if there is nothing to evacuate.
224 // If so, evac_in_progress would be unset by collection set preparation code.
225 if (heap->is_evacuation_in_progress()) {
226 // Concurrently evacuate
227 entry_evacuate();
228 if (check_cancellation_and_abort(ShenandoahDegenPoint::_degenerated_evac)) {
229 return false;
230 }
231
232 // Perform update-refs phase.
233 entry_concurrent_update_refs_prepare(heap);
234
235 if (ShenandoahHeap::heap()->mode()->is_generational()) {
236 entry_update_card_table();
237 }
238
239 if (ShenandoahVerify) {
240 vmop_entry_init_update_refs();
349 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
350 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_update_refs_gross);
351
352 heap->try_inject_alloc_failure();
353 heap->try_inject_pin();
354 VM_ShenandoahInitUpdateRefs op(this);
355 VMThread::execute(&op);
356 }
357
358 void ShenandoahConcurrentGC::vmop_entry_final_update_refs() {
359 ShenandoahHeap* const heap = ShenandoahHeap::heap();
360 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
361 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_gross);
362
363 heap->try_inject_alloc_failure();
364 heap->try_inject_pin();
365 VM_ShenandoahFinalUpdateRefs op(this);
366 VMThread::execute(&op);
367 }
368
369 void ShenandoahConcurrentGC::vmop_entry_final_roots() {
370 ShenandoahHeap* const heap = ShenandoahHeap::heap();
371 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
372 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_roots_gross);
373
374 // This phase does not use workers, no need for setup
375 heap->try_inject_pin();
376 VM_ShenandoahFinalRoots op(this);
377 VMThread::execute(&op);
378 }
379
380 void ShenandoahConcurrentGC::vmop_entry_final_verify() {
381 ShenandoahHeap* const heap = ShenandoahHeap::heap();
382 TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters());
383 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_verify_gross);
384
385 // This phase does not use workers, no need for setup
386 heap->try_inject_alloc_failure();
387 heap->try_inject_pin();
388 VM_ShenandoahFinalVerify op(this);
389 VMThread::execute(&op);
390 }
391
392 void ShenandoahConcurrentGC::entry_init_mark() {
393 ShenandoahHeap* const heap = ShenandoahHeap::heap();
394 assert(!heap->has_forwarded_objects(), "Should not have forwarded objects here");
395
396 SHENANDOAH_EVENT_MESSAGE(msg, _generation->type(), "Pause Init Mark", "");
397 ShenandoahPauseSubphase gc_phase(msg, ShenandoahPhaseTimings::init_mark);
398 EventMark em("%s", msg);
399
772 // Update region state for both young and old regions
773 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
774 ShenandoahInitMarkUpdateRegionStateClosure cl;
775 heap->parallel_heap_region_iterate(&cl);
776 heap->old_generation()->ref_processor()->reset_thread_locals();
777 } else {
778 // Update region state for only young regions
779 ShenandoahGCPhase phase(ShenandoahPhaseTimings::init_update_region_states);
780 ShenandoahInitMarkUpdateRegionStateClosure cl;
781 _generation->parallel_heap_region_iterate(&cl);
782 }
783
784 // Weak reference processing
785 ShenandoahReferenceProcessor* rp = _generation->ref_processor();
786 rp->reset_thread_locals();
787
788 // Make above changes visible to worker threads
789 OrderAccess::fence();
790
791 // Arm nmethods/stack for concurrent processing
792 CodeCache::arm_all_nmethods();
793
794 {
795 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::init_propagate_gc_state);
796 heap->propagate_gc_state_to_all_threads();
797 }
798 }
799
800 void ShenandoahConcurrentGC::op_mark_roots() {
801 _mark.mark_concurrent_roots();
802 }
803
804 void ShenandoahConcurrentGC::op_mark() {
805 _mark.concurrent_mark();
806 }
807
808 void ShenandoahConcurrentGC::op_final_mark() {
809 ShenandoahHeap* const heap = ShenandoahHeap::heap();
810 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Should be at safepoint");
811 assert(!heap->has_forwarded_objects(), "No forwarded objects on this path");
812
828
829 // Has to be done after cset selection
830 heap->prepare_concurrent_roots();
831
832 if (!heap->collection_set()->is_empty()) {
833 LogTarget(Debug, gc, cset) lt;
834 if (lt.is_enabled()) {
835 ResourceMark rm;
836 LogStream ls(lt);
837 heap->collection_set()->print_on(&ls);
838 }
839
840 if (ShenandoahVerify) {
841 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
842 heap->verifier()->verify_before_evacuation(_generation);
843 }
844
845 heap->set_evacuation_in_progress(true);
846 // From here on, we need to update references.
847 heap->set_has_forwarded_objects(true);
848 } else {
849 if (ShenandoahVerify) {
850 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify);
851 if (has_in_place_promotions(heap)) {
852 heap->verifier()->verify_after_concmark_with_promotions(_generation);
853 } else {
854 heap->verifier()->verify_after_concmark(_generation);
855 }
856 }
857 }
858 }
859
860 // Arm nmethods/stack for concurrent processing
861 CodeCache::arm_all_nmethods();
862
863 {
864 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_mark_propagate_gc_state);
865 heap->propagate_gc_state_to_all_threads();
866 }
867 }
868
869 bool ShenandoahConcurrentGC::has_in_place_promotions(ShenandoahHeap* heap) {
870 return heap->mode()->is_generational() && heap->old_generation()->has_in_place_promotions();
871 }
872
873 class ShenandoahConcurrentEvacThreadClosure : public ThreadClosure {
874 private:
875 OopClosure* const _oops;
876 public:
877 explicit ShenandoahConcurrentEvacThreadClosure(OopClosure* oops) : _oops(oops) {}
878
879 void do_thread(Thread* thread) override {
880 JavaThread* const jt = JavaThread::cast(thread);
881 StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc);
882 }
1062 }
1063
1064 void ShenandoahConcurrentGC::op_class_unloading() {
1065 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1066 assert (heap->is_concurrent_weak_root_in_progress() &&
1067 heap->unload_classes(),
1068 "Checked by caller");
1069 heap->do_class_unloading();
1070 }
1071
1072 class ShenandoahEvacUpdateCodeCacheClosure : public NMethodClosure {
1073 private:
1074 ShenandoahEvacuateUpdateMetadataClosure _cl;
1075
1076 public:
1077 ShenandoahEvacUpdateCodeCacheClosure() : _cl() {}
1078
1079 void do_nmethod(nmethod* n) {
1080 ShenandoahNMethod* data = ShenandoahNMethod::gc_data(n);
1081 ShenandoahNMethodLocker locker(data->lock());
1082 ICacheInvalidationContext icic;
1083 data->oops_do(&_cl, /* fix_relocations = */ true, &icic);
1084 }
1085 };
1086
1087 class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
1088 private:
1089 ShenandoahPhaseTimings::Phase _phase;
1090 ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
1091 ShenandoahClassLoaderDataRoots<true /*concurrent*/>
1092 _cld_roots;
1093 ShenandoahConcurrentNMethodIterator _nmethod_itr;
1094
1095 public:
1096 ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
1097 WorkerTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
1098 _phase(phase),
1099 _vm_roots(phase),
1100 _cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
1101 _nmethod_itr(ShenandoahCodeRoots::table()) {}
1102
1103 void work(uint worker_id) {
1244
1245 // If we are running in generational mode, this will also age active regions that
1246 // haven't been used for allocation.
1247 heap->update_heap_region_states(true /*concurrent*/);
1248
1249 heap->set_update_refs_in_progress(false);
1250 heap->set_has_forwarded_objects(false);
1251
1252 if (ShenandoahVerify) {
1253 ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify);
1254 heap->verifier()->verify_after_update_refs(_generation);
1255 }
1256
1257 if (VerifyAfterGC) {
1258 Universe::verify();
1259 }
1260
1261 heap->rebuild_free_set(true /*concurrent*/);
1262 _generation->heuristics()->start_idle_span();
1263
1264 // Final pause: update GC barriers to idle state.
1265 CodeCache::arm_all_nmethods();
1266
1267 {
1268 ShenandoahTimingsTracker timing(ShenandoahPhaseTimings::final_update_refs_propagate_gc_state);
1269 heap->propagate_gc_state_to_all_threads();
1270 }
1271 }
1272
1273 void ShenandoahConcurrentGC::entry_final_roots() {
1274 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1275 SHENANDOAH_EVENT_MESSAGE(msg, _generation->type(), "Pause Final Roots", "");
1276 ShenandoahPauseSubphase gc_phase(msg, ShenandoahPhaseTimings::final_roots);
1277 EventMark em("%s", msg);
1278
1279 heap->op_final_roots();
1280 }
1281
1282 void ShenandoahConcurrentGC::op_verify_final() {
1283 assert(ShenandoahVerify, "Should have been checked before");
1284 ShenandoahHeap* const heap = ShenandoahHeap::heap();
1285 heap->verifier()->verify_after_gc(_generation);
1286 }
1287
1288 void ShenandoahConcurrentGC::op_cleanup_complete() {
1289 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1290 ShenandoahWorkerPolicy::calc_workers_for_conc_cleanup(),
1291 "cleanup complete.");
1292 ShenandoahHeap::heap()->recycle_trash();
1293 }
1294
1295 void ShenandoahConcurrentGC::op_reset_after_collect() {
1296 ShenandoahWorkerScope scope(ShenandoahHeap::heap()->workers(),
1297 ShenandoahWorkerPolicy::calc_workers_for_conc_reset(),
1298 "reset after collection.");
1299
|