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 |
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; |