comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 3886:eeae91c9baba

7080389: G1: refactor marking code in evacuation pause copy closures Summary: Refactor code marking code in the evacuation pause copy closures so that an evacuated object is only marked by the thread that successfully copies it. Reviewed-by: stefank, brutisso, tonyp
author johnc
date Mon, 29 Aug 2011 10:13:06 -0700
parents 7f776886a215
children 20213c8a3c40 c2bf0120ee5d
comparison
equal deleted inserted replaced
3885:3cd0157e1d4d 3886:eeae91c9baba
4067 guarantee(_cm->isMarked(oop(addr)), "it should be!"); 4067 guarantee(_cm->isMarked(oop(addr)), "it should be!");
4068 return true; 4068 return true;
4069 } 4069 }
4070 #endif // PRODUCT 4070 #endif // PRODUCT
4071 4071
4072 G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
4073 ParGCAllocBuffer(gclab_word_size),
4074 _should_mark_objects(false),
4075 _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size),
4076 _retired(false)
4077 {
4078 //_should_mark_objects is set to true when G1ParCopyHelper needs to
4079 // mark the forwarded location of an evacuated object.
4080 // We set _should_mark_objects to true if marking is active, i.e. when we
4081 // need to propagate a mark, or during an initial mark pause, i.e. when we
4082 // need to mark objects immediately reachable by the roots.
4083 if (G1CollectedHeap::heap()->mark_in_progress() ||
4084 G1CollectedHeap::heap()->g1_policy()->during_initial_mark_pause()) {
4085 _should_mark_objects = true;
4086 }
4087 }
4088
4072 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) 4089 G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num)
4073 : _g1h(g1h), 4090 : _g1h(g1h),
4074 _refs(g1h->task_queue(queue_num)), 4091 _refs(g1h->task_queue(queue_num)),
4075 _dcq(&g1h->dirty_card_queue_set()), 4092 _dcq(&g1h->dirty_card_queue_set()),
4076 _ct_bs((CardTableModRefBS*)_g1h->barrier_set()), 4093 _ct_bs((CardTableModRefBS*)_g1h->barrier_set()),
4182 } while (!refs()->is_empty()); 4199 } while (!refs()->is_empty());
4183 } 4200 }
4184 4201
4185 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : 4202 G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
4186 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), 4203 _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
4187 _par_scan_state(par_scan_state) { } 4204 _par_scan_state(par_scan_state),
4188 4205 _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()),
4189 template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { 4206 _mark_in_progress(_g1->mark_in_progress()) { }
4190 // This is called _after_ do_oop_work has been called, hence after 4207
4191 // the object has been relocated to its new location and *p points 4208 template <class T> void G1ParCopyHelper::mark_object(T* p) {
4192 // to its new location. 4209 // This is called from do_oop_work for objects that are not
4210 // in the collection set. Objects in the collection set
4211 // are marked after they have been evacuated.
4193 4212
4194 T heap_oop = oopDesc::load_heap_oop(p); 4213 T heap_oop = oopDesc::load_heap_oop(p);
4195 if (!oopDesc::is_null(heap_oop)) { 4214 if (!oopDesc::is_null(heap_oop)) {
4196 oop obj = oopDesc::decode_heap_oop(heap_oop); 4215 oop obj = oopDesc::decode_heap_oop(heap_oop);
4197 HeapWord* addr = (HeapWord*)obj; 4216 HeapWord* addr = (HeapWord*)obj;
4199 _cm->grayRoot(oop(addr)); 4218 _cm->grayRoot(oop(addr));
4200 } 4219 }
4201 } 4220 }
4202 } 4221 }
4203 4222
4204 oop G1ParCopyHelper::copy_to_survivor_space(oop old) { 4223 oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) {
4205 size_t word_sz = old->size(); 4224 size_t word_sz = old->size();
4206 HeapRegion* from_region = _g1->heap_region_containing_raw(old); 4225 HeapRegion* from_region = _g1->heap_region_containing_raw(old);
4207 // +1 to make the -1 indexes valid... 4226 // +1 to make the -1 indexes valid...
4208 int young_index = from_region->young_index_in_cset()+1; 4227 int young_index = from_region->young_index_in_cset()+1;
4209 assert( (from_region->is_young() && young_index > 0) || 4228 assert( (from_region->is_young() && young_index > 0) ||
4255 _par_scan_state->age_table()->add(obj, word_sz); 4274 _par_scan_state->age_table()->add(obj, word_sz);
4256 } else { 4275 } else {
4257 obj->set_mark(m); 4276 obj->set_mark(m);
4258 } 4277 }
4259 4278
4260 // preserve "next" mark bit 4279 // Mark the evacuated object or propagate "next" mark bit
4261 if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { 4280 if (should_mark_copy) {
4262 if (!use_local_bitmaps || 4281 if (!use_local_bitmaps ||
4263 !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { 4282 !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) {
4264 // if we couldn't mark it on the local bitmap (this happens when 4283 // if we couldn't mark it on the local bitmap (this happens when
4265 // the object was not allocated in the GCLab), we have to bite 4284 // the object was not allocated in the GCLab), we have to bite
4266 // the bullet and do the standard parallel mark 4285 // the bullet and do the standard parallel mark
4267 _cm->markAndGrayObjectIfNecessary(obj); 4286 _cm->markAndGrayObjectIfNecessary(obj);
4268 } 4287 }
4269 #if 1 4288
4270 if (_g1->isMarkedNext(old)) { 4289 if (_g1->isMarkedNext(old)) {
4290 // Unmark the object's old location so that marking
4291 // doesn't think the old object is alive.
4271 _cm->nextMarkBitMap()->parClear((HeapWord*)old); 4292 _cm->nextMarkBitMap()->parClear((HeapWord*)old);
4272 } 4293 }
4273 #endif
4274 } 4294 }
4275 4295
4276 size_t* surv_young_words = _par_scan_state->surviving_young_words(); 4296 size_t* surv_young_words = _par_scan_state->surviving_young_words();
4277 surv_young_words[young_index] += word_sz; 4297 surv_young_words[young_index] += word_sz;
4278 4298
4291 obj = forward_ptr; 4311 obj = forward_ptr;
4292 } 4312 }
4293 return obj; 4313 return obj;
4294 } 4314 }
4295 4315
4296 template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> 4316 template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
4297 template <class T> 4317 template <class T>
4298 void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee> 4318 void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
4299 ::do_oop_work(T* p) { 4319 ::do_oop_work(T* p) {
4300 oop obj = oopDesc::load_decode_heap_oop(p); 4320 oop obj = oopDesc::load_decode_heap_oop(p);
4301 assert(barrier != G1BarrierRS || obj != NULL, 4321 assert(barrier != G1BarrierRS || obj != NULL,
4302 "Precondition: G1BarrierRS implies obj is nonNull"); 4322 "Precondition: G1BarrierRS implies obj is nonNull");
4303 4323
4324 // Marking:
4325 // If the object is in the collection set, then the thread
4326 // that copies the object should mark, or propagate the
4327 // mark to, the evacuated object.
4328 // If the object is not in the collection set then we
4329 // should call the mark_object() method depending on the
4330 // value of the template parameter do_mark_object (which will
4331 // be true for root scanning closures during an initial mark
4332 // pause).
4333 // The mark_object() method first checks whether the object
4334 // is marked and, if not, attempts to mark the object.
4335
4304 // here the null check is implicit in the cset_fast_test() test 4336 // here the null check is implicit in the cset_fast_test() test
4305 if (_g1->in_cset_fast_test(obj)) { 4337 if (_g1->in_cset_fast_test(obj)) {
4306 if (obj->is_forwarded()) { 4338 if (obj->is_forwarded()) {
4307 oopDesc::encode_store_heap_oop(p, obj->forwardee()); 4339 oopDesc::encode_store_heap_oop(p, obj->forwardee());
4340 // If we are a root scanning closure during an initial
4341 // mark pause (i.e. do_mark_object will be true) then
4342 // we also need to handle marking of roots in the
4343 // event of an evacuation failure. In the event of an
4344 // evacuation failure, the object is forwarded to itself
4345 // and not copied so let's mark it here.
4346 if (do_mark_object && obj->forwardee() == obj) {
4347 mark_object(p);
4348 }
4308 } else { 4349 } else {
4309 oop copy_oop = copy_to_survivor_space(obj); 4350 // We need to mark the copied object if we're a root scanning
4351 // closure during an initial mark pause (i.e. do_mark_object
4352 // will be true), or the object is already marked and we need
4353 // to propagate the mark to the evacuated copy.
4354 bool should_mark_copy = do_mark_object ||
4355 _during_initial_mark ||
4356 (_mark_in_progress && !_g1->is_obj_ill(obj));
4357
4358 oop copy_oop = copy_to_survivor_space(obj, should_mark_copy);
4310 oopDesc::encode_store_heap_oop(p, copy_oop); 4359 oopDesc::encode_store_heap_oop(p, copy_oop);
4311 } 4360 }
4312 // When scanning the RS, we only care about objs in CS. 4361 // When scanning the RS, we only care about objs in CS.
4313 if (barrier == G1BarrierRS) { 4362 if (barrier == G1BarrierRS) {
4314 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 4363 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
4364 }
4365 } else {
4366 // The object is not in collection set. If we're a root scanning
4367 // closure during an initial mark pause (i.e. do_mark_object will
4368 // be true) then attempt to mark the object.
4369 if (do_mark_object) {
4370 mark_object(p);
4315 } 4371 }
4316 } 4372 }
4317 4373
4318 if (barrier == G1BarrierEvac && obj != NULL) { 4374 if (barrier == G1BarrierEvac && obj != NULL) {
4319 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); 4375 _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());