3602
3603 Ticks start = Ticks::now();
3604 G1ParEvacuateFollowersClosure cl(_g1h, pss, _task_queues, _terminator.terminator(), objcopy_phase);
3605 cl.do_void();
3606
3607 assert(pss->queue_is_empty(), "should be empty");
3608
3609 Tickspan evac_time = (Ticks::now() - start);
3610 p->record_or_add_time_secs(objcopy_phase, worker_id, evac_time.seconds() - cl.term_time());
3611
3612 p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABWaste);
3613 p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_undo_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABUndoWaste);
3614
3615 if (termination_phase == G1GCPhaseTimes::Termination) {
3616 p->record_time_secs(termination_phase, worker_id, cl.term_time());
3617 p->record_thread_work_item(termination_phase, worker_id, cl.term_attempts());
3618 } else {
3619 p->record_or_add_time_secs(termination_phase, worker_id, cl.term_time());
3620 p->record_or_add_thread_work_item(termination_phase, worker_id, cl.term_attempts());
3621 }
3622 assert(pss->trim_ticks().seconds() == 0.0, "Unexpected partial trimming during evacuation");
3623 }
3624
3625 virtual void start_work(uint worker_id) { }
3626
3627 virtual void end_work(uint worker_id) { }
3628
3629 virtual void scan_roots(G1ParScanThreadState* pss, uint worker_id) = 0;
3630
3631 virtual void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) = 0;
3632
3633 public:
3634 G1EvacuateRegionsBaseTask(const char* name, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet* task_queues, uint num_workers) :
3635 AbstractGangTask(name),
3636 _g1h(G1CollectedHeap::heap()),
3637 _per_thread_states(per_thread_states),
3638 _task_queues(task_queues),
3639 _terminator(num_workers, _task_queues),
3640 _num_workers(num_workers)
3641 { }
3642
3644 start_work(worker_id);
3645
3646 {
3647 ResourceMark rm;
3648 HandleMark hm;
3649
3650 G1ParScanThreadState* pss = _per_thread_states->state_for_worker(worker_id);
3651 pss->set_ref_discoverer(_g1h->ref_processor_stw());
3652
3653 scan_roots(pss, worker_id);
3654 evacuate_live_objects(pss, worker_id);
3655 }
3656
3657 end_work(worker_id);
3658 }
3659 };
3660
3661 class G1EvacuateRegionsTask : public G1EvacuateRegionsBaseTask {
3662 G1RootProcessor* _root_processor;
3663
3664 void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
3665 _root_processor->evacuate_roots(pss, worker_id);
3666 _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ObjCopy);
3667 _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy);
3668 }
3669
3670 void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
3671 G1EvacuateRegionsBaseTask::evacuate_live_objects(pss, worker_id, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::Termination);
3672 }
3673
3674 void start_work(uint worker_id) {
3675 _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerStart, worker_id, Ticks::now().seconds());
3676 }
3677
3678 void end_work(uint worker_id) {
3679 _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerEnd, worker_id, Ticks::now().seconds());
3680 }
3681
3682 public:
3683 G1EvacuateRegionsTask(G1CollectedHeap* g1h,
3684 G1ParScanThreadStateSet* per_thread_states,
3685 RefToScanQueueSet* task_queues,
3686 G1RootProcessor* root_processor,
3687 uint num_workers) :
3688 G1EvacuateRegionsBaseTask("G1 Evacuate Regions", per_thread_states, task_queues, num_workers),
3689 _root_processor(root_processor)
3690 { }
3691 };
|
3602
3603 Ticks start = Ticks::now();
3604 G1ParEvacuateFollowersClosure cl(_g1h, pss, _task_queues, _terminator.terminator(), objcopy_phase);
3605 cl.do_void();
3606
3607 assert(pss->queue_is_empty(), "should be empty");
3608
3609 Tickspan evac_time = (Ticks::now() - start);
3610 p->record_or_add_time_secs(objcopy_phase, worker_id, evac_time.seconds() - cl.term_time());
3611
3612 p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABWaste);
3613 p->record_or_add_thread_work_item(objcopy_phase, worker_id, pss->lab_undo_waste_words() * HeapWordSize, G1GCPhaseTimes::ObjCopyLABUndoWaste);
3614
3615 if (termination_phase == G1GCPhaseTimes::Termination) {
3616 p->record_time_secs(termination_phase, worker_id, cl.term_time());
3617 p->record_thread_work_item(termination_phase, worker_id, cl.term_attempts());
3618 } else {
3619 p->record_or_add_time_secs(termination_phase, worker_id, cl.term_time());
3620 p->record_or_add_thread_work_item(termination_phase, worker_id, cl.term_attempts());
3621 }
3622 }
3623
3624 virtual void start_work(uint worker_id) { }
3625
3626 virtual void end_work(uint worker_id) { }
3627
3628 virtual void scan_roots(G1ParScanThreadState* pss, uint worker_id) = 0;
3629
3630 virtual void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) = 0;
3631
3632 public:
3633 G1EvacuateRegionsBaseTask(const char* name, G1ParScanThreadStateSet* per_thread_states, RefToScanQueueSet* task_queues, uint num_workers) :
3634 AbstractGangTask(name),
3635 _g1h(G1CollectedHeap::heap()),
3636 _per_thread_states(per_thread_states),
3637 _task_queues(task_queues),
3638 _terminator(num_workers, _task_queues),
3639 _num_workers(num_workers)
3640 { }
3641
3643 start_work(worker_id);
3644
3645 {
3646 ResourceMark rm;
3647 HandleMark hm;
3648
3649 G1ParScanThreadState* pss = _per_thread_states->state_for_worker(worker_id);
3650 pss->set_ref_discoverer(_g1h->ref_processor_stw());
3651
3652 scan_roots(pss, worker_id);
3653 evacuate_live_objects(pss, worker_id);
3654 }
3655
3656 end_work(worker_id);
3657 }
3658 };
3659
3660 class G1EvacuateRegionsTask : public G1EvacuateRegionsBaseTask {
3661 G1RootProcessor* _root_processor;
3662
3663 void verify_trim_ticks(G1ParScanThreadState* pss, const char* location) {
3664 assert(pss->trim_ticks().seconds() == 0.0, "Unexpected partial trimming during evacuation at %s %.3lf " JLONG_FORMAT, location, pss->trim_ticks().seconds(), pss->trim_ticks().value());
3665 }
3666
3667 void scan_roots(G1ParScanThreadState* pss, uint worker_id) {
3668 _root_processor->evacuate_roots(pss, worker_id);
3669 verify_trim_ticks(pss, "roots");
3670 _g1h->rem_set()->scan_heap_roots(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::ObjCopy);
3671 verify_trim_ticks(pss, "heap roots");
3672 _g1h->rem_set()->scan_collection_set_regions(pss, worker_id, G1GCPhaseTimes::ScanHR, G1GCPhaseTimes::CodeRoots, G1GCPhaseTimes::ObjCopy);
3673 verify_trim_ticks(pss, "scan cset");
3674 }
3675
3676 void evacuate_live_objects(G1ParScanThreadState* pss, uint worker_id) {
3677 G1EvacuateRegionsBaseTask::evacuate_live_objects(pss, worker_id, G1GCPhaseTimes::ObjCopy, G1GCPhaseTimes::Termination);
3678 verify_trim_ticks(pss, "evac live");
3679 }
3680
3681 void start_work(uint worker_id) {
3682 _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerStart, worker_id, Ticks::now().seconds());
3683 }
3684
3685 void end_work(uint worker_id) {
3686 _g1h->phase_times()->record_time_secs(G1GCPhaseTimes::GCWorkerEnd, worker_id, Ticks::now().seconds());
3687 }
3688
3689 public:
3690 G1EvacuateRegionsTask(G1CollectedHeap* g1h,
3691 G1ParScanThreadStateSet* per_thread_states,
3692 RefToScanQueueSet* task_queues,
3693 G1RootProcessor* root_processor,
3694 uint num_workers) :
3695 G1EvacuateRegionsBaseTask("G1 Evacuate Regions", per_thread_states, task_queues, num_workers),
3696 _root_processor(root_processor)
3697 { }
3698 };
|