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