Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @ 11975:ca9dedeebdec
6412968: CMS Long initial mark pauses
Reviewed-by: rasbold, tschatzl, jmasa
Contributed-by: yamauchi@google.com
author | jmasa |
---|---|
date | Thu, 25 Jul 2013 11:07:23 -0700 |
parents | 7b06ae405d7b |
children | 9766f73e770d |
comparison
equal
deleted
inserted
replaced
11974:fb7010c7c011 | 11975:ca9dedeebdec |
---|---|
731 } | 731 } |
732 } | 732 } |
733 assert(_eden_chunk_array != NULL || _eden_chunk_capacity == 0, "Error"); | 733 assert(_eden_chunk_array != NULL || _eden_chunk_capacity == 0, "Error"); |
734 | 734 |
735 // Support for parallelizing survivor space rescan | 735 // Support for parallelizing survivor space rescan |
736 if (CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) { | 736 if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) { |
737 const size_t max_plab_samples = | 737 const size_t max_plab_samples = |
738 ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize; | 738 ((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize; |
739 | 739 |
740 _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC); | 740 _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC); |
741 _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC); | 741 _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC); |
3581 } | 3581 } |
3582 } | 3582 } |
3583 | 3583 |
3584 // CMS work | 3584 // CMS work |
3585 | 3585 |
3586 // The common parts of CMSParInitialMarkTask and CMSParRemarkTask. | |
3587 class CMSParMarkTask : public AbstractGangTask { | |
3588 protected: | |
3589 CMSCollector* _collector; | |
3590 int _n_workers; | |
3591 CMSParMarkTask(const char* name, CMSCollector* collector, int n_workers) : | |
3592 AbstractGangTask(name), | |
3593 _collector(collector), | |
3594 _n_workers(n_workers) {} | |
3595 // Work method in support of parallel rescan ... of young gen spaces | |
3596 void do_young_space_rescan(uint worker_id, OopsInGenClosure* cl, | |
3597 ContiguousSpace* space, | |
3598 HeapWord** chunk_array, size_t chunk_top); | |
3599 void work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl); | |
3600 }; | |
3601 | |
3602 // Parallel initial mark task | |
3603 class CMSParInitialMarkTask: public CMSParMarkTask { | |
3604 public: | |
3605 CMSParInitialMarkTask(CMSCollector* collector, int n_workers) : | |
3606 CMSParMarkTask("Scan roots and young gen for initial mark in parallel", | |
3607 collector, n_workers) {} | |
3608 void work(uint worker_id); | |
3609 }; | |
3610 | |
3586 // Checkpoint the roots into this generation from outside | 3611 // Checkpoint the roots into this generation from outside |
3587 // this generation. [Note this initial checkpoint need only | 3612 // this generation. [Note this initial checkpoint need only |
3588 // be approximate -- we'll do a catch up phase subsequently.] | 3613 // be approximate -- we'll do a catch up phase subsequently.] |
3589 void CMSCollector::checkpointRootsInitial(bool asynch) { | 3614 void CMSCollector::checkpointRootsInitial(bool asynch) { |
3590 assert(_collectorState == InitialMarking, "Wrong collector state"); | 3615 assert(_collectorState == InitialMarking, "Wrong collector state"); |
3682 | 3707 |
3683 if (CMSPrintEdenSurvivorChunks) { | 3708 if (CMSPrintEdenSurvivorChunks) { |
3684 print_eden_and_survivor_chunk_arrays(); | 3709 print_eden_and_survivor_chunk_arrays(); |
3685 } | 3710 } |
3686 | 3711 |
3687 CMKlassClosure klass_closure(¬Older); | |
3688 { | 3712 { |
3689 COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;) | 3713 COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;) |
3690 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. | 3714 if (CMSParallelInitialMarkEnabled && CollectedHeap::use_parallel_gc_threads()) { |
3691 gch->gen_process_strong_roots(_cmsGen->level(), | 3715 // The parallel version. |
3692 true, // younger gens are roots | 3716 FlexibleWorkGang* workers = gch->workers(); |
3693 true, // activate StrongRootsScope | 3717 assert(workers != NULL, "Need parallel worker threads."); |
3694 false, // not scavenging | 3718 int n_workers = workers->active_workers(); |
3695 SharedHeap::ScanningOption(roots_scanning_options()), | 3719 CMSParInitialMarkTask tsk(this, n_workers); |
3696 ¬Older, | 3720 gch->set_par_threads(n_workers); |
3697 true, // walk all of code cache if (so & SO_CodeCache) | 3721 initialize_sequential_subtasks_for_young_gen_rescan(n_workers); |
3698 NULL, | 3722 if (n_workers > 1) { |
3699 &klass_closure); | 3723 GenCollectedHeap::StrongRootsScope srs(gch); |
3724 workers->run_task(&tsk); | |
3725 } else { | |
3726 GenCollectedHeap::StrongRootsScope srs(gch); | |
3727 tsk.work(0); | |
3728 } | |
3729 gch->set_par_threads(0); | |
3730 } else { | |
3731 // The serial version. | |
3732 CMKlassClosure klass_closure(¬Older); | |
3733 gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. | |
3734 gch->gen_process_strong_roots(_cmsGen->level(), | |
3735 true, // younger gens are roots | |
3736 true, // activate StrongRootsScope | |
3737 false, // not scavenging | |
3738 SharedHeap::ScanningOption(roots_scanning_options()), | |
3739 ¬Older, | |
3740 true, // walk all of code cache if (so & SO_CodeCache) | |
3741 NULL, | |
3742 &klass_closure); | |
3743 } | |
3700 } | 3744 } |
3701 | 3745 |
3702 // Clear mod-union table; it will be dirtied in the prologue of | 3746 // Clear mod-union table; it will be dirtied in the prologue of |
3703 // CMS generation per each younger generation collection. | 3747 // CMS generation per each younger generation collection. |
3704 | 3748 |
5160 if (UseAdaptiveSizePolicy) { | 5204 if (UseAdaptiveSizePolicy) { |
5161 size_policy()->checkpoint_roots_final_end(gch->gc_cause()); | 5205 size_policy()->checkpoint_roots_final_end(gch->gc_cause()); |
5162 } | 5206 } |
5163 } | 5207 } |
5164 | 5208 |
5209 void CMSParInitialMarkTask::work(uint worker_id) { | |
5210 elapsedTimer _timer; | |
5211 ResourceMark rm; | |
5212 HandleMark hm; | |
5213 | |
5214 // ---------- scan from roots -------------- | |
5215 _timer.start(); | |
5216 GenCollectedHeap* gch = GenCollectedHeap::heap(); | |
5217 Par_MarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap)); | |
5218 CMKlassClosure klass_closure(&par_mri_cl); | |
5219 | |
5220 // ---------- young gen roots -------------- | |
5221 { | |
5222 work_on_young_gen_roots(worker_id, &par_mri_cl); | |
5223 _timer.stop(); | |
5224 if (PrintCMSStatistics != 0) { | |
5225 gclog_or_tty->print_cr( | |
5226 "Finished young gen initial mark scan work in %dth thread: %3.3f sec", | |
5227 worker_id, _timer.seconds()); | |
5228 } | |
5229 } | |
5230 | |
5231 // ---------- remaining roots -------------- | |
5232 _timer.reset(); | |
5233 _timer.start(); | |
5234 gch->gen_process_strong_roots(_collector->_cmsGen->level(), | |
5235 false, // yg was scanned above | |
5236 false, // this is parallel code | |
5237 false, // not scavenging | |
5238 SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), | |
5239 &par_mri_cl, | |
5240 true, // walk all of code cache if (so & SO_CodeCache) | |
5241 NULL, | |
5242 &klass_closure); | |
5243 assert(_collector->should_unload_classes() | |
5244 || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache), | |
5245 "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); | |
5246 _timer.stop(); | |
5247 if (PrintCMSStatistics != 0) { | |
5248 gclog_or_tty->print_cr( | |
5249 "Finished remaining root initial mark scan work in %dth thread: %3.3f sec", | |
5250 worker_id, _timer.seconds()); | |
5251 } | |
5252 } | |
5253 | |
5165 // Parallel remark task | 5254 // Parallel remark task |
5166 class CMSParRemarkTask: public AbstractGangTask { | 5255 class CMSParRemarkTask: public CMSParMarkTask { |
5167 CMSCollector* _collector; | |
5168 int _n_workers; | |
5169 CompactibleFreeListSpace* _cms_space; | 5256 CompactibleFreeListSpace* _cms_space; |
5170 | 5257 |
5171 // The per-thread work queues, available here for stealing. | 5258 // The per-thread work queues, available here for stealing. |
5172 OopTaskQueueSet* _task_queues; | 5259 OopTaskQueueSet* _task_queues; |
5173 ParallelTaskTerminator _term; | 5260 ParallelTaskTerminator _term; |
5177 // workers to be taken from the active workers in the work gang. | 5264 // workers to be taken from the active workers in the work gang. |
5178 CMSParRemarkTask(CMSCollector* collector, | 5265 CMSParRemarkTask(CMSCollector* collector, |
5179 CompactibleFreeListSpace* cms_space, | 5266 CompactibleFreeListSpace* cms_space, |
5180 int n_workers, FlexibleWorkGang* workers, | 5267 int n_workers, FlexibleWorkGang* workers, |
5181 OopTaskQueueSet* task_queues): | 5268 OopTaskQueueSet* task_queues): |
5182 AbstractGangTask("Rescan roots and grey objects in parallel"), | 5269 CMSParMarkTask("Rescan roots and grey objects in parallel", |
5183 _collector(collector), | 5270 collector, n_workers), |
5184 _cms_space(cms_space), | 5271 _cms_space(cms_space), |
5185 _n_workers(n_workers), | |
5186 _task_queues(task_queues), | 5272 _task_queues(task_queues), |
5187 _term(n_workers, task_queues) { } | 5273 _term(n_workers, task_queues) { } |
5188 | 5274 |
5189 OopTaskQueueSet* task_queues() { return _task_queues; } | 5275 OopTaskQueueSet* task_queues() { return _task_queues; } |
5190 | 5276 |
5194 int n_workers() { return _n_workers; } | 5280 int n_workers() { return _n_workers; } |
5195 | 5281 |
5196 void work(uint worker_id); | 5282 void work(uint worker_id); |
5197 | 5283 |
5198 private: | 5284 private: |
5199 // Work method in support of parallel rescan ... of young gen spaces | |
5200 void do_young_space_rescan(int i, Par_MarkRefsIntoAndScanClosure* cl, | |
5201 ContiguousSpace* space, | |
5202 HeapWord** chunk_array, size_t chunk_top); | |
5203 | |
5204 // ... of dirty cards in old space | 5285 // ... of dirty cards in old space |
5205 void do_dirty_card_rescan_tasks(CompactibleFreeListSpace* sp, int i, | 5286 void do_dirty_card_rescan_tasks(CompactibleFreeListSpace* sp, int i, |
5206 Par_MarkRefsIntoAndScanClosure* cl); | 5287 Par_MarkRefsIntoAndScanClosure* cl); |
5207 | 5288 |
5208 // ... work stealing for the above | 5289 // ... work stealing for the above |
5230 // The klass has modified fields, need to scan the klass. | 5311 // The klass has modified fields, need to scan the klass. |
5231 _cm_klass_closure.do_klass(k); | 5312 _cm_klass_closure.do_klass(k); |
5232 } | 5313 } |
5233 }; | 5314 }; |
5234 | 5315 |
5316 void CMSParMarkTask::work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl) { | |
5317 DefNewGeneration* dng = _collector->_young_gen->as_DefNewGeneration(); | |
5318 EdenSpace* eden_space = dng->eden(); | |
5319 ContiguousSpace* from_space = dng->from(); | |
5320 ContiguousSpace* to_space = dng->to(); | |
5321 | |
5322 HeapWord** eca = _collector->_eden_chunk_array; | |
5323 size_t ect = _collector->_eden_chunk_index; | |
5324 HeapWord** sca = _collector->_survivor_chunk_array; | |
5325 size_t sct = _collector->_survivor_chunk_index; | |
5326 | |
5327 assert(ect <= _collector->_eden_chunk_capacity, "out of bounds"); | |
5328 assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds"); | |
5329 | |
5330 do_young_space_rescan(worker_id, cl, to_space, NULL, 0); | |
5331 do_young_space_rescan(worker_id, cl, from_space, sca, sct); | |
5332 do_young_space_rescan(worker_id, cl, eden_space, eca, ect); | |
5333 } | |
5334 | |
5235 // work_queue(i) is passed to the closure | 5335 // work_queue(i) is passed to the closure |
5236 // Par_MarkRefsIntoAndScanClosure. The "i" parameter | 5336 // Par_MarkRefsIntoAndScanClosure. The "i" parameter |
5237 // also is passed to do_dirty_card_rescan_tasks() and to | 5337 // also is passed to do_dirty_card_rescan_tasks() and to |
5238 // do_work_steal() to select the i-th task_queue. | 5338 // do_work_steal() to select the i-th task_queue. |
5239 | 5339 |
5254 // coarsely partitioned and may, on that account, constitute | 5354 // coarsely partitioned and may, on that account, constitute |
5255 // the critical path; thus, it's best to start off that | 5355 // the critical path; thus, it's best to start off that |
5256 // work first. | 5356 // work first. |
5257 // ---------- young gen roots -------------- | 5357 // ---------- young gen roots -------------- |
5258 { | 5358 { |
5259 DefNewGeneration* dng = _collector->_young_gen->as_DefNewGeneration(); | 5359 work_on_young_gen_roots(worker_id, &par_mrias_cl); |
5260 EdenSpace* eden_space = dng->eden(); | |
5261 ContiguousSpace* from_space = dng->from(); | |
5262 ContiguousSpace* to_space = dng->to(); | |
5263 | |
5264 HeapWord** eca = _collector->_eden_chunk_array; | |
5265 size_t ect = _collector->_eden_chunk_index; | |
5266 HeapWord** sca = _collector->_survivor_chunk_array; | |
5267 size_t sct = _collector->_survivor_chunk_index; | |
5268 | |
5269 assert(ect <= _collector->_eden_chunk_capacity, "out of bounds"); | |
5270 assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds"); | |
5271 | |
5272 do_young_space_rescan(worker_id, &par_mrias_cl, to_space, NULL, 0); | |
5273 do_young_space_rescan(worker_id, &par_mrias_cl, from_space, sca, sct); | |
5274 do_young_space_rescan(worker_id, &par_mrias_cl, eden_space, eca, ect); | |
5275 | |
5276 _timer.stop(); | 5360 _timer.stop(); |
5277 if (PrintCMSStatistics != 0) { | 5361 if (PrintCMSStatistics != 0) { |
5278 gclog_or_tty->print_cr( | 5362 gclog_or_tty->print_cr( |
5279 "Finished young gen rescan work in %dth thread: %3.3f sec", | 5363 "Finished young gen rescan work in %dth thread: %3.3f sec", |
5280 worker_id, _timer.seconds()); | 5364 worker_id, _timer.seconds()); |
5378 } | 5462 } |
5379 } | 5463 } |
5380 | 5464 |
5381 // Note that parameter "i" is not used. | 5465 // Note that parameter "i" is not used. |
5382 void | 5466 void |
5383 CMSParRemarkTask::do_young_space_rescan(int i, | 5467 CMSParMarkTask::do_young_space_rescan(uint worker_id, |
5384 Par_MarkRefsIntoAndScanClosure* cl, ContiguousSpace* space, | 5468 OopsInGenClosure* cl, ContiguousSpace* space, |
5385 HeapWord** chunk_array, size_t chunk_top) { | 5469 HeapWord** chunk_array, size_t chunk_top) { |
5386 // Until all tasks completed: | 5470 // Until all tasks completed: |
5387 // . claim an unclaimed task | 5471 // . claim an unclaimed task |
5388 // . compute region boundaries corresponding to task claimed | 5472 // . compute region boundaries corresponding to task claimed |
5389 // using chunk_array | 5473 // using chunk_array |
5623 } | 5707 } |
5624 } | 5708 } |
5625 | 5709 |
5626 // Merge the per-thread plab arrays into the global survivor chunk | 5710 // Merge the per-thread plab arrays into the global survivor chunk |
5627 // array which will provide the partitioning of the survivor space | 5711 // array which will provide the partitioning of the survivor space |
5628 // for CMS rescan. | 5712 // for CMS initial scan and rescan. |
5629 void CMSCollector::merge_survivor_plab_arrays(ContiguousSpace* surv, | 5713 void CMSCollector::merge_survivor_plab_arrays(ContiguousSpace* surv, |
5630 int no_of_gc_threads) { | 5714 int no_of_gc_threads) { |
5631 assert(_survivor_plab_array != NULL, "Error"); | 5715 assert(_survivor_plab_array != NULL, "Error"); |
5632 assert(_survivor_chunk_array != NULL, "Error"); | 5716 assert(_survivor_chunk_array != NULL, "Error"); |
5633 assert(_collectorState == FinalMarking, "Error"); | 5717 assert(_collectorState == FinalMarking || |
5718 (CMSParallelInitialMarkEnabled && _collectorState == InitialMarking), "Error"); | |
5634 for (int j = 0; j < no_of_gc_threads; j++) { | 5719 for (int j = 0; j < no_of_gc_threads; j++) { |
5635 _cursor[j] = 0; | 5720 _cursor[j] = 0; |
5636 } | 5721 } |
5637 HeapWord* top = surv->top(); | 5722 HeapWord* top = surv->top(); |
5638 size_t i; | 5723 size_t i; |
5691 } | 5776 } |
5692 #endif // ASSERT | 5777 #endif // ASSERT |
5693 } | 5778 } |
5694 | 5779 |
5695 // Set up the space's par_seq_tasks structure for work claiming | 5780 // Set up the space's par_seq_tasks structure for work claiming |
5696 // for parallel rescan of young gen. | 5781 // for parallel initial scan and rescan of young gen. |
5697 // See ParRescanTask where this is currently used. | 5782 // See ParRescanTask where this is currently used. |
5698 void | 5783 void |
5699 CMSCollector:: | 5784 CMSCollector:: |
5700 initialize_sequential_subtasks_for_young_gen_rescan(int n_threads) { | 5785 initialize_sequential_subtasks_for_young_gen_rescan(int n_threads) { |
5701 assert(n_threads > 0, "Unexpected n_threads argument"); | 5786 assert(n_threads > 0, "Unexpected n_threads argument"); |
6817 } | 6902 } |
6818 } | 6903 } |
6819 | 6904 |
6820 void MarkRefsIntoClosure::do_oop(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } | 6905 void MarkRefsIntoClosure::do_oop(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } |
6821 void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } | 6906 void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } |
6907 | |
6908 Par_MarkRefsIntoClosure::Par_MarkRefsIntoClosure( | |
6909 MemRegion span, CMSBitMap* bitMap): | |
6910 _span(span), | |
6911 _bitMap(bitMap) | |
6912 { | |
6913 assert(_ref_processor == NULL, "deliberately left NULL"); | |
6914 assert(_bitMap->covers(_span), "_bitMap/_span mismatch"); | |
6915 } | |
6916 | |
6917 void Par_MarkRefsIntoClosure::do_oop(oop obj) { | |
6918 // if p points into _span, then mark corresponding bit in _markBitMap | |
6919 assert(obj->is_oop(), "expected an oop"); | |
6920 HeapWord* addr = (HeapWord*)obj; | |
6921 if (_span.contains(addr)) { | |
6922 // this should be made more efficient | |
6923 _bitMap->par_mark(addr); | |
6924 } | |
6925 } | |
6926 | |
6927 void Par_MarkRefsIntoClosure::do_oop(oop* p) { Par_MarkRefsIntoClosure::do_oop_work(p); } | |
6928 void Par_MarkRefsIntoClosure::do_oop(narrowOop* p) { Par_MarkRefsIntoClosure::do_oop_work(p); } | |
6822 | 6929 |
6823 // A variant of the above, used for CMS marking verification. | 6930 // A variant of the above, used for CMS marking verification. |
6824 MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure( | 6931 MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure( |
6825 MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm): | 6932 MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm): |
6826 _span(span), | 6933 _span(span), |
9375 assert(chunk_at_end->end() == (uintptr_t*) _cmsSpace->end(), | 9482 assert(chunk_at_end->end() == (uintptr_t*) _cmsSpace->end(), |
9376 "Shrinking is inconsistent"); | 9483 "Shrinking is inconsistent"); |
9377 return; | 9484 return; |
9378 } | 9485 } |
9379 } | 9486 } |
9380 | |
9381 // Transfer some number of overflown objects to usual marking | 9487 // Transfer some number of overflown objects to usual marking |
9382 // stack. Return true if some objects were transferred. | 9488 // stack. Return true if some objects were transferred. |
9383 bool MarkRefsIntoAndScanClosure::take_from_overflow_list() { | 9489 bool MarkRefsIntoAndScanClosure::take_from_overflow_list() { |
9384 size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4, | 9490 size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4, |
9385 (size_t)ParGCDesiredObjsFromOverflowList); | 9491 (size_t)ParGCDesiredObjsFromOverflowList); |