index

src/share/vm/gc_implementation/g1/concurrentMark.cpp

Print this page
rev 7184 : 6979279
rev 7185 : [mq]: rev1

*** 606,623 **** warning("Can't have more ConcGCThreads (" UINTX_FORMAT ") " "than ParallelGCThreads (" UINTX_FORMAT ").", ConcGCThreads, ParallelGCThreads); return; } - if (ParallelGCThreads == 0) { - // if we are not running with any parallel GC threads we will not - // spawn any marking threads either - _parallel_marking_threads = 0; - _max_parallel_marking_threads = 0; - _sleep_factor = 0.0; - _marking_task_overhead = 1.0; - } else { if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set _sleep_factor = 0.0; _marking_task_overhead = 1.0; --- 606,615 ----
*** 666,684 **** gclog_or_tty->print_cr("CM Sleep Factor %1.4lf", sleep_factor()); gclog_or_tty->print_cr("CL Marking Task Overhead %1.4lf", cleanup_task_overhead()); gclog_or_tty->print_cr("CL Sleep Factor %1.4lf", cleanup_sleep_factor()); #endif - guarantee(parallel_marking_threads() > 0, "peace of mind"); _parallel_workers = new FlexibleWorkGang("G1 Parallel Marking Threads", _max_parallel_marking_threads, false, true); if (_parallel_workers == NULL) { vm_exit_during_initialization("Failed necessary allocation."); } else { _parallel_workers->initialize_workers(); } - } if (FLAG_IS_DEFAULT(MarkStackSize)) { uintx mark_stack_size = MIN2(MarkStackSizeMax, MAX2(MarkStackSize, (uintx) (parallel_marking_threads() * TASKQUEUE_SIZE))); --- 658,674 ----
*** 1161,1171 **** }; // Calculates the number of active workers for a concurrent // phase. uint ConcurrentMark::calc_parallel_marking_threads() { - if (G1CollectedHeap::use_parallel_gc_threads()) { uint n_conc_workers = 0; if (!UseDynamicNumberOfGCThreads || (!FLAG_IS_DEFAULT(ConcGCThreads) && !ForceDynamicNumberOfGCThreads)) { n_conc_workers = max_parallel_marking_threads(); --- 1151,1160 ----
*** 1179,1193 **** // Don't scale down "n_conc_workers" by scale_parallel_threads() because // that scaling has already gone into "_max_parallel_marking_threads". } assert(n_conc_workers > 0, "Always need at least 1"); return n_conc_workers; - } - // If we are not running with any parallel GC threads we will not - // have spawned any marking threads either. Hence the number of - // concurrent workers should be 0. - return 0; } void ConcurrentMark::scanRootRegion(HeapRegion* hr, uint worker_id) { // Currently, only survivors can be root regions. assert(hr->next_top_at_mark_start() == hr->bottom(), "invariant"); --- 1168,1177 ----
*** 1238,1253 **** assert(parallel_marking_threads() <= max_parallel_marking_threads(), "Maximum number of marking threads exceeded"); uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); ! if (use_parallel_marking_threads()) { ! _parallel_workers->set_active_workers((int) active_workers); _parallel_workers->run_task(&task); - } else { - task.work(0); - } // It's possible that has_aborted() is true here without actually // aborting the survivor scan earlier. This is OK as it's // mainly used for sanity checking. root_regions()->scan_finished(); --- 1222,1233 ---- assert(parallel_marking_threads() <= max_parallel_marking_threads(), "Maximum number of marking threads exceeded"); uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); ! _parallel_workers->set_active_workers(active_workers); _parallel_workers->run_task(&task); // It's possible that has_aborted() is true here without actually // aborting the survivor scan earlier. This is OK as it's // mainly used for sanity checking. root_regions()->scan_finished();
*** 1274,1292 **** // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); ! if (use_parallel_marking_threads()) { ! _parallel_workers->set_active_workers((int)active_workers); // Don't set _n_par_threads because it affects MT in process_roots() // and the decisions on that MT processing is made elsewhere. assert(_parallel_workers->active_workers() > 0, "Should have been set"); _parallel_workers->run_task(&markingTask); - } else { - markingTask.work(0); - } print_stats(); } // Helper class to get rid of some boilerplate code. class G1CMTraceTime : public GCTraceTime { --- 1254,1268 ---- // Parallel task terminator is set in "set_concurrency_and_phase()" set_concurrency_and_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); ! _parallel_workers->set_active_workers(active_workers); // Don't set _n_par_threads because it affects MT in process_roots() // and the decisions on that MT processing is made elsewhere. assert(_parallel_workers->active_workers() > 0, "Should have been set"); _parallel_workers->run_task(&markingTask); print_stats(); } // Helper class to get rid of some boilerplate code. class G1CMTraceTime : public GCTraceTime {
*** 1709,1723 **** _actual_region_bm, _actual_card_bm, _expected_region_bm, _expected_card_bm, _verbose); - if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&verify_cl); - } Atomic::add(verify_cl.failures(), &_failures); } int failures() const { return _failures; } --- 1685,1695 ----
*** 1816,1830 **** FinalCountDataUpdateClosure final_update_cl(_g1h, _actual_region_bm, _actual_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&final_update_cl); - } } }; class G1ParNoteEndTask; --- 1788,1798 ----
*** 1917,1931 **** double start = os::elapsedTime(); FreeRegionList local_cleanup_list("Local Cleanup List"); HRRSCleanupTask hrrs_cleanup_task; G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, &hrrs_cleanup_task); - if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&g1_note_end); - } assert(g1_note_end.complete(), "Shouldn't have yielded!"); // Now update the lists _g1h->remove_from_old_sets(g1_note_end.old_regions_removed(), g1_note_end.humongous_regions_removed()); { --- 1885,1895 ----
*** 1972,1986 **** G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, uint n_workers) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) { } void work(uint worker_id) { ! if (G1CollectedHeap::use_parallel_gc_threads()) { ! _g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer); ! } else { ! _g1rs->scrub(_region_bm, _card_bm); ! } } }; void ConcurrentMark::cleanup() { --- 1936,1946 ---- G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, uint n_workers) : AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) { } void work(uint worker_id) { ! _g1rs->scrub(_region_bm, _card_bm, worker_id, &_hrclaimer); } }; void ConcurrentMark::cleanup() {
*** 2015,2036 **** uint n_workers; // Do counting once more with the world stopped for good measure. G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads(); n_workers = g1h->n_par_threads(); assert(g1h->n_par_threads() == n_workers, "Should not have been reset"); g1h->workers()->run_task(&g1_par_count_task); // Done with the parallel phase so reset to 0. g1h->set_par_threads(0); - } else { - n_workers = 1; - g1_par_count_task.work(0); - } if (VerifyDuringGC) { // Verify that the counting data accumulated during marking matches // that calculated by walking the marking bitmap. --- 1975,1991 ----
*** 2042,2059 **** &_region_bm, &_card_bm, &expected_region_bm, &expected_card_bm); - if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads((int)n_workers); g1h->workers()->run_task(&g1_par_verify_task); // Done with the parallel phase so reset to 0. g1h->set_par_threads(0); - } else { - g1_par_verify_task.work(0); - } guarantee(g1_par_verify_task.failures() == 0, "Unexpected accounting failures"); } size_t start_used_bytes = g1h->used(); --- 1997,2010 ----
*** 2073,2089 **** g1h->reset_gc_time_stamp(); // Note end of marking in all heap regions. G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads((int)n_workers); g1h->workers()->run_task(&g1_par_note_end_task); g1h->set_par_threads(0); - } else { - g1_par_note_end_task.work(0); - } g1h->check_gc_time_stamps(); if (!cleanup_list_is_empty()) { // The cleanup list is not empty, so we'll have to process it // concurrently. Notify anyone else that might be wanting free --- 2024,2036 ----
*** 2094,2110 **** // call below, since it affects the metric by which we sort the heap // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads((int)n_workers); g1h->workers()->run_task(&g1_par_scrub_rs_task); g1h->set_par_threads(0); - } else { - g1_par_scrub_rs_task.work(0); - } double rs_scrub_end = os::elapsedTime(); double this_rs_scrub_time = (rs_scrub_end - rs_scrub_start); _total_rs_scrub_time += this_rs_scrub_time; } --- 2041,2053 ----
*** 2497,2507 **** // We need at least one active thread. If reference processing // is not multi-threaded we use the current (VMThread) thread, // otherwise we use the work gang from the G1CollectedHeap and // we utilize all the worker threads we can. ! bool processing_is_mt = rp->processing_is_mt() && g1h->workers() != NULL; uint active_workers = (processing_is_mt ? g1h->workers()->active_workers() : 1U); active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); // Parallel processing task executor. G1CMRefProcTaskExecutor par_task_executor(g1h, this, --- 2440,2450 ---- // We need at least one active thread. If reference processing // is not multi-threaded we use the current (VMThread) thread, // otherwise we use the work gang from the G1CollectedHeap and // we utilize all the worker threads we can. ! bool processing_is_mt = rp->processing_is_mt(); uint active_workers = (processing_is_mt ? g1h->workers()->active_workers() : 1U); active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); // Parallel processing task executor. G1CMRefProcTaskExecutor par_task_executor(g1h, this,
*** 2606,2625 **** class G1RemarkThreadsClosure : public ThreadClosure { CMObjectClosure _cm_obj; G1CMOopClosure _cm_cl; MarkingCodeBlobClosure _code_cl; int _thread_parity; - bool _is_par; public: ! G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) : _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations), ! _thread_parity(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {} void do_thread(Thread* thread) { if (thread->is_Java_thread()) { ! if (thread->claim_oops_do(_is_par, _thread_parity)) { JavaThread* jt = (JavaThread*)thread; // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking // however the liveness of oops reachable from nmethods have very complex lifecycles: // * Alive if on the stack of an executing method --- 2549,2567 ---- class G1RemarkThreadsClosure : public ThreadClosure { CMObjectClosure _cm_obj; G1CMOopClosure _cm_cl; MarkingCodeBlobClosure _code_cl; int _thread_parity; public: ! G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task) : _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations), ! _thread_parity(SharedHeap::heap()->strong_roots_parity()) {} void do_thread(Thread* thread) { if (thread->is_Java_thread()) { ! if (thread->claim_oops_do(true, _thread_parity)) { JavaThread* jt = (JavaThread*)thread; // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking // however the liveness of oops reachable from nmethods have very complex lifecycles: // * Alive if on the stack of an executing method
*** 2629,2649 **** jt->nmethods_do(&_code_cl); jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj); } } else if (thread->is_VM_thread()) { ! if (thread->claim_oops_do(_is_par, _thread_parity)) { JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj); } } } }; class CMRemarkTask: public AbstractGangTask { private: ConcurrentMark* _cm; - bool _is_serial; public: void work(uint worker_id) { // Since all available tasks are actually started, we should // only proceed if we're supposed to be active. if (worker_id < _cm->active_tasks()) { --- 2571,2590 ---- jt->nmethods_do(&_code_cl); jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj); } } else if (thread->is_VM_thread()) { ! if (thread->claim_oops_do(true, _thread_parity)) { JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj); } } } }; class CMRemarkTask: public AbstractGangTask { private: ConcurrentMark* _cm; public: void work(uint worker_id) { // Since all available tasks are actually started, we should // only proceed if we're supposed to be active. if (worker_id < _cm->active_tasks()) {
*** 2651,2677 **** task->record_start_time(); { ResourceMark rm; HandleMark hm; ! G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task, !_is_serial); Threads::threads_do(&threads_f); } do { task->do_marking_step(1000000000.0 /* something very large */, true /* do_termination */, ! _is_serial); } while (task->has_aborted() && !_cm->has_overflown()); // If we overflow, then we do not want to restart. We instead // want to abort remark and do concurrent marking again. task->record_end_time(); } } ! CMRemarkTask(ConcurrentMark* cm, int active_workers, bool is_serial) : ! AbstractGangTask("Par Remark"), _cm(cm), _is_serial(is_serial) { _cm->terminator()->reset_for_reuse(active_workers); } }; void ConcurrentMark::checkpointRootsFinalWork() { --- 2592,2618 ---- task->record_start_time(); { ResourceMark rm; HandleMark hm; ! G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task); Threads::threads_do(&threads_f); } do { task->do_marking_step(1000000000.0 /* something very large */, true /* do_termination */, ! false /* is_serial */); } while (task->has_aborted() && !_cm->has_overflown()); // If we overflow, then we do not want to restart. We instead // want to abort remark and do concurrent marking again. task->record_end_time(); } } ! CMRemarkTask(ConcurrentMark* cm, int active_workers) : ! AbstractGangTask("Par Remark"), _cm(cm) { _cm->terminator()->reset_for_reuse(active_workers); } }; void ConcurrentMark::checkpointRootsFinalWork() {
*** 2681,2691 **** G1CMTraceTime trace("Finalize Marking", G1Log::finer()); g1h->ensure_parsability(false); - if (G1CollectedHeap::use_parallel_gc_threads()) { G1CollectedHeap::StrongRootsScope srs(g1h); // this is remark, so we'll use up all active threads uint active_workers = g1h->workers()->active_workers(); if (active_workers == 0) { assert(active_workers > 0, "Should have been set earlier"); --- 2622,2631 ----
*** 2696,2727 **** // Leave _parallel_marking_threads at it's // value originally calculated in the ConcurrentMark // constructor and pass values of the active workers // through the gang in the task. ! CMRemarkTask remarkTask(this, active_workers, false /* is_serial */); // We will start all available threads, even if we decide that the // active_workers will be fewer. The extra ones will just bail out // immediately. g1h->set_par_threads(active_workers); g1h->workers()->run_task(&remarkTask); g1h->set_par_threads(0); - } else { - G1CollectedHeap::StrongRootsScope srs(g1h); - uint active_workers = 1; - set_concurrency_and_phase(active_workers, false /* concurrent */); - // Note - if there's no work gang then the VMThread will be - // the thread to execute the remark - serially. We have - // to pass true for the is_serial parameter so that - // CMTask::do_marking_step() doesn't enter the sync - // barriers in the event of an overflow. Doing so will - // cause an assert that the current thread is not a - // concurrent GC thread. - CMRemarkTask remarkTask(this, active_workers, true /* is_serial*/); - remarkTask.work(0); - } SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, err_msg("Invariant: has_overflown = %s, num buffers = %d", BOOL_TO_STR(has_overflown()), --- 2636,2653 ---- // Leave _parallel_marking_threads at it's // value originally calculated in the ConcurrentMark // constructor and pass values of the active workers // through the gang in the task. ! CMRemarkTask remarkTask(this, active_workers); // We will start all available threads, even if we decide that the // active_workers will be fewer. The extra ones will just bail out // immediately. g1h->set_par_threads(active_workers); g1h->workers()->run_task(&remarkTask); g1h->set_par_threads(0); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, err_msg("Invariant: has_overflown = %s, num buffers = %d", BOOL_TO_STR(has_overflown()),
*** 3263,3296 **** } void work(uint worker_id) { AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); - if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); - } else { - _g1h->heap_region_iterate(&cl); - } } }; void ConcurrentMark::aggregate_count_data() { ! int n_workers = (G1CollectedHeap::use_parallel_gc_threads() ? ! _g1h->workers()->active_workers() : ! 1); G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, _max_worker_id, n_workers); - if (G1CollectedHeap::use_parallel_gc_threads()) { _g1h->set_par_threads(n_workers); _g1h->workers()->run_task(&g1_par_agg_task); _g1h->set_par_threads(0); - } else { - g1_par_agg_task.work(0); - } _g1h->allocation_context_stats().update_at_remark(); } // Clear the per-worker arrays used to store the per-region counting data void ConcurrentMark::clear_all_count_data() { --- 3189,3212 ---- } void work(uint worker_id) { AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); } }; void ConcurrentMark::aggregate_count_data() { ! int n_workers = _g1h->workers()->active_workers(); G1AggregateCountDataTask g1_par_agg_task(_g1h, this, &_card_bm, _max_worker_id, n_workers); _g1h->set_par_threads(n_workers); _g1h->workers()->run_task(&g1_par_agg_task); _g1h->set_par_threads(0); _g1h->allocation_context_stats().update_at_remark(); } // Clear the per-worker arrays used to store the per-region counting data void ConcurrentMark::clear_all_count_data() {
*** 3414,3426 **** cmThread()->vtime_accum(), cmThread()->vtime_mark_accum()); } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - if (use_parallel_marking_threads()) { _parallel_workers->print_worker_threads_on(st); - } } void ConcurrentMark::print_on_error(outputStream* st) const { st->print_cr("Marking Bits (Prev, Next): (CMBitMap*) " PTR_FORMAT ", (CMBitMap*) " PTR_FORMAT, p2i(_prevMarkBitMap), p2i(_nextMarkBitMap)); --- 3330,3340 ----
*** 3937,3985 **** // very counter productive if it did that. :-) _draining_satb_buffers = true; CMObjectClosure oc(this); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); ! if (G1CollectedHeap::use_parallel_gc_threads()) { ! satb_mq_set.set_par_closure(_worker_id, &oc); ! } else { ! satb_mq_set.set_closure(&oc); ! } // This keeps claiming and applying the closure to completed buffers // until we run out of buffers or we need to abort. - if (G1CollectedHeap::use_parallel_gc_threads()) { - while (!has_aborted() && - satb_mq_set.par_apply_closure_to_completed_buffer(_worker_id)) { - if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); - } - statsOnly( ++_satb_buffers_processed ); - regular_clock_call(); - } - } else { while (!has_aborted() && ! satb_mq_set.apply_closure_to_completed_buffer()) { if (_cm->verbose_medium()) { gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); } statsOnly( ++_satb_buffers_processed ); regular_clock_call(); } - } _draining_satb_buffers = false; assert(has_aborted() || concurrent() || satb_mq_set.completed_buffers_num() == 0, "invariant"); ! if (G1CollectedHeap::use_parallel_gc_threads()) { ! satb_mq_set.set_par_closure(_worker_id, NULL); ! } else { ! satb_mq_set.set_closure(NULL); ! } // again, this was a potentially expensive operation, decrease the // limits to get the regular clock call early decrease_limits(); } --- 3851,3880 ---- // very counter productive if it did that. :-) _draining_satb_buffers = true; CMObjectClosure oc(this); SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); ! satb_mq_set.set_closure(_worker_id, &oc); // This keeps claiming and applying the closure to completed buffers // until we run out of buffers or we need to abort. while (!has_aborted() && ! satb_mq_set.apply_closure_to_completed_buffer(_worker_id)) { if (_cm->verbose_medium()) { gclog_or_tty->print_cr("[%u] processed an SATB buffer", _worker_id); } statsOnly( ++_satb_buffers_processed ); regular_clock_call(); } _draining_satb_buffers = false; assert(has_aborted() || concurrent() || satb_mq_set.completed_buffers_num() == 0, "invariant"); ! satb_mq_set.set_closure(_worker_id, NULL); // again, this was a potentially expensive operation, decrease the // limits to get the regular clock call early decrease_limits(); }
index