2752
2753 CMSPhaseAccounting::~CMSPhaseAccounting() {
2754 _collector->gc_timer_cm()->register_gc_concurrent_end();
2755 _collector->stopTimer();
2756 log_debug(gc)("Concurrent active time: %.3fms", TimeHelper::counter_to_seconds(_collector->timerTicks()));
2757 log_trace(gc)(" (CMS %s yielded %d times)", _title, _collector->yields());
2758 }
2759
2760 // CMS work
2761
2762 // The common parts of CMSParInitialMarkTask and CMSParRemarkTask.
2763 class CMSParMarkTask : public AbstractGangTask {
2764 protected:
2765 CMSCollector* _collector;
2766 uint _n_workers;
2767 CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) :
2768 AbstractGangTask(name),
2769 _collector(collector),
2770 _n_workers(n_workers) {}
2771 // Work method in support of parallel rescan ... of young gen spaces
2772 void do_young_space_rescan(uint worker_id, OopsInGenClosure* cl,
2773 ContiguousSpace* space,
2774 HeapWord** chunk_array, size_t chunk_top);
2775 void work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl);
2776 };
2777
2778 // Parallel initial mark task
2779 class CMSParInitialMarkTask: public CMSParMarkTask {
2780 StrongRootsScope* _strong_roots_scope;
2781 public:
2782 CMSParInitialMarkTask(CMSCollector* collector, StrongRootsScope* strong_roots_scope, uint n_workers) :
2783 CMSParMarkTask("Scan roots and young gen for initial mark in parallel", collector, n_workers),
2784 _strong_roots_scope(strong_roots_scope) {}
2785 void work(uint worker_id);
2786 };
2787
2788 // Checkpoint the roots into this generation from outside
2789 // this generation. [Note this initial checkpoint need only
2790 // be approximate -- we'll do a catch up phase subsequently.]
2791 void CMSCollector::checkpointRootsInitial() {
2792 assert(_collectorState == InitialMarking, "Wrong collector state");
2793 check_correct_thread_executing();
2794 TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
2795
4238 _collectorState = Sweeping;
4239 // Call isAllClear() under bitMapLock
4240 assert(_modUnionTable.isAllClear(),
4241 "Should be clear by end of the final marking");
4242 assert(_ct->klass_rem_set()->mod_union_is_clear(),
4243 "Should be clear by end of the final marking");
4244 }
4245
4246 void CMSParInitialMarkTask::work(uint worker_id) {
4247 elapsedTimer _timer;
4248 ResourceMark rm;
4249 HandleMark hm;
4250
4251 // ---------- scan from roots --------------
4252 _timer.start();
4253 GenCollectedHeap* gch = GenCollectedHeap::heap();
4254 ParMarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap));
4255
4256 // ---------- young gen roots --------------
4257 {
4258 work_on_young_gen_roots(worker_id, &par_mri_cl);
4259 _timer.stop();
4260 log_trace(gc, task)("Finished young gen initial mark scan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4261 }
4262
4263 // ---------- remaining roots --------------
4264 _timer.reset();
4265 _timer.start();
4266
4267 CLDToOopClosure cld_closure(&par_mri_cl, true);
4268
4269 gch->gen_process_roots(_strong_roots_scope,
4270 GenCollectedHeap::OldGen,
4271 false, // yg was scanned above
4272 GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
4273 _collector->should_unload_classes(),
4274 &par_mri_cl,
4275 NULL,
4276 &cld_closure);
4277 assert(_collector->should_unload_classes()
4278 || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
4329 RemarkKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
4330 void do_klass(Klass* k) {
4331 // Check if we have modified any oops in the Klass during the concurrent marking.
4332 if (k->has_accumulated_modified_oops()) {
4333 k->clear_accumulated_modified_oops();
4334
4335 // We could have transfered the current modified marks to the accumulated marks,
4336 // like we do with the Card Table to Mod Union Table. But it's not really necessary.
4337 } else if (k->has_modified_oops()) {
4338 // Don't clear anything, this info is needed by the next young collection.
4339 } else {
4340 // No modified oops in the Klass.
4341 return;
4342 }
4343
4344 // The klass has modified fields, need to scan the klass.
4345 _cm_klass_closure.do_klass(k);
4346 }
4347 };
4348
4349 void CMSParMarkTask::work_on_young_gen_roots(uint worker_id, OopsInGenClosure* cl) {
4350 ParNewGeneration* young_gen = _collector->_young_gen;
4351 ContiguousSpace* eden_space = young_gen->eden();
4352 ContiguousSpace* from_space = young_gen->from();
4353 ContiguousSpace* to_space = young_gen->to();
4354
4355 HeapWord** eca = _collector->_eden_chunk_array;
4356 size_t ect = _collector->_eden_chunk_index;
4357 HeapWord** sca = _collector->_survivor_chunk_array;
4358 size_t sct = _collector->_survivor_chunk_index;
4359
4360 assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
4361 assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
4362
4363 do_young_space_rescan(worker_id, cl, to_space, NULL, 0);
4364 do_young_space_rescan(worker_id, cl, from_space, sca, sct);
4365 do_young_space_rescan(worker_id, cl, eden_space, eca, ect);
4366 }
4367
4368 // work_queue(i) is passed to the closure
4369 // ParMarkRefsIntoAndScanClosure. The "i" parameter
4370 // also is passed to do_dirty_card_rescan_tasks() and to
4371 // do_work_steal() to select the i-th task_queue.
4372
4373 void CMSParRemarkTask::work(uint worker_id) {
4374 elapsedTimer _timer;
4375 ResourceMark rm;
4376 HandleMark hm;
4377
4378 // ---------- rescan from roots --------------
4379 _timer.start();
4380 GenCollectedHeap* gch = GenCollectedHeap::heap();
4381 ParMarkRefsIntoAndScanClosure par_mrias_cl(_collector,
4382 _collector->_span, _collector->ref_processor(),
4383 &(_collector->_markBitMap),
4384 work_queue(worker_id));
4385
4386 // Rescan young gen roots first since these are likely
4387 // coarsely partitioned and may, on that account, constitute
4388 // the critical path; thus, it's best to start off that
4389 // work first.
4390 // ---------- young gen roots --------------
4391 {
4392 work_on_young_gen_roots(worker_id, &par_mrias_cl);
4393 _timer.stop();
4394 log_trace(gc, task)("Finished young gen rescan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4395 }
4396
4397 // ---------- remaining roots --------------
4398 _timer.reset();
4399 _timer.start();
4400 gch->gen_process_roots(_strong_roots_scope,
4401 GenCollectedHeap::OldGen,
4402 false, // yg was scanned above
4403 GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
4404 _collector->should_unload_classes(),
4405 &par_mrias_cl,
4406 NULL,
4407 NULL); // The dirty klasses will be handled below
4408
4409 assert(_collector->should_unload_classes()
4410 || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
4411 "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
4412 _timer.stop();
4454 // ---------- rescan dirty cards ------------
4455 _timer.reset();
4456 _timer.start();
4457
4458 // Do the rescan tasks for each of the two spaces
4459 // (cms_space) in turn.
4460 // "worker_id" is passed to select the task_queue for "worker_id"
4461 do_dirty_card_rescan_tasks(_cms_space, worker_id, &par_mrias_cl);
4462 _timer.stop();
4463 log_trace(gc, task)("Finished dirty card rescan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4464
4465 // ---------- steal work from other threads ...
4466 // ---------- ... and drain overflow list.
4467 _timer.reset();
4468 _timer.start();
4469 do_work_steal(worker_id, &par_mrias_cl, _collector->hash_seed(worker_id));
4470 _timer.stop();
4471 log_trace(gc, task)("Finished work stealing in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4472 }
4473
4474 // Note that parameter "i" is not used.
4475 void
4476 CMSParMarkTask::do_young_space_rescan(uint worker_id,
4477 OopsInGenClosure* cl, ContiguousSpace* space,
4478 HeapWord** chunk_array, size_t chunk_top) {
4479 // Until all tasks completed:
4480 // . claim an unclaimed task
4481 // . compute region boundaries corresponding to task claimed
4482 // using chunk_array
4483 // . par_oop_iterate(cl) over that region
4484
4485 ResourceMark rm;
4486 HandleMark hm;
4487
4488 SequentialSubTasksDone* pst = space->par_seq_tasks();
4489
4490 uint nth_task = 0;
4491 uint n_tasks = pst->n_tasks();
4492
4493 if (n_tasks > 0) {
4494 assert(pst->valid(), "Uninitialized use?");
4495 HeapWord *start, *end;
4496 while (!pst->is_task_claimed(/* reference */ nth_task)) {
|
2752
2753 CMSPhaseAccounting::~CMSPhaseAccounting() {
2754 _collector->gc_timer_cm()->register_gc_concurrent_end();
2755 _collector->stopTimer();
2756 log_debug(gc)("Concurrent active time: %.3fms", TimeHelper::counter_to_seconds(_collector->timerTicks()));
2757 log_trace(gc)(" (CMS %s yielded %d times)", _title, _collector->yields());
2758 }
2759
2760 // CMS work
2761
2762 // The common parts of CMSParInitialMarkTask and CMSParRemarkTask.
2763 class CMSParMarkTask : public AbstractGangTask {
2764 protected:
2765 CMSCollector* _collector;
2766 uint _n_workers;
2767 CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) :
2768 AbstractGangTask(name),
2769 _collector(collector),
2770 _n_workers(n_workers) {}
2771 // Work method in support of parallel rescan ... of young gen spaces
2772 void do_young_space_rescan(OopsInGenClosure* cl,
2773 ContiguousSpace* space,
2774 HeapWord** chunk_array, size_t chunk_top);
2775 void work_on_young_gen_roots(OopsInGenClosure* cl);
2776 };
2777
2778 // Parallel initial mark task
2779 class CMSParInitialMarkTask: public CMSParMarkTask {
2780 StrongRootsScope* _strong_roots_scope;
2781 public:
2782 CMSParInitialMarkTask(CMSCollector* collector, StrongRootsScope* strong_roots_scope, uint n_workers) :
2783 CMSParMarkTask("Scan roots and young gen for initial mark in parallel", collector, n_workers),
2784 _strong_roots_scope(strong_roots_scope) {}
2785 void work(uint worker_id);
2786 };
2787
2788 // Checkpoint the roots into this generation from outside
2789 // this generation. [Note this initial checkpoint need only
2790 // be approximate -- we'll do a catch up phase subsequently.]
2791 void CMSCollector::checkpointRootsInitial() {
2792 assert(_collectorState == InitialMarking, "Wrong collector state");
2793 check_correct_thread_executing();
2794 TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
2795
4238 _collectorState = Sweeping;
4239 // Call isAllClear() under bitMapLock
4240 assert(_modUnionTable.isAllClear(),
4241 "Should be clear by end of the final marking");
4242 assert(_ct->klass_rem_set()->mod_union_is_clear(),
4243 "Should be clear by end of the final marking");
4244 }
4245
4246 void CMSParInitialMarkTask::work(uint worker_id) {
4247 elapsedTimer _timer;
4248 ResourceMark rm;
4249 HandleMark hm;
4250
4251 // ---------- scan from roots --------------
4252 _timer.start();
4253 GenCollectedHeap* gch = GenCollectedHeap::heap();
4254 ParMarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap));
4255
4256 // ---------- young gen roots --------------
4257 {
4258 work_on_young_gen_roots(&par_mri_cl);
4259 _timer.stop();
4260 log_trace(gc, task)("Finished young gen initial mark scan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4261 }
4262
4263 // ---------- remaining roots --------------
4264 _timer.reset();
4265 _timer.start();
4266
4267 CLDToOopClosure cld_closure(&par_mri_cl, true);
4268
4269 gch->gen_process_roots(_strong_roots_scope,
4270 GenCollectedHeap::OldGen,
4271 false, // yg was scanned above
4272 GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
4273 _collector->should_unload_classes(),
4274 &par_mri_cl,
4275 NULL,
4276 &cld_closure);
4277 assert(_collector->should_unload_classes()
4278 || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
4329 RemarkKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
4330 void do_klass(Klass* k) {
4331 // Check if we have modified any oops in the Klass during the concurrent marking.
4332 if (k->has_accumulated_modified_oops()) {
4333 k->clear_accumulated_modified_oops();
4334
4335 // We could have transfered the current modified marks to the accumulated marks,
4336 // like we do with the Card Table to Mod Union Table. But it's not really necessary.
4337 } else if (k->has_modified_oops()) {
4338 // Don't clear anything, this info is needed by the next young collection.
4339 } else {
4340 // No modified oops in the Klass.
4341 return;
4342 }
4343
4344 // The klass has modified fields, need to scan the klass.
4345 _cm_klass_closure.do_klass(k);
4346 }
4347 };
4348
4349 void CMSParMarkTask::work_on_young_gen_roots(OopsInGenClosure* cl) {
4350 ParNewGeneration* young_gen = _collector->_young_gen;
4351 ContiguousSpace* eden_space = young_gen->eden();
4352 ContiguousSpace* from_space = young_gen->from();
4353 ContiguousSpace* to_space = young_gen->to();
4354
4355 HeapWord** eca = _collector->_eden_chunk_array;
4356 size_t ect = _collector->_eden_chunk_index;
4357 HeapWord** sca = _collector->_survivor_chunk_array;
4358 size_t sct = _collector->_survivor_chunk_index;
4359
4360 assert(ect <= _collector->_eden_chunk_capacity, "out of bounds");
4361 assert(sct <= _collector->_survivor_chunk_capacity, "out of bounds");
4362
4363 do_young_space_rescan(cl, to_space, NULL, 0);
4364 do_young_space_rescan(cl, from_space, sca, sct);
4365 do_young_space_rescan(cl, eden_space, eca, ect);
4366 }
4367
4368 // work_queue(i) is passed to the closure
4369 // ParMarkRefsIntoAndScanClosure. The "i" parameter
4370 // also is passed to do_dirty_card_rescan_tasks() and to
4371 // do_work_steal() to select the i-th task_queue.
4372
4373 void CMSParRemarkTask::work(uint worker_id) {
4374 elapsedTimer _timer;
4375 ResourceMark rm;
4376 HandleMark hm;
4377
4378 // ---------- rescan from roots --------------
4379 _timer.start();
4380 GenCollectedHeap* gch = GenCollectedHeap::heap();
4381 ParMarkRefsIntoAndScanClosure par_mrias_cl(_collector,
4382 _collector->_span, _collector->ref_processor(),
4383 &(_collector->_markBitMap),
4384 work_queue(worker_id));
4385
4386 // Rescan young gen roots first since these are likely
4387 // coarsely partitioned and may, on that account, constitute
4388 // the critical path; thus, it's best to start off that
4389 // work first.
4390 // ---------- young gen roots --------------
4391 {
4392 work_on_young_gen_roots(&par_mrias_cl);
4393 _timer.stop();
4394 log_trace(gc, task)("Finished young gen rescan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4395 }
4396
4397 // ---------- remaining roots --------------
4398 _timer.reset();
4399 _timer.start();
4400 gch->gen_process_roots(_strong_roots_scope,
4401 GenCollectedHeap::OldGen,
4402 false, // yg was scanned above
4403 GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
4404 _collector->should_unload_classes(),
4405 &par_mrias_cl,
4406 NULL,
4407 NULL); // The dirty klasses will be handled below
4408
4409 assert(_collector->should_unload_classes()
4410 || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
4411 "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
4412 _timer.stop();
4454 // ---------- rescan dirty cards ------------
4455 _timer.reset();
4456 _timer.start();
4457
4458 // Do the rescan tasks for each of the two spaces
4459 // (cms_space) in turn.
4460 // "worker_id" is passed to select the task_queue for "worker_id"
4461 do_dirty_card_rescan_tasks(_cms_space, worker_id, &par_mrias_cl);
4462 _timer.stop();
4463 log_trace(gc, task)("Finished dirty card rescan work in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4464
4465 // ---------- steal work from other threads ...
4466 // ---------- ... and drain overflow list.
4467 _timer.reset();
4468 _timer.start();
4469 do_work_steal(worker_id, &par_mrias_cl, _collector->hash_seed(worker_id));
4470 _timer.stop();
4471 log_trace(gc, task)("Finished work stealing in %dth thread: %3.3f sec", worker_id, _timer.seconds());
4472 }
4473
4474 void
4475 CMSParMarkTask::do_young_space_rescan(
4476 OopsInGenClosure* cl, ContiguousSpace* space,
4477 HeapWord** chunk_array, size_t chunk_top) {
4478 // Until all tasks completed:
4479 // . claim an unclaimed task
4480 // . compute region boundaries corresponding to task claimed
4481 // using chunk_array
4482 // . par_oop_iterate(cl) over that region
4483
4484 ResourceMark rm;
4485 HandleMark hm;
4486
4487 SequentialSubTasksDone* pst = space->par_seq_tasks();
4488
4489 uint nth_task = 0;
4490 uint n_tasks = pst->n_tasks();
4491
4492 if (n_tasks > 0) {
4493 assert(pst->valid(), "Uninitialized use?");
4494 HeapWord *start, *end;
4495 while (!pst->is_task_claimed(/* reference */ nth_task)) {
|