comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 1261:0414c1049f15

6923991: G1: improve scalability of RSet scanning Summary: Implemented block-based work stealing. Moved copying during the rset scanning phase to the main copying phase. Made the size of rset table depend on the region size. Reviewed-by: apetrusenko, tonyp
author iveresov
date Thu, 11 Feb 2010 15:52:19 -0800
parents 6484c4ee11cb
children b81f3572f355
comparison
equal deleted inserted replaced
1260:8859772195c6 1261:0414c1049f15
2644 _surviving_young_words = NULL; 2644 _surviving_young_words = NULL;
2645 } 2645 }
2646 2646
2647 // </NEW PREDICTION> 2647 // </NEW PREDICTION>
2648 2648
2649 struct PrepareForRSScanningClosure : public HeapRegionClosure {
2650 bool doHeapRegion(HeapRegion *r) {
2651 r->rem_set()->set_iter_claimed(0);
2652 return false;
2653 }
2654 };
2655
2649 void 2656 void
2650 G1CollectedHeap::do_collection_pause_at_safepoint() { 2657 G1CollectedHeap::do_collection_pause_at_safepoint() {
2651 if (PrintHeapAtGC) { 2658 if (PrintHeapAtGC) {
2652 Universe::print_heap_before_gc(); 2659 Universe::print_heap_before_gc();
2653 } 2660 }
2782 if (!abandoned) { 2789 if (!abandoned) {
2783 #if G1_REM_SET_LOGGING 2790 #if G1_REM_SET_LOGGING
2784 gclog_or_tty->print_cr("\nAfter pause, heap:"); 2791 gclog_or_tty->print_cr("\nAfter pause, heap:");
2785 print(); 2792 print();
2786 #endif 2793 #endif
2794 PrepareForRSScanningClosure prepare_for_rs_scan;
2795 collection_set_iterate(&prepare_for_rs_scan);
2787 2796
2788 setup_surviving_young_words(); 2797 setup_surviving_young_words();
2789 2798
2790 // Set up the gc allocation regions. 2799 // Set up the gc allocation regions.
2791 get_gc_alloc_regions(); 2800 get_gc_alloc_regions();
3779 obj = forward_ptr; 3788 obj = forward_ptr;
3780 } 3789 }
3781 return obj; 3790 return obj;
3782 } 3791 }
3783 3792
3784 template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test> 3793 template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee>
3785 template <class T> 3794 template <class T>
3786 void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test> 3795 void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee>
3787 ::do_oop_work(T* p) { 3796 ::do_oop_work(T* p) {
3788 oop obj = oopDesc::load_decode_heap_oop(p); 3797 oop obj = oopDesc::load_decode_heap_oop(p);
3789 assert(barrier != G1BarrierRS || obj != NULL, 3798 assert(barrier != G1BarrierRS || obj != NULL,
3790 "Precondition: G1BarrierRS implies obj is nonNull"); 3799 "Precondition: G1BarrierRS implies obj is nonNull");
3791 3800
3792 // The only time we skip the cset test is when we're scanning
3793 // references popped from the queue. And we only push on the queue
3794 // references that we know point into the cset, so no point in
3795 // checking again. But we'll leave an assert here for peace of mind.
3796 assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant");
3797
3798 // here the null check is implicit in the cset_fast_test() test 3801 // here the null check is implicit in the cset_fast_test() test
3799 if (skip_cset_test || _g1->in_cset_fast_test(obj)) { 3802 if (_g1->in_cset_fast_test(obj)) {
3800 #if G1_REM_SET_LOGGING 3803 #if G1_REM_SET_LOGGING
3801 gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" " 3804 gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" "
3802 "into CS.", p, (void*) obj); 3805 "into CS.", p, (void*) obj);
3803 #endif 3806 #endif
3804 if (obj->is_forwarded()) { 3807 if (obj->is_forwarded()) {
3811 if (barrier == G1BarrierRS) { 3814 if (barrier == G1BarrierRS) {
3812 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 3815 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
3813 } 3816 }
3814 } 3817 }
3815 3818
3816 // When scanning moved objs, must look at all oops.
3817 if (barrier == G1BarrierEvac && obj != NULL) { 3819 if (barrier == G1BarrierEvac && obj != NULL) {
3818 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 3820 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
3819 } 3821 }
3820 3822
3821 if (do_gen_barrier && obj != NULL) { 3823 if (do_gen_barrier && obj != NULL) {
3822 par_do_barrier(p); 3824 par_do_barrier(p);
3823 } 3825 }
3824 } 3826 }
3825 3827
3826 template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p); 3828 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p);
3827 template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p); 3829 template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(narrowOop* p);
3828 3830
3829 template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { 3831 template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) {
3830 assert(has_partial_array_mask(p), "invariant"); 3832 assert(has_partial_array_mask(p), "invariant");
3831 oop old = clear_partial_array_mask(p); 3833 oop old = clear_partial_array_mask(p);
3832 assert(old->is_objArray(), "must be obj array"); 3834 assert(old->is_objArray(), "must be obj array");
3894 assert((oop*)stolen_task != NULL, "Error"); 3896 assert((oop*)stolen_task != NULL, "Error");
3895 if (stolen_task.is_narrow()) { 3897 if (stolen_task.is_narrow()) {
3896 assert(UseCompressedOops, "Error"); 3898 assert(UseCompressedOops, "Error");
3897 narrowOop* p = (narrowOop*) stolen_task; 3899 narrowOop* p = (narrowOop*) stolen_task;
3898 assert(has_partial_array_mask(p) || 3900 assert(has_partial_array_mask(p) ||
3899 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error"); 3901 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "Error");
3900 pss->push_on_queue(p); 3902 pss->push_on_queue(p);
3901 } else { 3903 } else {
3902 oop* p = (oop*) stolen_task; 3904 oop* p = (oop*) stolen_task;
3903 assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error"); 3905 assert(has_partial_array_mask(p) || _g1h->is_in_g1_reserved(*p), "Error");
3904 pss->push_on_queue(p); 3906 pss->push_on_queue(p);
3905 } 3907 }
3906 continue; 3908 continue;
3907 } 3909 }
3908 pss->start_term_time(); 3910 pss->start_term_time();
3960 pss.set_partial_scan_closure(&partial_scan_cl); 3962 pss.set_partial_scan_closure(&partial_scan_cl);
3961 3963
3962 G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss); 3964 G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss);
3963 G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss); 3965 G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss);
3964 G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss); 3966 G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss);
3967 G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
3965 3968
3966 G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss); 3969 G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss);
3967 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); 3970 G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss);
3968 G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss); 3971 G1ParScanAndMarkHeapRSClosure scan_mark_heap_rs_cl(_g1h, &pss);
3969 3972
3983 3986
3984 pss.start_strong_roots(); 3987 pss.start_strong_roots();
3985 _g1h->g1_process_strong_roots(/* not collecting perm */ false, 3988 _g1h->g1_process_strong_roots(/* not collecting perm */ false,
3986 SharedHeap::SO_AllClasses, 3989 SharedHeap::SO_AllClasses,
3987 scan_root_cl, 3990 scan_root_cl,
3988 &only_scan_heap_rs_cl, 3991 &push_heap_rs_cl,
3989 scan_so_cl, 3992 scan_so_cl,
3990 scan_perm_cl, 3993 scan_perm_cl,
3991 i); 3994 i);
3992 pss.end_strong_roots(); 3995 pss.end_strong_roots();
3993 { 3996 {