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(&notOlder);
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 &notOlder, 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(&notOlder);
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 &notOlder,
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);