--- old/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp 2018-06-19 21:10:10.294553141 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp 2018-06-19 21:10:10.101555505 +0200 @@ -211,6 +211,29 @@ } }; +class ShenandoahSATBThreadsClosure : public ThreadClosure { + ShenandoahSATBBufferClosure* _satb_cl; + int _thread_parity; + + public: + ShenandoahSATBThreadsClosure(ShenandoahSATBBufferClosure* satb_cl) : + _satb_cl(satb_cl), + _thread_parity(Threads::thread_claim_parity()) {} + + void do_thread(Thread* thread) { + if (thread->is_Java_thread()) { + if (thread->claim_oops_do(true, _thread_parity)) { + JavaThread* jt = (JavaThread*)thread; + ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl); + } + } else if (thread->is_VM_thread()) { + if (thread->claim_oops_do(true, _thread_parity)) { + ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); + } + } + } +}; + class ShenandoahFinalMarkingTask : public AbstractGangTask { private: ShenandoahConcurrentMark* _cm; @@ -232,7 +255,12 @@ // it requires a StrongRootsScope around the task, we need to claim the // threads, and performance-wise it doesn't really matter. Adds about 1ms to // full-gc. - _cm->drain_satb_buffers(worker_id); + ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id); + ShenandoahSATBBufferClosure cl(q); + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); + while (satb_mq_set.apply_closure_to_completed_buffer(&cl)); + ShenandoahSATBThreadsClosure tc(&cl); + Threads::threads_do(&tc); ReferenceProcessor* rp; if (_cm->process_references()) { @@ -474,36 +502,6 @@ } -class ShenandoahSATBThreadsClosure : public ThreadClosure { - ShenandoahSATBBufferClosure* _satb_cl; - int _thread_parity; - - public: - ShenandoahSATBThreadsClosure(ShenandoahSATBBufferClosure* satb_cl) : - _satb_cl(satb_cl), - _thread_parity(Threads::thread_claim_parity()) {} - - void do_thread(Thread* thread) { - if (thread->is_Java_thread()) { - if (thread->claim_oops_do(true, _thread_parity)) { - JavaThread* jt = (JavaThread*)thread; - ShenandoahThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(_satb_cl); - } - } else if (thread->is_VM_thread()) { - if (thread->claim_oops_do(true, _thread_parity)) { - ShenandoahBarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(_satb_cl); - } - } - } -}; - -void ShenandoahConcurrentMark::drain_satb_buffers(uint worker_id) { - ShenandoahObjToScanQueue* q = get_queue(worker_id); - ShenandoahSATBBufferClosure cl(q); - ShenandoahSATBThreadsClosure tc(&cl); - Threads::threads_do(&tc); -} - #if TASKQUEUE_STATS void ShenandoahConcurrentMark::print_taskqueue_stats_hdr(outputStream* const st) { st->print_raw_cr("GC Task Stats"); --- old/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp 2018-06-19 21:10:10.871546073 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp 2018-06-19 21:10:10.686548339 +0200 @@ -118,7 +118,6 @@ ShenandoahObjToScanQueue* get_queue(uint worker_id); void clear_queue(ShenandoahObjToScanQueue *q); - void drain_satb_buffers(uint worker_id); ShenandoahObjToScanQueueSet* task_queues() { return _task_queues;} jushort* get_liveness(uint worker_id); --- old/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2018-06-19 21:10:11.436539153 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2018-06-19 21:10:11.242541529 +0200 @@ -243,8 +243,17 @@ rp = _heap->ref_processor(); } - // Step 1: Process ordinary GC roots. + // Step 0: Drain outstanding SATB queues. + // NOTE: we piggy-back draining of remaining thread SATB buffers on the final root scan below. ShenandoahTraversalSATBBufferClosure satb_cl(q); + { + // Process remaining finished SATB buffers. + SATBMarkQueueSet& satb_mq_set = ShenandoahBarrierSet::satb_mark_queue_set(); + while (satb_mq_set.apply_closure_to_completed_buffer(&satb_cl)); + // Process remaining threads SATB buffers below. + } + + // Step 1: Process ordinary GC roots. if (!_heap->is_degenerated_gc_in_progress()) { ShenandoahTraversalClosure roots_cl(q, rp); CLDToOopClosure cld_cl(&roots_cl);