diff -r 13588c901957 -r 9cf78a70fa4f src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Thu Oct 17 20:27:44 2019 +0100 +++ b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp Thu Oct 17 20:53:35 2019 +0100 @@ -27,13 +27,10 @@ #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahRuntime.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp" -#ifndef PATCHED_ADDR -#define PATCHED_ADDR (max_jint) -#endif - #ifdef ASSERT #define __ gen->lir(__FILE__, __LINE__)-> #else @@ -50,6 +47,10 @@ bs->gen_load_reference_barrier_stub(ce, this); } +ShenandoahBarrierSetC1::ShenandoahBarrierSetC1() : + _pre_barrier_c1_runtime_code_blob(NULL), + _load_reference_barrier_rt_code_blob(NULL) {} + void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) { // First we test whether marking is in progress. BasicType flag_type; @@ -104,21 +105,25 @@ __ branch_destination(slow->continuation()); } -LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) { +LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { if (ShenandoahLoadRefBarrier) { - return load_reference_barrier_impl(gen, obj, info, need_null_check); + return load_reference_barrier_impl(gen, obj, addr); } else { return obj; } } -LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) { +LIR_Opr ShenandoahBarrierSetC1::load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr) { assert(ShenandoahLoadRefBarrier, "Should be enabled"); obj = ensure_in_register(gen, obj); assert(obj->is_register(), "must be a register at this point"); - LIR_Opr result = gen->new_register(T_OBJECT); + addr = ensure_in_register(gen, addr); + assert(addr->is_register(), "must be a register at this point"); + LIR_Opr result = gen->result_register_for(obj->value_type()); __ move(obj, result); + LIR_Opr tmp1 = gen->new_register(T_OBJECT); + LIR_Opr tmp2 = gen->new_register(T_OBJECT); LIR_Opr thrd = gen->getThreadPointer(); LIR_Address* active_flag_addr = @@ -143,7 +148,7 @@ } __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0)); - CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check); + CodeStub* slow = new ShenandoahLoadReferenceBarrierStub(obj, addr, result, tmp1, tmp2); __ branch(lir_cond_notEqual, T_INT, slow); __ branch_destination(slow->continuation()); @@ -152,10 +157,18 @@ LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) { if (!obj->is_register()) { - LIR_Opr obj_reg = gen->new_register(T_OBJECT); + LIR_Opr obj_reg; if (obj->is_constant()) { + obj_reg = gen->new_register(T_OBJECT); __ move(obj, obj_reg); } else { +#ifdef AARCH64 + // AArch64 expects double-size register. + obj_reg = gen->new_pointer_register(); +#else + // x86 expects single-size register. + obj_reg = gen->new_register(T_OBJECT); +#endif __ leal(obj, obj_reg); } obj = obj_reg; @@ -181,25 +194,47 @@ BarrierSetC1::store_at_resolved(access, value); } +LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) { + // We must resolve in register when patching. This is to avoid + // having a patch area in the load barrier stub, since the call + // into the runtime to patch will not have the proper oop map. + const bool patch_before_barrier = access.is_oop() && (access.decorators() & C1_NEEDS_PATCHING) != 0; + return BarrierSetC1::resolve_address(access, resolve_in_register || patch_before_barrier); +} + void ShenandoahBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { if (!access.is_oop()) { BarrierSetC1::load_at_resolved(access, result); return; } - LIRGenerator *gen = access.gen(); + LIRGenerator* gen = access.gen(); + + DecoratorSet decorators = access.decorators(); + if ((decorators & IN_NATIVE) != 0) { + assert(access.is_oop(), "IN_NATIVE access only for oop values"); + BarrierSetC1::load_at_resolved(access, result); + LIR_OprList* args = new LIR_OprList(); + args->append(result); + BasicTypeList signature; + signature.append(T_OBJECT); + LIR_Opr call_result = gen->call_runtime(&signature, args, + CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native), + objectType, NULL); + __ move(call_result, result); + return; + } if (ShenandoahLoadRefBarrier) { LIR_Opr tmp = gen->new_register(T_OBJECT); BarrierSetC1::load_at_resolved(access, tmp); - tmp = load_reference_barrier(access.gen(), tmp, access.access_emit_info(), true); + tmp = load_reference_barrier(access.gen(), tmp, access.resolved_addr()); __ move(tmp, result); } else { BarrierSetC1::load_at_resolved(access, result); } if (ShenandoahKeepAliveBarrier) { - DecoratorSet decorators = access.decorators(); bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0; bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0; @@ -227,9 +262,30 @@ } }; +class C1ShenandoahLoadReferenceBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { + virtual OopMapSet* generate_code(StubAssembler* sasm) { + ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler(); + bs->generate_c1_load_reference_barrier_runtime_stub(sasm); + return NULL; + } +}; + void ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) { C1ShenandoahPreBarrierCodeGenClosure pre_code_gen_cl; _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "shenandoah_pre_barrier_slow", false, &pre_code_gen_cl); + if (ShenandoahLoadRefBarrier) { + C1ShenandoahLoadReferenceBarrierCodeGenClosure lrb_code_gen_cl; + _load_reference_barrier_rt_code_blob = Runtime1::generate_blob(buffer_blob, -1, + "shenandoah_load_reference_barrier_slow", + false, &lrb_code_gen_cl); + } } + +const char* ShenandoahBarrierSetC1::rtcall_name_for_address(address entry) { + if (entry == CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native)) { + return "ShenandoahRuntime::load_reference_barrier_native"; + } + return NULL; +}