59
60 ShenandoahRootProcessor::~ShenandoahRootProcessor() {
61 delete _process_strong_tasks;
62 if (ShenandoahStringDedup::is_enabled()) {
63 StringDedup::gc_epilogue();
64 }
65
66 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
67 }
68
69 void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) {
70 CLDToOopClosure clds(oops);
71 CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
72
73 CodeCache::blobs_do(&blobs);
74 ClassLoaderDataGraph::cld_do(&clds);
75 Universe::oops_do(oops);
76 Management::oops_do(oops);
77 JvmtiExport::oops_do(oops);
78 JNIHandles::oops_do(oops);
79 WeakProcessor::oops_do(oops);
80 ObjectSynchronizer::oops_do(oops);
81 SystemDictionary::oops_do(oops);
82 StringTable::oops_do(oops);
83
84 if (ShenandoahStringDedup::is_enabled()) {
85 ShenandoahStringDedup::oops_do_slow(oops);
86 }
87
88 // Do thread roots the last. This allows verification code to find
89 // any broken objects from those special roots first, not the accidental
90 // dangling reference from the thread root.
91 Threads::possibly_parallel_oops_do(false, oops, &blobs);
92 }
93
94 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops,
95 OopClosure* weak_oops,
96 CLDClosure* clds,
97 CLDClosure* weak_clds,
98 CodeBlobClosure* blobs,
99 ThreadClosure* thread_cl,
100 uint worker_id) {
101
102 process_java_roots(oops, clds, weak_clds, blobs, thread_cl, worker_id);
103 process_vm_roots(oops, NULL, weak_oops, worker_id);
104
105 _process_strong_tasks->all_tasks_completed(n_workers());
106 }
107
108 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops,
109 OopClosure* weak_oops,
110 CLDClosure* clds,
111 CodeBlobClosure* blobs,
112 ThreadClosure* thread_cl,
113 uint worker_id) {
114
115 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
116 process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id);
117 process_vm_roots(oops, oops, weak_oops, worker_id);
118
119 if (blobs != NULL) {
120 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
121 _coderoots_all_iterator.possibly_parallel_blobs_do(blobs);
122 }
123
124 _process_strong_tasks->all_tasks_completed(n_workers());
125 }
126
127 class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
128 private:
129 OopClosure* _f;
130 CodeBlobClosure* _cf;
131 ThreadClosure* _thread_cl;
132 public:
133 ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) :
134 _f(f), _cf(cf), _thread_cl(thread_cl) {}
135
136 void do_thread(Thread* t) {
137 if (_thread_cl != NULL) {
138 _thread_cl->do_thread(t);
139 }
140 t->oops_do(_f, _cf);
141 }
142 };
143
144 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots,
150 {
151 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
152 // Iterating over the CLDG and the Threads are done early to allow us to
153 // first process the strong CLDs and nmethods and then, after a barrier,
154 // let the thread process the weak CLDs and nmethods.
155 {
156 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
157 _cld_iterator.root_cld_do(strong_clds, weak_clds);
158 }
159
160 {
161 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
162 bool is_par = n_workers() > 1;
163 ResourceMark rm;
164 ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl);
165 Threads::possibly_parallel_threads_do(is_par, &cl);
166 }
167 }
168
169 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots,
170 OopClosure* weak_roots,
171 OopClosure* jni_weak_roots,
172 uint worker_id)
173 {
174 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
175 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Universe_oops_do)) {
176 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
177 Universe::oops_do(strong_roots);
178 }
179
180 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_oops_do)) {
181 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
182 JNIHandles::oops_do(strong_roots);
183 }
184 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Management_oops_do)) {
185 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
186 Management::oops_do(strong_roots);
187 }
188 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_jvmti_oops_do)) {
189 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
190 JvmtiExport::oops_do(strong_roots);
191 }
192 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) {
193 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
194 SystemDictionary::oops_do(strong_roots);
195 }
196 if (jni_weak_roots != NULL) {
197 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_weak_oops_do)) {
198 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIWeakRoots, worker_id);
199 WeakProcessor::oops_do(jni_weak_roots);
200 }
201 }
202
203 if (ShenandoahStringDedup::is_enabled() && weak_roots != NULL) {
204 ShenandoahStringDedup::parallel_oops_do(weak_roots, worker_id);
205 }
206
207 {
208 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
209 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) {
210 ObjectSynchronizer::oops_do(strong_roots);
211 }
212 }
213
214 // All threads execute the following. A specific chunk of buckets
215 // from the StringTable are the individual tasks.
216 if (weak_roots != NULL) {
217 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::StringTableRoots, worker_id);
218 StringTable::possibly_parallel_oops_do(&_par_state_string, weak_roots);
219 }
220 }
221
222 uint ShenandoahRootProcessor::n_workers() const {
223 return _srs.n_threads();
224 }
225
226 ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) :
227 _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
228 _srs(n_workers),
229 _phase(phase),
230 _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator())
231 {
232 heap->phase_timings()->record_workers_start(_phase);
233 }
234
235 ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
236 delete _evacuation_tasks;
237 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
238 }
|
59
60 ShenandoahRootProcessor::~ShenandoahRootProcessor() {
61 delete _process_strong_tasks;
62 if (ShenandoahStringDedup::is_enabled()) {
63 StringDedup::gc_epilogue();
64 }
65
66 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
67 }
68
69 void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) {
70 CLDToOopClosure clds(oops);
71 CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
72
73 CodeCache::blobs_do(&blobs);
74 ClassLoaderDataGraph::cld_do(&clds);
75 Universe::oops_do(oops);
76 Management::oops_do(oops);
77 JvmtiExport::oops_do(oops);
78 JNIHandles::oops_do(oops);
79 ObjectSynchronizer::oops_do(oops);
80 SystemDictionary::oops_do(oops);
81 StringTable::oops_do(oops);
82
83 // Do thread roots the last. This allows verification code to find
84 // any broken objects from those special roots first, not the accidental
85 // dangling reference from the thread root.
86 Threads::possibly_parallel_oops_do(false, oops, &blobs);
87 }
88
89 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops,
90 CLDClosure* clds,
91 CodeBlobClosure* blobs,
92 ThreadClosure* thread_cl,
93 uint worker_id) {
94
95 process_java_roots(oops, clds, NULL, blobs, thread_cl, worker_id);
96 process_vm_roots(oops, worker_id);
97
98 _process_strong_tasks->all_tasks_completed(n_workers());
99 }
100
101 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops,
102 CLDClosure* clds,
103 CodeBlobClosure* blobs,
104 ThreadClosure* thread_cl,
105 uint worker_id) {
106
107 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
108 process_java_roots(oops, clds, clds, blobs, thread_cl, worker_id);
109 process_vm_roots(oops, worker_id);
110
111 if (blobs != NULL) {
112 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CodeCacheRoots, worker_id);
113 _coderoots_all_iterator.possibly_parallel_blobs_do(blobs);
114 }
115
116 // All threads execute the following. A specific chunk of buckets
117 // from the StringTable are the individual tasks.
118 {
119 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::StringTableRoots, worker_id);
120 StringTable::possibly_parallel_oops_do(&_par_state_string, oops);
121 }
122
123 _process_strong_tasks->all_tasks_completed(n_workers());
124
125 }
126
127 class ShenandoahParallelOopsDoThreadClosure : public ThreadClosure {
128 private:
129 OopClosure* _f;
130 CodeBlobClosure* _cf;
131 ThreadClosure* _thread_cl;
132 public:
133 ShenandoahParallelOopsDoThreadClosure(OopClosure* f, CodeBlobClosure* cf, ThreadClosure* thread_cl) :
134 _f(f), _cf(cf), _thread_cl(thread_cl) {}
135
136 void do_thread(Thread* t) {
137 if (_thread_cl != NULL) {
138 _thread_cl->do_thread(t);
139 }
140 t->oops_do(_f, _cf);
141 }
142 };
143
144 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots,
150 {
151 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
152 // Iterating over the CLDG and the Threads are done early to allow us to
153 // first process the strong CLDs and nmethods and then, after a barrier,
154 // let the thread process the weak CLDs and nmethods.
155 {
156 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::CLDGRoots, worker_id);
157 _cld_iterator.root_cld_do(strong_clds, weak_clds);
158 }
159
160 {
161 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ThreadRoots, worker_id);
162 bool is_par = n_workers() > 1;
163 ResourceMark rm;
164 ShenandoahParallelOopsDoThreadClosure cl(strong_roots, strong_code, thread_cl);
165 Threads::possibly_parallel_threads_do(is_par, &cl);
166 }
167 }
168
169 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots,
170 uint worker_id) {
171 ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
172 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Universe_oops_do)) {
173 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::UniverseRoots, worker_id);
174 Universe::oops_do(strong_roots);
175 }
176
177 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_oops_do)) {
178 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIRoots, worker_id);
179 JNIHandles::oops_do(strong_roots);
180 }
181 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Management_oops_do)) {
182 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ManagementRoots, worker_id);
183 Management::oops_do(strong_roots);
184 }
185 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_jvmti_oops_do)) {
186 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JVMTIRoots, worker_id);
187 JvmtiExport::oops_do(strong_roots);
188 }
189 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) {
190 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::SystemDictionaryRoots, worker_id);
191 SystemDictionary::oops_do(strong_roots);
192 }
193
194 {
195 ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::ObjectSynchronizerRoots, worker_id);
196 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) {
197 ObjectSynchronizer::oops_do(strong_roots);
198 }
199 }
200 }
201
202 uint ShenandoahRootProcessor::n_workers() const {
203 return _srs.n_threads();
204 }
205
206 ShenandoahRootEvacuator::ShenandoahRootEvacuator(ShenandoahHeap* heap, uint n_workers, ShenandoahPhaseTimings::Phase phase) :
207 _evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
208 _srs(n_workers),
209 _phase(phase),
210 _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator())
211 {
212 heap->phase_timings()->record_workers_start(_phase);
213 }
214
215 ShenandoahRootEvacuator::~ShenandoahRootEvacuator() {
216 delete _evacuation_tasks;
217 ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
218 }
|