< prev index next >
src/share/vm/gc_implementation/shenandoah/shenandoahBarrierSet.cpp
Print this page
rev 10496 : [backport] Rename "cancel_concgc" to "cancel_gc"
rev 10498 : [backport] Move heuristics from ShCollectorPolicy to ShHeap
rev 10525 : [backport] Replace ShBarrierSet* casts with accessor
rev 10532 : [backport] Apply ShenandoahEvacOOMScope only for evac-taking paths in ShenandoahBarrierSet
rev 10533 : [backport] Replace risky SBS::need_update_refs_barrier with straightforward check
rev 10534 : [backport] Pre-filter oops before enqueing them in SBS slowpaths
rev 10551 : [backport] Remove safe_equals()
rev 10594 : [backport] Split write barrier paths for mutator and GC workers
rev 10596 : [backport] WB slowpath should assist with evacuation of adjacent objects
rev 10610 : [backport] Evac assist should touch marked objects only
rev 10614 : [backport] Replace custom asserts with shenandoah_assert_*
@@ -25,21 +25,24 @@
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/shenandoah/shenandoahAsserts.hpp"
#include "gc_implementation/shenandoah/shenandoahBarrierSet.hpp"
#include "gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp"
#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
+#include "gc_implementation/shenandoah/shenandoahHeuristics.hpp"
#include "runtime/interfaceSupport.hpp"
class ShenandoahUpdateRefsForOopClosure: public ExtendedOopClosure {
private:
ShenandoahHeap* _heap;
+ ShenandoahBarrierSet* _bs;
+
template <class T>
inline void do_oop_work(T* p) {
_heap->maybe_update_with_forwarded(p);
}
public:
- ShenandoahUpdateRefsForOopClosure() : _heap(ShenandoahHeap::heap()) {
+ ShenandoahUpdateRefsForOopClosure() : _heap(ShenandoahHeap::heap()), _bs(ShenandoahBarrierSet::barrier_set()) {
assert(UseShenandoahGC && ShenandoahCloneBarrier, "should be enabled");
}
void do_oop(oop* p) { do_oop_work(p); }
void do_oop(narrowOop* p) { do_oop_work(p); }
};
@@ -152,26 +155,17 @@
bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
Unimplemented();
return false;
}
-bool ShenandoahBarrierSet::need_update_refs_barrier() {
- if (_heap->shenandoahPolicy()->update_refs()) {
- return _heap->is_update_refs_in_progress();
- } else {
- return _heap->is_concurrent_mark_in_progress() && _heap->has_forwarded_objects();
- }
-}
-
void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
ShouldNotReachHere();
}
template <class T>
void ShenandoahBarrierSet::write_ref_array_loop(HeapWord* start, size_t count) {
assert(UseShenandoahGC && ShenandoahCloneBarrier, "Should be enabled");
- ShenandoahEvacOOMScope oom_evac_scope;
ShenandoahUpdateRefsForOopClosure cl;
T* dst = (T*) start;
for (size_t i = 0; i < count; i++) {
cl.do_oop(dst++);
}
@@ -180,10 +174,11 @@
void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
assert(UseShenandoahGC, "should be enabled");
if (!ShenandoahCloneBarrier) return;
if (!need_update_refs_barrier()) return;
+ ShenandoahEvacOOMScope oom_evac_scope;
if (UseCompressedOops) {
write_ref_array_loop<narrowOop>(start, count);
} else {
write_ref_array_loop<oop>(start, count);
}
@@ -191,18 +186,18 @@
template <class T>
void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, size_t count) {
assert (UseShenandoahGC && ShenandoahSATBBarrier, "Should be enabled");
- shenandoah_assert_not_in_cset_loc_except(dst, _heap->cancelled_concgc());
+ shenandoah_assert_not_in_cset_loc_except(dst, _heap->cancelled_gc());
if (! JavaThread::satb_mark_queue_set().is_active()) return;
T* elem_ptr = dst;
for (size_t i = 0; i < count; i++, elem_ptr++) {
T heap_oop = oopDesc::load_heap_oop(elem_ptr);
if (!oopDesc::is_null(heap_oop)) {
- G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
+ enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
}
}
}
void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
@@ -219,14 +214,14 @@
template <class T>
void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop newVal) {
T heap_oop = oopDesc::load_heap_oop(field);
- shenandoah_assert_not_in_cset_loc_except(field, ShenandoahHeap::heap()->cancelled_concgc());
+ shenandoah_assert_not_in_cset_loc_except(field, ShenandoahHeap::heap()->cancelled_gc());
if (!oopDesc::is_null(heap_oop)) {
- G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
+ ShenandoahBarrierSet::barrier_set()->enqueue(oopDesc::decode_heap_oop(heap_oop));
}
}
template <class T>
inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
@@ -245,13 +240,13 @@
void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
guarantee(false, "Not needed");
}
void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
- shenandoah_assert_not_in_cset_loc_except(v, _heap->cancelled_concgc());
- shenandoah_assert_not_forwarded_except (v, o, o == NULL || _heap->cancelled_concgc() || !_heap->is_concurrent_mark_in_progress());
- shenandoah_assert_not_in_cset_except (v, o, o == NULL || _heap->cancelled_concgc() || !_heap->is_concurrent_mark_in_progress());
+ shenandoah_assert_not_in_cset_loc_except(v, _heap->cancelled_gc());
+ shenandoah_assert_not_forwarded_except (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
+ shenandoah_assert_not_in_cset_except (v, o, o == NULL || _heap->cancelled_gc() || !_heap->is_concurrent_mark_in_progress());
}
void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
assert(UseShenandoahGC, "should be enabled");
if (!ShenandoahCloneBarrier) return;
@@ -262,11 +257,11 @@
// it would be NULL in any case. But we *are* interested in any oop*
// that potentially need to be updated.
ShenandoahEvacOOMScope oom_evac_scope;
oop obj = oop(mr.start());
- assert(obj->is_oop(), "must be an oop");
+ shenandoah_assert_correct(NULL, obj);
ShenandoahUpdateRefsForOopClosure cl;
obj->oop_iterate(&cl);
}
oop ShenandoahBarrierSet::read_barrier(oop src) {
@@ -295,42 +290,91 @@
bool ShenandoahBarrierSet::obj_equals(narrowOop obj1, narrowOop obj2) {
return obj_equals(oopDesc::decode_heap_oop(obj1), oopDesc::decode_heap_oop(obj2));
}
JRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_JRT(oopDesc* src))
- oop result = ((ShenandoahBarrierSet*)oopDesc::bs())->write_barrier(src);
+ oop result = ShenandoahBarrierSet::barrier_set()->write_barrier_mutator(src);
return (oopDesc*) result;
JRT_END
IRT_LEAF(oopDesc*, ShenandoahBarrierSet::write_barrier_IRT(oopDesc* src))
- oop result = ((ShenandoahBarrierSet*)oopDesc::bs())->write_barrier(src);
+ oop result = ShenandoahBarrierSet::barrier_set()->write_barrier_mutator(src);
return (oopDesc*) result;
IRT_END
+oop ShenandoahBarrierSet::write_barrier_mutator(oop obj) {
+ assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
+ assert(_heap->is_gc_in_progress_mask(ShenandoahHeap::EVACUATION), "evac should be in progress");
+ shenandoah_assert_in_cset(NULL, obj);
+
+ oop fwd = resolve_forwarded_not_null(obj);
+ if (oopDesc::unsafe_equals(obj, fwd)) {
+ ShenandoahEvacOOMScope oom_evac_scope;
+ bool evac;
+
+ Thread* thread = Thread::current();
+ oop res_oop = _heap->evacuate_object(obj, thread, evac);
+
+ // Since we are already here and paid the price of getting through runtime call adapters
+ // and acquiring oom-scope, it makes sense to try and evacuate more adjacent objects,
+ // thus amortizing the overhead. For sparsely live heaps, scan costs easily dominate
+ // total assist costs, and can introduce a lot of evacuation latency. This is why we
+ // only scan for _nearest_ N objects, regardless if they are eligible for evac or not.
+ // The scan itself should also avoid touching the non-marked objects below TAMS, because
+ // their metadata (notably, klasses) may be incorrect already.
+
+ size_t max = ShenandoahEvacAssist;
+ if (max > 0) {
+ ShenandoahMarkingContext* ctx = _heap->complete_marking_context();
+
+ ShenandoahHeapRegion* r = _heap->heap_region_containing(obj);
+ assert(r->is_cset(), "sanity");
+
+ HeapWord* cur = (HeapWord*)obj + obj->size() + BrooksPointer::word_size();
+
+ size_t count = 0;
+ while ((cur < r->top()) && ctx->is_marked(oop(cur)) && (count++ < max)) {
+ oop cur_oop = oop(cur);
+ if (oopDesc::unsafe_equals(cur_oop, resolve_forwarded_not_null(cur_oop))) {
+ _heap->evacuate_object(cur_oop, thread, evac);
+ }
+ cur = cur + cur_oop->size() + BrooksPointer::word_size();
+ }
+ }
+
+ return res_oop;
+ }
+ return fwd;
+}
+
oop ShenandoahBarrierSet::write_barrier(oop obj) {
if (ShenandoahWriteBarrier) {
if (!oopDesc::is_null(obj)) {
bool evac_in_progress = _heap->is_evacuation_in_progress();
oop fwd = resolve_forwarded_not_null(obj);
if (evac_in_progress &&
_heap->in_collection_set(obj) &&
oopDesc::unsafe_equals(obj, fwd)) {
- ShenandoahEvacOOMScope oom_evac_scope;
+ Thread *t = Thread::current();
bool evac;
- return _heap->evacuate_object(obj, Thread::current(), evac);
+ if (t->is_Worker_thread()) {
+ return _heap->evacuate_object(obj, t, evac);
+ } else {
+ ShenandoahEvacOOMScope oom_evac_scope;
+ return _heap->evacuate_object(obj, t, evac);
+ }
} else {
return fwd;
}
}
}
return obj;
}
-#ifdef ASSERT
-void ShenandoahBarrierSet::verify_safe_oop(oop p) {
- shenandoah_assert_not_in_cset_except(NULL, p, (p == NULL) || ShenandoahHeap::heap()->cancelled_concgc());
-}
+void ShenandoahBarrierSet::enqueue(oop obj) {
+ // Filter marked objects before hitting the SATB queues. The same predicate would
+ // be used by SATBMQ::filter to eliminate already marked objects downstream, but
+ // filtering here helps to avoid wasteful SATB queueing work to begin with.
+ if (!_heap->requires_marking(obj)) return;
-void ShenandoahBarrierSet::verify_safe_oop(narrowOop p) {
- verify_safe_oop(oopDesc::decode_heap_oop(p));
+ G1SATBCardTableModRefBS::enqueue(obj);
}
-#endif
< prev index next >