22 */ |
22 */ |
23 |
23 |
24 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |
24 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |
25 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |
25 #define SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |
26 |
26 |
|
27 #include "classfile/classLoaderDataGraph.hpp" |
|
28 #include "classfile/stringTable.hpp" |
|
29 #include "classfile/systemDictionary.hpp" |
|
30 #include "gc/shared/oopStorageParState.inline.hpp" |
27 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
31 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
28 #include "gc/shenandoah/shenandoahRootProcessor.hpp" |
32 #include "gc/shenandoah/shenandoahRootProcessor.hpp" |
29 #include "gc/shenandoah/shenandoahTimingTracker.hpp" |
33 #include "gc/shenandoah/shenandoahTimingTracker.hpp" |
30 #include "gc/shenandoah/shenandoahUtils.hpp" |
34 #include "gc/shenandoah/shenandoahUtils.hpp" |
31 #include "memory/resourceArea.hpp" |
35 #include "memory/resourceArea.hpp" |
32 |
36 #include "prims/resolvedMethodTable.hpp" |
33 template <typename IsAlive, typename KeepAlive> |
37 #include "runtime/safepoint.hpp" |
34 void ShenandoahWeakRoots::oops_do(IsAlive* is_alive, KeepAlive* keep_alive, uint worker_id) { |
38 |
35 _task.work<IsAlive, KeepAlive>(worker_id, is_alive, keep_alive); |
39 template <bool CONCURRENT> |
|
40 inline ShenandoahVMRoot<CONCURRENT>::ShenandoahVMRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : |
|
41 _itr(storage), _phase(phase) { |
|
42 } |
|
43 |
|
44 template <bool CONCURRENT> |
|
45 template <typename Closure> |
|
46 inline void ShenandoahVMRoot<CONCURRENT>::oops_do(Closure* cl, uint worker_id) { |
|
47 if (CONCURRENT) { |
|
48 _itr.oops_do(cl); |
|
49 } else { |
|
50 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
|
51 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); |
|
52 _itr.oops_do(cl); |
|
53 } |
|
54 } |
|
55 |
|
56 template <bool CONCURRENT> |
|
57 inline ShenandoahWeakRoot<CONCURRENT>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : |
|
58 ShenandoahVMRoot<CONCURRENT>(storage, phase) { |
|
59 } |
|
60 |
|
61 inline ShenandoahWeakRoot<false>::ShenandoahWeakRoot(OopStorage* storage, ShenandoahPhaseTimings::GCParPhases phase) : |
|
62 _itr(storage), _phase(phase) { |
|
63 } |
|
64 |
|
65 template <typename IsAliveClosure, typename KeepAliveClosure> |
|
66 void ShenandoahWeakRoot<false /* concurrent */>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) { |
|
67 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
|
68 ShenandoahWorkerTimingsTracker timer(worker_times, _phase, worker_id); |
|
69 _itr.weak_oops_do(is_alive, keep_alive); |
|
70 } |
|
71 |
|
72 template <bool CONCURRENT> |
|
73 ShenandoahWeakRoots<CONCURRENT>::ShenandoahWeakRoots() : |
|
74 _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots), |
|
75 _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots), |
|
76 _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots), |
|
77 _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) { |
|
78 } |
|
79 |
|
80 template <bool CONCURRENT> |
|
81 template <typename Closure> |
|
82 void ShenandoahWeakRoots<CONCURRENT>::oops_do(Closure* cl, uint worker_id) { |
|
83 _jni_roots.oops_do(cl, worker_id); |
|
84 _string_table_roots.oops_do(cl, worker_id); |
|
85 _resolved_method_table_roots.oops_do(cl, worker_id); |
|
86 _vm_roots.oops_do(cl, worker_id); |
|
87 } |
|
88 |
|
89 inline ShenandoahWeakRoots<false /* concurrent */>::ShenandoahWeakRoots() : |
|
90 _jni_roots(OopStorageSet::jni_weak(), ShenandoahPhaseTimings::JNIWeakRoots), |
|
91 _string_table_roots(OopStorageSet::string_table_weak(), ShenandoahPhaseTimings::StringTableRoots), |
|
92 _resolved_method_table_roots(OopStorageSet::resolved_method_table_weak(), ShenandoahPhaseTimings::ResolvedMethodTableRoots), |
|
93 _vm_roots(OopStorageSet::vm_weak(), ShenandoahPhaseTimings::VMWeakRoots) { |
|
94 } |
|
95 |
|
96 template <typename IsAliveClosure, typename KeepAliveClosure> |
|
97 void ShenandoahWeakRoots<false /* concurrent*/>::weak_oops_do(IsAliveClosure* is_alive, KeepAliveClosure* keep_alive, uint worker_id) { |
|
98 _jni_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
|
99 _string_table_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
|
100 _resolved_method_table_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
|
101 _vm_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
|
102 } |
|
103 |
|
104 template <typename Closure> |
|
105 void ShenandoahWeakRoots<false /* concurrent */>::oops_do(Closure* cl, uint worker_id) { |
|
106 AlwaysTrueClosure always_true; |
|
107 weak_oops_do<AlwaysTrueClosure, Closure>(&always_true, cl, worker_id); |
|
108 } |
|
109 |
|
110 template <bool CONCURRENT> |
|
111 ShenandoahVMRoots<CONCURRENT>::ShenandoahVMRoots() : |
|
112 _jni_handle_roots(OopStorageSet::jni_global(), ShenandoahPhaseTimings::JNIRoots), |
|
113 _vm_global_roots(OopStorageSet::vm_global(), ShenandoahPhaseTimings::VMGlobalRoots) { |
|
114 } |
|
115 |
|
116 template <bool CONCURRENT> |
|
117 template <typename T> |
|
118 void ShenandoahVMRoots<CONCURRENT>::oops_do(T* cl, uint worker_id) { |
|
119 _jni_handle_roots.oops_do(cl, worker_id); |
|
120 _vm_global_roots.oops_do(cl, worker_id); |
|
121 } |
|
122 |
|
123 template <bool CONCURRENT, bool SINGLE_THREADED> |
|
124 ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::ShenandoahClassLoaderDataRoots() { |
|
125 if (!SINGLE_THREADED) { |
|
126 ClassLoaderDataGraph::clear_claimed_marks(); |
|
127 } |
|
128 if (CONCURRENT) { |
|
129 ClassLoaderDataGraph_lock->lock(); |
|
130 } |
|
131 } |
|
132 |
|
133 template <bool CONCURRENT, bool SINGLE_THREADED> |
|
134 ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::~ShenandoahClassLoaderDataRoots() { |
|
135 if (CONCURRENT) { |
|
136 ClassLoaderDataGraph_lock->unlock(); |
|
137 } |
|
138 } |
|
139 |
|
140 |
|
141 template <bool CONCURRENT, bool SINGLE_THREADED> |
|
142 void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::always_strong_cld_do(CLDClosure* clds, uint worker_id) { |
|
143 if (SINGLE_THREADED) { |
|
144 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
|
145 assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread"); |
|
146 ClassLoaderDataGraph::always_strong_cld_do(clds); |
|
147 } else if (CONCURRENT) { |
|
148 ClassLoaderDataGraph::always_strong_cld_do(clds); |
|
149 } else { |
|
150 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
|
151 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); |
|
152 ClassLoaderDataGraph::always_strong_cld_do(clds); |
|
153 } |
|
154 } |
|
155 |
|
156 template <bool CONCURRENT, bool SINGLE_THREADED> |
|
157 void ShenandoahClassLoaderDataRoots<CONCURRENT, SINGLE_THREADED>::cld_do(CLDClosure* clds, uint worker_id) { |
|
158 if (SINGLE_THREADED) { |
|
159 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); |
|
160 assert(Thread::current()->is_VM_thread(), "Single threaded CLDG iteration can only be done by VM thread"); |
|
161 ClassLoaderDataGraph::cld_do(clds); |
|
162 } else if (CONCURRENT) { |
|
163 ClassLoaderDataGraph::cld_do(clds); |
|
164 } else { |
|
165 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times(); |
|
166 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id); |
|
167 ClassLoaderDataGraph::cld_do(clds); |
|
168 } |
36 } |
169 } |
37 |
170 |
38 template <typename ITR> |
171 template <typename ITR> |
39 ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() { |
172 ShenandoahCodeCacheRoots<ITR>::ShenandoahCodeCacheRoots() { |
40 nmethod::oops_do_marking_prologue(); |
173 nmethod::oops_do_marking_prologue(); |
91 |
224 |
92 template <typename ITR> |
225 template <typename ITR> |
93 void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) { |
226 void ShenandoahRootScanner<ITR>::roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure *tc) { |
94 assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint() || |
227 assert(!ShenandoahSafepoint::is_at_shenandoah_safepoint() || |
95 !ShenandoahHeap::heap()->unload_classes() || |
228 !ShenandoahHeap::heap()->unload_classes() || |
96 ShenandoahHeap::heap()->heuristics()->can_do_traversal_gc(), |
229 ShenandoahHeap::heap()->is_traversal_mode(), |
97 "Expect class unloading or traversal when Shenandoah cycle is running"); |
230 "Expect class unloading or traversal when Shenandoah cycle is running"); |
98 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); |
231 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); |
99 ResourceMark rm; |
232 ResourceMark rm; |
100 |
233 |
101 _serial_roots.oops_do(oops, worker_id); |
234 _serial_roots.oops_do(oops, worker_id); |
102 _cld_roots.clds_do(clds, clds, worker_id); |
235 _vm_roots.oops_do(oops, worker_id); |
|
236 |
|
237 if (clds != NULL) { |
|
238 _cld_roots.cld_do(clds, worker_id); |
|
239 } else { |
|
240 assert(ShenandoahHeap::heap()->is_concurrent_traversal_in_progress(), "Only possible with traversal GC"); |
|
241 } |
|
242 |
103 _thread_roots.threads_do(&tc_cl, worker_id); |
243 _thread_roots.threads_do(&tc_cl, worker_id); |
104 |
244 |
105 // With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, |
245 // With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, |
106 // and instead do that in concurrent phase under the relevant lock. This saves init mark |
246 // and instead do that in concurrent phase under the relevant lock. This saves init mark |
107 // pause time. |
247 // pause time. |
115 assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); |
255 assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); |
116 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); |
256 ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); |
117 ResourceMark rm; |
257 ResourceMark rm; |
118 |
258 |
119 _serial_roots.oops_do(oops, worker_id); |
259 _serial_roots.oops_do(oops, worker_id); |
120 _cld_roots.clds_do(clds, NULL, worker_id); |
260 _vm_roots.oops_do(oops, worker_id); |
|
261 _cld_roots.always_strong_cld_do(clds, worker_id); |
121 _thread_roots.threads_do(&tc_cl, worker_id); |
262 _thread_roots.threads_do(&tc_cl, worker_id); |
122 } |
263 } |
123 |
264 |
124 template <typename IsAlive, typename KeepAlive> |
265 template <typename IsAlive, typename KeepAlive> |
125 void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) { |
266 void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAlive* keep_alive) { |
126 CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations); |
267 CodeBlobToOopClosure update_blobs(keep_alive, CodeBlobToOopClosure::FixRelocations); |
127 CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong); |
268 CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong); |
128 CLDToOopClosure* weak_clds = ShenandoahHeap::heap()->unload_classes() ? NULL : &clds; |
|
129 |
269 |
130 _serial_roots.oops_do(keep_alive, worker_id); |
270 _serial_roots.oops_do(keep_alive, worker_id); |
|
271 _vm_roots.oops_do(keep_alive, worker_id); |
131 |
272 |
132 _thread_roots.oops_do(keep_alive, NULL, worker_id); |
273 _thread_roots.oops_do(keep_alive, NULL, worker_id); |
133 _cld_roots.clds_do(&clds, weak_clds, worker_id); |
274 _cld_roots.cld_do(&clds, worker_id); |
134 |
275 _code_roots.code_blobs_do(&update_blobs, worker_id); |
135 if(_update_code_cache) { |
276 |
136 _code_roots.code_blobs_do(&update_blobs, worker_id); |
277 _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
137 } |
278 _weak_roots.weak_oops_do(is_alive, keep_alive, worker_id); |
138 |
|
139 _weak_roots.oops_do<IsAlive, KeepAlive>(is_alive, keep_alive, worker_id); |
|
140 _dedup_roots.oops_do(is_alive, keep_alive, worker_id); |
279 _dedup_roots.oops_do(is_alive, keep_alive, worker_id); |
141 } |
280 } |
142 |
281 |
143 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |
282 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTPROCESSOR_INLINE_HPP |