comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 5986:500023bd0818

7143511: G1: Another instance of high GC Worker Other time (50ms) Summary: Tiered compilation has increased the number of nmethods in the code cache. This has, in turn, significantly increased the number of marked nmethods processed during the StrongRootsScope destructor. Create a specialized version of CodeBlobToOopClosure for G1 which places only those nmethods that contain pointers into the collection set on to the marked nmethods list. Reviewed-by: iveresov, tonyp
author johnc
date Tue, 13 Mar 2012 11:05:32 -0700
parents 64bf7c8270cb
children 748051fd24ce
comparison
equal deleted inserted replaced
5972:9a9bb0010c91 5986:500023bd0818
4673 if (worker_id >= _n_workers) return; // no work needed this round 4673 if (worker_id >= _n_workers) return; // no work needed this round
4674 4674
4675 double start_time_ms = os::elapsedTime() * 1000.0; 4675 double start_time_ms = os::elapsedTime() * 1000.0;
4676 _g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms); 4676 _g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms);
4677 4677
4678 ResourceMark rm;
4679 HandleMark hm;
4680
4681 ReferenceProcessor* rp = _g1h->ref_processor_stw();
4682
4683 G1ParScanThreadState pss(_g1h, worker_id);
4684 G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp);
4685 G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
4686 G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp);
4687
4688 pss.set_evac_closure(&scan_evac_cl);
4689 pss.set_evac_failure_closure(&evac_failure_cl);
4690 pss.set_partial_scan_closure(&partial_scan_cl);
4691
4692 G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp);
4693 G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp);
4694
4695 G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
4696 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp);
4697
4698 OopClosure* scan_root_cl = &only_scan_root_cl;
4699 OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl;
4700
4701 if (_g1h->g1_policy()->during_initial_mark_pause()) {
4702 // We also need to mark copied objects.
4703 scan_root_cl = &scan_mark_root_cl;
4704 scan_perm_cl = &scan_mark_perm_cl;
4705 }
4706
4707 G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
4708
4709 pss.start_strong_roots();
4710 _g1h->g1_process_strong_roots(/* not collecting perm */ false,
4711 SharedHeap::SO_AllClasses,
4712 scan_root_cl,
4713 &push_heap_rs_cl,
4714 scan_perm_cl,
4715 worker_id);
4716 pss.end_strong_roots();
4717
4718 { 4678 {
4719 double start = os::elapsedTime(); 4679 ResourceMark rm;
4720 G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator); 4680 HandleMark hm;
4721 evac.do_void(); 4681
4722 double elapsed_ms = (os::elapsedTime()-start)*1000.0; 4682 ReferenceProcessor* rp = _g1h->ref_processor_stw();
4723 double term_ms = pss.term_time()*1000.0; 4683
4724 _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms); 4684 G1ParScanThreadState pss(_g1h, worker_id);
4725 _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts()); 4685 G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp);
4726 } 4686 G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
4727 _g1h->g1_policy()->record_thread_age_table(pss.age_table()); 4687 G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp);
4728 _g1h->update_surviving_young_words(pss.surviving_young_words()+1); 4688
4729 4689 pss.set_evac_closure(&scan_evac_cl);
4730 // Clean up any par-expanded rem sets. 4690 pss.set_evac_failure_closure(&evac_failure_cl);
4731 HeapRegionRemSet::par_cleanup(); 4691 pss.set_partial_scan_closure(&partial_scan_cl);
4732 4692
4733 if (ParallelGCVerbose) { 4693 G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp);
4734 MutexLocker x(stats_lock()); 4694 G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp);
4735 pss.print_termination_stats(worker_id); 4695
4736 } 4696 G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
4737 4697 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp);
4738 assert(pss.refs()->is_empty(), "should be empty"); 4698
4699 OopClosure* scan_root_cl = &only_scan_root_cl;
4700 OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl;
4701
4702 if (_g1h->g1_policy()->during_initial_mark_pause()) {
4703 // We also need to mark copied objects.
4704 scan_root_cl = &scan_mark_root_cl;
4705 scan_perm_cl = &scan_mark_perm_cl;
4706 }
4707
4708 G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
4709
4710 pss.start_strong_roots();
4711 _g1h->g1_process_strong_roots(/* not collecting perm */ false,
4712 SharedHeap::SO_AllClasses,
4713 scan_root_cl,
4714 &push_heap_rs_cl,
4715 scan_perm_cl,
4716 worker_id);
4717 pss.end_strong_roots();
4718
4719 {
4720 double start = os::elapsedTime();
4721 G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
4722 evac.do_void();
4723 double elapsed_ms = (os::elapsedTime()-start)*1000.0;
4724 double term_ms = pss.term_time()*1000.0;
4725 _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
4726 _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts());
4727 }
4728 _g1h->g1_policy()->record_thread_age_table(pss.age_table());
4729 _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
4730
4731 // Clean up any par-expanded rem sets.
4732 HeapRegionRemSet::par_cleanup();
4733
4734 if (ParallelGCVerbose) {
4735 MutexLocker x(stats_lock());
4736 pss.print_termination_stats(worker_id);
4737 }
4738
4739 assert(pss.refs()->is_empty(), "should be empty");
4740
4741 // Close the inner scope so that the ResourceMark and HandleMark
4742 // destructors are executed here and are included as part of the
4743 // "GC Worker Time".
4744 }
4745
4739 double end_time_ms = os::elapsedTime() * 1000.0; 4746 double end_time_ms = os::elapsedTime() * 1000.0;
4740 _g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms); 4747 _g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms);
4741 } 4748 }
4742 }; 4749 };
4743 4750
4744 // *** Common G1 Evacuation Stuff 4751 // *** Common G1 Evacuation Stuff
4752
4753 // Closures that support the filtering of CodeBlobs scanned during
4754 // external root scanning.
4755
4756 // Closure applied to reference fields in code blobs (specifically nmethods)
4757 // to determine whether an nmethod contains references that point into
4758 // the collection set. Used as a predicate when walking code roots so
4759 // that only nmethods that point into the collection set are added to the
4760 // 'marked' list.
4761
4762 class G1FilteredCodeBlobToOopClosure : public CodeBlobToOopClosure {
4763
4764 class G1PointsIntoCSOopClosure : public OopClosure {
4765 G1CollectedHeap* _g1;
4766 bool _points_into_cs;
4767 public:
4768 G1PointsIntoCSOopClosure(G1CollectedHeap* g1) :
4769 _g1(g1), _points_into_cs(false) { }
4770
4771 bool points_into_cs() const { return _points_into_cs; }
4772
4773 template <class T>
4774 void do_oop_nv(T* p) {
4775 if (!_points_into_cs) {
4776 T heap_oop = oopDesc::load_heap_oop(p);
4777 if (!oopDesc::is_null(heap_oop) &&
4778 _g1->in_cset_fast_test(oopDesc::decode_heap_oop_not_null(heap_oop))) {
4779 _points_into_cs = true;
4780 }
4781 }
4782 }
4783
4784 virtual void do_oop(oop* p) { do_oop_nv(p); }
4785 virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
4786 };
4787
4788 G1CollectedHeap* _g1;
4789
4790 public:
4791 G1FilteredCodeBlobToOopClosure(G1CollectedHeap* g1, OopClosure* cl) :
4792 CodeBlobToOopClosure(cl, true), _g1(g1) { }
4793
4794 virtual void do_code_blob(CodeBlob* cb) {
4795 nmethod* nm = cb->as_nmethod_or_null();
4796 if (nm != NULL && !(nm->test_oops_do_mark())) {
4797 G1PointsIntoCSOopClosure predicate_cl(_g1);
4798 nm->oops_do(&predicate_cl);
4799
4800 if (predicate_cl.points_into_cs()) {
4801 // At least one of the reference fields or the oop relocations
4802 // in the nmethod points into the collection set. We have to
4803 // 'mark' this nmethod.
4804 // Note: Revisit the following if CodeBlobToOopClosure::do_code_blob()
4805 // or MarkingCodeBlobClosure::do_code_blob() change.
4806 if (!nm->test_set_oops_do_mark()) {
4807 do_newly_marked_nmethod(nm);
4808 }
4809 }
4810 }
4811 }
4812 };
4745 4813
4746 // This method is run in a GC worker. 4814 // This method is run in a GC worker.
4747 4815
4748 void 4816 void
4749 G1CollectedHeap:: 4817 G1CollectedHeap::
4762 BufferingOopsInGenClosure buf_scan_perm(scan_perm); 4830 BufferingOopsInGenClosure buf_scan_perm(scan_perm);
4763 buf_scan_perm.set_generation(perm_gen()); 4831 buf_scan_perm.set_generation(perm_gen());
4764 4832
4765 // Walk the code cache w/o buffering, because StarTask cannot handle 4833 // Walk the code cache w/o buffering, because StarTask cannot handle
4766 // unaligned oop locations. 4834 // unaligned oop locations.
4767 CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true); 4835 G1FilteredCodeBlobToOopClosure eager_scan_code_roots(this, scan_non_heap_roots);
4768 4836
4769 process_strong_roots(false, // no scoping; this is parallel code 4837 process_strong_roots(false, // no scoping; this is parallel code
4770 collecting_perm_gen, so, 4838 collecting_perm_gen, so,
4771 &buf_scan_non_heap_roots, 4839 &buf_scan_non_heap_roots,
4772 &eager_scan_code_roots, 4840 &eager_scan_code_roots,
5376 init_for_evac_failure(NULL); 5444 init_for_evac_failure(NULL);
5377 5445
5378 rem_set()->prepare_for_younger_refs_iterate(true); 5446 rem_set()->prepare_for_younger_refs_iterate(true);
5379 5447
5380 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); 5448 assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
5381 double start_par = os::elapsedTime(); 5449 double start_par_time_sec = os::elapsedTime();
5382 5450 double end_par_time_sec;
5383 if (G1CollectedHeap::use_parallel_gc_threads()) { 5451
5384 // The individual threads will set their evac-failure closures. 5452 {
5385 StrongRootsScope srs(this); 5453 StrongRootsScope srs(this);
5386 if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr(); 5454
5387 // These tasks use ShareHeap::_process_strong_tasks 5455 if (G1CollectedHeap::use_parallel_gc_threads()) {
5388 assert(UseDynamicNumberOfGCThreads || 5456 // The individual threads will set their evac-failure closures.
5389 workers()->active_workers() == workers()->total_workers(), 5457 if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
5390 "If not dynamic should be using all the workers"); 5458 // These tasks use ShareHeap::_process_strong_tasks
5391 workers()->run_task(&g1_par_task); 5459 assert(UseDynamicNumberOfGCThreads ||
5392 } else { 5460 workers()->active_workers() == workers()->total_workers(),
5393 StrongRootsScope srs(this); 5461 "If not dynamic should be using all the workers");
5394 g1_par_task.set_for_termination(n_workers); 5462 workers()->run_task(&g1_par_task);
5395 g1_par_task.work(0); 5463 } else {
5396 } 5464 g1_par_task.set_for_termination(n_workers);
5397 5465 g1_par_task.work(0);
5398 double par_time = (os::elapsedTime() - start_par) * 1000.0; 5466 }
5399 g1_policy()->record_par_time(par_time); 5467 end_par_time_sec = os::elapsedTime();
5468
5469 // Closing the inner scope will execute the destructor
5470 // for the StrongRootsScope object. We record the current
5471 // elapsed time before closing the scope so that time
5472 // taken for the SRS destructor is NOT included in the
5473 // reported parallel time.
5474 }
5475
5476 double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
5477 g1_policy()->record_par_time(par_time_ms);
5478
5479 double code_root_fixup_time_ms =
5480 (os::elapsedTime() - end_par_time_sec) * 1000.0;
5481 g1_policy()->record_code_root_fixup_time(code_root_fixup_time_ms);
5400 5482
5401 set_par_threads(0); 5483 set_par_threads(0);
5402 5484
5403 // Process any discovered reference objects - we have 5485 // Process any discovered reference objects - we have
5404 // to do this _before_ we retire the GC alloc regions 5486 // to do this _before_ we retire the GC alloc regions