165 ShenandoahConcurrentWorkerSession worker_session(worker_id);
166 ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
167 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
168 ReferenceProcessor* rp;
169 if (heap->process_references()) {
170 rp = heap->ref_processor();
171 shenandoah_assert_rp_isalive_installed();
172 } else {
173 rp = NULL;
174 }
175
176 _cm->concurrent_scan_code_roots(worker_id, rp);
177 _cm->mark_loop(worker_id, _terminator, rp,
178 true, // cancellable
179 ShenandoahStringDedup::is_enabled()); // perform string dedup
180 }
181 };
182
183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
184 private:
185 ShenandoahSATBBufferClosure* _satb_cl;
186 MarkingCodeBlobClosure* _code_cl;
187 uintx _claim_token;
188
189 public:
190 ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl, MarkingCodeBlobClosure* code_cl) :
191 _satb_cl(satb_cl), _code_cl(code_cl),
192 _claim_token(Threads::thread_claim_token()) {}
193
194 void do_thread(Thread* thread) {
195 if (thread->claim_threads_do(true, _claim_token)) {
196 ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
197 if (_code_cl != NULL && thread->is_Java_thread()) {
198 // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
199 // however the liveness of oops reachable from nmethods have very complex lifecycles:
200 // * Alive if on the stack of an executing method
201 // * Weakly reachable otherwise
202 // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
203 // live by the SATB invariant but other oops recorded in nmethods may behave differently.
204 JavaThread* jt = (JavaThread*)thread;
205 jt->nmethods_do(_code_cl);
206 }
207 }
208 }
209 };
210
211 class ShenandoahFinalMarkingTask : public AbstractGangTask {
212 private:
213 ShenandoahConcurrentMark* _cm;
214 TaskTerminator* _terminator;
215 bool _dedup_string;
216
217 public:
226 ReferenceProcessor* rp;
227 if (heap->process_references()) {
228 rp = heap->ref_processor();
229 shenandoah_assert_rp_isalive_installed();
230 } else {
231 rp = NULL;
232 }
233
234 // First drain remaining SATB buffers.
235 // Notice that this is not strictly necessary for mark-compact. But since
236 // it requires a StrongRootsScope around the task, we need to claim the
237 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
238 // full-gc.
239 {
240 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
241
242 ShenandoahSATBBufferClosure cl(q);
243 SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
244 while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
245
246 if (heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading()) {
247 if (heap->has_forwarded_objects()) {
248 ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
249 MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
250 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);
251 Threads::threads_do(&tc);
252 } else {
253 ShenandoahMarkRefsClosure mark_cl(q, rp);
254 MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
255 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, &blobsCl);
256 Threads::threads_do(&tc);
257 }
258 } else {
259 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl, NULL);
260 Threads::threads_do(&tc);
261 }
262 }
263
264 if (heap->is_degenerated_gc_in_progress()) {
265 // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
266 // let's check here.
267 _cm->concurrent_scan_code_roots(worker_id, rp);
268 }
269
270 _cm->mark_loop(worker_id, _terminator, rp,
271 false, // not cancellable
272 _dedup_string);
273
274 assert(_cm->task_queues()->is_empty(), "Should be empty");
275 }
276 };
277
278 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
279 assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
|
165 ShenandoahConcurrentWorkerSession worker_session(worker_id);
166 ShenandoahSuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
167 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
168 ReferenceProcessor* rp;
169 if (heap->process_references()) {
170 rp = heap->ref_processor();
171 shenandoah_assert_rp_isalive_installed();
172 } else {
173 rp = NULL;
174 }
175
176 _cm->concurrent_scan_code_roots(worker_id, rp);
177 _cm->mark_loop(worker_id, _terminator, rp,
178 true, // cancellable
179 ShenandoahStringDedup::is_enabled()); // perform string dedup
180 }
181 };
182
183 class ShenandoahSATBAndRemarkCodeRootsThreadsClosure : public ThreadClosure {
184 private:
185 ShenandoahSATBBufferClosure* const _satb_cl;
186 OopClosure* const _cl;
187 MarkingCodeBlobClosure* const _code_cl;
188 uintx _claim_token;
189 public:
190 ShenandoahSATBAndRemarkCodeRootsThreadsClosure(ShenandoahSATBBufferClosure* satb_cl,
191 OopClosure* cl, MarkingCodeBlobClosure* code_cl) :
192 _satb_cl(satb_cl), _cl(cl), _code_cl(code_cl),
193 _claim_token(Threads::thread_claim_token()) {}
194
195 void do_thread(Thread* thread) {
196 if (thread->claim_threads_do(true, _claim_token)) {
197 ShenandoahThreadLocalData::satb_mark_queue(thread).apply_closure_and_empty(_satb_cl);
198 if (_cl != NULL) {
199 // This doesn't appear to add very much to final-mark latency. If that ever becomes a problem,
200 // we can attempt to trim it to only scan actual thread-stacks (and avoid stuff like handles, monitors, etc)
201 // and there only compiled frames. We can also make thread-scans templatized to avoid virtual calls and
202 // instead inline the closures.
203 ResourceMark rm;
204 thread->oops_do(_cl, _code_cl);
205 } else if (_code_cl != NULL && thread->is_Java_thread()) {
206 // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
207 // however the liveness of oops reachable from nmethods have very complex lifecycles:
208 // * Alive if on the stack of an executing method
209 // * Weakly reachable otherwise
210 // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
211 // live by the SATB invariant but other oops recorded in nmethods may behave differently.
212 JavaThread* jt = (JavaThread*)thread;
213 jt->nmethods_do(_code_cl);
214 }
215 }
216 }
217 };
218
219 class ShenandoahFinalMarkingTask : public AbstractGangTask {
220 private:
221 ShenandoahConcurrentMark* _cm;
222 TaskTerminator* _terminator;
223 bool _dedup_string;
224
225 public:
234 ReferenceProcessor* rp;
235 if (heap->process_references()) {
236 rp = heap->ref_processor();
237 shenandoah_assert_rp_isalive_installed();
238 } else {
239 rp = NULL;
240 }
241
242 // First drain remaining SATB buffers.
243 // Notice that this is not strictly necessary for mark-compact. But since
244 // it requires a StrongRootsScope around the task, we need to claim the
245 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
246 // full-gc.
247 {
248 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
249
250 ShenandoahSATBBufferClosure cl(q);
251 SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
252 while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
253
254 bool do_nmethods = heap->unload_classes() && !ShenandoahConcurrentRoots::can_do_concurrent_class_unloading();
255 if (heap->has_forwarded_objects()) {
256 ShenandoahMarkResolveRefsClosure resolve_mark_cl(q, rp);
257 MarkingCodeBlobClosure blobsCl(&resolve_mark_cl, !CodeBlobToOopClosure::FixRelocations);
258 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
259 ShenandoahAggressiveReferenceDiscovery ? &resolve_mark_cl : NULL,
260 do_nmethods ? &blobsCl : NULL);
261 Threads::threads_do(&tc);
262 } else {
263 ShenandoahMarkRefsClosure mark_cl(q, rp);
264 MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
265 ShenandoahSATBAndRemarkCodeRootsThreadsClosure tc(&cl,
266 ShenandoahAggressiveReferenceDiscovery ? &mark_cl : NULL,
267 do_nmethods ? &blobsCl : NULL);
268 Threads::threads_do(&tc);
269 }
270 }
271
272 if (heap->is_degenerated_gc_in_progress()) {
273 // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
274 // let's check here.
275 _cm->concurrent_scan_code_roots(worker_id, rp);
276 }
277
278 _cm->mark_loop(worker_id, _terminator, rp,
279 false, // not cancellable
280 _dedup_string);
281
282 assert(_cm->task_queues()->is_empty(), "Should be empty");
283 }
284 };
285
286 void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_phase) {
287 assert(Thread::current()->is_VM_thread(), "can only do this in VMThread");
|