113 // class unloading. |
113 // class unloading. |
114 // b. With unload_classes = false, we have to nominally retain all the references from code |
114 // b. With unload_classes = false, we have to nominally retain all the references from code |
115 // cache, because there could be the case of embedded class/oop in the generated code, |
115 // cache, because there could be the case of embedded class/oop in the generated code, |
116 // which we will never visit during mark. Without code cache invalidation, as in (a), |
116 // which we will never visit during mark. Without code cache invalidation, as in (a), |
117 // we risk executing that code cache blob, and crashing. |
117 // we risk executing that code cache blob, and crashing. |
118 // c. With ShenandoahConcurrentScanCodeRoots, we avoid scanning the entire code cache here, |
|
119 // and instead do that in concurrent phase under the relevant lock. This saves init mark |
|
120 // pause time. |
|
121 |
|
122 CLDToOopClosure clds_cl(oops, ClassLoaderData::_claim_strong); |
|
123 MarkingCodeBlobClosure blobs_cl(oops, ! CodeBlobToOopClosure::FixRelocations); |
|
124 |
|
125 ResourceMark m; |
|
126 if (heap->unload_classes()) { |
118 if (heap->unload_classes()) { |
127 _rp->process_strong_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id); |
119 _rp->strong_roots_do(worker_id, oops); |
128 } else { |
120 } else { |
129 if (ShenandoahConcurrentScanCodeRoots) { |
121 _rp->roots_do(worker_id, oops); |
130 CodeBlobClosure* code_blobs = NULL; |
|
131 #ifdef ASSERT |
|
132 ShenandoahAssertToSpaceClosure assert_to_space_oops; |
|
133 CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations); |
|
134 // If conc code cache evac is disabled, code cache should have only to-space ptrs. |
|
135 // Otherwise, it should have to-space ptrs only if mark does not update refs. |
|
136 if (!heap->has_forwarded_objects()) { |
|
137 code_blobs = &assert_to_space; |
|
138 } |
|
139 #endif |
|
140 _rp->process_all_roots(oops, &clds_cl, code_blobs, NULL, worker_id); |
|
141 } else { |
|
142 _rp->process_all_roots(oops, &clds_cl, &blobs_cl, NULL, worker_id); |
|
143 } |
|
144 } |
122 } |
145 } |
123 } |
146 }; |
124 }; |
147 |
125 |
148 class ShenandoahUpdateRootsTask : public AbstractGangTask { |
126 class ShenandoahUpdateRootsTask : public AbstractGangTask { |
149 private: |
127 private: |
150 ShenandoahRootProcessor* _rp; |
128 ShenandoahRootUpdater* _root_updater; |
151 const bool _update_code_cache; |
129 public: |
152 public: |
130 ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater) : |
153 ShenandoahUpdateRootsTask(ShenandoahRootProcessor* rp, bool update_code_cache) : |
|
154 AbstractGangTask("Shenandoah update roots task"), |
131 AbstractGangTask("Shenandoah update roots task"), |
155 _rp(rp), |
132 _root_updater(root_updater) { |
156 _update_code_cache(update_code_cache) { |
|
157 } |
133 } |
158 |
134 |
159 void work(uint worker_id) { |
135 void work(uint worker_id) { |
160 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint"); |
136 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint"); |
161 ShenandoahParallelWorkerSession worker_session(worker_id); |
137 ShenandoahParallelWorkerSession worker_session(worker_id); |
162 |
138 |
163 ShenandoahHeap* heap = ShenandoahHeap::heap(); |
139 ShenandoahHeap* heap = ShenandoahHeap::heap(); |
164 ShenandoahUpdateRefsClosure cl; |
140 ShenandoahUpdateRefsClosure cl; |
165 CLDToOopClosure cldCl(&cl, ClassLoaderData::_claim_strong); |
141 AlwaysTrueClosure always_true; |
166 |
142 _root_updater->roots_do<AlwaysTrueClosure, ShenandoahUpdateRefsClosure>(worker_id, &always_true, &cl); |
167 CodeBlobClosure* code_blobs; |
|
168 CodeBlobToOopClosure update_blobs(&cl, CodeBlobToOopClosure::FixRelocations); |
|
169 #ifdef ASSERT |
|
170 ShenandoahAssertToSpaceClosure assert_to_space_oops; |
|
171 CodeBlobToOopClosure assert_to_space(&assert_to_space_oops, !CodeBlobToOopClosure::FixRelocations); |
|
172 #endif |
|
173 if (_update_code_cache) { |
|
174 code_blobs = &update_blobs; |
|
175 } else { |
|
176 code_blobs = |
|
177 DEBUG_ONLY(&assert_to_space) |
|
178 NOT_DEBUG(NULL); |
|
179 } |
|
180 _rp->update_all_roots<AlwaysTrueClosure>(&cl, &cldCl, code_blobs, NULL, worker_id); |
|
181 } |
143 } |
182 }; |
144 }; |
183 |
145 |
184 class ShenandoahConcurrentMarkingTask : public AbstractGangTask { |
146 class ShenandoahConcurrentMarkingTask : public AbstractGangTask { |
185 private: |
147 private: |
287 WorkGang* workers = heap->workers(); |
249 WorkGang* workers = heap->workers(); |
288 uint nworkers = workers->active_workers(); |
250 uint nworkers = workers->active_workers(); |
289 |
251 |
290 assert(nworkers <= task_queues()->size(), "Just check"); |
252 assert(nworkers <= task_queues()->size(), "Just check"); |
291 |
253 |
292 ShenandoahRootProcessor root_proc(heap, nworkers, root_phase); |
254 ShenandoahRootScanner root_proc(nworkers, root_phase); |
293 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); |
255 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); |
294 task_queues()->reserve(nworkers); |
256 task_queues()->reserve(nworkers); |
295 |
257 |
296 if (heap->has_forwarded_objects()) { |
258 if (heap->has_forwarded_objects()) { |
297 ShenandoahInitMarkRootsTask<RESOLVE> mark_roots(&root_proc, _heap->process_references()); |
259 ShenandoahInitMarkRootsTask<RESOLVE> mark_roots(&root_proc, _heap->process_references()); |