# HG changeset patch # User rkennke # Date 1489685926 -3600 # Thu Mar 16 18:38:46 2017 +0100 # Node ID 33a7de594e20524dd9d6973b449bca5c84c19f55 # Parent b35e273953d4a3bcbab187203fcd4f44232ab7c2 Partial GC: Only evacuating threads push oop to work queue. diff --git a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp @@ -398,7 +398,8 @@ assert(_heap->in_collection_set(src), "only evacuate objects in collection set"); assert(! _heap->heap_region_containing(src)->is_humongous(), "never evacuate humongous objects"); // TODO: Consider passing thread from caller. - oop dst = _heap->evacuate_object(src, Thread::current()); + bool evac; + oop dst = _heap->evacuate_object(src, Thread::current(), evac); log_develop_trace(gc, compaction)("src = "PTR_FORMAT" dst = "PTR_FORMAT" src-2 = "PTR_FORMAT, p2i(src), p2i(dst), p2i(((HeapWord*) src) - 2)); diff --git a/src/share/vm/gc/shenandoah/shenandoahHeap.cpp b/src/share/vm/gc/shenandoah/shenandoahHeap.cpp --- a/src/share/vm/gc/shenandoah/shenandoahHeap.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeap.cpp @@ -796,7 +796,8 @@ assert(_heap->is_marked_complete(p), "expect only marked objects"); if (oopDesc::unsafe_equals(p, ShenandoahBarrierSet::resolve_oop_static_not_null(p))) { - _heap->evacuate_object(p, _thread); + bool evac; + _heap->evacuate_object(p, _thread, evac); } } }; @@ -1230,7 +1231,8 @@ _heap->is_marked_complete(obj), _heap->is_marked_complete(ShenandoahBarrierSet::resolve_oop_static_not_null(obj))); oop resolved = ShenandoahBarrierSet::resolve_oop_static_not_null(obj); if (oopDesc::unsafe_equals(resolved, obj)) { - resolved = _heap->evacuate_object(obj, _thread); + bool evac; + resolved = _heap->evacuate_object(obj, _thread, evac); } oopDesc::encode_store_heap_oop(p, resolved); } diff --git a/src/share/vm/gc/shenandoah/shenandoahHeap.hpp b/src/share/vm/gc/shenandoah/shenandoahHeap.hpp --- a/src/share/vm/gc/shenandoah/shenandoahHeap.hpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeap.hpp @@ -337,7 +337,11 @@ void set_complete_top_at_mark_start(HeapWord* region_base, HeapWord* addr); HeapWord* complete_top_at_mark_start(HeapWord* region_base); - inline oop evacuate_object(oop src, Thread* thread); + // Evacuates object src. Returns the evacuated object if this thread + // succeeded, otherwise rolls back the evacuation and returns the + // evacuated object by the competing thread. 'succeeded' is an out + // param and set to true if this thread succeeded, otherwise to false. + inline oop evacuate_object(oop src, Thread* thread, bool& evacuated); inline bool cancelled_concgc() const; inline void set_cancelled_concgc(bool v); inline bool try_cancel_concgc() const; diff --git a/src/share/vm/gc/shenandoah/shenandoahHeap.inline.hpp b/src/share/vm/gc/shenandoah/shenandoahHeap.inline.hpp --- a/src/share/vm/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeap.inline.hpp @@ -276,9 +276,11 @@ log_develop_trace(gc, compaction)("copy object from "PTR_FORMAT" to: "PTR_FORMAT, p2i((HeapWord*) p), p2i(copy)); } -inline oop ShenandoahHeap::evacuate_object(oop p, Thread* thread) { +inline oop ShenandoahHeap::evacuate_object(oop p, Thread* thread, bool& evacuated) { size_t required; + evacuated = false; + #ifdef ASSERT ShenandoahHeapRegion* hr = NULL; if (ShenandoahVerifyReadsToFromSpace) { @@ -341,6 +343,7 @@ oop return_val; if (oopDesc::unsafe_equals(result, p)) { + evacuated = true; return_val = copy_val; log_develop_trace(gc, compaction)("Copy of "PTR_FORMAT" to "PTR_FORMAT" succeeded \n", diff --git a/src/share/vm/gc/shenandoah/shenandoahPartialGC.cpp b/src/share/vm/gc/shenandoah/shenandoahPartialGC.cpp --- a/src/share/vm/gc/shenandoah/shenandoahPartialGC.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahPartialGC.cpp @@ -279,21 +279,19 @@ if (_heap->in_collection_set(obj)) { oop forw = ShenandoahBarrierSet::resolve_oop_static_not_null(obj); if (oopDesc::unsafe_equals(obj, forw)) { - forw = _heap->evacuate_object(obj, thread); + bool evacuated = false; + forw = _heap->evacuate_object(obj, thread, evacuated); + + // Only the thread that succeeded evacuating this object pushes it to its work queue. + if (evacuated) { + assert(forw->is_oop(), "sanity"); + bool succeeded = queue->push(SCMTask(forw)); + assert(succeeded, "must succeed to push to task queue"); + } } assert(! oopDesc::unsafe_equals(obj, forw) || _heap->cancelled_concgc(), "must be evacuated"); - // TODO: Only the thread that succeeds *evacuating* the object should need to - // update the matrix and push the evacuated object to its queue. This would also - // enable to only have one CAS (the one in evacuate_object()) and use simple - // store for updating the ref. - oop oldval = _heap->atomic_compare_exchange_oop(forw, p, obj); - if (oopDesc::unsafe_equals(obj, oldval)) { - assert(forw->is_oop(), "sanity"); - bool succeeded = queue->push(SCMTask(forw)); - assert(succeeded, "must succeed to push to task queue"); - } else { - assert(oopDesc::unsafe_equals(oldval, forw), "other thread must have punched the same forwarded oop"); - } + // Update reference. + oopDesc::encode_store_heap_oop_not_null(p, forw); obj = forw; // For matrix update below. } // TODO: Make this templated