hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
changeset 11396 917d8673b5ef
parent 11204 b68d1c33b2ad
child 11640 778999c69a3e
equal deleted inserted replaced
11395:33260c27554b 11396:917d8673b5ef
  3777 
  3777 
  3778   virtual void set_for_termination(int active_workers) {
  3778   virtual void set_for_termination(int active_workers) {
  3779     terminator()->reset_for_reuse(active_workers);
  3779     terminator()->reset_for_reuse(active_workers);
  3780   }
  3780   }
  3781 
  3781 
  3782   void work(int i);
  3782   void work(uint worker_id);
  3783   bool should_yield() {
  3783   bool should_yield() {
  3784     return    ConcurrentMarkSweepThread::should_yield()
  3784     return    ConcurrentMarkSweepThread::should_yield()
  3785            && !_collector->foregroundGCIsActive()
  3785            && !_collector->foregroundGCIsActive()
  3786            && _asynch;
  3786            && _asynch;
  3787   }
  3787   }
  3850 //    . check global overflow stack; steal a batch of oops and trace
  3850 //    . check global overflow stack; steal a batch of oops and trace
  3851 //    . try to steal from other threads oif GOS is empty
  3851 //    . try to steal from other threads oif GOS is empty
  3852 //    . if neither is available, offer termination
  3852 //    . if neither is available, offer termination
  3853 // -- Terminate and return result
  3853 // -- Terminate and return result
  3854 //
  3854 //
  3855 void CMSConcMarkingTask::work(int i) {
  3855 void CMSConcMarkingTask::work(uint worker_id) {
  3856   elapsedTimer _timer;
  3856   elapsedTimer _timer;
  3857   ResourceMark rm;
  3857   ResourceMark rm;
  3858   HandleMark hm;
  3858   HandleMark hm;
  3859 
  3859 
  3860   DEBUG_ONLY(_collector->verify_overflow_empty();)
  3860   DEBUG_ONLY(_collector->verify_overflow_empty();)
  3861 
  3861 
  3862   // Before we begin work, our work queue should be empty
  3862   // Before we begin work, our work queue should be empty
  3863   assert(work_queue(i)->size() == 0, "Expected to be empty");
  3863   assert(work_queue(worker_id)->size() == 0, "Expected to be empty");
  3864   // Scan the bitmap covering _cms_space, tracing through grey objects.
  3864   // Scan the bitmap covering _cms_space, tracing through grey objects.
  3865   _timer.start();
  3865   _timer.start();
  3866   do_scan_and_mark(i, _cms_space);
  3866   do_scan_and_mark(worker_id, _cms_space);
  3867   _timer.stop();
  3867   _timer.stop();
  3868   if (PrintCMSStatistics != 0) {
  3868   if (PrintCMSStatistics != 0) {
  3869     gclog_or_tty->print_cr("Finished cms space scanning in %dth thread: %3.3f sec",
  3869     gclog_or_tty->print_cr("Finished cms space scanning in %dth thread: %3.3f sec",
  3870       i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
  3870       worker_id, _timer.seconds());
       
  3871       // XXX: need xxx/xxx type of notation, two timers
  3871   }
  3872   }
  3872 
  3873 
  3873   // ... do the same for the _perm_space
  3874   // ... do the same for the _perm_space
  3874   _timer.reset();
  3875   _timer.reset();
  3875   _timer.start();
  3876   _timer.start();
  3876   do_scan_and_mark(i, _perm_space);
  3877   do_scan_and_mark(worker_id, _perm_space);
  3877   _timer.stop();
  3878   _timer.stop();
  3878   if (PrintCMSStatistics != 0) {
  3879   if (PrintCMSStatistics != 0) {
  3879     gclog_or_tty->print_cr("Finished perm space scanning in %dth thread: %3.3f sec",
  3880     gclog_or_tty->print_cr("Finished perm space scanning in %dth thread: %3.3f sec",
  3880       i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
  3881       worker_id, _timer.seconds());
       
  3882       // XXX: need xxx/xxx type of notation, two timers
  3881   }
  3883   }
  3882 
  3884 
  3883   // ... do work stealing
  3885   // ... do work stealing
  3884   _timer.reset();
  3886   _timer.reset();
  3885   _timer.start();
  3887   _timer.start();
  3886   do_work_steal(i);
  3888   do_work_steal(worker_id);
  3887   _timer.stop();
  3889   _timer.stop();
  3888   if (PrintCMSStatistics != 0) {
  3890   if (PrintCMSStatistics != 0) {
  3889     gclog_or_tty->print_cr("Finished work stealing in %dth thread: %3.3f sec",
  3891     gclog_or_tty->print_cr("Finished work stealing in %dth thread: %3.3f sec",
  3890       i, _timer.seconds()); // XXX: need xxx/xxx type of notation, two timers
  3892       worker_id, _timer.seconds());
       
  3893       // XXX: need xxx/xxx type of notation, two timers
  3891   }
  3894   }
  3892   assert(_collector->_markStack.isEmpty(), "Should have been emptied");
  3895   assert(_collector->_markStack.isEmpty(), "Should have been emptied");
  3893   assert(work_queue(i)->size() == 0, "Should have been emptied");
  3896   assert(work_queue(worker_id)->size() == 0, "Should have been emptied");
  3894   // Note that under the current task protocol, the
  3897   // Note that under the current task protocol, the
  3895   // following assertion is true even of the spaces
  3898   // following assertion is true even of the spaces
  3896   // expanded since the completion of the concurrent
  3899   // expanded since the completion of the concurrent
  3897   // marking. XXX This will likely change under a strict
  3900   // marking. XXX This will likely change under a strict
  3898   // ABORT semantics.
  3901   // ABORT semantics.
  3944   SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
  3947   SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
  3945   int n_tasks = pst->n_tasks();
  3948   int n_tasks = pst->n_tasks();
  3946   // We allow that there may be no tasks to do here because
  3949   // We allow that there may be no tasks to do here because
  3947   // we are restarting after a stack overflow.
  3950   // we are restarting after a stack overflow.
  3948   assert(pst->valid() || n_tasks == 0, "Uninitialized use?");
  3951   assert(pst->valid() || n_tasks == 0, "Uninitialized use?");
  3949   int nth_task = 0;
  3952   uint nth_task = 0;
  3950 
  3953 
  3951   HeapWord* aligned_start = sp->bottom();
  3954   HeapWord* aligned_start = sp->bottom();
  3952   if (sp->used_region().contains(_restart_addr)) {
  3955   if (sp->used_region().contains(_restart_addr)) {
  3953     // Align down to a card boundary for the start of 0th task
  3956     // Align down to a card boundary for the start of 0th task
  3954     // for this space.
  3957     // for this space.
  5073   OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
  5076   OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
  5074 
  5077 
  5075   ParallelTaskTerminator* terminator() { return &_term; }
  5078   ParallelTaskTerminator* terminator() { return &_term; }
  5076   int n_workers() { return _n_workers; }
  5079   int n_workers() { return _n_workers; }
  5077 
  5080 
  5078   void work(int i);
  5081   void work(uint worker_id);
  5079 
  5082 
  5080  private:
  5083  private:
  5081   // Work method in support of parallel rescan ... of young gen spaces
  5084   // Work method in support of parallel rescan ... of young gen spaces
  5082   void do_young_space_rescan(int i, Par_MarkRefsIntoAndScanClosure* cl,
  5085   void do_young_space_rescan(int i, Par_MarkRefsIntoAndScanClosure* cl,
  5083                              ContiguousSpace* space,
  5086                              ContiguousSpace* space,
  5094 // work_queue(i) is passed to the closure
  5097 // work_queue(i) is passed to the closure
  5095 // Par_MarkRefsIntoAndScanClosure.  The "i" parameter
  5098 // Par_MarkRefsIntoAndScanClosure.  The "i" parameter
  5096 // also is passed to do_dirty_card_rescan_tasks() and to
  5099 // also is passed to do_dirty_card_rescan_tasks() and to
  5097 // do_work_steal() to select the i-th task_queue.
  5100 // do_work_steal() to select the i-th task_queue.
  5098 
  5101 
  5099 void CMSParRemarkTask::work(int i) {
  5102 void CMSParRemarkTask::work(uint worker_id) {
  5100   elapsedTimer _timer;
  5103   elapsedTimer _timer;
  5101   ResourceMark rm;
  5104   ResourceMark rm;
  5102   HandleMark   hm;
  5105   HandleMark   hm;
  5103 
  5106 
  5104   // ---------- rescan from roots --------------
  5107   // ---------- rescan from roots --------------
  5105   _timer.start();
  5108   _timer.start();
  5106   GenCollectedHeap* gch = GenCollectedHeap::heap();
  5109   GenCollectedHeap* gch = GenCollectedHeap::heap();
  5107   Par_MarkRefsIntoAndScanClosure par_mrias_cl(_collector,
  5110   Par_MarkRefsIntoAndScanClosure par_mrias_cl(_collector,
  5108     _collector->_span, _collector->ref_processor(),
  5111     _collector->_span, _collector->ref_processor(),
  5109     &(_collector->_markBitMap),
  5112     &(_collector->_markBitMap),
  5110     work_queue(i), &(_collector->_revisitStack));
  5113     work_queue(worker_id), &(_collector->_revisitStack));
  5111 
  5114 
  5112   // Rescan young gen roots first since these are likely
  5115   // Rescan young gen roots first since these are likely
  5113   // coarsely partitioned and may, on that account, constitute
  5116   // coarsely partitioned and may, on that account, constitute
  5114   // the critical path; thus, it's best to start off that
  5117   // the critical path; thus, it's best to start off that
  5115   // work first.
  5118   // work first.
  5126     size_t     sct = _collector->_survivor_chunk_index;
  5129     size_t     sct = _collector->_survivor_chunk_index;
  5127 
  5130 
  5128     assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
  5131     assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
  5129     assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
  5132     assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
  5130 
  5133 
  5131     do_young_space_rescan(i, &par_mrias_cl, to_space, NULL, 0);
  5134     do_young_space_rescan(worker_id, &par_mrias_cl, to_space, NULL, 0);
  5132     do_young_space_rescan(i, &par_mrias_cl, from_space, sca, sct);
  5135     do_young_space_rescan(worker_id, &par_mrias_cl, from_space, sca, sct);
  5133     do_young_space_rescan(i, &par_mrias_cl, eden_space, eca, ect);
  5136     do_young_space_rescan(worker_id, &par_mrias_cl, eden_space, eca, ect);
  5134 
  5137 
  5135     _timer.stop();
  5138     _timer.stop();
  5136     if (PrintCMSStatistics != 0) {
  5139     if (PrintCMSStatistics != 0) {
  5137       gclog_or_tty->print_cr(
  5140       gclog_or_tty->print_cr(
  5138         "Finished young gen rescan work in %dth thread: %3.3f sec",
  5141         "Finished young gen rescan work in %dth thread: %3.3f sec",
  5139         i, _timer.seconds());
  5142         worker_id, _timer.seconds());
  5140     }
  5143     }
  5141   }
  5144   }
  5142 
  5145 
  5143   // ---------- remaining roots --------------
  5146   // ---------- remaining roots --------------
  5144   _timer.reset();
  5147   _timer.reset();
  5156          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
  5159          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
  5157   _timer.stop();
  5160   _timer.stop();
  5158   if (PrintCMSStatistics != 0) {
  5161   if (PrintCMSStatistics != 0) {
  5159     gclog_or_tty->print_cr(
  5162     gclog_or_tty->print_cr(
  5160       "Finished remaining root rescan work in %dth thread: %3.3f sec",
  5163       "Finished remaining root rescan work in %dth thread: %3.3f sec",
  5161       i, _timer.seconds());
  5164       worker_id, _timer.seconds());
  5162   }
  5165   }
  5163 
  5166 
  5164   // ---------- rescan dirty cards ------------
  5167   // ---------- rescan dirty cards ------------
  5165   _timer.reset();
  5168   _timer.reset();
  5166   _timer.start();
  5169   _timer.start();
  5167 
  5170 
  5168   // Do the rescan tasks for each of the two spaces
  5171   // Do the rescan tasks for each of the two spaces
  5169   // (cms_space and perm_space) in turn.
  5172   // (cms_space and perm_space) in turn.
  5170   // "i" is passed to select the "i-th" task_queue
  5173   // "worker_id" is passed to select the task_queue for "worker_id"
  5171   do_dirty_card_rescan_tasks(_cms_space, i, &par_mrias_cl);
  5174   do_dirty_card_rescan_tasks(_cms_space, worker_id, &par_mrias_cl);
  5172   do_dirty_card_rescan_tasks(_perm_space, i, &par_mrias_cl);
  5175   do_dirty_card_rescan_tasks(_perm_space, worker_id, &par_mrias_cl);
  5173   _timer.stop();
  5176   _timer.stop();
  5174   if (PrintCMSStatistics != 0) {
  5177   if (PrintCMSStatistics != 0) {
  5175     gclog_or_tty->print_cr(
  5178     gclog_or_tty->print_cr(
  5176       "Finished dirty card rescan work in %dth thread: %3.3f sec",
  5179       "Finished dirty card rescan work in %dth thread: %3.3f sec",
  5177       i, _timer.seconds());
  5180       worker_id, _timer.seconds());
  5178   }
  5181   }
  5179 
  5182 
  5180   // ---------- steal work from other threads ...
  5183   // ---------- steal work from other threads ...
  5181   // ---------- ... and drain overflow list.
  5184   // ---------- ... and drain overflow list.
  5182   _timer.reset();
  5185   _timer.reset();
  5183   _timer.start();
  5186   _timer.start();
  5184   do_work_steal(i, &par_mrias_cl, _collector->hash_seed(i));
  5187   do_work_steal(worker_id, &par_mrias_cl, _collector->hash_seed(worker_id));
  5185   _timer.stop();
  5188   _timer.stop();
  5186   if (PrintCMSStatistics != 0) {
  5189   if (PrintCMSStatistics != 0) {
  5187     gclog_or_tty->print_cr(
  5190     gclog_or_tty->print_cr(
  5188       "Finished work stealing in %dth thread: %3.3f sec",
  5191       "Finished work stealing in %dth thread: %3.3f sec",
  5189       i, _timer.seconds());
  5192       worker_id, _timer.seconds());
  5190   }
  5193   }
  5191 }
  5194 }
  5192 
  5195 
  5193 // Note that parameter "i" is not used.
  5196 // Note that parameter "i" is not used.
  5194 void
  5197 void
  5205   HandleMark   hm;
  5208   HandleMark   hm;
  5206 
  5209 
  5207   SequentialSubTasksDone* pst = space->par_seq_tasks();
  5210   SequentialSubTasksDone* pst = space->par_seq_tasks();
  5208   assert(pst->valid(), "Uninitialized use?");
  5211   assert(pst->valid(), "Uninitialized use?");
  5209 
  5212 
  5210   int nth_task = 0;
  5213   uint nth_task = 0;
  5211   int n_tasks  = pst->n_tasks();
  5214   uint n_tasks  = pst->n_tasks();
  5212 
  5215 
  5213   HeapWord *start, *end;
  5216   HeapWord *start, *end;
  5214   while (!pst->is_task_claimed(/* reference */ nth_task)) {
  5217   while (!pst->is_task_claimed(/* reference */ nth_task)) {
  5215     // We claimed task # nth_task; compute its boundaries.
  5218     // We claimed task # nth_task; compute its boundaries.
  5216     if (chunk_top == 0) {  // no samples were taken
  5219     if (chunk_top == 0) {  // no samples were taken
  5218       start = space->bottom();
  5221       start = space->bottom();
  5219       end   = space->top();
  5222       end   = space->top();
  5220     } else if (nth_task == 0) {
  5223     } else if (nth_task == 0) {
  5221       start = space->bottom();
  5224       start = space->bottom();
  5222       end   = chunk_array[nth_task];
  5225       end   = chunk_array[nth_task];
  5223     } else if (nth_task < (jint)chunk_top) {
  5226     } else if (nth_task < (uint)chunk_top) {
  5224       assert(nth_task >= 1, "Control point invariant");
  5227       assert(nth_task >= 1, "Control point invariant");
  5225       start = chunk_array[nth_task - 1];
  5228       start = chunk_array[nth_task - 1];
  5226       end   = chunk_array[nth_task];
  5229       end   = chunk_array[nth_task];
  5227     } else {
  5230     } else {
  5228       assert(nth_task == (jint)chunk_top, "Control point invariant");
  5231       assert(nth_task == (uint)chunk_top, "Control point invariant");
  5229       start = chunk_array[chunk_top - 1];
  5232       start = chunk_array[chunk_top - 1];
  5230       end   = space->top();
  5233       end   = space->top();
  5231     }
  5234     }
  5232     MemRegion mr(start, end);
  5235     MemRegion mr(start, end);
  5233     // Verify that mr is in space
  5236     // Verify that mr is in space
  5286     greyRescanClosure(_collector, full_span, // entire span of interest
  5289     greyRescanClosure(_collector, full_span, // entire span of interest
  5287                       sp, bm, work_q, rs, cl);
  5290                       sp, bm, work_q, rs, cl);
  5288 
  5291 
  5289   SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
  5292   SequentialSubTasksDone* pst = sp->conc_par_seq_tasks();
  5290   assert(pst->valid(), "Uninitialized use?");
  5293   assert(pst->valid(), "Uninitialized use?");
  5291   int nth_task = 0;
  5294   uint nth_task = 0;
  5292   const int alignment = CardTableModRefBS::card_size * BitsPerWord;
  5295   const int alignment = CardTableModRefBS::card_size * BitsPerWord;
  5293   MemRegion span = sp->used_region();
  5296   MemRegion span = sp->used_region();
  5294   HeapWord* start_addr = span.start();
  5297   HeapWord* start_addr = span.start();
  5295   HeapWord* end_addr = (HeapWord*)round_to((intptr_t)span.end(),
  5298   HeapWord* end_addr = (HeapWord*)round_to((intptr_t)span.end(),
  5296                                            alignment);
  5299                                            alignment);
  5734   void do_work_steal(int i,
  5737   void do_work_steal(int i,
  5735                      CMSParDrainMarkingStackClosure* drain,
  5738                      CMSParDrainMarkingStackClosure* drain,
  5736                      CMSParKeepAliveClosure* keep_alive,
  5739                      CMSParKeepAliveClosure* keep_alive,
  5737                      int* seed);
  5740                      int* seed);
  5738 
  5741 
  5739   virtual void work(int i);
  5742   virtual void work(uint worker_id);
  5740 };
  5743 };
  5741 
  5744 
  5742 void CMSRefProcTaskProxy::work(int i) {
  5745 void CMSRefProcTaskProxy::work(uint worker_id) {
  5743   assert(_collector->_span.equals(_span), "Inconsistency in _span");
  5746   assert(_collector->_span.equals(_span), "Inconsistency in _span");
  5744   CMSParKeepAliveClosure par_keep_alive(_collector, _span,
  5747   CMSParKeepAliveClosure par_keep_alive(_collector, _span,
  5745                                         _mark_bit_map,
  5748                                         _mark_bit_map,
  5746                                         &_collector->_revisitStack,
  5749                                         &_collector->_revisitStack,
  5747                                         work_queue(i));
  5750                                         work_queue(worker_id));
  5748   CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span,
  5751   CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span,
  5749                                                  _mark_bit_map,
  5752                                                  _mark_bit_map,
  5750                                                  &_collector->_revisitStack,
  5753                                                  &_collector->_revisitStack,
  5751                                                  work_queue(i));
  5754                                                  work_queue(worker_id));
  5752   CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map);
  5755   CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map);
  5753   _task.work(i, is_alive_closure, par_keep_alive, par_drain_stack);
  5756   _task.work(worker_id, is_alive_closure, par_keep_alive, par_drain_stack);
  5754   if (_task.marks_oops_alive()) {
  5757   if (_task.marks_oops_alive()) {
  5755     do_work_steal(i, &par_drain_stack, &par_keep_alive,
  5758     do_work_steal(worker_id, &par_drain_stack, &par_keep_alive,
  5756                   _collector->hash_seed(i));
  5759                   _collector->hash_seed(worker_id));
  5757   }
  5760   }
  5758   assert(work_queue(i)->size() == 0, "work_queue should be empty");
  5761   assert(work_queue(worker_id)->size() == 0, "work_queue should be empty");
  5759   assert(_collector->_overflow_list == NULL, "non-empty _overflow_list");
  5762   assert(_collector->_overflow_list == NULL, "non-empty _overflow_list");
  5760 }
  5763 }
  5761 
  5764 
  5762 class CMSRefEnqueueTaskProxy: public AbstractGangTask {
  5765 class CMSRefEnqueueTaskProxy: public AbstractGangTask {
  5763   typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
  5766   typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask;
  5767   CMSRefEnqueueTaskProxy(EnqueueTask& task)
  5770   CMSRefEnqueueTaskProxy(EnqueueTask& task)
  5768     : AbstractGangTask("Enqueue reference objects in parallel"),
  5771     : AbstractGangTask("Enqueue reference objects in parallel"),
  5769       _task(task)
  5772       _task(task)
  5770   { }
  5773   { }
  5771 
  5774 
  5772   virtual void work(int i)
  5775   virtual void work(uint worker_id)
  5773   {
  5776   {
  5774     _task.work(i);
  5777     _task.work(worker_id);
  5775   }
  5778   }
  5776 };
  5779 };
  5777 
  5780 
  5778 CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector,
  5781 CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector,
  5779   MemRegion span, CMSBitMap* bit_map, CMSMarkStack* revisit_stack,
  5782   MemRegion span, CMSBitMap* bit_map, CMSMarkStack* revisit_stack,