194 SuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
195 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
196 jushort* live_data = _cm->get_liveness(worker_id);
197 ReferenceProcessor* rp;
198 if (_cm->process_references()) {
199 rp = ShenandoahHeap::heap()->ref_processor();
200 shenandoah_assert_rp_isalive_installed();
201 } else {
202 rp = NULL;
203 }
204
205 _cm->concurrent_scan_code_roots(worker_id, rp, _update_refs);
206 _cm->mark_loop(worker_id, _terminator, rp,
207 true, // cancellable
208 _cm->unload_classes(),
209 _update_refs,
210 ShenandoahStringDedup::is_enabled()); // perform string dedup
211 }
212 };
213
214 class ShenandoahFinalMarkingTask : public AbstractGangTask {
215 private:
216 ShenandoahConcurrentMark* _cm;
217 ParallelTaskTerminator* _terminator;
218 bool _update_refs;
219 bool _unload_classes;
220 bool _dedup_string;
221
222 public:
223 ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator,
224 bool update_refs, bool unload_classes, bool dedup_string) :
225 AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator),
226 _update_refs(update_refs), _unload_classes(unload_classes), _dedup_string(dedup_string) {
227 }
228
229 void work(uint worker_id) {
230 // First drain remaining SATB buffers.
231 // Notice that this is not strictly necessary for mark-compact. But since
232 // it requires a StrongRootsScope around the task, we need to claim the
233 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
234 // full-gc.
235 _cm->drain_satb_buffers(worker_id);
236
237 ReferenceProcessor* rp;
238 if (_cm->process_references()) {
239 rp = ShenandoahHeap::heap()->ref_processor();
240 shenandoah_assert_rp_isalive_installed();
241 } else {
242 rp = NULL;
243 }
244
245 // Degenerated cycle may bypass concurrent cycle, so code roots might not be scanned,
246 // let's check here.
247 _cm->concurrent_scan_code_roots(worker_id, rp, _update_refs);
248 _cm->mark_loop(worker_id, _terminator, rp,
249 false, // not cancellable
250 _unload_classes,
251 _update_refs,
252 _dedup_string);
253
254 assert(_cm->task_queues()->is_empty(), "Should be empty");
255 }
455 ShenandoahFinalMarkingTask task(this, &terminator, sh->has_forwarded_objects(),
456 unload_classes(), full_gc && ShenandoahStringDedup::is_enabled());
457 sh->workers()->run_task(&task);
458 }
459 }
460
461 assert(task_queues()->is_empty(), "Should be empty");
462
463 // When we're done marking everything, we process weak references.
464 if (process_references()) {
465 weak_refs_work(full_gc);
466 }
467
468 // And finally finish class unloading
469 if (unload_classes()) {
470 sh->unload_classes_and_cleanup_tables(full_gc);
471 }
472
473 assert(task_queues()->is_empty(), "Should be empty");
474
475 }
476
477 class ShenandoahSATBThreadsClosure : public ThreadClosure {
478 ShenandoahSATBBufferClosure* _satb_cl;
479 int _thread_parity;
480
481 public:
482 ShenandoahSATBThreadsClosure(ShenandoahSATBBufferClosure* satb_cl) :
483 _satb_cl(satb_cl),
484 _thread_parity(Threads::thread_claim_parity()) {}
485
486 void do_thread(Thread* thread) {
487 if (thread->is_Java_thread()) {
488 if (thread->claim_oops_do(true, _thread_parity)) {
489 JavaThread* jt = (JavaThread*)thread;
490 ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl);
491 }
492 } else if (thread->is_VM_thread()) {
493 if (thread->claim_oops_do(true, _thread_parity)) {
494 ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl);
495 }
496 }
497 }
498 };
499
500 void ShenandoahConcurrentMark::drain_satb_buffers(uint worker_id) {
501 ShenandoahObjToScanQueue* q = get_queue(worker_id);
502 ShenandoahSATBBufferClosure cl(q);
503 ShenandoahSATBThreadsClosure tc(&cl);
504 Threads::threads_do(&tc);
505 }
506
507 #if TASKQUEUE_STATS
508 void ShenandoahConcurrentMark::print_taskqueue_stats_hdr(outputStream* const st) {
509 st->print_raw_cr("GC Task Stats");
510 st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
511 st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
512 }
513
514 void ShenandoahConcurrentMark::print_taskqueue_stats() const {
515 if (!log_develop_is_enabled(Trace, gc, task, stats)) {
516 return;
517 }
518 Log(gc, task, stats) log;
519 ResourceMark rm;
520 LogStream ls(log.trace());
521 outputStream* st = &ls;
522 print_taskqueue_stats_hdr(st);
523
524 TaskQueueStats totals;
|
194 SuspendibleThreadSetJoiner stsj(ShenandoahSuspendibleWorkers);
195 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
196 jushort* live_data = _cm->get_liveness(worker_id);
197 ReferenceProcessor* rp;
198 if (_cm->process_references()) {
199 rp = ShenandoahHeap::heap()->ref_processor();
200 shenandoah_assert_rp_isalive_installed();
201 } else {
202 rp = NULL;
203 }
204
205 _cm->concurrent_scan_code_roots(worker_id, rp, _update_refs);
206 _cm->mark_loop(worker_id, _terminator, rp,
207 true, // cancellable
208 _cm->unload_classes(),
209 _update_refs,
210 ShenandoahStringDedup::is_enabled()); // perform string dedup
211 }
212 };
213
214 class ShenandoahSATBThreadsClosure : public ThreadClosure {
215 ShenandoahSATBBufferClosure* _satb_cl;
216 int _thread_parity;
217
218 public:
219 ShenandoahSATBThreadsClosure(ShenandoahSATBBufferClosure* satb_cl) :
220 _satb_cl(satb_cl),
221 _thread_parity(Threads::thread_claim_parity()) {}
222
223 void do_thread(Thread* thread) {
224 if (thread->is_Java_thread()) {
225 if (thread->claim_oops_do(true, _thread_parity)) {
226 JavaThread* jt = (JavaThread*)thread;
227 ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl);
228 }
229 } else if (thread->is_VM_thread()) {
230 if (thread->claim_oops_do(true, _thread_parity)) {
231 ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl);
232 }
233 }
234 }
235 };
236
237 class ShenandoahFinalMarkingTask : public AbstractGangTask {
238 private:
239 ShenandoahConcurrentMark* _cm;
240 ParallelTaskTerminator* _terminator;
241 bool _update_refs;
242 bool _unload_classes;
243 bool _dedup_string;
244
245 public:
246 ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, ParallelTaskTerminator* terminator,
247 bool update_refs, bool unload_classes, bool dedup_string) :
248 AbstractGangTask("Shenandoah Final Marking"), _cm(cm), _terminator(terminator),
249 _update_refs(update_refs), _unload_classes(unload_classes), _dedup_string(dedup_string) {
250 }
251
252 void work(uint worker_id) {
253 // First drain remaining SATB buffers.
254 // Notice that this is not strictly necessary for mark-compact. But since
255 // it requires a StrongRootsScope around the task, we need to claim the
256 // threads, and performance-wise it doesn't really matter. Adds about 1ms to
257 // full-gc.
258 ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id);
259 ShenandoahSATBBufferClosure cl(q);
260 SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set();
261 while (satb_mq_set.apply_closure_to_completed_buffer(&cl));
262 ShenandoahSATBThreadsClosure tc(&cl);
263 Threads::threads_do(&tc);
264
265 ReferenceProcessor* rp;
266 if (_cm->process_references()) {
267 rp = ShenandoahHeap::heap()->ref_processor();
268 shenandoah_assert_rp_isalive_installed();
269 } else {
270 rp = NULL;
271 }
272
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, _update_refs);
276 _cm->mark_loop(worker_id, _terminator, rp,
277 false, // not cancellable
278 _unload_classes,
279 _update_refs,
280 _dedup_string);
281
282 assert(_cm->task_queues()->is_empty(), "Should be empty");
283 }
483 ShenandoahFinalMarkingTask task(this, &terminator, sh->has_forwarded_objects(),
484 unload_classes(), full_gc && ShenandoahStringDedup::is_enabled());
485 sh->workers()->run_task(&task);
486 }
487 }
488
489 assert(task_queues()->is_empty(), "Should be empty");
490
491 // When we're done marking everything, we process weak references.
492 if (process_references()) {
493 weak_refs_work(full_gc);
494 }
495
496 // And finally finish class unloading
497 if (unload_classes()) {
498 sh->unload_classes_and_cleanup_tables(full_gc);
499 }
500
501 assert(task_queues()->is_empty(), "Should be empty");
502
503 }
504
505 #if TASKQUEUE_STATS
506 void ShenandoahConcurrentMark::print_taskqueue_stats_hdr(outputStream* const st) {
507 st->print_raw_cr("GC Task Stats");
508 st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
509 st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
510 }
511
512 void ShenandoahConcurrentMark::print_taskqueue_stats() const {
513 if (!log_develop_is_enabled(Trace, gc, task, stats)) {
514 return;
515 }
516 Log(gc, task, stats) log;
517 ResourceMark rm;
518 LogStream ls(log.trace());
519 outputStream* st = &ls;
520 print_taskqueue_stats_hdr(st);
521
522 TaskQueueStats totals;
|