1 /* 2 * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. 3 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef SHARE_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP 27 #define SHARE_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP 28 29 #include "c1/c1_CodeStubs.hpp" 30 #include "gc/shared/c1/barrierSetC1.hpp" 31 32 class ShenandoahPreBarrierStub: public CodeStub { 33 friend class ShenandoahBarrierSetC1; 34 private: 35 bool _do_load; 36 LIR_Opr _addr; 37 LIR_Opr _pre_val; 38 LIR_PatchCode _patch_code; 39 CodeEmitInfo* _info; 40 41 public: 42 // Version that _does_ generate a load of the previous value from addr. 43 // addr (the address of the field to be read) must be a LIR_Address 44 // pre_val (a temporary register) must be a register; 45 ShenandoahPreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : 46 _do_load(true), _addr(addr), _pre_val(pre_val), 47 _patch_code(patch_code), _info(info) 48 { 49 assert(_pre_val->is_register(), "should be temporary register"); 50 assert(_addr->is_address(), "should be the address of the field"); 51 FrameMap* f = Compilation::current()->frame_map(); 52 f->update_reserved_argument_area_size(2 * BytesPerWord); 53 } 54 55 // Version that _does not_ generate load of the previous value; the 56 // previous value is assumed to have already been loaded into pre_val. 57 ShenandoahPreBarrierStub(LIR_Opr pre_val) : 58 _do_load(false), _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), 59 _patch_code(lir_patch_none), _info(nullptr) 60 { 61 assert(_pre_val->is_register(), "should be a register"); 62 } 63 64 LIR_Opr addr() const { return _addr; } 65 LIR_Opr pre_val() const { return _pre_val; } 66 LIR_PatchCode patch_code() const { return _patch_code; } 67 CodeEmitInfo* info() const { return _info; } 68 bool do_load() const { return _do_load; } 69 70 virtual void emit_code(LIR_Assembler* e); 71 virtual void visit(LIR_OpVisitState* visitor) { 72 if (_do_load) { 73 // don't pass in the code emit info since it's processed in the fast 74 // path 75 if (_info != nullptr) 76 visitor->do_slow_case(_info); 77 else 78 visitor->do_slow_case(); 79 80 visitor->do_input(_addr); 81 visitor->do_temp(_pre_val); 82 } else { 83 visitor->do_slow_case(); 84 visitor->do_input(_pre_val); 85 } 86 } 87 #ifndef PRODUCT 88 virtual void print_name(outputStream* out) const { out->print("ShenandoahPreBarrierStub"); } 89 #endif // PRODUCT 90 }; 91 92 class ShenandoahLoadReferenceBarrierStub: public CodeStub { 93 friend class ShenandoahBarrierSetC1; 94 private: 95 LIR_Opr _obj; 96 LIR_Opr _addr; 97 LIR_Opr _result; 98 LIR_Opr _tmp1; 99 LIR_Opr _tmp2; 100 DecoratorSet _decorators; 101 public: 102 ShenandoahLoadReferenceBarrierStub(LIR_Opr obj, LIR_Opr addr, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2, DecoratorSet decorators) : 103 _obj(obj), _addr(addr), _result(result), _tmp1(tmp1), _tmp2(tmp2), _decorators(decorators) 104 { 105 assert(_obj->is_register(), "should be register"); 106 assert(_addr->is_register(), "should be register"); 107 assert(_result->is_register(), "should be register"); 108 assert(_tmp1->is_register(), "should be register"); 109 assert(_tmp2->is_register(), "should be register"); 110 111 FrameMap* f = Compilation::current()->frame_map(); 112 f->update_reserved_argument_area_size(2 * BytesPerWord); 113 } 114 115 LIR_Opr obj() const { return _obj; } 116 LIR_Opr addr() const { return _addr; } 117 LIR_Opr result() const { return _result; } 118 LIR_Opr tmp1() const { return _tmp1; } 119 LIR_Opr tmp2() const { return _tmp2; } 120 DecoratorSet decorators() const { return _decorators; } 121 122 virtual void emit_code(LIR_Assembler* e); 123 virtual void visit(LIR_OpVisitState* visitor) { 124 visitor->do_slow_case(); 125 visitor->do_input(_obj); 126 visitor->do_temp(_obj); 127 visitor->do_input(_addr); 128 visitor->do_temp(_addr); 129 visitor->do_temp(_result); 130 visitor->do_temp(_tmp1); 131 visitor->do_temp(_tmp2); 132 } 133 #ifndef PRODUCT 134 virtual void print_name(outputStream* out) const { out->print("ShenandoahLoadReferenceBarrierStub"); } 135 #endif // PRODUCT 136 }; 137 138 class LIR_OpShenandoahCompareAndSwap : public LIR_Op { 139 friend class LIR_OpVisitState; 140 141 private: 142 LIR_Opr _addr; 143 LIR_Opr _cmp_value; 144 LIR_Opr _new_value; 145 LIR_Opr _tmp1; 146 LIR_Opr _tmp2; 147 148 public: 149 LIR_OpShenandoahCompareAndSwap(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, 150 LIR_Opr t1, LIR_Opr t2, LIR_Opr result) 151 : LIR_Op(lir_none, result, nullptr) // no info 152 , _addr(addr) 153 , _cmp_value(cmp_value) 154 , _new_value(new_value) 155 , _tmp1(t1) 156 , _tmp2(t2) { } 157 158 LIR_Opr addr() const { return _addr; } 159 LIR_Opr cmp_value() const { return _cmp_value; } 160 LIR_Opr new_value() const { return _new_value; } 161 LIR_Opr tmp1() const { return _tmp1; } 162 LIR_Opr tmp2() const { return _tmp2; } 163 164 virtual void visit(LIR_OpVisitState* state) { 165 if (_info) state->do_info(_info); 166 assert(_addr->is_valid(), "used"); state->do_input(_addr); 167 state->do_temp(_addr); 168 assert(_cmp_value->is_valid(), "used"); state->do_input(_cmp_value); 169 state->do_temp(_cmp_value); 170 assert(_new_value->is_valid(), "used"); state->do_input(_new_value); 171 state->do_temp(_new_value); 172 if (_tmp1->is_valid()) state->do_temp(_tmp1); 173 if (_tmp2->is_valid()) state->do_temp(_tmp2); 174 if (_result->is_valid()) state->do_output(_result); 175 } 176 177 virtual void emit_code(LIR_Assembler* masm); 178 179 virtual void print_instr(outputStream* out) const { 180 addr()->print(out); out->print(" "); 181 cmp_value()->print(out); out->print(" "); 182 new_value()->print(out); out->print(" "); 183 tmp1()->print(out); out->print(" "); 184 tmp2()->print(out); out->print(" "); 185 } 186 #ifndef PRODUCT 187 virtual const char* name() const { 188 return "shenandoah_cas_obj"; 189 } 190 #endif // PRODUCT 191 }; 192 193 class SCAddressTable; 194 195 class ShenandoahBarrierSetC1 : public BarrierSetC1 { 196 friend class SCAddressTable; 197 private: 198 CodeBlob* _pre_barrier_c1_runtime_code_blob; 199 CodeBlob* _load_reference_barrier_strong_rt_code_blob; 200 CodeBlob* _load_reference_barrier_strong_native_rt_code_blob; 201 CodeBlob* _load_reference_barrier_weak_rt_code_blob; 202 CodeBlob* _load_reference_barrier_phantom_rt_code_blob; 203 204 void pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val); 205 206 LIR_Opr load_reference_barrier(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, DecoratorSet decorators); 207 208 LIR_Opr load_reference_barrier_impl(LIRGenerator* gen, LIR_Opr obj, LIR_Opr addr, DecoratorSet decorators); 209 210 LIR_Opr ensure_in_register(LIRGenerator* gen, LIR_Opr obj, BasicType type); 211 212 public: 213 ShenandoahBarrierSetC1(); 214 215 CodeBlob* pre_barrier_c1_runtime_code_blob() { 216 assert(_pre_barrier_c1_runtime_code_blob != nullptr, ""); 217 return _pre_barrier_c1_runtime_code_blob; 218 } 219 220 CodeBlob* load_reference_barrier_strong_rt_code_blob() { 221 assert(_load_reference_barrier_strong_rt_code_blob != nullptr, ""); 222 return _load_reference_barrier_strong_rt_code_blob; 223 } 224 225 CodeBlob* load_reference_barrier_strong_native_rt_code_blob() { 226 assert(_load_reference_barrier_strong_native_rt_code_blob != nullptr, ""); 227 return _load_reference_barrier_strong_native_rt_code_blob; 228 } 229 230 CodeBlob* load_reference_barrier_weak_rt_code_blob() { 231 assert(_load_reference_barrier_weak_rt_code_blob != nullptr, ""); 232 return _load_reference_barrier_weak_rt_code_blob; 233 } 234 235 CodeBlob* load_reference_barrier_phantom_rt_code_blob() { 236 assert(_load_reference_barrier_phantom_rt_code_blob != nullptr, ""); 237 return _load_reference_barrier_phantom_rt_code_blob; 238 } 239 240 protected: 241 242 virtual void store_at_resolved(LIRAccess& access, LIR_Opr value); 243 virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register); 244 virtual void load_at_resolved(LIRAccess& access, LIR_Opr result); 245 246 virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value); 247 248 virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value); 249 250 void post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Opr new_val); 251 252 public: 253 254 virtual bool generate_c1_runtime_stubs(BufferBlob* buffer_blob); 255 }; 256 257 #endif // SHARE_GC_SHENANDOAH_C1_SHENANDOAHBARRIERSETC1_HPP