8064473: Improved handling of age during object copy in G1
Reviewed-by: brutisso, tschatzl
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 14 14:23:25 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Nov 14 15:03:39 2014 +0100
@@ -4270,10 +4270,11 @@
if (state == G1CollectedHeap::InCSet) {
oop forwardee;
- if (obj->is_forwarded()) {
- forwardee = obj->forwardee();
+ markOop m = obj->mark();
+ if (m->is_marked()) {
+ forwardee = (oop) m->decode_pointer();
} else {
- forwardee = _par_scan_state->copy_to_survivor_space(obj);
+ forwardee = _par_scan_state->copy_to_survivor_space(obj, m);
}
assert(forwardee != NULL, "forwardee should not be NULL");
oopDesc::encode_store_heap_oop(p, forwardee);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Nov 14 14:23:25 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Fri Nov 14 15:03:39 2014 +0100
@@ -150,7 +150,8 @@
} while (!_refs->is_empty());
}
-oop G1ParScanThreadState::copy_to_survivor_space(oop const old) {
+oop G1ParScanThreadState::copy_to_survivor_space(oop const old,
+ markOop const old_mark) {
size_t word_sz = old->size();
HeapRegion* from_region = _g1h->heap_region_containing_raw(old);
// +1 to make the -1 indexes valid...
@@ -158,9 +159,8 @@
assert( (from_region->is_young() && young_index > 0) ||
(!from_region->is_young() && young_index == 0), "invariant" );
G1CollectorPolicy* g1p = _g1h->g1_policy();
- markOop m = old->mark();
- int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age()
- : m->age();
+ uint age = old_mark->has_displaced_mark_helper() ? old_mark->displaced_mark_helper()->age()
+ : old_mark->age();
GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age,
word_sz);
AllocationContext_t context = from_region->allocation_context();
@@ -196,30 +196,22 @@
alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured;
if (g1p->track_object_age(alloc_purpose)) {
- // We could simply do obj->incr_age(). However, this causes a
- // performance issue. obj->incr_age() will first check whether
- // the object has a displaced mark by checking its mark word;
- // getting the mark word from the new location of the object
- // stalls. So, given that we already have the mark word and we
- // are about to install it anyway, it's better to increase the
- // age on the mark word, when the object does not have a
- // displaced mark word. We're not expecting many objects to have
- // a displaced marked word, so that case is not optimized
- // further (it could be...) and we simply call obj->incr_age().
-
- if (m->has_displaced_mark_helper()) {
- // in this case, we have to install the mark word first,
+ if (age < markOopDesc::max_age) {
+ age++;
+ }
+ if (old_mark->has_displaced_mark_helper()) {
+ // In this case, we have to install the mark word first,
// otherwise obj looks to be forwarded (the old mark word,
// which contains the forward pointer, was copied)
- obj->set_mark(m);
- obj->incr_age();
+ obj->set_mark(old_mark);
+ markOop new_mark = old_mark->displaced_mark_helper()->set_age(age);
+ old_mark->set_displaced_mark_helper(new_mark);
} else {
- m = m->incr_age();
- obj->set_mark(m);
+ obj->set_mark(old_mark->set_age(age));
}
- age_table()->add(obj, word_sz);
+ age_table()->add(age, word_sz);
} else {
- obj->set_mark(m);
+ obj->set_mark(old_mark);
}
if (G1StringDedup::is_enabled()) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Fri Nov 14 14:23:25 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Fri Nov 14 15:03:39 2014 +0100
@@ -195,7 +195,7 @@
inline void dispatch_reference(StarTask ref);
public:
- oop copy_to_survivor_space(oop const obj);
+ oop copy_to_survivor_space(oop const obj, markOop const old_mark);
void trim_queue();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Nov 14 14:23:25 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Fri Nov 14 15:03:39 2014 +0100
@@ -41,10 +41,11 @@
G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj);
if (in_cset_state == G1CollectedHeap::InCSet) {
oop forwardee;
- if (obj->is_forwarded()) {
- forwardee = obj->forwardee();
+ markOop m = obj->mark();
+ if (m->is_marked()) {
+ forwardee = (oop) m->decode_pointer();
} else {
- forwardee = copy_to_survivor_space(obj);
+ forwardee = copy_to_survivor_space(obj, m);
}
oopDesc::encode_store_heap_oop(p, forwardee);
} else if (in_cset_state == G1CollectedHeap::IsHumongous) {
--- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Nov 14 14:23:25 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.hpp Fri Nov 14 15:03:39 2014 +0100
@@ -55,7 +55,10 @@
// add entry
void add(oop p, size_t oop_size) {
- uint age = p->age();
+ add(p->age(), oop_size);
+ }
+
+ void add(uint age, size_t oop_size) {
assert(age > 0 && age < table_size, "invalid age of object");
sizes[age] += oop_size;
}