Mercurial > hg > graal-jvmci-8
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()); |