< prev index next >

src/hotspot/share/gc/g1/g1ConcurrentMark.cpp

Print this page
rev 47875 : 8190408: Run G1CMRemarkTask with the appropriate amount of threads instead of starting up everyone

Removing an if statement. The if-statement did safeguard that the
worker_id was always within the number of active tasks in _cm.

However the active number of tasks in _cm is set directly before the
remark task is created (set_concurrency_and_phase()). The value is
taken from the work gang (g1h->workers()->active_workers()). Thus, as
set_concurrency*() is not called during the actual remarking, the size
of the work-gang will be in sync with the _cm->active_tasks() -- at
least during the remark phase.

The code becomes somewhat easier to read, and hopefully one does not
get confused that we have too many threads running.


1739         // * Weakly reachable otherwise
1740         // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
1741         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
1742         jt->nmethods_do(&_code_cl);
1743 
1744         jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
1745       }
1746     } else if (thread->is_VM_thread()) {
1747       if (thread->claim_oops_do(true, _thread_parity)) {
1748         JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
1749       }
1750     }
1751   }
1752 };
1753 
1754 class G1CMRemarkTask: public AbstractGangTask {
1755 private:
1756   G1ConcurrentMark* _cm;
1757 public:
1758   void work(uint worker_id) {
1759     // Since all available tasks are actually started, we should
1760     // only proceed if we're supposed to be active.
1761     if (worker_id < _cm->active_tasks()) {
1762       G1CMTask* task = _cm->task(worker_id);
1763       task->record_start_time();
1764       {
1765         ResourceMark rm;
1766         HandleMark hm;
1767 
1768         G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task);
1769         Threads::threads_do(&threads_f);
1770       }
1771 
1772       do {
1773         task->do_marking_step(1000000000.0 /* something very large */,
1774                               true         /* do_termination       */,
1775                               false        /* is_serial            */);
1776       } while (task->has_aborted() && !_cm->has_overflown());
1777       // If we overflow, then we do not want to restart. We instead
1778       // want to abort remark and do concurrent marking again.
1779       task->record_end_time();
1780     }









1781   }
1782 
1783   G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) :
1784     AbstractGangTask("Par Remark"), _cm(cm) {
1785     _cm->terminator()->reset_for_reuse(active_workers);
1786   }
1787 };
1788 
1789 void G1ConcurrentMark::checkpoint_roots_final_work() {
1790   ResourceMark rm;
1791   HandleMark   hm;
1792   G1CollectedHeap* g1h = G1CollectedHeap::heap();
1793 
1794   GCTraceTime(Debug, gc, phases) trace("Finalize Marking", _gc_timer_cm);
1795 
1796   g1h->ensure_parsability(false);
1797 
1798   // this is remark, so we'll use up all active threads
1799   uint active_workers = g1h->workers()->active_workers();
1800   set_concurrency_and_phase(active_workers, false /* concurrent */);




1739         // * Weakly reachable otherwise
1740         // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
1741         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
1742         jt->nmethods_do(&_code_cl);
1743 
1744         jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
1745       }
1746     } else if (thread->is_VM_thread()) {
1747       if (thread->claim_oops_do(true, _thread_parity)) {
1748         JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
1749       }
1750     }
1751   }
1752 };
1753 
1754 class G1CMRemarkTask: public AbstractGangTask {
1755 private:
1756   G1ConcurrentMark* _cm;
1757 public:
1758   void work(uint worker_id) {
1759     G1CMTask* task = _cm->task(worker_id);
1760     task->record_start_time();
1761     {
1762       ResourceMark rm;
1763       HandleMark hm;



1764 
1765       G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task);
1766       Threads::threads_do(&threads_f);










1767     }
1768 
1769     do {
1770       task->do_marking_step(1000000000.0 /* something very large */,
1771                             true         /* do_termination       */,
1772                             false        /* is_serial            */);
1773     } while (task->has_aborted() && !_cm->has_overflown());
1774     // If we overflow, then we do not want to restart. We instead
1775     // want to abort remark and do concurrent marking again.
1776     task->record_end_time();
1777   }
1778 
1779   G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) :
1780     AbstractGangTask("Par Remark"), _cm(cm) {
1781     _cm->terminator()->reset_for_reuse(active_workers);
1782   }
1783 };
1784 
1785 void G1ConcurrentMark::checkpoint_roots_final_work() {
1786   ResourceMark rm;
1787   HandleMark   hm;
1788   G1CollectedHeap* g1h = G1CollectedHeap::heap();
1789 
1790   GCTraceTime(Debug, gc, phases) trace("Finalize Marking", _gc_timer_cm);
1791 
1792   g1h->ensure_parsability(false);
1793 
1794   // this is remark, so we'll use up all active threads
1795   uint active_workers = g1h->workers()->active_workers();
1796   set_concurrency_and_phase(active_workers, false /* concurrent */);


< prev index next >