Path: blob/master/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp
40976 views
/*1* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "c1/c1_LIR.hpp"25#include "c1/c1_LIRGenerator.hpp"26#include "c1/c1_CodeStubs.hpp"27#include "gc/z/c1/zBarrierSetC1.hpp"28#include "gc/z/zBarrierSet.hpp"29#include "gc/z/zBarrierSetAssembler.hpp"30#include "gc/z/zThreadLocalData.hpp"31#include "utilities/macros.hpp"3233ZLoadBarrierStubC1::ZLoadBarrierStubC1(LIRAccess& access, LIR_Opr ref, address runtime_stub) :34_decorators(access.decorators()),35_ref_addr(access.resolved_addr()),36_ref(ref),37_tmp(LIR_OprFact::illegalOpr),38_runtime_stub(runtime_stub) {3940assert(_ref_addr->is_address(), "Must be an address");41assert(_ref->is_register(), "Must be a register");4243// Allocate tmp register if needed44if (_ref_addr->as_address_ptr()->index()->is_valid() ||45_ref_addr->as_address_ptr()->disp() != 0) {46// Has index or displacement, need tmp register to load address into47_tmp = access.gen()->new_pointer_register();48}49}5051DecoratorSet ZLoadBarrierStubC1::decorators() const {52return _decorators;53}5455LIR_Opr ZLoadBarrierStubC1::ref() const {56return _ref;57}5859LIR_Opr ZLoadBarrierStubC1::ref_addr() const {60return _ref_addr;61}6263LIR_Opr ZLoadBarrierStubC1::tmp() const {64return _tmp;65}6667address ZLoadBarrierStubC1::runtime_stub() const {68return _runtime_stub;69}7071void ZLoadBarrierStubC1::visit(LIR_OpVisitState* visitor) {72visitor->do_slow_case();73visitor->do_input(_ref_addr);74visitor->do_output(_ref);75if (_tmp->is_valid()) {76visitor->do_temp(_tmp);77}78}7980void ZLoadBarrierStubC1::emit_code(LIR_Assembler* ce) {81ZBarrierSet::assembler()->generate_c1_load_barrier_stub(ce, this);82}8384#ifndef PRODUCT85void ZLoadBarrierStubC1::print_name(outputStream* out) const {86out->print("ZLoadBarrierStubC1");87}88#endif // PRODUCT8990class LIR_OpZLoadBarrierTest : public LIR_Op {91private:92LIR_Opr _opr;9394public:95LIR_OpZLoadBarrierTest(LIR_Opr opr) :96LIR_Op(),97_opr(opr) {}9899virtual void visit(LIR_OpVisitState* state) {100state->do_input(_opr);101}102103virtual void emit_code(LIR_Assembler* ce) {104ZBarrierSet::assembler()->generate_c1_load_barrier_test(ce, _opr);105}106107virtual void print_instr(outputStream* out) const {108_opr->print(out);109out->print(" ");110}111112#ifndef PRODUCT113virtual const char* name() const {114return "lir_z_load_barrier_test";115}116#endif // PRODUCT117};118119static bool barrier_needed(LIRAccess& access) {120return ZBarrierSet::barrier_needed(access.decorators(), access.type());121}122123ZBarrierSetC1::ZBarrierSetC1() :124_load_barrier_on_oop_field_preloaded_runtime_stub(NULL),125_load_barrier_on_weak_oop_field_preloaded_runtime_stub(NULL) {}126127address ZBarrierSetC1::load_barrier_on_oop_field_preloaded_runtime_stub(DecoratorSet decorators) const {128assert((decorators & ON_PHANTOM_OOP_REF) == 0, "Unsupported decorator");129//assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Unsupported decorator");130131if ((decorators & ON_WEAK_OOP_REF) != 0) {132return _load_barrier_on_weak_oop_field_preloaded_runtime_stub;133} else {134return _load_barrier_on_oop_field_preloaded_runtime_stub;135}136}137138#ifdef ASSERT139#define __ access.gen()->lir(__FILE__, __LINE__)->140#else141#define __ access.gen()->lir()->142#endif143144void ZBarrierSetC1::load_barrier(LIRAccess& access, LIR_Opr result) const {145// Fast path146__ append(new LIR_OpZLoadBarrierTest(result));147148// Slow path149const address runtime_stub = load_barrier_on_oop_field_preloaded_runtime_stub(access.decorators());150CodeStub* const stub = new ZLoadBarrierStubC1(access, result, runtime_stub);151__ branch(lir_cond_notEqual, stub);152__ branch_destination(stub->continuation());153}154155LIR_Opr ZBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {156// We must resolve in register when patching. This is to avoid157// having a patch area in the load barrier stub, since the call158// into the runtime to patch will not have the proper oop map.159const bool patch_before_barrier = barrier_needed(access) && (access.decorators() & C1_NEEDS_PATCHING) != 0;160return BarrierSetC1::resolve_address(access, resolve_in_register || patch_before_barrier);161}162163#undef __164165void ZBarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {166BarrierSetC1::load_at_resolved(access, result);167168if (barrier_needed(access)) {169load_barrier(access, result);170}171}172173static void pre_load_barrier(LIRAccess& access) {174DecoratorSet decorators = access.decorators();175176// Downgrade access to MO_UNORDERED177decorators = (decorators & ~MO_DECORATOR_MASK) | MO_UNORDERED;178179// Remove ACCESS_WRITE180decorators = (decorators & ~ACCESS_WRITE);181182// Generate synthetic load at183access.gen()->access_load_at(decorators,184access.type(),185access.base().item(),186access.offset().opr(),187access.gen()->new_register(access.type()),188NULL /* patch_emit_info */,189NULL /* load_emit_info */);190}191192LIR_Opr ZBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value) {193if (barrier_needed(access)) {194pre_load_barrier(access);195}196197return BarrierSetC1::atomic_xchg_at_resolved(access, value);198}199200LIR_Opr ZBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) {201if (barrier_needed(access)) {202pre_load_barrier(access);203}204205return BarrierSetC1::atomic_cmpxchg_at_resolved(access, cmp_value, new_value);206}207208class ZLoadBarrierRuntimeStubCodeGenClosure : public StubAssemblerCodeGenClosure {209private:210const DecoratorSet _decorators;211212public:213ZLoadBarrierRuntimeStubCodeGenClosure(DecoratorSet decorators) :214_decorators(decorators) {}215216virtual OopMapSet* generate_code(StubAssembler* sasm) {217ZBarrierSet::assembler()->generate_c1_load_barrier_runtime_stub(sasm, _decorators);218return NULL;219}220};221222static address generate_c1_runtime_stub(BufferBlob* blob, DecoratorSet decorators, const char* name) {223ZLoadBarrierRuntimeStubCodeGenClosure cl(decorators);224CodeBlob* const code_blob = Runtime1::generate_blob(blob, -1 /* stub_id */, name, false /* expect_oop_map*/, &cl);225return code_blob->code_begin();226}227228void ZBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* blob) {229_load_barrier_on_oop_field_preloaded_runtime_stub =230generate_c1_runtime_stub(blob, ON_STRONG_OOP_REF, "load_barrier_on_oop_field_preloaded_runtime_stub");231_load_barrier_on_weak_oop_field_preloaded_runtime_stub =232generate_c1_runtime_stub(blob, ON_WEAK_OOP_REF, "load_barrier_on_weak_oop_field_preloaded_runtime_stub");233}234235236