25 |
25 |
26 #include "classfile/classLoaderDataGraph.hpp" |
26 #include "classfile/classLoaderDataGraph.hpp" |
27 #include "classfile/stringTable.hpp" |
27 #include "classfile/stringTable.hpp" |
28 #include "classfile/systemDictionary.hpp" |
28 #include "classfile/systemDictionary.hpp" |
29 #include "code/codeCache.hpp" |
29 #include "code/codeCache.hpp" |
30 #include "gc/shenandoah/shenandoahClosures.inline.hpp" |
|
31 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" |
30 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" |
32 #include "gc/shenandoah/shenandoahHeap.hpp" |
31 #include "gc/shenandoah/shenandoahHeap.hpp" |
33 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
|
34 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" |
32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp" |
35 #include "gc/shenandoah/shenandoahStringDedup.hpp" |
33 #include "gc/shenandoah/shenandoahStringDedup.hpp" |
36 #include "gc/shenandoah/shenandoahTimingTracker.hpp" |
34 #include "gc/shenandoah/shenandoahTimingTracker.hpp" |
37 #include "gc/shenandoah/shenandoahUtils.hpp" |
|
38 #include "gc/shenandoah/shenandoahVMOperations.hpp" |
35 #include "gc/shenandoah/shenandoahVMOperations.hpp" |
39 #include "gc/shared/weakProcessor.inline.hpp" |
36 #include "jfr/jfr.hpp" |
40 #include "memory/allocation.inline.hpp" |
|
41 #include "memory/iterator.hpp" |
37 #include "memory/iterator.hpp" |
42 #include "memory/resourceArea.hpp" |
38 #include "memory/resourceArea.hpp" |
43 #include "memory/universe.hpp" |
39 #include "memory/universe.hpp" |
44 #include "runtime/thread.hpp" |
40 #include "runtime/thread.hpp" |
45 #include "services/management.hpp" |
41 #include "services/management.hpp" |
46 |
42 |
47 ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) : |
43 ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do, ShenandoahPhaseTimings::GCParPhases phase) : |
48 _claimed(false), _oops_do(oops_do), _phase(phase) { |
44 _oops_do(oops_do), _phase(phase) { |
49 } |
45 } |
50 |
46 |
51 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) { |
47 void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) { |
52 if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { |
48 if (_claimed.try_set()) { |
53 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
49 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
54 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); |
50 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); |
55 _oops_do(cl); |
51 _oops_do(cl); |
56 } |
52 } |
|
53 } |
|
54 |
|
55 // Overwrite the second argument for SD::oops_do, don't include vm global oop storage. |
|
56 static void system_dictionary_oops_do(OopClosure* cl) { |
|
57 SystemDictionary::oops_do(cl, false); |
57 } |
58 } |
58 |
59 |
59 ShenandoahSerialRoots::ShenandoahSerialRoots() : |
60 ShenandoahSerialRoots::ShenandoahSerialRoots() : |
60 _universe_root(&Universe::oops_do, ShenandoahPhaseTimings::UniverseRoots), |
61 _universe_root(&Universe::oops_do, ShenandoahPhaseTimings::UniverseRoots), |
61 _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots), |
62 _object_synchronizer_root(&ObjectSynchronizer::oops_do, ShenandoahPhaseTimings::ObjectSynchronizerRoots), |
62 _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots), |
63 _management_root(&Management::oops_do, ShenandoahPhaseTimings::ManagementRoots), |
63 _system_dictionary_root(&SystemDictionary::oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots), |
64 _system_dictionary_root(&system_dictionary_oops_do, ShenandoahPhaseTimings::SystemDictionaryRoots), |
64 _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots), |
65 _jvmti_root(&JvmtiExport::oops_do, ShenandoahPhaseTimings::JVMTIRoots) { |
65 _jni_handle_root(&JNIHandles::oops_do, ShenandoahPhaseTimings::JNIRoots) { |
|
66 } |
66 } |
67 |
67 |
68 void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) { |
68 void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) { |
69 _universe_root.oops_do(cl, worker_id); |
69 _universe_root.oops_do(cl, worker_id); |
70 _object_synchronizer_root.oops_do(cl, worker_id); |
70 _object_synchronizer_root.oops_do(cl, worker_id); |
71 _management_root.oops_do(cl, worker_id); |
71 _management_root.oops_do(cl, worker_id); |
72 _system_dictionary_root.oops_do(cl, worker_id); |
72 _system_dictionary_root.oops_do(cl, worker_id); |
73 _jvmti_root.oops_do(cl, worker_id); |
73 _jvmti_root.oops_do(cl, worker_id); |
74 _jni_handle_root.oops_do(cl, worker_id); |
74 } |
|
75 |
|
76 ShenandoahWeakSerialRoot::ShenandoahWeakSerialRoot(ShenandoahWeakSerialRoot::WeakOopsDo weak_oops_do, ShenandoahPhaseTimings::GCParPhases phase) : |
|
77 _weak_oops_do(weak_oops_do), _phase(phase) { |
|
78 } |
|
79 |
|
80 void ShenandoahWeakSerialRoot::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) { |
|
81 if (_claimed.try_set()) { |
|
82 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
|
83 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); |
|
84 _weak_oops_do(is_alive, keep_alive); |
|
85 } |
|
86 } |
|
87 |
|
88 #if INCLUDE_JVMTI |
|
89 ShenandoahJVMTIWeakRoot::ShenandoahJVMTIWeakRoot() : |
|
90 ShenandoahWeakSerialRoot(&JvmtiExport::weak_oops_do, ShenandoahPhaseTimings::JVMTIWeakRoots) { |
|
91 } |
|
92 #endif // INCLUDE_JVMTI |
|
93 |
|
94 #if INCLUDE_JFR |
|
95 ShenandoahJFRWeakRoot::ShenandoahJFRWeakRoot() : |
|
96 ShenandoahWeakSerialRoot(&Jfr::weak_oops_do, ShenandoahPhaseTimings::JFRWeakRoots) { |
|
97 } |
|
98 #endif // INCLUDE_JFR |
|
99 |
|
100 void ShenandoahSerialWeakRoots::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id) { |
|
101 JVMTI_ONLY(_jvmti_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);) |
|
102 JFR_ONLY(_jfr_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);) |
|
103 } |
|
104 |
|
105 void ShenandoahSerialWeakRoots::weak_oops_do(OopClosure* cl, uint worker_id) { |
|
106 AlwaysTrueClosure always_true; |
|
107 weak_oops_do(&always_true, cl, worker_id); |
75 } |
108 } |
76 |
109 |
77 ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) { |
110 ShenandoahThreadRoots::ShenandoahThreadRoots(bool is_par) : _is_par(is_par) { |
78 Threads::change_thread_claim_token(); |
111 Threads::change_thread_claim_token(); |
79 } |
112 } |
145 ShenandoahRootProcessor::~ShenandoahRootProcessor() { |
157 ShenandoahRootProcessor::~ShenandoahRootProcessor() { |
146 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); |
158 assert(SafepointSynchronize::is_at_safepoint(), "Must at safepoint"); |
147 _heap->phase_timings()->record_workers_end(_phase); |
159 _heap->phase_timings()->record_workers_end(_phase); |
148 } |
160 } |
149 |
161 |
150 ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase) : |
162 ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool include_concurrent_roots) : |
151 ShenandoahRootProcessor(phase), |
163 ShenandoahRootProcessor(phase), |
152 _thread_roots(n_workers > 1), |
164 _thread_roots(n_workers > 1), |
153 _weak_roots(n_workers) { |
165 _include_concurrent_roots(include_concurrent_roots) { |
154 } |
166 } |
155 |
167 |
156 void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { |
168 void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) { |
157 MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations); |
169 MarkingCodeBlobClosure blobsCl(oops, CodeBlobToOopClosure::FixRelocations); |
158 CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); |
|
159 CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds; |
|
160 |
|
161 AlwaysTrueClosure always_true; |
170 AlwaysTrueClosure always_true; |
162 |
171 |
163 _serial_roots.oops_do(oops, worker_id); |
172 _serial_roots.oops_do(oops, worker_id); |
|
173 _serial_weak_roots.weak_oops_do(oops, worker_id); |
|
174 if (_include_concurrent_roots) { |
|
175 CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong); |
|
176 _vm_roots.oops_do<OopClosure>(oops, worker_id); |
|
177 _cld_roots.cld_do(&clds, worker_id); |
|
178 _weak_roots.oops_do<OopClosure>(oops, worker_id); |
|
179 } |
164 |
180 |
165 _thread_roots.oops_do(oops, NULL, worker_id); |
181 _thread_roots.oops_do(oops, NULL, worker_id); |
166 _cld_roots.clds_do(&clds, &clds, worker_id); |
|
167 _code_roots.code_blobs_do(&blobsCl, worker_id); |
182 _code_roots.code_blobs_do(&blobsCl, worker_id); |
168 |
183 |
169 _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); |
|
170 _dedup_roots.oops_do(&always_true, oops, worker_id); |
184 _dedup_roots.oops_do(&always_true, oops, worker_id); |
171 } |
185 } |
172 |
186 |
173 ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase, bool update_code_cache) : |
187 ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) : |
174 ShenandoahRootProcessor(phase), |
188 ShenandoahRootProcessor(phase), |
175 _thread_roots(n_workers > 1), |
189 _thread_roots(n_workers > 1) { |
176 _weak_roots(n_workers), |
|
177 _update_code_cache(update_code_cache) { |
|
178 } |
190 } |
179 |
191 |
180 ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : |
192 ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : |
181 ShenandoahRootProcessor(phase), |
193 ShenandoahRootProcessor(phase), |
182 _thread_roots(n_workers > 1), |
194 _thread_roots(n_workers > 1) { |
183 _weak_roots(n_workers) { |
|
184 assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only"); |
195 assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Full GC only"); |
185 } |
196 } |
186 |
197 |
187 void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { |
198 void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) { |
188 CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations); |
199 CodeBlobToOopClosure adjust_code_closure(oops, CodeBlobToOopClosure::FixRelocations); |
189 CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong); |
200 CLDToOopClosure adjust_cld_closure(oops, ClassLoaderData::_claim_strong); |
190 AlwaysTrueClosure always_true; |
201 AlwaysTrueClosure always_true; |
191 |
202 |
192 _serial_roots.oops_do(oops, worker_id); |
203 _serial_roots.oops_do(oops, worker_id); |
|
204 _vm_roots.oops_do(oops, worker_id); |
193 |
205 |
194 _thread_roots.oops_do(oops, NULL, worker_id); |
206 _thread_roots.oops_do(oops, NULL, worker_id); |
195 _cld_roots.clds_do(&adjust_cld_closure, NULL, worker_id); |
207 _cld_roots.cld_do(&adjust_cld_closure, worker_id); |
196 _code_roots.code_blobs_do(&adjust_code_closure, worker_id); |
208 _code_roots.code_blobs_do(&adjust_code_closure, worker_id); |
197 |
209 |
198 _weak_roots.oops_do<AlwaysTrueClosure, OopClosure>(&always_true, oops, worker_id); |
210 _serial_weak_roots.weak_oops_do(oops, worker_id); |
|
211 _weak_roots.oops_do<OopClosure>(oops, worker_id); |
199 _dedup_roots.oops_do(&always_true, oops, worker_id); |
212 _dedup_roots.oops_do(&always_true, oops, worker_id); |
200 } |
213 } |
|
214 |
|
215 ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() : |
|
216 ShenandoahRootProcessor(ShenandoahPhaseTimings::_num_phases), |
|
217 _thread_roots(false /*is par*/) { |
|
218 } |
|
219 |
|
220 void ShenandoahHeapIterationRootScanner::roots_do(OopClosure* oops) { |
|
221 assert(Thread::current()->is_VM_thread(), "Only by VM thread"); |
|
222 // Must use _claim_none to avoid interfering with concurrent CLDG iteration |
|
223 CLDToOopClosure clds(oops, ClassLoaderData::_claim_none); |
|
224 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); |
|
225 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); |
|
226 AlwaysTrueClosure always_true; |
|
227 ResourceMark rm; |
|
228 |
|
229 _serial_roots.oops_do(oops, 0); |
|
230 _vm_roots.oops_do(oops, 0); |
|
231 _cld_roots.cld_do(&clds, 0); |
|
232 _thread_roots.threads_do(&tc_cl, 0); |
|
233 _code_roots.code_blobs_do(&code, 0); |
|
234 |
|
235 _serial_weak_roots.weak_oops_do(oops, 0); |
|
236 _weak_roots.oops_do<OopClosure>(oops, 0); |
|
237 _dedup_roots.oops_do(&always_true, oops, 0); |
|
238 } |
|
239 |
|
240 void ShenandoahHeapIterationRootScanner::strong_roots_do(OopClosure* oops) { |
|
241 assert(Thread::current()->is_VM_thread(), "Only by VM thread"); |
|
242 // Must use _claim_none to avoid interfering with concurrent CLDG iteration |
|
243 CLDToOopClosure clds(oops, ClassLoaderData::_claim_none); |
|
244 MarkingCodeBlobClosure code(oops, !CodeBlobToOopClosure::FixRelocations); |
|
245 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, &code, NULL); |
|
246 ResourceMark rm; |
|
247 |
|
248 _serial_roots.oops_do(oops, 0); |
|
249 _vm_roots.oops_do(oops, 0); |
|
250 _cld_roots.always_strong_cld_do(&clds, 0); |
|
251 _thread_roots.threads_do(&tc_cl, 0); |
|
252 } |