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 %}
30
31 instruct load_P_shenandoah(iRegPNoSp dst, memory mem, rFlagsReg cr)
32 %{
33 match(Set dst (LoadP mem));
34 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
35 effect(TEMP_DEF dst, KILL cr);
36 // The main load is a candidate to implement implicit null checks.
37 ins_is_late_expanded_null_check_candidate(true);
38 format %{ "ld $dst, $mem\t# ptr, shenandoah late-barrier, #@loadP_shenandoah" %}
39 ins_encode %{
40 ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp), t0, t1, false);
41 %}
42 ins_cost(3 * LOAD_COST);
43 ins_pipe(iload_reg_mem);
44 %}
45
46 instruct load_N_shenandoah(iRegNNoSp dst, memory mem, rFlagsReg cr)
47 %{
48 match(Set dst (LoadN mem));
49 predicate(UseShenandoahGC && n->as_Load()->barrier_data() != 0);
50 effect(TEMP_DEF dst, KILL cr);
51 // The main load is a candidate to implement implicit null checks.
52 ins_is_late_expanded_null_check_candidate(true);
53 format %{ "lwu $dst, $mem\t# compressed ptr, shenandoah late-barrier, #@loadN_shenandoah" %}
54 ins_encode %{
55 ShenandoahBarrierSet::assembler()->load_c2(this, masm, as_Register($dst$$reg), Address(as_Register($mem$$base), $mem$$disp), t0, t1, true);
56 %}
57 ins_cost(3 * LOAD_COST);
58 ins_pipe(iload_reg_mem);
59 %}
60
61 instruct storeP_shenandoah(iRegP src, memory mem, iRegPNoSp tmp, rFlagsReg cr)
62 %{
63 match(Set mem (StoreP mem src));
64 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
65 effect(TEMP tmp, KILL cr);
66 format %{ "sd $src, $mem\t# ptr, shenandoah late-barrier, #@storeP_shenandoah" %}
67 ins_encode %{
68 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
69 Address(as_Register($mem$$base), $mem$$disp), /* dst_narrow = */ false,
70 as_Register($src$$reg), /* src_narrow = */ false,
71 as_Register($tmp$$reg),
72 t0,
73 t1);
74 %}
75 ins_cost(3 * STORE_COST);
76 ins_pipe(istore_reg_mem);
77 %}
78
79 instruct storeN_shenandoah(iRegN src, memory mem, iRegPNoSp tmp, rFlagsReg cr)
80 %{
81 match(Set mem (StoreN mem src));
82 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
83 effect(TEMP tmp, KILL cr);
84 format %{ "sw $src, $mem\t# compressed ptr, shenandoah late-barrier, #@storeN_shenandoah" %}
85 ins_encode %{
86 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
87 Address(as_Register($mem$$base), $mem$$disp), /* dst_narrow = */ true,
88 as_Register($src$$reg), /* src_narrow = */ true,
89 as_Register($tmp$$reg),
90 t0,
91 t1);
92 %}
93 ins_cost(3 * STORE_COST);
94 ins_pipe(istore_reg_mem);
95 %}
96
97 instruct encodePAndStoreN_shenandoah(iRegP src, memory mem, iRegPNoSp tmp, rFlagsReg cr)
98 %{
99 match(Set mem (StoreN mem (EncodeP src)));
100 predicate(UseShenandoahGC && n->as_Store()->barrier_data() != 0);
101 effect(TEMP tmp, KILL cr);
102 format %{
103 "encode_heap_oop $tmp, $src\n\t"
104 "sw $tmp, $mem\t# compressed ptr, shenandoah late-barrier, #@encodePAndStoreN_shenandoah"
105 %}
106 ins_encode %{
107 ShenandoahBarrierSet::assembler()->store_c2(this, masm,
108 Address(as_Register($mem$$base), $mem$$disp), /* dst_narrow = */ true,
109 as_Register($src$$reg), /* src_narrow = */ false,
110 as_Register($tmp$$reg),
111 t0,
112 t1);
113 %}
114 ins_cost(4 * STORE_COST);
115 ins_pipe(istore_reg_mem);
116 %}
117
118 instruct compareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
119 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
120 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
121 effect(TEMP_DEF res, TEMP tmp, KILL cr);
122 format %{ "cmpxchg_P_A_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_P_shenandoah" %}
123 ins_encode %{
124 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
125 as_Register($res$$reg),
126 as_Register($mem$$base),
127 as_Register($oldval$$reg),
128 as_Register($newval$$reg),
129 as_Register($tmp$$reg),
130 t0,
131 t1,
132 /* exchange */ false,
133 /* is_narrow */ false,
134 /* acquire */ true);
135 %}
136 ins_cost(10 * DEFAULT_COST);
137 ins_pipe(pipe_slow);
138 %}
139
140 instruct compareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
141 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
142 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
143 effect(TEMP_DEF res, TEMP tmp, KILL cr);
144 format %{ "cmpxchg_P_N_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_P_shenandoah" %}
145 ins_encode %{
146 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
147 as_Register($res$$reg),
148 as_Register($mem$$base),
149 as_Register($oldval$$reg),
150 as_Register($newval$$reg),
151 as_Register($tmp$$reg),
152 t0,
153 t1,
154 /* exchange */ false,
155 /* is_narrow */ false,
156 /* acquire */ false);
157 %}
158 ins_cost(10 * DEFAULT_COST);
159 ins_pipe(pipe_slow);
160 %}
161
162 instruct compareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
163 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
164 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
165 effect(TEMP_DEF res, TEMP tmp, KILL cr);
166 format %{ "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (narrow ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_N_shenandoah" %}
167 ins_encode %{
168 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
169 as_Register($res$$reg),
170 as_Register($mem$$base),
171 as_Register($oldval$$reg),
172 as_Register($newval$$reg),
173 as_Register($tmp$$reg),
174 t0,
175 t1,
176 /* exchange */ false,
177 /* is_narrow */ true,
178 /* acquire */ true);
179 %}
180 ins_cost(10 * DEFAULT_COST);
181 ins_pipe(pipe_slow);
182 %}
183
184 instruct compareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
185 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
186 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
187 effect(TEMP_DEF res, TEMP tmp, KILL cr);
188 format %{ "cmpxchg_N_shenandoah $mem, $oldval, $newval\t# (narrow ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndSwap_N_shenandoah" %}
189 ins_encode %{
190 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
191 as_Register($res$$reg),
192 as_Register($mem$$base),
193 as_Register($oldval$$reg),
194 as_Register($newval$$reg),
195 as_Register($tmp$$reg),
196 t0,
197 t1,
198 /* exchange */ false,
199 /* is_narrow */ true,
200 /* acquire */ false);
201 %}
202 ins_cost(10 * DEFAULT_COST);
203 ins_pipe(pipe_slow);
204 %}
205
206 instruct compareAndExchange_N_A_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
207 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
208 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
209 effect(TEMP_DEF res, TEMP tmp, KILL cr);
210 format %{ "cae_N_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_N_shenandoah" %}
211 ins_encode %{
212 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
213 as_Register($res$$reg),
214 as_Register($mem$$base),
215 as_Register($oldval$$reg),
216 as_Register($newval$$reg),
217 as_Register($tmp$$reg),
218 t0,
219 t1,
220 /* exchange */ true,
221 /* is_narrow */ true,
222 /* acquire */ true);
223 %}
224 ins_cost(10 * DEFAULT_COST);
225 ins_pipe(pipe_slow);
226 %}
227
228 instruct compareAndExchange_N_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
229 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
230 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
231 effect(TEMP_DEF res, TEMP tmp, KILL cr);
232 format %{ "cae_N_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_N_shenandoah" %}
233 ins_encode %{
234 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
235 as_Register($res$$reg),
236 as_Register($mem$$base),
237 as_Register($oldval$$reg),
238 as_Register($newval$$reg),
239 as_Register($tmp$$reg),
240 t0,
241 t1,
242 /* exchange */ true,
243 /* is_narrow */ true,
244 /* acquire */ false);
245 %}
246 ins_cost(10 * DEFAULT_COST);
247 ins_pipe(pipe_slow);
248 %}
249
250 instruct compareAndExchange_P_A_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
251 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
252 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
253 effect(TEMP_DEF res, TEMP tmp, KILL cr);
254 format %{ "cae_P_shenandoah $res = $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_P_shenandoah" %}
255 ins_encode %{
256 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
257 as_Register($res$$reg),
258 as_Register($mem$$base),
259 as_Register($oldval$$reg),
260 as_Register($newval$$reg),
261 as_Register($tmp$$reg),
262 t0,
263 t1,
264 /* exchange */ true,
265 /* is_narrow */ false,
266 /* acquire */ true);
267 %}
268 ins_cost(10 * DEFAULT_COST);
269 ins_pipe(pipe_slow);
270 %}
271
272 instruct compareAndExchange_P_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
273 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
274 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
275 effect(TEMP_DEF res, TEMP tmp, KILL cr);
276 format %{ "cae_P_shenandoah $res = $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval, #@compareAndExchange_P_shenandoah" %}
277 ins_encode %{
278 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
279 as_Register($res$$reg),
280 as_Register($mem$$base),
281 as_Register($oldval$$reg),
282 as_Register($newval$$reg),
283 as_Register($tmp$$reg),
284 t0,
285 t1,
286 /* exchange */ true,
287 /* is_narrow */ false,
288 /* acquire */ false);
289 %}
290 ins_cost(10 * DEFAULT_COST);
291 ins_pipe(pipe_slow);
292 %}
293
294 instruct weakCompareAndSwap_N_A_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
295 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
296 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
297 effect(TEMP_DEF res, TEMP tmp, KILL cr);
298 format %{ "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_N_shenandoah" %}
299 ins_encode %{
300 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
301 as_Register($res$$reg),
302 as_Register($mem$$base),
303 as_Register($oldval$$reg),
304 as_Register($newval$$reg),
305 as_Register($tmp$$reg),
306 t0,
307 t1,
308 /* exchange */ false,
309 /* is_narrow */ true,
310 /* acquire */ true);
311 %}
312 ins_cost(10 * DEFAULT_COST);
313 ins_pipe(pipe_slow);
314 %}
315
316 instruct weakCompareAndSwap_N_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp, rFlagsReg cr) %{
317 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
318 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
319 effect(TEMP_DEF res, TEMP tmp, KILL cr);
320 format %{ "cae_N_weak_shenandoah $res = $mem, $oldval, $newval\t# (N, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_N_shenandoah" %}
321 ins_encode %{
322 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
323 as_Register($res$$reg),
324 as_Register($mem$$base),
325 as_Register($oldval$$reg),
326 as_Register($newval$$reg),
327 as_Register($tmp$$reg),
328 t0,
329 t1,
330 /* exchange */ false,
331 /* is_narrow */ true,
332 /* acquire */ false);
333 %}
334 ins_cost(10 * DEFAULT_COST);
335 ins_pipe(pipe_slow);
336 %}
337
338 instruct weakCompareAndSwap_P_A_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
339 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
340 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
341 effect(TEMP_DEF res, TEMP tmp, KILL cr);
342 format %{ "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_P_shenandoah" %}
343 ins_encode %{
344 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
345 as_Register($res$$reg),
346 as_Register($mem$$base),
347 as_Register($oldval$$reg),
348 as_Register($newval$$reg),
349 as_Register($tmp$$reg),
350 t0,
351 t1,
352 /* exchange */ false,
353 /* is_narrow */ false,
354 /* acquire */ true);
355 %}
356 ins_cost(10 * DEFAULT_COST);
357 ins_pipe(pipe_slow);
358 %}
359
360 instruct weakCompareAndSwap_P_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
361 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
362 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
363 effect(TEMP_DEF res, TEMP tmp, KILL cr);
364 format %{ "cae_P_weak_shenandoah $res = $mem, $oldval, $newval\t# (P, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwap_P_shenandoah" %}
365 ins_encode %{
366 ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
367 as_Register($res$$reg),
368 as_Register($mem$$base),
369 as_Register($oldval$$reg),
370 as_Register($newval$$reg),
371 as_Register($tmp$$reg),
372 t0,
373 t1,
374 /* exchange */ false,
375 /* is_narrow */ false,
376 /* acquire */ false);
377 %}
378 ins_cost(10 * DEFAULT_COST);
379 ins_pipe(pipe_slow);
380 %}
381
382 instruct getAndSet_P_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
383 %{
384 match(Set preval (GetAndSetP mem newval));
385 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
386 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
387 format %{ "get_and_set_P $preval, $newval, [$mem], #@getAndSet_P_shenandoah" %}
388 ins_encode %{
389 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
390 as_Register($preval$$reg),
391 as_Register($newval$$reg),
392 as_Register($mem$$base),
393 as_Register($tmp$$reg),
394 t0,
395 t1,
396 /* acquire */ false);
397 %}
398 ins_cost(10 * DEFAULT_COST);
399 ins_pipe(pipe_slow);
400 %}
401
402 instruct getAndSet_P_A_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
403 %{
404 match(Set preval (GetAndSetP mem newval));
405 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
406 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
407 format %{ "get_and_set_P $preval, $newval, [$mem], #@getAndSet_P_shenandoah" %}
408 ins_encode %{
409 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
410 as_Register($preval$$reg),
411 as_Register($newval$$reg),
412 as_Register($mem$$base),
413 as_Register($tmp$$reg),
414 t0,
415 t1,
416 /* acquire */ true);
417 %}
418 ins_cost(10 * DEFAULT_COST);
419 ins_pipe(pipe_slow);
420 %}
421
422 instruct getAndSet_N_A_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
423 %{
424 match(Set preval (GetAndSetN mem newval));
425 predicate(UseShenandoahGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
426 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
427 format %{ "get_and_set_N $preval, $newval, [$mem], #@getAndSet_N_shenandoah" %}
428 ins_encode %{
429 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
430 as_Register($preval$$reg),
431 as_Register($newval$$reg),
432 as_Register($mem$$base),
433 as_Register($tmp$$reg),
434 t0,
435 t1,
436 /* acquire */ true);
437 %}
438 ins_cost(10 * DEFAULT_COST);
439 ins_pipe(pipe_slow);
440 %}
441
442 instruct getAndSet_N_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
443 %{
444 match(Set preval (GetAndSetN mem newval));
445 predicate(UseShenandoahGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0);
446 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
447 format %{ "get_and_set_N $preval, $newval, [$mem], #@getAndSet_N_shenandoah" %}
448 ins_encode %{
449 ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
450 as_Register($preval$$reg),
451 as_Register($newval$$reg),
452 as_Register($mem$$base),
453 as_Register($tmp$$reg),
454 t0,
455 t1,
456 /* acquire */ false);
457 %}
458 ins_cost(10 * DEFAULT_COST);
459 ins_pipe(pipe_slow);
460 %}