1 /* 2 * Copyright (c) 2018, Red Hat, Inc. All rights reserved. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 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 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #ifndef SHARE_VM_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP 25 #define SHARE_VM_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP 26 27 #include "c1/c1_CodeStubs.hpp" 28 #include "gc/shared/c1/barrierSetC1.hpp" 29 30 class ShenandoahPreBarrierStub: public CodeStub { 31 friend class ShenandoahBarrierSetC1; 32 private: 33 bool _do_load; 34 LIR_Opr _addr; 35 LIR_Opr _pre_val; 36 LIR_PatchCode _patch_code; 37 CodeEmitInfo* _info; 38 39 public: 40 // Version that _does_ generate a load of the previous value from addr. 41 // addr (the address of the field to be read) must be a LIR_Address 42 // pre_val (a temporary register) must be a register; 43 ShenandoahPreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : 44 _do_load(true), _addr(addr), _pre_val(pre_val), 45 _patch_code(patch_code), _info(info) 46 { 47 assert(_pre_val->is_register(), "should be temporary register"); 48 assert(_addr->is_address(), "should be the address of the field"); 49 } 50 51 // Version that _does not_ generate load of the previous value; the 52 // previous value is assumed to have already been loaded into pre_val. 53 ShenandoahPreBarrierStub(LIR_Opr pre_val) : 54 _do_load(false), _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), 55 _patch_code(lir_patch_none), _info(NULL) 56 { 57 assert(_pre_val->is_register(), "should be a register"); 58 } 59 60 LIR_Opr addr() const { return _addr; } 61 LIR_Opr pre_val() const { return _pre_val; } 62 LIR_PatchCode patch_code() const { return _patch_code; } 63 CodeEmitInfo* info() const { return _info; } 64 bool do_load() const { return _do_load; } 65 66 virtual void emit_code(LIR_Assembler* e); 67 virtual void visit(LIR_OpVisitState* visitor) { 68 if (_do_load) { 69 // don't pass in the code emit info since it's processed in the fast 70 // path 71 if (_info != NULL) 72 visitor->do_slow_case(_info); 73 else 74 visitor->do_slow_case(); 75 76 visitor->do_input(_addr); 77 visitor->do_temp(_pre_val); 78 } else { 79 visitor->do_slow_case(); 80 visitor->do_input(_pre_val); 81 } 82 } 83 #ifndef PRODUCT 84 virtual void print_name(outputStream* out) const { out->print("ShenandoahPreBarrierStub"); } 85 #endif // PRODUCT 86 }; 87 88 class ShenandoahWriteBarrierStub: public CodeStub { 89 friend class ShenandoahBarrierSetC1; 90 private: 91 LIR_Opr _obj; 92 LIR_Opr _result; 93 CodeEmitInfo* _info; 94 bool _needs_null_check; 95 96 public: 97 ShenandoahWriteBarrierStub(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info, bool needs_null_check) : 98 _obj(obj), _result(result), _info(info), _needs_null_check(needs_null_check) 99 { 100 assert(_obj->is_register(), "should be register"); 101 assert(_result->is_register(), "should be register"); 102 } 103 104 LIR_Opr obj() const { return _obj; } 105 LIR_Opr result() const { return _result; } 106 CodeEmitInfo* info() const { return _info; } 107 bool needs_null_check() const { return _needs_null_check; } 108 109 virtual void emit_code(LIR_Assembler* e); 110 virtual void visit(LIR_OpVisitState* visitor) { 111 visitor->do_slow_case(); 112 visitor->do_input(_obj); 113 visitor->do_temp(_result); 114 } 115 #ifndef PRODUCT 116 virtual void print_name(outputStream* out) const { out->print("ShenandoahWritePreBarrierStub"); } 117 #endif // PRODUCT 118 }; 119 120 class LIR_OpShenandoahCompareAndSwap : public LIR_Op { 121 friend class LIR_OpVisitState; 122 123 private: 124 LIR_Opr _addr; 125 LIR_Opr _cmp_value; 126 LIR_Opr _new_value; 127 LIR_Opr _tmp1; 128 LIR_Opr _tmp2; 129 130 public: 131 LIR_OpShenandoahCompareAndSwap(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, 132 LIR_Opr t1, LIR_Opr t2, LIR_Opr result) 133 : LIR_Op(lir_none, result, NULL) // no info 134 , _addr(addr) 135 , _cmp_value(cmp_value) 136 , _new_value(new_value) 137 , _tmp1(t1) 138 , _tmp2(t2) { } 139 140 LIR_Opr addr() const { return _addr; } 141 LIR_Opr cmp_value() const { return _cmp_value; } 142 LIR_Opr new_value() const { return _new_value; } 143 LIR_Opr tmp1() const { return _tmp1; } 144 LIR_Opr tmp2() const { return _tmp2; } 145 146 virtual void visit(LIR_OpVisitState* state) { 147 assert(_addr->is_valid(), "used"); 148 assert(_cmp_value->is_valid(), "used"); 149 assert(_new_value->is_valid(), "used"); 150 if (_info) state->do_info(_info); 151 state->do_input(_addr); 152 state->do_temp(_addr); 153 state->do_input(_cmp_value); 154 state->do_temp(_cmp_value); 155 state->do_input(_new_value); 156 state->do_temp(_new_value); 157 if (_tmp1->is_valid()) state->do_temp(_tmp1); 158 if (_tmp2->is_valid()) state->do_temp(_tmp2); 159 if (_result->is_valid()) state->do_output(_result); 160 } 161 162 virtual void emit_code(LIR_Assembler* masm); 163 164 virtual void print_instr(outputStream* out) const { 165 addr()->print(out); out->print(" "); 166 cmp_value()->print(out); out->print(" "); 167 new_value()->print(out); out->print(" "); 168 tmp1()->print(out); out->print(" "); 169 tmp2()->print(out); out->print(" "); 170 } 171 #ifndef PRODUCT 172 virtual const char* name() const { 173 return "shenandoah_cas_obj"; 174 } 175 #endif // PRODUCT 176 }; 177 178 class ShenandoahBarrierSetC1 : public BarrierSetC1 { 179 private: 180 CodeBlob* _pre_barrier_c1_runtime_code_blob; 181 182 void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val); 183 184 LIR_Opr read_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); 185 LIR_Opr write_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); 186 LIR_Opr storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators); 187 188 LIR_Opr read_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); 189 LIR_Opr write_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); 190 191 LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj); 192 193 public: 194 CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; } 195 196 protected: 197 virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register); 198 199 virtual void store_at_resolved(LIRAccess& access, LIR_Opr value); 200 virtual void load_at_resolved(LIRAccess& access, LIR_Opr result); 201 202 virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value); 203 204 virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value); 205 virtual LIR_Opr atomic_add_at_resolved(LIRAccess& access, LIRItem& value); 206 207 public: 208 virtual LIR_Opr resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj); 209 210 virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob); 211 }; 212 213 #endif // SHARE_VM_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP