comparison src/share/vm/gc_implementation/g1/concurrentMark.cpp @ 4097:dc467e8b2c5e

7112743: G1: Reduce overhead of marking closure during evacuation pauses Summary: Parallelize the serial code that was used to mark objects reachable from survivor objects in the collection set. Some minor improvments in the timers used to track the freeing of the collection set along with some tweaks to PrintGCDetails. Reviewed-by: tonyp, brutisso
author johnc
date Thu, 17 Nov 2011 12:40:15 -0800
parents bca17e38de00
children adedfbbf0360
comparison
equal deleted inserted replaced
4096:00dd86e542eb 4097:dc467e8b2c5e
2904 gclog_or_tty->print_cr("---------------------------------------------------------------------"); 2904 gclog_or_tty->print_cr("---------------------------------------------------------------------");
2905 } 2905 }
2906 } 2906 }
2907 } 2907 }
2908 2908
2909 class CSMarkOopClosure: public OopClosure { 2909 // Closures used by ConcurrentMark::complete_marking_in_collection_set().
2910 friend class CSMarkBitMapClosure; 2910
2911 class CSetMarkOopClosure: public OopClosure {
2912 friend class CSetMarkBitMapClosure;
2911 2913
2912 G1CollectedHeap* _g1h; 2914 G1CollectedHeap* _g1h;
2913 CMBitMap* _bm; 2915 CMBitMap* _bm;
2914 ConcurrentMark* _cm; 2916 ConcurrentMark* _cm;
2915 oop* _ms; 2917 oop* _ms;
2916 jint* _array_ind_stack; 2918 jint* _array_ind_stack;
2917 int _ms_size; 2919 int _ms_size;
2918 int _ms_ind; 2920 int _ms_ind;
2919 int _array_increment; 2921 int _array_increment;
2922 int _worker_i;
2920 2923
2921 bool push(oop obj, int arr_ind = 0) { 2924 bool push(oop obj, int arr_ind = 0) {
2922 if (_ms_ind == _ms_size) { 2925 if (_ms_ind == _ms_size) {
2923 gclog_or_tty->print_cr("Mark stack is full."); 2926 gclog_or_tty->print_cr("Mark stack is full.");
2924 return false; 2927 return false;
2955 // Now process this portion of this one. 2958 // Now process this portion of this one.
2956 int lim = MIN2(next_arr_ind, len); 2959 int lim = MIN2(next_arr_ind, len);
2957 for (int j = arr_ind; j < lim; j++) { 2960 for (int j = arr_ind; j < lim; j++) {
2958 do_oop(aobj->objArrayOopDesc::obj_at_addr<T>(j)); 2961 do_oop(aobj->objArrayOopDesc::obj_at_addr<T>(j));
2959 } 2962 }
2960
2961 } else { 2963 } else {
2962 obj->oop_iterate(this); 2964 obj->oop_iterate(this);
2963 } 2965 }
2964 if (abort()) return false; 2966 if (abort()) return false;
2965 } 2967 }
2966 return true; 2968 return true;
2967 } 2969 }
2968 2970
2969 public: 2971 public:
2970 CSMarkOopClosure(ConcurrentMark* cm, int ms_size) : 2972 CSetMarkOopClosure(ConcurrentMark* cm, int ms_size, int worker_i) :
2971 _g1h(G1CollectedHeap::heap()), 2973 _g1h(G1CollectedHeap::heap()),
2972 _cm(cm), 2974 _cm(cm),
2973 _bm(cm->nextMarkBitMap()), 2975 _bm(cm->nextMarkBitMap()),
2974 _ms_size(ms_size), _ms_ind(0), 2976 _ms_size(ms_size), _ms_ind(0),
2975 _ms(NEW_C_HEAP_ARRAY(oop, ms_size)), 2977 _ms(NEW_C_HEAP_ARRAY(oop, ms_size)),
2976 _array_ind_stack(NEW_C_HEAP_ARRAY(jint, ms_size)), 2978 _array_ind_stack(NEW_C_HEAP_ARRAY(jint, ms_size)),
2977 _array_increment(MAX2(ms_size/8, 16)) 2979 _array_increment(MAX2(ms_size/8, 16)),
2978 {} 2980 _worker_i(worker_i) { }
2979 2981
2980 ~CSMarkOopClosure() { 2982 ~CSetMarkOopClosure() {
2981 FREE_C_HEAP_ARRAY(oop, _ms); 2983 FREE_C_HEAP_ARRAY(oop, _ms);
2982 FREE_C_HEAP_ARRAY(jint, _array_ind_stack); 2984 FREE_C_HEAP_ARRAY(jint, _array_ind_stack);
2983 } 2985 }
2984 2986
2985 virtual void do_oop(narrowOop* p) { do_oop_work(p); } 2987 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
2998 } 3000 }
2999 HeapRegion* hr = _g1h->heap_region_containing(obj); 3001 HeapRegion* hr = _g1h->heap_region_containing(obj);
3000 if (hr != NULL) { 3002 if (hr != NULL) {
3001 if (hr->in_collection_set()) { 3003 if (hr->in_collection_set()) {
3002 if (_g1h->is_obj_ill(obj)) { 3004 if (_g1h->is_obj_ill(obj)) {
3003 _bm->mark((HeapWord*)obj); 3005 if (_bm->parMark((HeapWord*)obj)) {
3004 if (!push(obj)) { 3006 if (!push(obj)) {
3005 gclog_or_tty->print_cr("Setting abort in CSMarkOopClosure because push failed."); 3007 gclog_or_tty->print_cr("Setting abort in CSetMarkOopClosure because push failed.");
3006 set_abort(); 3008 set_abort();
3009 }
3007 } 3010 }
3008 } 3011 }
3009 } else { 3012 } else {
3010 // Outside the collection set; we need to gray it 3013 // Outside the collection set; we need to gray it
3011 _cm->deal_with_reference(obj); 3014 _cm->deal_with_reference(obj);
3012 } 3015 }
3013 } 3016 }
3014 } 3017 }
3015 }; 3018 };
3016 3019
3017 class CSMarkBitMapClosure: public BitMapClosure { 3020 class CSetMarkBitMapClosure: public BitMapClosure {
3018 G1CollectedHeap* _g1h; 3021 G1CollectedHeap* _g1h;
3019 CMBitMap* _bitMap; 3022 CMBitMap* _bitMap;
3020 ConcurrentMark* _cm; 3023 ConcurrentMark* _cm;
3021 CSMarkOopClosure _oop_cl; 3024 CSetMarkOopClosure _oop_cl;
3025 int _worker_i;
3026
3022 public: 3027 public:
3023 CSMarkBitMapClosure(ConcurrentMark* cm, int ms_size) : 3028 CSetMarkBitMapClosure(ConcurrentMark* cm, int ms_size, int worker_i) :
3024 _g1h(G1CollectedHeap::heap()), 3029 _g1h(G1CollectedHeap::heap()),
3025 _bitMap(cm->nextMarkBitMap()), 3030 _bitMap(cm->nextMarkBitMap()),
3026 _oop_cl(cm, ms_size) 3031 _oop_cl(cm, ms_size, worker_i),
3027 {} 3032 _worker_i(worker_i) { }
3028
3029 ~CSMarkBitMapClosure() {}
3030 3033
3031 bool do_bit(size_t offset) { 3034 bool do_bit(size_t offset) {
3032 // convert offset into a HeapWord* 3035 // convert offset into a HeapWord*
3033 HeapWord* addr = _bitMap->offsetToHeapWord(offset); 3036 HeapWord* addr = _bitMap->offsetToHeapWord(offset);
3034 assert(_bitMap->endWord() && addr < _bitMap->endWord(), 3037 assert(_bitMap->endWord() && addr < _bitMap->endWord(),
3046 // Otherwise... 3049 // Otherwise...
3047 return true; 3050 return true;
3048 } 3051 }
3049 }; 3052 };
3050 3053
3051 3054 class CompleteMarkingInCSetHRClosure: public HeapRegionClosure {
3052 class CompleteMarkingInCSHRClosure: public HeapRegionClosure { 3055 CMBitMap* _bm;
3053 CMBitMap* _bm; 3056 CSetMarkBitMapClosure _bit_cl;
3054 CSMarkBitMapClosure _bit_cl; 3057 int _worker_i;
3058
3055 enum SomePrivateConstants { 3059 enum SomePrivateConstants {
3056 MSSize = 1000 3060 MSSize = 1000
3057 }; 3061 };
3058 bool _completed; 3062
3059 public: 3063 public:
3060 CompleteMarkingInCSHRClosure(ConcurrentMark* cm) : 3064 CompleteMarkingInCSetHRClosure(ConcurrentMark* cm, int worker_i) :
3061 _bm(cm->nextMarkBitMap()), 3065 _bm(cm->nextMarkBitMap()),
3062 _bit_cl(cm, MSSize), 3066 _bit_cl(cm, MSSize, worker_i),
3063 _completed(true) 3067 _worker_i(worker_i) { }
3064 {} 3068
3065 3069 bool doHeapRegion(HeapRegion* hr) {
3066 ~CompleteMarkingInCSHRClosure() {} 3070 if (hr->claimHeapRegion(HeapRegion::CompleteMarkCSetClaimValue)) {
3067 3071 // The current worker has successfully claimed the region.
3068 bool doHeapRegion(HeapRegion* r) { 3072 if (!hr->evacuation_failed()) {
3069 if (!r->evacuation_failed()) { 3073 MemRegion mr = MemRegion(hr->bottom(), hr->next_top_at_mark_start());
3070 MemRegion mr = MemRegion(r->bottom(), r->next_top_at_mark_start()); 3074 if (!mr.is_empty()) {
3071 if (!mr.is_empty()) { 3075 bool done = false;
3072 if (!_bm->iterate(&_bit_cl, mr)) { 3076 while (!done) {
3073 _completed = false; 3077 done = _bm->iterate(&_bit_cl, mr);
3074 return true; 3078 }
3075 } 3079 }
3076 } 3080 }
3077 } 3081 }
3078 return false; 3082 return false;
3079 } 3083 }
3080
3081 bool completed() { return _completed; }
3082 }; 3084 };
3083 3085
3084 class ClearMarksInHRClosure: public HeapRegionClosure { 3086 class SetClaimValuesInCSetHRClosure: public HeapRegionClosure {
3085 CMBitMap* _bm; 3087 jint _claim_value;
3088
3086 public: 3089 public:
3087 ClearMarksInHRClosure(CMBitMap* bm): _bm(bm) { } 3090 SetClaimValuesInCSetHRClosure(jint claim_value) :
3088 3091 _claim_value(claim_value) { }
3089 bool doHeapRegion(HeapRegion* r) { 3092
3090 if (!r->used_region().is_empty() && !r->evacuation_failed()) { 3093 bool doHeapRegion(HeapRegion* hr) {
3091 MemRegion usedMR = r->used_region(); 3094 hr->set_claim_value(_claim_value);
3092 _bm->clearRange(r->used_region());
3093 }
3094 return false; 3095 return false;
3096 }
3097 };
3098
3099 class G1ParCompleteMarkInCSetTask: public AbstractGangTask {
3100 protected:
3101 G1CollectedHeap* _g1h;
3102 ConcurrentMark* _cm;
3103
3104 public:
3105 G1ParCompleteMarkInCSetTask(G1CollectedHeap* g1h,
3106 ConcurrentMark* cm) :
3107 AbstractGangTask("Complete Mark in CSet"),
3108 _g1h(g1h), _cm(cm) { }
3109
3110 void work(int worker_i) {
3111 CompleteMarkingInCSetHRClosure cmplt(_cm, worker_i);
3112 HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_i);
3113 _g1h->collection_set_iterate_from(hr, &cmplt);
3095 } 3114 }
3096 }; 3115 };
3097 3116
3098 void ConcurrentMark::complete_marking_in_collection_set() { 3117 void ConcurrentMark::complete_marking_in_collection_set() {
3099 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 3118 G1CollectedHeap* g1h = G1CollectedHeap::heap();
3101 if (!g1h->mark_in_progress()) { 3120 if (!g1h->mark_in_progress()) {
3102 g1h->g1_policy()->record_mark_closure_time(0.0); 3121 g1h->g1_policy()->record_mark_closure_time(0.0);
3103 return; 3122 return;
3104 } 3123 }
3105 3124
3106 int i = 1;
3107 double start = os::elapsedTime(); 3125 double start = os::elapsedTime();
3108 while (true) { 3126 int n_workers = g1h->workers()->total_workers();
3109 i++; 3127
3110 CompleteMarkingInCSHRClosure cmplt(this); 3128 G1ParCompleteMarkInCSetTask complete_mark_task(g1h, this);
3111 g1h->collection_set_iterate(&cmplt); 3129
3112 if (cmplt.completed()) break; 3130 assert(g1h->check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
3113 } 3131
3114 3132 if (G1CollectedHeap::use_parallel_gc_threads()) {
3115 ClearMarksInHRClosure clr(nextMarkBitMap()); 3133 g1h->set_par_threads(n_workers);
3116 g1h->collection_set_iterate(&clr); 3134 g1h->workers()->run_task(&complete_mark_task);
3135 g1h->set_par_threads(0);
3136 } else {
3137 complete_mark_task.work(0);
3138 }
3139
3140 assert(g1h->check_cset_heap_region_claim_values(HeapRegion::CompleteMarkCSetClaimValue), "sanity");
3141
3142 // Now reset the claim values in the regions in the collection set.
3143 SetClaimValuesInCSetHRClosure set_cv_cl(HeapRegion::InitialClaimValue);
3144 g1h->collection_set_iterate(&set_cv_cl);
3145
3146 assert(g1h->check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
3117 3147
3118 double end_time = os::elapsedTime(); 3148 double end_time = os::elapsedTime();
3119 double elapsed_time_ms = (end_time - start) * 1000.0; 3149 double elapsed_time_ms = (end_time - start) * 1000.0;
3120 g1h->g1_policy()->record_mark_closure_time(elapsed_time_ms); 3150 g1h->g1_policy()->record_mark_closure_time(elapsed_time_ms);
3121 } 3151 }