1 //
2 // Copyright (c) 2018, Red Hat, Inc. All rights reserved.
3 // Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 source %{
27 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
28 #include "gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp"
29 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
30 %}
31
32 // Load Pointer
33 instruct loadP_shenandoah(iRegPNoSp dst, memory mem)
34 %{
35 match(Set dst (LoadP mem));
36 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
37
38 effect(TEMP_DEF dst);
39 ins_is_late_expanded_null_check_candidate(true);
40
41 ins_cost(3 * LOAD_COST);
42 format %{ "ld $dst, $mem\t# ptr, shenandoah late-barrier, #@loadP_shenandoah" %}
43
44 ins_encode %{
45 ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg),
46 Address(as_Register($mem$$base), $mem$$disp));
47 %}
48
49 ins_pipe(iload_reg_mem);
50 %}
51
52 // Load Compressed Pointer
53 instruct loadN_shenandoah(iRegNNoSp dst, memory mem)
54 %{
55 match(Set dst (LoadN mem));
56 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
57
58 effect(TEMP_DEF dst);
59 ins_is_late_expanded_null_check_candidate(true);
60
61 ins_cost(3 * LOAD_COST);
62 format %{ "lwu $dst, $mem\t# compressed ptr, shenandoah late-barrier, #@loadN_shenandoah" %}
63
64 ins_encode %{
65 ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg),
66 Address(as_Register($mem$$base), $mem$$disp));
67 %}
68
69 ins_pipe(iload_reg_mem);
70 %}
71
72 // Store Pointer
73 instruct storeP_shenandoah(memory mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
74 %{
75 match(Set mem (StoreP mem src));
76 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
77
78 effect(TEMP tmp, KILL cr);
79
80 ins_cost(3 * STORE_COST);
81 format %{ "sd $src, $mem\t# ptr, shenandoah late-barrier, #@storeP_shenandoah" %}
82
83 ins_encode %{
84 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
85 Address(as_Register($mem$$base), $mem$$disp),
86 /* dst_narrow = */ false,
87 as_Register($src$$reg),
88 /* src_narrow = */ false,
89 as_Register($tmp$$reg));
90 %}
91
92 ins_pipe(istore_reg_mem);
93 %}
94
95 // Store Compressed Pointer
96 instruct storeN_shenandoah(memory mem, iRegN src, iRegNNoSp tmp, rFlagsReg cr)
97 %{
98 match(Set mem (StoreN mem src));
99 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
100
101 effect(TEMP tmp, KILL cr);
102
103 ins_cost(3 * STORE_COST);
104 format %{ "sw $src, $mem\t# compressed ptr, shenandoah late-barrier, #@storeN_shenandoah" %}
105
106 ins_encode %{
107 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
108 Address(as_Register($mem$$base), $mem$$disp),
109 /* dst_narrow = */ true,
110 as_Register($src$$reg),
111 /* src_narrow = */ true,
112 as_Register($tmp$$reg));
113 %}
114
115 ins_pipe(istore_reg_mem);
116 %}
117
118 // Encode and Store Compressed Pointer
119 instruct encodePAndStoreN_shenandoah(memory mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
120 %{
121 match(Set mem (StoreN mem (EncodeP src)));
122 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
123
124 effect(TEMP tmp, KILL cr);
125
126 ins_cost(4 * STORE_COST);
127 format %{
128 "encode_heap_oop $tmp, $src\n\t"
129 "sw $tmp, $mem\t# compressed ptr, shenandoah late-barrier, #@encodePAndStoreN_shenandoah"
130 %}
131
132 ins_encode %{
133 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
134 Address(as_Register($mem$$base), $mem$$disp),
135 /* dst_narrow = */ true,
136 as_Register($src$$reg),
137 /* src_narrow = */ false,
138 as_Register($tmp$$reg));
139 %}
140
141 ins_pipe(istore_reg_mem);
142 %}
143
144 instruct compareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
145 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
146 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
147 ins_cost(10 * DEFAULT_COST);
148
149 effect(TEMP_DEF res, TEMP tmp, KILL cr);
150
151 format %{
152 "cmpxchg_P_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_P_shenandoah"
153 %}
154
155 ins_encode %{
156 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
157 as_Register($res$$reg),
158 as_Register($mem$$base),
159 as_Register($oldval$$reg),
160 as_Register($newval$$reg),
161 as_Register($tmp$$reg),
162 /* exchange */ false,
163 /* maybe_null */ true,
164 /* is_narrow */ false,
165 /* weak */ false);
166 %}
167
168 ins_pipe(pipe_slow);
169 %}
170
171 instruct compareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
172 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
173 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
174 ins_cost(10 * DEFAULT_COST);
175
176 effect(TEMP_DEF res, TEMP tmp, KILL cr);
177
178 format %{
179 "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (narrow ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_N_shenandoah"
180 %}
181
182 ins_encode %{
183 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
184 as_Register($res$$reg),
185 as_Register($mem$$base),
186 as_Register($oldval$$reg),
187 as_Register($newval$$reg),
188 as_Register($tmp$$reg),
189 /* exchange */ false,
190 /* maybe_null */ true,
191 /* is_narrow */ true,
192 /* weak */ false);
193 %}
194
195 ins_pipe(pipe_slow);
196 %}
197
198 instruct compareAndExchange_N_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
199 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
200 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
201 ins_cost(10 * DEFAULT_COST);
202 effect(TEMP_DEF res, TEMP tmp, KILL cr);
203
204 format %{
205 "cae_N_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_N_shenandoah"
206 %}
207
208 ins_encode %{
209 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
210 as_Register($res$$reg),
211 as_Register($mem$$base),
212 as_Register($oldval$$reg),
213 as_Register($newval$$reg),
214 as_Register($tmp$$reg),
215 /* exchange */ true,
216 /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
217 /* is_narrow */ true,
218 /* weak */ false);
219 %}
220
221 ins_pipe(pipe_slow);
222 %}
223
224 instruct compareAndExchange_P_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
225 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
226 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
227 ins_cost(10 * DEFAULT_COST);
228
229 effect(TEMP_DEF res, TEMP tmp, KILL cr);
230 format %{
231 "cae_P_shenandoah $res = $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_P_shenandoah"
232 %}
233
234 ins_encode %{
235 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
236 as_Register($res$$reg),
237 as_Register($mem$$base),
238 as_Register($oldval$$reg),
239 as_Register($newval$$reg),
240 as_Register($tmp$$reg),
241 /* exchange */ true,
242 /* maybe_null */ (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull),
243 /* is_narrow */ false,
244 /* weak */ false);
245 %}
246
247 ins_pipe(pipe_slow);
248 %}
249
250 instruct weakCompareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
251 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
252 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
253 ins_cost(10 * DEFAULT_COST);
254
255 effect(TEMP_DEF res, TEMP tmp, KILL cr);
256 format %{
257 "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_N_shenandoah"
258 %}
259
260 ins_encode %{
261 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
262 as_Register($res$$reg),
263 as_Register($mem$$base),
264 as_Register($oldval$$reg),
265 as_Register($newval$$reg),
266 as_Register($tmp$$reg),
267 /* exchange */ false,
268 /* maybe_null */ true,
269 /* is_narrow */ true,
270 /* weak */ true);
271 %}
272
273 ins_pipe(pipe_slow);
274 %}
275
276 instruct weakCompareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
277 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
278 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
279 ins_cost(10 * DEFAULT_COST);
280
281 effect(TEMP_DEF res, TEMP tmp, KILL cr);
282 format %{
283 "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_P_shenandoah"
284 %}
285
286 ins_encode %{
287 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
288 as_Register($res$$reg),
289 as_Register($mem$$base),
290 as_Register($oldval$$reg),
291 as_Register($newval$$reg),
292 as_Register($tmp$$reg),
293 /* exchange */ false,
294 /* maybe_null */ true,
295 /* is_narrow */ false,
296 /* weak */ true);
297 %}
298
299 ins_pipe(pipe_slow);
300 %}
301
302 instruct getAndSet_P_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
303 %{
304 match(Set preval (GetAndSetP mem newval));
305 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
306 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
307 ins_cost(10 * DEFAULT_COST);
308 format %{ "get_and_set_P $preval, $newval, [$mem], #@getAndSet_P_shenandoah" %}
309 ins_encode %{
310 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
311 as_Register($preval$$reg),
312 as_Register($newval$$reg),
313 as_Register($mem$$base),
314 as_Register($tmp$$reg));
315 %}
316 ins_pipe(pipe_slow);
317 %}
318
319 instruct getAndSet_N_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegNNoSp tmp, rFlagsReg cr)
320 %{
321 match(Set preval (GetAndSetN mem newval));
322 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
323 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
324 ins_cost(10 * DEFAULT_COST);
325 format %{ "get_and_set_N $preval, $newval, [$mem], #@getAndSet_N_shenandoah" %}
326 ins_encode %{
327 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
328 as_Register($preval$$reg),
329 as_Register($newval$$reg),
330 as_Register($mem$$base),
331 as_Register($tmp$$reg));
332 %}
333 ins_pipe(pipe_slow);
334 %}