Fri, 14 Nov 2014 15:03:39 +0100
8064473: Improved handling of age during object copy in G1
Reviewed-by: brutisso, tschatzl
1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 10 12:15:51 2014 +0200 1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 14 15:03:39 2014 +0100 1.3 @@ -4479,10 +4479,11 @@ 1.4 1.5 if (state == G1CollectedHeap::InCSet) { 1.6 oop forwardee; 1.7 - if (obj->is_forwarded()) { 1.8 - forwardee = obj->forwardee(); 1.9 + markOop m = obj->mark(); 1.10 + if (m->is_marked()) { 1.11 + forwardee = (oop) m->decode_pointer(); 1.12 } else { 1.13 - forwardee = _par_scan_state->copy_to_survivor_space(obj); 1.14 + forwardee = _par_scan_state->copy_to_survivor_space(obj, m); 1.15 } 1.16 assert(forwardee != NULL, "forwardee should not be NULL"); 1.17 oopDesc::encode_store_heap_oop(p, forwardee);
2.1 --- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Oct 10 12:15:51 2014 +0200 2.2 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Nov 14 15:03:39 2014 +0100 2.3 @@ -150,7 +150,8 @@ 2.4 } while (!_refs->is_empty()); 2.5 } 2.6 2.7 -oop G1ParScanThreadState::copy_to_survivor_space(oop const old) { 2.8 +oop G1ParScanThreadState::copy_to_survivor_space(oop const old, 2.9 + markOop const old_mark) { 2.10 size_t word_sz = old->size(); 2.11 HeapRegion* from_region = _g1h->heap_region_containing_raw(old); 2.12 // +1 to make the -1 indexes valid... 2.13 @@ -158,9 +159,8 @@ 2.14 assert( (from_region->is_young() && young_index > 0) || 2.15 (!from_region->is_young() && young_index == 0), "invariant" ); 2.16 G1CollectorPolicy* g1p = _g1h->g1_policy(); 2.17 - markOop m = old->mark(); 2.18 - int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() 2.19 - : m->age(); 2.20 + uint age = old_mark->has_displaced_mark_helper() ? old_mark->displaced_mark_helper()->age() 2.21 + : old_mark->age(); 2.22 GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, 2.23 word_sz); 2.24 AllocationContext_t context = from_region->allocation_context(); 2.25 @@ -196,30 +196,22 @@ 2.26 alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured; 2.27 2.28 if (g1p->track_object_age(alloc_purpose)) { 2.29 - // We could simply do obj->incr_age(). However, this causes a 2.30 - // performance issue. obj->incr_age() will first check whether 2.31 - // the object has a displaced mark by checking its mark word; 2.32 - // getting the mark word from the new location of the object 2.33 - // stalls. So, given that we already have the mark word and we 2.34 - // are about to install it anyway, it's better to increase the 2.35 - // age on the mark word, when the object does not have a 2.36 - // displaced mark word. We're not expecting many objects to have 2.37 - // a displaced marked word, so that case is not optimized 2.38 - // further (it could be...) and we simply call obj->incr_age(). 2.39 - 2.40 - if (m->has_displaced_mark_helper()) { 2.41 - // in this case, we have to install the mark word first, 2.42 + if (age < markOopDesc::max_age) { 2.43 + age++; 2.44 + } 2.45 + if (old_mark->has_displaced_mark_helper()) { 2.46 + // In this case, we have to install the mark word first, 2.47 // otherwise obj looks to be forwarded (the old mark word, 2.48 // which contains the forward pointer, was copied) 2.49 - obj->set_mark(m); 2.50 - obj->incr_age(); 2.51 + obj->set_mark(old_mark); 2.52 + markOop new_mark = old_mark->displaced_mark_helper()->set_age(age); 2.53 + old_mark->set_displaced_mark_helper(new_mark); 2.54 } else { 2.55 - m = m->incr_age(); 2.56 - obj->set_mark(m); 2.57 + obj->set_mark(old_mark->set_age(age)); 2.58 } 2.59 - age_table()->add(obj, word_sz); 2.60 + age_table()->add(age, word_sz); 2.61 } else { 2.62 - obj->set_mark(m); 2.63 + obj->set_mark(old_mark); 2.64 } 2.65 2.66 if (G1StringDedup::is_enabled()) {
3.1 --- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Fri Oct 10 12:15:51 2014 +0200 3.2 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Fri Nov 14 15:03:39 2014 +0100 3.3 @@ -195,7 +195,7 @@ 3.4 inline void dispatch_reference(StarTask ref); 3.5 public: 3.6 3.7 - oop copy_to_survivor_space(oop const obj); 3.8 + oop copy_to_survivor_space(oop const obj, markOop const old_mark); 3.9 3.10 void trim_queue(); 3.11
4.1 --- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Oct 10 12:15:51 2014 +0200 4.2 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Nov 14 15:03:39 2014 +0100 4.3 @@ -41,10 +41,11 @@ 4.4 G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj); 4.5 if (in_cset_state == G1CollectedHeap::InCSet) { 4.6 oop forwardee; 4.7 - if (obj->is_forwarded()) { 4.8 - forwardee = obj->forwardee(); 4.9 + markOop m = obj->mark(); 4.10 + if (m->is_marked()) { 4.11 + forwardee = (oop) m->decode_pointer(); 4.12 } else { 4.13 - forwardee = copy_to_survivor_space(obj); 4.14 + forwardee = copy_to_survivor_space(obj, m); 4.15 } 4.16 oopDesc::encode_store_heap_oop(p, forwardee); 4.17 } else if (in_cset_state == G1CollectedHeap::IsHumongous) {
5.1 --- a/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Oct 10 12:15:51 2014 +0200 5.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Nov 14 15:03:39 2014 +0100 5.3 @@ -55,7 +55,10 @@ 5.4 5.5 // add entry 5.6 void add(oop p, size_t oop_size) { 5.7 - uint age = p->age(); 5.8 + add(p->age(), oop_size); 5.9 + } 5.10 + 5.11 + void add(uint age, size_t oop_size) { 5.12 assert(age > 0 && age < table_size, "invalid age of object"); 5.13 sizes[age] += oop_size; 5.14 }