提交 2d2ad866 编写于 作者: J johnc

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
上级 6c916f33
...@@ -4069,6 +4069,23 @@ bool GCLabBitMapClosure::do_bit(size_t offset) { ...@@ -4069,6 +4069,23 @@ bool GCLabBitMapClosure::do_bit(size_t offset) {
} }
#endif // PRODUCT #endif // PRODUCT
G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
ParGCAllocBuffer(gclab_word_size),
_should_mark_objects(false),
_bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size),
_retired(false)
{
//_should_mark_objects is set to true when G1ParCopyHelper needs to
// mark the forwarded location of an evacuated object.
// We set _should_mark_objects to true if marking is active, i.e. when we
// need to propagate a mark, or during an initial mark pause, i.e. when we
// need to mark objects immediately reachable by the roots.
if (G1CollectedHeap::heap()->mark_in_progress() ||
G1CollectedHeap::heap()->g1_policy()->during_initial_mark_pause()) {
_should_mark_objects = true;
}
}
G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num) G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, int queue_num)
: _g1h(g1h), : _g1h(g1h),
_refs(g1h->task_queue(queue_num)), _refs(g1h->task_queue(queue_num)),
...@@ -4184,12 +4201,14 @@ void G1ParScanThreadState::trim_queue() { ...@@ -4184,12 +4201,14 @@ void G1ParScanThreadState::trim_queue() {
G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
_g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
_par_scan_state(par_scan_state) { } _par_scan_state(par_scan_state),
_during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()),
_mark_in_progress(_g1->mark_in_progress()) { }
template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { template <class T> void G1ParCopyHelper::mark_object(T* p) {
// This is called _after_ do_oop_work has been called, hence after // This is called from do_oop_work for objects that are not
// the object has been relocated to its new location and *p points // in the collection set. Objects in the collection set
// to its new location. // are marked after they have been evacuated.
T heap_oop = oopDesc::load_heap_oop(p); T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) { if (!oopDesc::is_null(heap_oop)) {
...@@ -4201,7 +4220,7 @@ template <class T> void G1ParCopyHelper::mark_forwardee(T* p) { ...@@ -4201,7 +4220,7 @@ template <class T> void G1ParCopyHelper::mark_forwardee(T* p) {
} }
} }
oop G1ParCopyHelper::copy_to_survivor_space(oop old) { oop G1ParCopyHelper::copy_to_survivor_space(oop old, bool should_mark_copy) {
size_t word_sz = old->size(); size_t word_sz = old->size();
HeapRegion* from_region = _g1->heap_region_containing_raw(old); HeapRegion* from_region = _g1->heap_region_containing_raw(old);
// +1 to make the -1 indexes valid... // +1 to make the -1 indexes valid...
...@@ -4257,8 +4276,8 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { ...@@ -4257,8 +4276,8 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) {
obj->set_mark(m); obj->set_mark(m);
} }
// preserve "next" mark bit // Mark the evacuated object or propagate "next" mark bit
if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) { if (should_mark_copy) {
if (!use_local_bitmaps || if (!use_local_bitmaps ||
!_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) {
// if we couldn't mark it on the local bitmap (this happens when // if we couldn't mark it on the local bitmap (this happens when
...@@ -4266,11 +4285,12 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { ...@@ -4266,11 +4285,12 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) {
// the bullet and do the standard parallel mark // the bullet and do the standard parallel mark
_cm->markAndGrayObjectIfNecessary(obj); _cm->markAndGrayObjectIfNecessary(obj);
} }
#if 1
if (_g1->isMarkedNext(old)) { if (_g1->isMarkedNext(old)) {
// Unmark the object's old location so that marking
// doesn't think the old object is alive.
_cm->nextMarkBitMap()->parClear((HeapWord*)old); _cm->nextMarkBitMap()->parClear((HeapWord*)old);
} }
#endif
} }
size_t* surv_young_words = _par_scan_state->surviving_young_words(); size_t* surv_young_words = _par_scan_state->surviving_young_words();
...@@ -4293,26 +4313,62 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { ...@@ -4293,26 +4313,62 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) {
return obj; return obj;
} }
template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee> template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
template <class T> template <class T>
void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee> void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
::do_oop_work(T* p) { ::do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p); oop obj = oopDesc::load_decode_heap_oop(p);
assert(barrier != G1BarrierRS || obj != NULL, assert(barrier != G1BarrierRS || obj != NULL,
"Precondition: G1BarrierRS implies obj is nonNull"); "Precondition: G1BarrierRS implies obj is nonNull");
// Marking:
// If the object is in the collection set, then the thread
// that copies the object should mark, or propagate the
// mark to, the evacuated object.
// If the object is not in the collection set then we
// should call the mark_object() method depending on the
// value of the template parameter do_mark_object (which will
// be true for root scanning closures during an initial mark
// pause).
// The mark_object() method first checks whether the object
// is marked and, if not, attempts to mark the object.
// here the null check is implicit in the cset_fast_test() test // here the null check is implicit in the cset_fast_test() test
if (_g1->in_cset_fast_test(obj)) { if (_g1->in_cset_fast_test(obj)) {
if (obj->is_forwarded()) { if (obj->is_forwarded()) {
oopDesc::encode_store_heap_oop(p, obj->forwardee()); oopDesc::encode_store_heap_oop(p, obj->forwardee());
// If we are a root scanning closure during an initial
// mark pause (i.e. do_mark_object will be true) then
// we also need to handle marking of roots in the
// event of an evacuation failure. In the event of an
// evacuation failure, the object is forwarded to itself
// and not copied so let's mark it here.
if (do_mark_object && obj->forwardee() == obj) {
mark_object(p);
}
} else { } else {
oop copy_oop = copy_to_survivor_space(obj); // We need to mark the copied object if we're a root scanning
// closure during an initial mark pause (i.e. do_mark_object
// will be true), or the object is already marked and we need
// to propagate the mark to the evacuated copy.
bool should_mark_copy = do_mark_object ||
_during_initial_mark ||
(_mark_in_progress && !_g1->is_obj_ill(obj));
oop copy_oop = copy_to_survivor_space(obj, should_mark_copy);
oopDesc::encode_store_heap_oop(p, copy_oop); oopDesc::encode_store_heap_oop(p, copy_oop);
} }
// When scanning the RS, we only care about objs in CS. // When scanning the RS, we only care about objs in CS.
if (barrier == G1BarrierRS) { if (barrier == G1BarrierRS) {
_par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
} }
} else {
// The object is not in collection set. If we're a root scanning
// closure during an initial mark pause (i.e. do_mark_object will
// be true) then attempt to mark the object.
if (do_mark_object) {
mark_object(p);
}
} }
if (barrier == G1BarrierEvac && obj != NULL) { if (barrier == G1BarrierEvac && obj != NULL) {
......
...@@ -1715,26 +1715,22 @@ public: ...@@ -1715,26 +1715,22 @@ public:
class G1ParGCAllocBuffer: public ParGCAllocBuffer { class G1ParGCAllocBuffer: public ParGCAllocBuffer {
private: private:
bool _retired; bool _retired;
bool _during_marking; bool _should_mark_objects;
GCLabBitMap _bitmap; GCLabBitMap _bitmap;
public: public:
G1ParGCAllocBuffer(size_t gclab_word_size) : G1ParGCAllocBuffer(size_t gclab_word_size);
ParGCAllocBuffer(gclab_word_size),
_during_marking(G1CollectedHeap::heap()->mark_in_progress()),
_bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size),
_retired(false)
{ }
inline bool mark(HeapWord* addr) { inline bool mark(HeapWord* addr) {
guarantee(use_local_bitmaps, "invariant"); guarantee(use_local_bitmaps, "invariant");
assert(_during_marking, "invariant"); assert(_should_mark_objects, "invariant");
return _bitmap.mark(addr); return _bitmap.mark(addr);
} }
inline void set_buf(HeapWord* buf) { inline void set_buf(HeapWord* buf) {
if (use_local_bitmaps && _during_marking) if (use_local_bitmaps && _should_mark_objects) {
_bitmap.set_buffer(buf); _bitmap.set_buffer(buf);
}
ParGCAllocBuffer::set_buf(buf); ParGCAllocBuffer::set_buf(buf);
_retired = false; _retired = false;
} }
...@@ -1742,7 +1738,7 @@ public: ...@@ -1742,7 +1738,7 @@ public:
inline void retire(bool end_of_gc, bool retain) { inline void retire(bool end_of_gc, bool retain) {
if (_retired) if (_retired)
return; return;
if (use_local_bitmaps && _during_marking) { if (use_local_bitmaps && _should_mark_objects) {
_bitmap.retire(); _bitmap.retire();
} }
ParGCAllocBuffer::retire(end_of_gc, retain); ParGCAllocBuffer::retire(end_of_gc, retain);
......
...@@ -50,6 +50,8 @@ protected: ...@@ -50,6 +50,8 @@ protected:
G1RemSet* _g1_rem; G1RemSet* _g1_rem;
ConcurrentMark* _cm; ConcurrentMark* _cm;
G1ParScanThreadState* _par_scan_state; G1ParScanThreadState* _par_scan_state;
bool _during_initial_mark;
bool _mark_in_progress;
public: public:
G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state); G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
bool apply_to_weak_ref_discovered_field() { return true; } bool apply_to_weak_ref_discovered_field() { return true; }
...@@ -102,8 +104,8 @@ public: ...@@ -102,8 +104,8 @@ public:
class G1ParCopyHelper : public G1ParClosureSuper { class G1ParCopyHelper : public G1ParClosureSuper {
G1ParScanClosure *_scanner; G1ParScanClosure *_scanner;
protected: protected:
template <class T> void mark_forwardee(T* p); template <class T> void mark_object(T* p);
oop copy_to_survivor_space(oop obj); oop copy_to_survivor_space(oop obj, bool should_mark_copy);
public: public:
G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
G1ParScanClosure *scanner) : G1ParScanClosure *scanner) :
...@@ -111,7 +113,7 @@ public: ...@@ -111,7 +113,7 @@ public:
}; };
template<bool do_gen_barrier, G1Barrier barrier, template<bool do_gen_barrier, G1Barrier barrier,
bool do_mark_forwardee> bool do_mark_object>
class G1ParCopyClosure : public G1ParCopyHelper { class G1ParCopyClosure : public G1ParCopyHelper {
G1ParScanClosure _scanner; G1ParScanClosure _scanner;
template <class T> void do_oop_work(T* p); template <class T> void do_oop_work(T* p);
...@@ -120,8 +122,6 @@ public: ...@@ -120,8 +122,6 @@ public:
_scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { } _scanner(g1, par_scan_state), G1ParCopyHelper(g1, par_scan_state, &_scanner) { }
template <class T> void do_oop_nv(T* p) { template <class T> void do_oop_nv(T* p) {
do_oop_work(p); do_oop_work(p);
if (do_mark_forwardee)
mark_forwardee(p);
} }
virtual void do_oop(oop* p) { do_oop_nv(p); } virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
......
...@@ -36,7 +36,7 @@ enum G1Barrier { ...@@ -36,7 +36,7 @@ enum G1Barrier {
}; };
template<bool do_gen_barrier, G1Barrier barrier, template<bool do_gen_barrier, G1Barrier barrier,
bool do_mark_forwardee> bool do_mark_object>
class G1ParCopyClosure; class G1ParCopyClosure;
class G1ParScanClosure; class G1ParScanClosure;
class G1ParPushHeapRSClosure; class G1ParPushHeapRSClosure;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册