# HG changeset patch # Parent 08b072339dfdb2368b9d1daa59bceb57dc37863d diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -403,6 +403,7 @@ __ push(rscratch1); // Save possibly live regs. + // __ pusha(); if (dst != rax) { __ push(rax); } @@ -430,6 +431,7 @@ __ movdbl(xmm0, Address(rsp, 0)); __ addptr(rsp, 2 * Interpreter::stackElementSize); + // __ popa(); if (dst != c_rarg1) { __ pop(c_rarg1); } @@ -445,7 +447,6 @@ if (dst != rax) { __ pop(rax); } - // Move result into dst reg. __ mov(dst, rscratch1); @@ -470,11 +471,13 @@ #ifdef _LP64 if (ShenandoahStoreValEnqueueBarrier) { - Label is_null; - __ testptr(dst, dst); - __ jcc(Assembler::zero, is_null); - write_barrier_impl(masm, dst); - __ bind(is_null); + if (!ShenandoahLoadValBarrier) { + Label is_null; + __ testptr(dst, dst); + __ jcc(Assembler::zero, is_null); + write_barrier_impl(masm, dst); + __ bind(is_null); + } // The set of registers to be saved+restored is the same as in the write-barrier above. // Those are the commonly used registers in the interpreter. @@ -489,7 +492,7 @@ //__ pop_callee_saved_registers(); __ popa(); } - if (ShenandoahStoreValReadBarrier) { + if (ShenandoahStoreValReadBarrier && !ShenandoahLoadValBarrier) { read_barrier_impl(masm, dst); } #else @@ -504,10 +507,17 @@ bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; bool on_reference = on_weak || on_phantom; - if (in_heap) { + if (in_heap && !ShenandoahLoadValBarrier) { read_barrier_not_null(masm, src.base()); } BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + if (ShenandoahLoadValBarrier && on_oop /*&& in_heap*/) { + Label is_null; + __ testptr(dst, dst); + __ jcc(Assembler::zero, is_null); + write_barrier(masm, dst); + __ bind(is_null); + } if (ShenandoahKeepAliveBarrier && on_oop && on_reference) { const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); NOT_LP64(__ get_thread(thread)); @@ -529,7 +539,7 @@ bool in_heap = (decorators & IN_HEAP) != 0; bool as_normal = (decorators & AS_NORMAL) != 0; - if (in_heap) { + if (in_heap && !ShenandoahLoadValBarrier) { write_barrier(masm, dst.base()); } if (type == T_OBJECT || type == T_ARRAY) { @@ -595,7 +605,7 @@ void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, Register op1, Register op2) { __ cmpptr(op1, op2); - if (ShenandoahAcmpBarrier) { + if (ShenandoahAcmpBarrier && !ShenandoahLoadValBarrier) { Label done; __ jccb(Assembler::equal, done); read_barrier(masm, op1); @@ -607,7 +617,7 @@ void ShenandoahBarrierSetAssembler::obj_equals(MacroAssembler* masm, Register src1, Address src2) { __ cmpptr(src1, src2); - if (ShenandoahAcmpBarrier) { + if (ShenandoahAcmpBarrier && !ShenandoahLoadValBarrier) { Label done; __ jccb(Assembler::equal, done); __ movptr(rscratch2, src2); @@ -668,16 +678,20 @@ } void ShenandoahBarrierSetAssembler::resolve_for_read(MacroAssembler* masm, DecoratorSet decorators, Register obj) { - bool oop_not_null = (decorators & IS_NOT_NULL) != 0; - if (oop_not_null) { - read_barrier_not_null(masm, obj); - } else { - read_barrier(masm, obj); + if (!ShenandoahLoadValBarrier) { + bool oop_not_null = (decorators & IS_NOT_NULL) != 0; + if (oop_not_null) { + read_barrier_not_null(masm, obj); + } else { + read_barrier(masm, obj); + } } } void ShenandoahBarrierSetAssembler::resolve_for_write(MacroAssembler* masm, DecoratorSet decorators, Register obj) { - write_barrier(masm, obj); + if (!ShenandoahLoadValBarrier) { + write_barrier(masm, obj); + } } // Special Shenandoah CAS implementation that handles false negatives @@ -694,11 +708,6 @@ Register res, Address addr, Register oldval, Register newval, bool exchange, bool encode, Register tmp1, Register tmp2) { - if (!ShenandoahCASBarrier) { - BarrierSetAssembler::cmpxchg_oop(masm, decorators, res, addr, oldval, newval, exchange, encode, tmp1, tmp2); - return; - } - assert(ShenandoahCASBarrier, "Should only be used when CAS barrier is enabled"); assert(oldval == rax, "must be in rax for implicit use in cmpxchg"); @@ -706,12 +715,17 @@ // Apply storeval barrier to newval. if (encode) { - if (newval == c_rarg1 && ShenandoahStoreValEnqueueBarrier) { - __ mov(tmp2, newval); - storeval_barrier(masm, tmp2, tmp1); - } else { - storeval_barrier(masm, newval, tmp1); + storeval_barrier(masm, newval, tmp1); + } + + if (!ShenandoahCASBarrier) { + BarrierSetAssembler::cmpxchg_oop(masm, decorators, res, addr, oldval, newval, exchange, encode, tmp1, tmp2); + if (!exchange) { + assert(res != NULL, "need result register"); + __ setb(Assembler::equal, res); + __ movzbl(res, res); } + return; } if (UseCompressedOops) { @@ -750,7 +764,9 @@ if (UseCompressedOops) { __ decode_heap_oop(tmp1); } - __ resolve_for_read(0, tmp1); + if (!ShenandoahLoadValBarrier) { + __ resolve_for_read(0, tmp1); + } if (UseCompressedOops) { __ movl(tmp2, oldval); @@ -793,6 +809,7 @@ // and promote the result. Note that we handle the flag from both the CAS // itself and from the retry loop. __ bind(done); + if (!exchange) { assert(res != NULL, "need result register"); __ setb(Assembler::equal, res); diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -232,10 +232,12 @@ LIRGenerator* gen = access.gen(); if (UseShenandoahGC) { if (ShenandoahStoreValEnqueueBarrier) { - obj = write_barrier_impl(access, obj, info, need_null_check); + if (!ShenandoahLoadValBarrier) { + obj = write_barrier_impl(access, obj, info, need_null_check); + } pre_barrier(access, LIR_OprFact::illegalOpr, obj); } - if (ShenandoahStoreValReadBarrier) { + if (ShenandoahStoreValReadBarrier && !ShenandoahLoadValBarrier) { obj = read_barrier_impl(access, obj, info, true /*need_null_check*/); } } @@ -243,7 +245,9 @@ } void ShenandoahBarrierSetC1::store_at(LIRAccess& access, LIR_Opr value) { - access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + if (!ShenandoahLoadValBarrier) { + access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + } LIR_Opr resolved = resolve_address(access, false); access.set_resolved_addr(resolved); if (access.is_oop()) { @@ -261,11 +265,23 @@ void ShenandoahBarrierSetC1::load_at(LIRAccess& access, LIR_Opr result) { LIRItem& base_item = access.base().item(); - access.set_base(read_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + if (!ShenandoahLoadValBarrier) { + access.set_base(read_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + } LIR_Opr resolved = resolve_address(access, false); access.set_resolved_addr(resolved); - BarrierSetC1::load_at_resolved(access, result); - access.set_base(base_item); + + if (ShenandoahLoadValBarrier && access.is_oop()) { + LIRGenerator* gen = access.gen(); + LIR_Opr result_tmp = gen->new_register(T_OBJECT); + BarrierSetC1::load_at_resolved(access, result_tmp); + access.set_base(base_item); + result_tmp = write_barrier(access, result_tmp, access.access_emit_info(), true /*access.needs_null_check()*/); + gen->lir()->move(result_tmp, result); + } else { + BarrierSetC1::load_at_resolved(access, result); + access.set_base(base_item); + } if (ShenandoahKeepAliveBarrier) { DecoratorSet decorators = access.decorators(); @@ -291,7 +307,9 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) { access.load_address(); - access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + if (!ShenandoahLoadValBarrier) { + access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + } LIR_Opr resolved = resolve_address(access, true); access.set_resolved_addr(resolved); if (access.is_oop()) { @@ -308,7 +326,9 @@ } LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at(LIRAccess& access, LIRItem& value) { - access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + if (!ShenandoahLoadValBarrier) { + access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + } LIR_Opr resolved = resolve_address(access, true); access.set_resolved_addr(resolved); if (access.is_oop()) { @@ -318,6 +338,9 @@ } } LIR_Opr result = BarrierSetC1::atomic_xchg_at_resolved(access, value); + if (ShenandoahLoadValBarrier && access.is_oop()) { + result = write_barrier(access, result, access.access_emit_info(), true /*access.needs_null_check()*/); + } if (access.is_oop() && UseShenandoahMatrix) { post_barrier(access, access.resolved_addr(), value.result()); } @@ -326,18 +349,29 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) { access.load_address(); - access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + if (!ShenandoahLoadValBarrier) { + access.set_base(write_barrier(access, access.base().item().result(), access.access_emit_info(), access.needs_null_check())); + } LIR_Opr resolved = resolve_address(access, true); access.set_resolved_addr(resolved); return BarrierSetC1::atomic_add_at_resolved(access, value); } LIR_Opr ShenandoahBarrierSetC1::resolve_for_read(LIRAccess& access) { - return read_barrier(access, access.base().opr(), access.access_emit_info(), access.needs_null_check()); + if (!ShenandoahLoadValBarrier) { + return read_barrier(access, access.base().opr(), access.access_emit_info(), access.needs_null_check()); + } else { + return access.base().opr(); + } } LIR_Opr ShenandoahBarrierSetC1::resolve_for_write(LIRAccess& access) { - return write_barrier(access, access.base().opr(), access.access_emit_info(), access.needs_null_check()); + if (!ShenandoahLoadValBarrier) { + return write_barrier(access, access.base().opr(), access.access_emit_info(), access.needs_null_check()); + } else { + return access.base().opr(); + } + } class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -69,16 +69,19 @@ Node* ShenandoahBarrierSetC2::shenandoah_storeval_barrier(GraphKit* kit, Node* obj) const { if (ShenandoahStoreValEnqueueBarrier) { - obj = shenandoah_write_barrier(kit, obj); + if (!ShenandoahLoadValBarrier) { + obj = shenandoah_write_barrier(kit, obj); + } obj = shenandoah_enqueue_barrier(kit, obj); } - if (ShenandoahStoreValReadBarrier) { + if (ShenandoahStoreValReadBarrier && !ShenandoahLoadValBarrier) { obj = shenandoah_read_barrier_impl(kit, obj, true, false, false); } return obj; } Node* ShenandoahBarrierSetC2::shenandoah_read_barrier_acmp(GraphKit* kit, Node* obj) { + assert(!ShenandoahLoadValBarrier, "Should not get here with load-value barriers"); return shenandoah_read_barrier_impl(kit, obj, true, true, false); } @@ -680,6 +683,10 @@ Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : kit->top(); Node* load = BarrierSetC2::load_at_resolved(access, val_type); + if (ShenandoahLoadValBarrier && access.is_oop() && on_heap) { + load = shenandoah_write_barrier(kit, load); + } + // If we are reading the value of the referent field of a Reference // object (either by using Unsafe directly or through reflection) // then, if SATB is enabled, we need to record the referent in an @@ -712,6 +719,8 @@ Node* ShenandoahBarrierSetC2::atomic_cmpxchg_val_at_resolved(C2AtomicAccess& access, Node* expected_val, Node* val, const Type* value_type) const { + DecoratorSet decorators = access.decorators(); + bool on_heap = (decorators & IN_HEAP) != 0; GraphKit* kit = access.kit(); if (access.is_oop()) { val = shenandoah_storeval_barrier(kit, val); @@ -720,7 +729,11 @@ expected_val /* pre_val */, T_OBJECT); } - return BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, val, value_type); + Node* result = BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, val, value_type); + if (on_heap && access.is_oop() && ShenandoahLoadValBarrier) { + result = shenandoah_write_barrier(kit, result); + } + return result; } Node* ShenandoahBarrierSetC2::atomic_cmpxchg_val_at(C2AtomicAccess& access, Node* expected_val, @@ -748,12 +761,17 @@ } Node* ShenandoahBarrierSetC2::atomic_xchg_at_resolved(C2AtomicAccess& access, Node* val, const Type* value_type) const { + DecoratorSet decorators = access.decorators(); + bool on_heap = (decorators & IN_HEAP) != 0; GraphKit* kit = access.kit(); if (access.is_oop()) { val = shenandoah_storeval_barrier(kit, val); } Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, val, value_type); if (access.is_oop()) { + if (on_heap && ShenandoahLoadValBarrier) { + result = shenandoah_write_barrier(kit, result); + } shenandoah_write_barrier_pre(kit, false /* do_load */, NULL, NULL, max_juint, NULL, NULL, result /* pre_val */, T_OBJECT); @@ -777,11 +795,19 @@ } Node* ShenandoahBarrierSetC2::resolve_for_read(GraphKit* kit, Node* n) const { - return shenandoah_read_barrier(kit, n); + if (!ShenandoahLoadValBarrier) { + return shenandoah_read_barrier(kit, n); + } else { + return n; + } } Node* ShenandoahBarrierSetC2::resolve_for_write(GraphKit* kit, Node* n) const { - return shenandoah_write_barrier(kit, n); + if (!ShenandoahLoadValBarrier) { + return shenandoah_write_barrier(kit, n); + } else { + return n; + } } // Support for GC barriers emitted during parsing diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -193,7 +193,7 @@ */ void ShenandoahBarrierNode::do_cmpp_if(GraphKit& kit, Node*& taken_branch, Node*& untaken_branch, Node*& taken_memory, Node*& untaken_memory) { assert(taken_memory == NULL && untaken_memory == NULL, "unexpected memory inputs"); - if (!UseShenandoahGC || !ShenandoahAcmpBarrier || ShenandoahVerifyOptoBarriers) { + if (!UseShenandoahGC || !ShenandoahAcmpBarrier || ShenandoahLoadValBarrier || ShenandoahVerifyOptoBarriers) { return; } if (taken_branch->is_top() || untaken_branch->is_top()) { @@ -2603,7 +2603,7 @@ phase->register_new_node(heap_stable_cmp, ctrl); Node* heap_stable_test = new BoolNode(heap_stable_cmp, BoolTest::ne); phase->register_new_node(heap_stable_test, ctrl); - IfNode* heap_stable_iff = new IfNode(ctrl, heap_stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN); + IfNode* heap_stable_iff = new IfNode(ctrl, heap_stable_test, PROB_UNLIKELY(0.9), COUNT_UNKNOWN); phase->register_control(heap_stable_iff, loop, ctrl); heap_stable = new IfFalseNode(heap_stable_iff); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -267,7 +267,7 @@ bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) { bool eq = oopDesc::unsafe_equals(obj1, obj2); - if (! eq && ShenandoahAcmpBarrier) { + if (! eq && ShenandoahAcmpBarrier && !ShenandoahLoadValBarrier) { OrderAccess::loadload(); obj1 = resolve_forwarded(obj1); obj2 = resolve_forwarded(obj2); @@ -305,11 +305,13 @@ oop ShenandoahBarrierSet::storeval_barrier(oop obj) { if (ShenandoahStoreValEnqueueBarrier) { if (!CompressedOops::is_null(obj)) { - obj = write_barrier(obj); + if (!ShenandoahLoadValBarrier) { + obj = write_barrier(obj); + } enqueue(obj); } } - if (ShenandoahStoreValReadBarrier) { + if (ShenandoahStoreValReadBarrier && !ShenandoahLoadValBarrier) { obj = resolve_forwarded(obj); } return obj; @@ -346,6 +348,9 @@ void ShenandoahBarrierSet::verify_safe_oop(oop p) { shenandoah_assert_not_in_cset_except(NULL, p, (p == NULL) || ShenandoahHeap::heap()->cancelled_gc()); } +void ShenandoahBarrierSet::verify_safe_addr(void* p) { + shenandoah_assert_not_in_cset_except(p, NULL, ShenandoahHeap::heap()->cancelled_gc()); +} #endif void ShenandoahBarrierSet::on_thread_create(Thread* thread) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -104,6 +104,7 @@ #ifdef ASSERT virtual void verify_safe_oop(oop p); + void verify_safe_addr(void* p); #endif void enqueue(oop obj); @@ -165,19 +166,23 @@ template static T load_in_heap_at(oop base, ptrdiff_t offset) { - base = ShenandoahBarrierSet::barrier_set()->read_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->read_barrier(base); + } return Raw::template load_at(base, offset); } template static void store_in_heap(T* addr, T value) { - ShouldNotReachHere(); + ShenandoahBarrierSet::barrier_set()->verify_safe_addr(addr); Raw::store(addr, value); } template static void store_in_heap_at(oop base, ptrdiff_t offset, T value) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } Raw::store_at(base, offset, value); } @@ -189,7 +194,9 @@ template static T atomic_cmpxchg_in_heap_at(T new_value, oop base, ptrdiff_t offset, T compare_value) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } return Raw::oop_atomic_cmpxchg_at(new_value, base, offset, compare_value); } @@ -201,7 +208,9 @@ template static T atomic_xchg_in_heap_at(T new_value, oop base, ptrdiff_t offset) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } return Raw::atomic_xchg_at(new_value, base, offset); } @@ -218,13 +227,21 @@ // ShouldNotReachHere(); oop value = Raw::template oop_load(addr); keep_alive_if_weak(decorators, value); + if (ShenandoahLoadValBarrier) { + value = ShenandoahBarrierSet::barrier_set()->write_barrier(value); + } return value; } static oop oop_load_in_heap_at(oop base, ptrdiff_t offset) { - base = ShenandoahBarrierSet::barrier_set()->read_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->read_barrier(base); + } oop value = Raw::template oop_load_at(base, offset); keep_alive_if_weak(AccessBarrierSupport::resolve_possibly_unknown_oop_ref_strength(base, offset), value); + if (ShenandoahLoadValBarrier) { + value = ShenandoahBarrierSet::barrier_set()->write_barrier(value); + } return value; } @@ -235,9 +252,10 @@ } static void oop_store_in_heap_at(oop base, ptrdiff_t offset, oop value) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(value); - oop_store_in_heap(AccessInternal::oop_field_addr(base, offset), value); } @@ -245,16 +263,21 @@ static oop oop_atomic_cmpxchg_in_heap(oop new_value, T* addr, oop compare_value); static oop oop_atomic_cmpxchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset, oop compare_value) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value); - return oop_atomic_cmpxchg_in_heap(new_value, AccessInternal::oop_field_addr(base, offset), compare_value); + oop oldval = oop_atomic_cmpxchg_in_heap(new_value, AccessInternal::oop_field_addr(base, offset), compare_value); + return oldval; } template static oop oop_atomic_xchg_in_heap(oop new_value, T* addr); static oop oop_atomic_xchg_in_heap_at(oop new_value, oop base, ptrdiff_t offset) { - base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + if (!ShenandoahLoadValBarrier) { + base = ShenandoahBarrierSet::barrier_set()->write_barrier(base); + } new_value = ShenandoahBarrierSet::barrier_set()->storeval_barrier(new_value); return oop_atomic_xchg_in_heap(new_value, AccessInternal::oop_field_addr(base, offset)); } @@ -272,15 +295,25 @@ static oop oop_load_not_in_heap(T* addr) { oop value = Raw::oop_load_not_in_heap(addr); keep_alive_if_weak(decorators, value); + if (ShenandoahLoadValBarrier) { + value = ShenandoahBarrierSet::barrier_set()->write_barrier(value); + } return value; } static oop resolve(oop obj) { - return ShenandoahBarrierSet::barrier_set()->write_barrier(obj); + if (!ShenandoahLoadValBarrier) { + obj = ShenandoahBarrierSet::barrier_set()->write_barrier(obj); + } + return obj; } static bool equals(oop o1, oop o2) { - return ShenandoahBarrierSet::barrier_set()->obj_equals(o1, o2); + if (!ShenandoahLoadValBarrier) { + return ShenandoahBarrierSet::barrier_set()->obj_equals(o1, o2); + } else { + return Raw::equals(o1, o2); + } } }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -68,6 +68,9 @@ matrix->set_connected(addr, new_value); } } + if (ShenandoahLoadValBarrier) { + res = ShenandoahBarrierSet::barrier_set()->write_barrier(res); + } return res; } @@ -84,6 +87,9 @@ ShenandoahConnectionMatrix* matrix = ShenandoahHeap::heap()->connection_matrix(); matrix->set_connected(addr, new_value); } + if (ShenandoahLoadValBarrier) { + previous = ShenandoahBarrierSet::barrier_set()->write_barrier(previous); + } return previous; } @@ -92,11 +98,13 @@ void ShenandoahBarrierSet::AccessBarrier::arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - if (!CompressedOops::is_null(src_obj)) { - src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj)); - } - if (!CompressedOops::is_null(dst_obj)) { - dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj)); + if (!ShenandoahLoadValBarrier) { + if (!CompressedOops::is_null(src_obj)) { + src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj)); + } + if (!CompressedOops::is_null(dst_obj)) { + dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj)); + } } Raw::arraycopy(src_obj, src_offset_in_bytes, src_raw, dst_obj, dst_offset_in_bytes, dst_raw, length); } @@ -251,8 +259,10 @@ // Clone barrier support template void ShenandoahBarrierSet::AccessBarrier::clone_in_heap(oop src, oop dst, size_t size) { - src = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src)); - dst = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst)); + if (!ShenandoahLoadValBarrier) { + src = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src)); + dst = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst)); + } Raw::clone(src, dst, size); ShenandoahBarrierSet::barrier_set()->write_region(MemRegion((HeapWord*) dst, size)); } @@ -264,13 +274,14 @@ arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { ShenandoahHeap* heap = ShenandoahHeap::heap(); - if (!CompressedOops::is_null(src_obj)) { - src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj)); + if (!ShenandoahLoadValBarrier) { + if (!CompressedOops::is_null(src_obj)) { + src_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->read_barrier(src_obj)); + } + if (!CompressedOops::is_null(dst_obj)) { + dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj)); + } } - if (!CompressedOops::is_null(dst_obj)) { - dst_obj = arrayOop(ShenandoahBarrierSet::barrier_set()->write_barrier(dst_obj)); - } - bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress(); bool checkcast = HasDecorator::value; ArrayCopyStoreValMode storeval_mode; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1269,6 +1269,27 @@ } }; +class ShenandoahEvacuateUpdateAllRootsTask : public AbstractGangTask { + ShenandoahRootProcessor* _rp; +public: + + ShenandoahEvacuateUpdateAllRootsTask(ShenandoahRootProcessor* rp) : + AbstractGangTask("Shenandoah evacuate and update all roots"), + _rp(rp) + { + // Nothing else to do. + } + + void work(uint worker_id) { + ShenandoahEvacOOMScope oom_evac_scope; + ShenandoahEvacuateUpdateRootsClosure cl; + CLDToOopClosure cldCl(&cl); + // MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations); + CodeBlobToOopClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations); + _rp->process_all_roots(&cl, &cl, &cldCl, &blobsCl, NULL, worker_id); + } +}; + class ShenandoahFixRootsTask : public AbstractGangTask { ShenandoahRootEvacuator* _rp; public: @@ -1289,6 +1310,26 @@ } }; +class ShenandoahFixAllRootsTask : public AbstractGangTask { + ShenandoahRootProcessor* _rp; +public: + + ShenandoahFixAllRootsTask(ShenandoahRootProcessor* rp) : + AbstractGangTask("Shenandoah update all roots"), + _rp(rp) + { + // Nothing else to do. + } + + void work(uint worker_id) { + ShenandoahEvacOOMScope oom_evac_scope; + ShenandoahUpdateRefsClosure cl; + CLDToOopClosure cldCl(&cl); + MarkingCodeBlobClosure blobsCl(&cl, CodeBlobToOopClosure::FixRelocations); + _rp->process_all_roots(&cl, &cl, &cldCl, &blobsCl, NULL, worker_id); + } +}; + void ShenandoahHeap::evacuate_and_update_roots() { #if defined(COMPILER2) || INCLUDE_JVMCI @@ -1296,7 +1337,11 @@ #endif assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Only iterate roots while world is stopped"); - { + if (ShenandoahLoadValBarrier) { + ShenandoahRootProcessor rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); + ShenandoahEvacuateUpdateAllRootsTask roots_task(&rp); + workers()->run_task(&roots_task); + } else { ShenandoahRootEvacuator rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); ShenandoahEvacuateUpdateRootsTask roots_task(&rp); workers()->run_task(&roots_task); @@ -1323,9 +1368,15 @@ #if defined(COMPILER2) || INCLUDE_JVMCI DerivedPointerTable::clear(); #endif - ShenandoahRootEvacuator rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); - ShenandoahFixRootsTask update_roots_task(&rp); - workers()->run_task(&update_roots_task); + if (ShenandoahLoadValBarrier) { + ShenandoahRootProcessor rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); + ShenandoahFixAllRootsTask update_roots_task(&rp); + workers()->run_task(&update_roots_task); + } else { + ShenandoahRootEvacuator rp(this, workers()->active_workers(), ShenandoahPhaseTimings::init_evac); + ShenandoahFixRootsTask update_roots_task(&rp); + workers()->run_task(&update_roots_task); + } #if defined(COMPILER2) || INCLUDE_JVMCI DerivedPointerTable::update_pointers(); #endif @@ -2511,7 +2562,9 @@ } assert(!cancelled_gc(), "Should have been done right before"); - concurrentMark()->update_roots(ShenandoahPhaseTimings::final_update_refs_roots); + if (!ShenandoahLoadValBarrier) { + concurrentMark()->update_roots(ShenandoahPhaseTimings::final_update_refs_roots); + } // Allocations might have happened before we STWed here, record peak: heuristics()->record_peak_occupancy(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -327,6 +327,9 @@ diagnostic(bool, ShenandoahCloneBarrier, true, \ "Turn on/off clone barriers in Shenandoah") \ \ + diagnostic(bool, ShenandoahLoadValBarrier, true, \ + "Turn on/off load-value-style barriers") \ + \ diagnostic(bool, UseShenandoahMatrix, false, \ "Turn on/off Shenandoah connection matrix collection") \ \