1 /* 2 * Copyright (c) 2018, 2020, 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_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP 25 #define SHARE_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 ShenandoahLoadReferenceBarrierStub: public CodeStub { 89 friend class ShenandoahBarrierSetC1; 90 private: 91 LIR_Opr _obj; 92 LIR_Opr _addr; 93 LIR_Opr _result; 94 LIR_Opr _tmp1; 95 LIR_Opr _tmp2; 96 97 public: 98 ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr addr, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2) : 99 _obj(obj), _addr(addr), _result(result), _tmp1(tmp1), _tmp2(tmp2) 100 { 101 assert(_obj->is_register(), "should be register"); 102 assert(_addr->is_register(), "should be register"); 103 assert(_result->is_register(), "should be register"); 104 assert(_tmp1->is_register(), "should be register"); 105 assert(_tmp2->is_register(), "should be register"); 106 } 107 108 LIR_Opr obj() const { return _obj; } 109 LIR_Opr addr() const { return _addr; } 110 LIR_Opr result() const { return _result; } 111 LIR_Opr tmp1() const { return _tmp1; } 112 LIR_Opr tmp2() const { return _tmp2; } 113 114 virtual void emit_code(LIR_Assembler* e); 115 virtual void visit(LIR_OpVisitState* visitor) { 116 visitor->do_slow_case(); 117 visitor->do_input(_obj); 118 visitor->do_temp(_obj); 119 visitor->do_input(_addr); 120 visitor->do_temp(_addr); 121 visitor->do_temp(_result); 122 visitor->do_temp(_tmp1); 123 visitor->do_temp(_tmp2); 124 } 125 #ifndef PRODUCT 126 virtual void print_name(outputStream* out) const { out->print("ShenandoahLoadReferenceBarrierStub"); } 127 #endif // PRODUCT 128 }; 129 130 class LIR_OpShenandoahCompareAndSwap : public LIR_Op { 131 friend class LIR_OpVisitState; 132 133 private: 134 LIR_Opr _addr; 135 LIR_Opr _cmp_value; 136 LIR_Opr _new_value; 137 LIR_Opr _tmp1; 138 LIR_Opr _tmp2; 139 140 public: 141 LIR_OpShenandoahCompareAndSwap(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, 142 LIR_Opr t1, LIR_Opr t2, LIR_Opr result) 143 : LIR_Op(lir_none, result, NULL) // no info 144 , _addr(addr) 145 , _cmp_value(cmp_value) 146 , _new_value(new_value) 147 , _tmp1(t1) 148 , _tmp2(t2) { } 149 150 LIR_Opr addr() const { return _addr; } 151 LIR_Opr cmp_value() const { return _cmp_value; } 152 LIR_Opr new_value() const { return _new_value; } 153 LIR_Opr tmp1() const { return _tmp1; } 154 LIR_Opr tmp2() const { return _tmp2; } 155 156 virtual void visit(LIR_OpVisitState* state) { 157 assert(_addr->is_valid(), "used"); 158 assert(_cmp_value->is_valid(), "used"); 159 assert(_new_value->is_valid(), "used"); 160 if (_info) state->do_info(_info); 161 state->do_input(_addr); 162 state->do_temp(_addr); 163 state->do_input(_cmp_value); 164 state->do_temp(_cmp_value); 165 state->do_input(_new_value); 166 state->do_temp(_new_value); 167 if (_tmp1->is_valid()) state->do_temp(_tmp1); 168 if (_tmp2->is_valid()) state->do_temp(_tmp2); 169 if (_result->is_valid()) state->do_output(_result); 170 } 171 172 virtual void emit_code(LIR_Assembler* masm); 173 174 virtual void print_instr(outputStream* out) const { 175 addr()->print(out); out->print(" "); 176 cmp_value()->print(out); out->print(" "); 177 new_value()->print(out); out->print(" "); 178 tmp1()->print(out); out->print(" "); 179 tmp2()->print(out); out->print(" "); 180 } 181 #ifndef PRODUCT 182 virtual const char* name() const { 183 return "shenandoah_cas_obj"; 184 } 185 #endif // PRODUCT 186 }; 187 188 class ShenandoahBarrierSetC1 : public BarrierSetC1 { 189 private: 190 CodeBlob* _pre_barrier_c1_runtime_code_blob; 191 CodeBlob* _load_reference_barrier_rt_code_blob; 192 193 void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val); 194 195 LIR_Opr load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr); 196 LIR_Opr storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators); 197 198 LIR_Opr load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr); 199 200 LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj, BasicType type); 201 202 public: 203 ShenandoahBarrierSetC1(); 204 205 CodeBlob* pre_barrier_c1_runtime_code_blob() { 206 assert(_pre_barrier_c1_runtime_code_blob != NULL, ""); 207 return _pre_barrier_c1_runtime_code_blob; 208 } 209 210 CodeBlob* load_reference_barrier_rt_code_blob() { 211 assert(_load_reference_barrier_rt_code_blob != NULL, ""); 212 return _load_reference_barrier_rt_code_blob; 213 } 214 215 protected: 216 217 virtual void store_at_resolved(LIRAccess& access, LIR_Opr value); 218 virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register); 219 virtual void load_at_resolved(LIRAccess& access, LIR_Opr result); 220 221 virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value); 222 223 virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value); 224 225 public: 226 227 virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob); 228 }; 229 230 #endif // SHARE_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP