1 //
2 // Copyright (c) 2018, 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 source %{
26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
27 #include "gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp"
28 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
29 %}
30
31 instruct storeP_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
32 %{
33 match(Set mem (StoreP mem src));
34 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
35 effect(TEMP tmp, KILL cr);
36 ins_cost(INSN_COST);
37 format %{ "str $src, $mem\t# ptr" %}
38 ins_encode %{
39 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
40 $mem$$Register /* addr */,
41 $tmp$$Register /* pre_val */);
42 __ str($src$$Register, $mem$$Register);
43 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
44 $mem$$Register /* addr */,
45 $tmp$$Register /* tmp */);
46 %}
47 ins_pipe(istore_reg_mem);
48 %}
49
50 instruct storePVolatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
51 %{
52 match(Set mem (StoreP mem src));
53 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
54 effect(TEMP tmp, KILL cr);
55 ins_cost(VOLATILE_REF_COST);
56 format %{ "stlr $src, $mem\t# ptr" %}
57 ins_encode %{
58 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
59 $mem$$Register /* obj */,
60 $tmp$$Register /* pre_val */);
61 __ stlr($src$$Register, $mem$$Register);
62 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
63 $mem$$Register /* addr */,
64 $tmp$$Register /* tmp */);
65 %}
66 ins_pipe(pipe_class_memory);
67 %}
68
69 instruct storeN_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
70 %{
71 match(Set mem (StoreN mem src));
72 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
73 effect(TEMP tmp, KILL cr);
74 ins_cost(INSN_COST);
75 format %{ "strw $src, $mem\t# compressed ptr" %}
76 ins_encode %{
77 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
78 $mem$$Register /* obj */,
79 $tmp$$Register /* pre_val */);
80 __ strw($src$$Register, $mem$$Register);
81 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
82 $mem$$Register /* addr */,
83 $tmp$$Register /* tmp */);
84 %}
85 ins_pipe(istore_reg_mem);
86 %}
87
88 instruct storeNVolatile_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
89 %{
90 match(Set mem (StoreN mem src));
91 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
92 effect(TEMP tmp, KILL cr);
93 ins_cost(VOLATILE_REF_COST);
94 format %{ "stlrw $src, $mem\t# compressed ptr" %}
95 ins_encode %{
96 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
97 $mem$$Register /* obj */,
98 $tmp$$Register /* pre_val */);
99 __ stlrw($src$$Register, $mem$$Register);
100 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
101 $mem$$Register /* addr */,
102 $tmp$$Register /* tmp */);
103 %}
104 ins_pipe(pipe_class_memory);
105 %}
106
107 instruct encodePAndStoreN_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
108 %{
109 match(Set mem (StoreN mem (EncodeP src)));
110 predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
111 effect(TEMP tmp, KILL cr);
112 ins_cost(INSN_COST);
113 format %{ "encode_heap_oop $tmp, $src\n\t"
114 "strw $tmp, $mem\t# compressed ptr" %}
115 ins_encode %{
116 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
117 $mem$$Register /* obj */,
118 $tmp$$Register /* pre_val */);
119 if ((barrier_data() & ShenandoahBarrierCardMarkNotNull) == 0) {
120 __ encode_heap_oop($tmp$$Register, $src$$Register);
121 } else {
122 __ encode_heap_oop_not_null($tmp$$Register, $src$$Register);
123 }
124 __ strw($tmp$$Register, $mem$$Register);
125 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
126 $mem$$Register /* addr */,
127 $tmp$$Register /* tmp */);
128 %}
129 ins_pipe(istore_reg_mem);
130 %}
131
132 instruct encodePAndStoreNVolatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
133 %{
134 match(Set mem (StoreN mem (EncodeP src)));
135 predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
136 effect(TEMP tmp, KILL cr);
137 ins_cost(VOLATILE_REF_COST);
138 format %{ "encode_heap_oop $tmp, $src\n\t"
139 "stlrw $tmp, $mem\t# compressed ptr" %}
140 ins_encode %{
141 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
142 $mem$$Register /* obj */,
143 $tmp$$Register /* pre_val */);
144 if ((barrier_data() & ShenandoahBarrierCardMarkNotNull) == 0) {
145 __ encode_heap_oop($tmp$$Register, $src$$Register);
146 } else {
147 __ encode_heap_oop_not_null($tmp$$Register, $src$$Register);
148 }
149 __ stlrw($tmp$$Register, $mem$$Register);
150 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
151 $mem$$Register /* addr */,
152 $tmp$$Register /* tmp */);
153 %}
154 ins_pipe(pipe_class_memory);
155 %}
156
157 instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
158
159 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
160 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
161 ins_cost(2 * VOLATILE_REF_COST);
162
163 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
164
165 format %{
166 "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
167 %}
168
169 ins_encode %{
170 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
171 guarantee(!UseCompressedOops, "must not be compressed oops");
172
173 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
174 __ mov($tmp1$$Register, $oldval$$Register);
175 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
176 noreg /* addr */,
177 $tmp1$$Register /* pre_val */);
178 }
179
180 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
181 $mem$$base$$Register,
182 $oldval$$Register,
183 $newval$$Register,
184 $res$$Register,
185 $tmp1$$Register,
186 $tmp2$$Register,
187 /*acquire*/ false,
188 /*release*/ true,
189 /*weak*/ false,
190 /*is_cae*/ false);
191
192 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
193 $mem$$Register /* addr */,
194 $tmp1$$Register /* tmp */);
195 %}
196
197 ins_pipe(pipe_slow);
198 %}
199
200 instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
201
202 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
203 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
204 ins_cost(2 * VOLATILE_REF_COST);
205
206 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
207
208 format %{
209 "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
210 %}
211
212 ins_encode %{
213 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
214 guarantee(UseCompressedOops, "must be compressed oops");
215 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
216 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
217 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
218 noreg /* obj */,
219 $tmp1$$Register /* pre_val */);
220 }
221 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
222 $mem$$base$$Register,
223 $oldval$$Register,
224 $newval$$Register,
225 $res$$Register,
226 $tmp1$$Register,
227 $tmp2$$Register,
228 /*acquire*/ false,
229 /*release*/ true,
230 /*weak*/ false,
231 /*is_cae*/ false);
232
233 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
234 $mem$$Register /* addr */,
235 $tmp1$$Register /* tmp */);
236 %}
237
238 ins_pipe(pipe_slow);
239 %}
240
241 instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegINoSp tmp1, iRegINoSp tmp2, rFlagsReg cr) %{
242
243 match(Set res (CompareAndSwapP mem (Binary oldval newval)));
244 predicate(needs_acquiring_load_exclusive(n));
245 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
246 ins_cost(VOLATILE_REF_COST);
247
248 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
249
250 format %{
251 "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
252 %}
253
254 ins_encode %{
255 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
256 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
257 noreg /* obj */,
258 $oldval$$Register /* pre_val */);
259
260 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
261 $mem$$base$$Register,
262 $oldval$$Register,
263 $newval$$Register,
264 $res$$Register,
265 $tmp1$$Register,
266 $tmp2$$Register,
267 /*acquire*/ true,
268 /*release*/ true,
269 /*weak*/ false,
270 /*is_cae*/ false);
271
272 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
273 $mem$$Register /* addr */,
274 $tmp1$$Register /* tmp */);
275 %}
276
277 ins_pipe(pipe_slow);
278 %}
279
280 instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
281
282 match(Set res (CompareAndSwapN mem (Binary oldval newval)));
283 predicate(needs_acquiring_load_exclusive(n));
284 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
285 ins_cost(VOLATILE_REF_COST);
286
287 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
288
289 format %{
290 "cmpxchgw_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
291 %}
292
293 ins_encode %{
294 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
295 guarantee(UseCompressedOops, "must be compressed oops");
296 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
297 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
298 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
299 noreg /* obj */,
300 $tmp1$$Register /* pre_val */);
301 }
302 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
303 $mem$$base$$Register,
304 $oldval$$Register,
305 $newval$$Register,
306 $res$$Register,
307 $tmp1$$Register,
308 $tmp2$$Register,
309 /*acquire*/ true,
310 /*release*/ true,
311 /*weak*/ false,
312 /*is_cae*/ false);
313
314 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
315 $mem$$Register /* addr */,
316 $tmp1$$Register /* tmp */);
317 %}
318
319 ins_pipe(pipe_slow);
320 %}
321
322 instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
323 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
324 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0 && !needs_acquiring_load_exclusive(n));
325 ins_cost(2 * VOLATILE_REF_COST);
326 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
327 format %{
328 "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
329 %}
330 ins_encode %{
331 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
332 guarantee(UseCompressedOops, "must be compressed oops");
333 __ block_comment("compareAndExchangeN_shenandoah");
334 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
335 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
336 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm, noreg /* obj */, $tmp1$$Register /* pre_val */);
337 }
338 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
339 $mem$$base$$Register,
340 $oldval$$Register,
341 $newval$$Register,
342 $res$$Register,
343 $tmp1$$Register,
344 $tmp2$$Register,
345 /*acquire*/ false,
346 /*release*/ true,
347 /*weak*/ false,
348 /*is_cae*/ true);
349
350 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
351 $res$$Register /* obj */,
352 $mem$$Register /* addr */,
353 $tmp1$$Register /* tmp */,
354 true /* narrow */,
355 true /* maybe_null */);
356
357 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
358 $mem$$Register /* addr */,
359 $tmp1$$Register /* tmp */);
360 __ block_comment("} compareAndExchangeN_shenandoah");
361 %}
362 ins_pipe(pipe_slow);
363 %}
364
365 instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
366 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
367 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
368 ins_cost(2 * VOLATILE_REF_COST);
369 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
370 format %{
371 "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
372 %}
373 ins_encode %{
374 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
375 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
376 noreg /* obj */,
377 $oldval$$Register /* pre_val */);
378
379 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
380 $mem$$base$$Register,
381 $oldval$$Register,
382 $newval$$Register,
383 $res$$Register,
384 $tmp1$$Register,
385 $tmp2$$Register,
386 /*acquire*/ false,
387 /*release*/ true,
388 /*weak*/ false,
389 /*is_cae*/ true);
390
391 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
392 $res$$Register /* obj */,
393 $mem$$Register /* addr */,
394 $tmp1$$Register /* tmp */,
395 false /* narrow */,
396 true /* maybe_null */);
397 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
398 $mem$$Register /* addr */,
399 $tmp1$$Register /* tmp */);
400 %}
401 ins_pipe(pipe_slow);
402 %}
403
404 instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
405 match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
406 predicate(needs_acquiring_load_exclusive(n));
407 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
408 ins_cost(VOLATILE_REF_COST);
409 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
410 format %{
411 "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
412 %}
413 ins_encode %{
414 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
415 guarantee(UseCompressedOops, "must be compressed oops");
416 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
417 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
418 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
419 noreg /* obj */,
420 $tmp1$$Register /* pre_val */);
421 }
422
423 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
424 $mem$$base$$Register,
425 $oldval$$Register,
426 $newval$$Register,
427 $res$$Register,
428 $tmp1$$Register,
429 $tmp2$$Register,
430 /*acquire*/ true,
431 /*release*/ true,
432 /*weak*/ false,
433 /*is_cae*/ true);
434
435 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
436 $res$$Register /* obj */,
437 $mem$$Register /* addr */,
438 $tmp1$$Register /* tmp */,
439 true /* narrow */,
440 true /* maybe_null */);
441 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
442 $mem$$Register /* addr */,
443 $tmp1$$Register /* tmp */);
444 %}
445 ins_pipe(pipe_slow);
446 %}
447
448 instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
449 match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
450 predicate(needs_acquiring_load_exclusive(n));
451 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
452 ins_cost(VOLATILE_REF_COST);
453 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
454 format %{
455 "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
456 %}
457 ins_encode %{
458 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
459 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
460 noreg /* obj */,
461 $oldval$$Register /* pre_val */);
462
463 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
464 $mem$$base$$Register,
465 $oldval$$Register,
466 $newval$$Register,
467 $res$$Register,
468 $tmp1$$Register,
469 $tmp2$$Register,
470 /*acquire*/ true,
471 /*release*/ true,
472 /*weak*/ false,
473 /*is_cae*/ true);
474
475 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
476 $res$$Register /* obj */,
477 $mem$$Register /* addr */,
478 $tmp1$$Register /* tmp */,
479 false /* narrow */,
480 true /* maybe_null */);
481 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
482 $mem$$Register /* addr */,
483 $tmp1$$Register /* tmp */);
484 %}
485 ins_pipe(pipe_slow);
486 %}
487
488 instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
489 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
490 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
491 ins_cost(2 * VOLATILE_REF_COST);
492 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
493 format %{
494 "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
495 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
496 %}
497 ins_encode %{
498 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
499 guarantee(UseCompressedOops, "must be compressed oops");
500 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
501 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
502 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
503 noreg /* obj */,
504 $tmp1$$Register /* pre_val */);
505 }
506
507 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
508 $mem$$base$$Register,
509 $oldval$$Register,
510 $newval$$Register,
511 $res$$Register,
512 $tmp1$$Register,
513 $tmp2$$Register,
514 /*acquire*/ false,
515 /*release*/ true,
516 /*weak*/ true,
517 /*is_cae*/ false);
518
519 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
520 $mem$$Register /* addr */,
521 $tmp1$$Register /* tmp */);
522 %}
523 ins_pipe(pipe_slow);
524 %}
525
526 instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegINoSp tmp1, iRegINoSp tmp2, rFlagsReg cr) %{
527 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
528 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
529 ins_cost(2 * VOLATILE_REF_COST);
530 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
531 format %{
532 "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
533 %}
534 ins_encode %{
535 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
536 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
537 noreg /* obj */,
538 $oldval$$Register /* pre_val */);
539
540 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
541 $mem$$base$$Register,
542 $oldval$$Register,
543 $newval$$Register,
544 $res$$Register,
545 $tmp1$$Register,
546 $tmp2$$Register,
547 /*acquire*/ false,
548 /*release*/ true,
549 /*weak*/ true,
550 /*is_cae*/ false);
551
552 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
553 $mem$$Register /* addr */,
554 $tmp1$$Register /* tmp */);
555 %}
556 ins_pipe(pipe_slow);
557 %}
558
559 instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
560 match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
561 predicate(needs_acquiring_load_exclusive(n));
562 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
563 ins_cost(VOLATILE_REF_COST);
564 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
565 format %{
566 "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
567 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
568 %}
569 ins_encode %{
570 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
571 guarantee(UseCompressedOops, "must be compressed oops");
572 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
573 __ decode_heap_oop($tmp1$$Register, $oldval$$Register);
574 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
575 noreg /* obj */,
576 $tmp1$$Register /* pre_val */);
577 }
578
579 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
580 $mem$$base$$Register,
581 $oldval$$Register,
582 $newval$$Register,
583 $res$$Register,
584 $tmp1$$Register,
585 $tmp2$$Register,
586 /*acquire*/ true,
587 /*release*/ true,
588 /*weak*/ true,
589 /*is_cae*/ false);
590
591 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
592 $mem$$Register /* addr */,
593 $tmp1$$Register /* tmp */);
594 %}
595 ins_pipe(pipe_slow);
596 %}
597
598 instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
599 match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
600 predicate(needs_acquiring_load_exclusive(n));
601 predicate(UseShenandoahGC && n->as_LoadStore()->barrier_data() != 0);
602 ins_cost(VOLATILE_REF_COST);
603 effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
604 format %{
605 "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
606 "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
607 %}
608 ins_encode %{
609 guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
610 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
611 noreg /* obj */,
612 $oldval$$Register /* pre_val */);
613
614 ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
615 $mem$$base$$Register,
616 $oldval$$Register,
617 $newval$$Register,
618 $res$$Register,
619 $tmp1$$Register,
620 $tmp2$$Register,
621 /*acquire*/ true,
622 /*release*/ true,
623 /*weak*/ true,
624 /*is_cae*/ false);
625
626 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
627 $mem$$Register /* addr */,
628 $tmp1$$Register /* tmp */);
629 %}
630 ins_pipe(pipe_slow);
631 %}
632
633 instruct getAndSetP_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
634 %{
635 match(Set preval (GetAndSetP mem newval));
636 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
637 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
638 ins_cost(2 * VOLATILE_REF_COST);
639 format %{ "atomic_xchg $preval, $newval, [$mem]" %}
640 ins_encode %{
641 assert_different_registers($mem$$Register, $newval$$Register);
642 __ atomic_xchg($preval$$Register, $newval$$Register, $mem$$Register);
643 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
644 noreg /* obj */,
645 $preval$$Register /* pre_val */);
646 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
647 $preval$$Register /* obj */,
648 $mem$$Register /* addr */,
649 $tmp$$Register /* tmp */,
650 false /* narrow */,
651 true /* maybe_null */);
652 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
653 $mem$$Register /* addr */,
654 $tmp$$Register /* tmp */);
655 %}
656 ins_pipe(pipe_serial);
657 %}
658
659 instruct getAndSetPAcq_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
660 %{
661 match(Set preval (GetAndSetP mem newval));
662 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
663 effect(TEMP_DEF preval, TEMP tmp, KILL cr);
664 ins_cost(VOLATILE_REF_COST);
665 format %{ "atomic_xchg_acq $preval, $newval, [$mem]" %}
666 ins_encode %{
667 assert_different_registers($mem$$Register, $newval$$Register);
668 __ atomic_xchgal($preval$$Register, $newval$$Register, $mem$$Register);
669 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
670 noreg /* obj */,
671 $preval$$Register /* pre_val */);
672 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
673 $preval$$Register /* obj */,
674 $mem$$Register /* addr */,
675 $tmp$$Register /* tmp */,
676 false /* narrow */,
677 true /* maybe_null */);
678 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
679 $mem$$Register /* addr */,
680 $tmp$$Register /* tmp */);
681 %}
682 ins_pipe(pipe_serial);
683 %}
684
685 instruct getAndSetN_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
686 %{
687 match(Set preval (GetAndSetN mem newval));
688 predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
689 effect(TEMP preval, TEMP tmp, KILL cr);
690 ins_cost(2 * VOLATILE_REF_COST);
691 format %{ "atomic_xchgw $preval, $newval, [$mem]" %}
692 ins_encode %{
693 assert_different_registers($mem$$Register, $newval$$Register);
694 __ atomic_xchgw($preval$$Register, $newval$$Register, $mem$$Register);
695 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
696 __ decode_heap_oop($tmp$$Register, $preval$$Register);
697 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
698 noreg /* obj */,
699 $tmp$$Register /* pre_val */);
700 }
701 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
702 $preval$$Register /* obj */,
703 $mem$$Register /* addr */,
704 $tmp$$Register /* tmp */,
705 true /* narrow */,
706 true /* maybe_null */);
707 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
708 $mem$$Register /* addr */,
709 $tmp$$Register /* tmp */);
710 %}
711 ins_pipe(pipe_serial);
712 %}
713
714 instruct getAndSetNAcq_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
715 %{
716 match(Set preval (GetAndSetN mem newval));
717 predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
718 effect(TEMP preval, TEMP tmp, KILL cr);
719 ins_cost(VOLATILE_REF_COST);
720 format %{ "atomic_xchgw_acq $preval, $newval, [$mem]" %}
721 ins_encode %{
722 assert_different_registers($mem$$Register, $newval$$Register);
723 __ atomic_xchgalw($preval$$Register, $newval$$Register, $mem$$Register);
724 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
725 __ decode_heap_oop($tmp$$Register, $preval$$Register);
726 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
727 noreg /* obj */,
728 $tmp$$Register /* pre_val */);
729 }
730 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
731 $preval$$Register /* obj */,
732 $mem$$Register /* addr */,
733 $tmp$$Register /* tmp */,
734 true /* narrow */,
735 true /* maybe_null */);
736 ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
737 $mem$$Register /* addr */,
738 $tmp$$Register /* tmp */);
739 %}
740 ins_pipe(pipe_serial);
741 %}
742
743 instruct loadP_shenandoah(iRegPNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
744 %{
745 // This instruction does not need an acquiring counterpart because it is only
746 // used for reference loading (Reference::get()).
747 match(Set dst (LoadP mem));
748 predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
749 effect(TEMP_DEF dst, TEMP tmp, KILL cr);
750 ins_cost(4 * INSN_COST);
751 format %{ "ldr $dst, $mem\t# ptr" %}
752 ins_encode %{
753 __ ldr($dst$$Register, $mem$$Register);
754 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
755 noreg /* obj */,
756 $dst$$Register /* pre_val */);
757
758 bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
759
760 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
761 $dst$$Register /* obj */,
762 $mem$$Register /* addr */,
763 $tmp$$Register /* tmp */,
764 false /* narrow */,
765 maybe_null);
766 %}
767 ins_pipe(iload_reg_mem);
768 %}
769
770 instruct loadP_volatile_shenandoah(iRegPNoSp dst, indirect mem, rFlagsReg cr)
771 %{
772 // This instruction does not need an acquiring counterpart because it is only
773 // used for reference loading (Reference::get()).
774 match(Set dst (LoadP mem));
775 predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
776 effect(TEMP dst, KILL cr);
777 ins_cost(4 * INSN_COST);
778 format %{ "ldar $dst, $mem\t# ptr" %}
779 ins_encode %{
780 __ ldar($dst$$Register, $mem$$Register);
781 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
782 noreg /* obj */,
783 $dst$$Register /* pre_val */);
784
785 bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
786 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
787 $dst$$Register /* obj */,
788 $mem$$Register /* addr */,
789 noreg /* noreg - not needed */,
790 false /* narrow */,
791 maybe_null);
792 %}
793 ins_pipe(iload_reg_mem);
794 %}
795
796 instruct loadN_decodeN_shenandoah(iRegPNoSp dst, indirect mem, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
797 match(Set dst (DecodeN (LoadN mem)));
798 predicate(UseShenandoahGC && !needs_acquiring_load(n->in(1)) && n->in(1)->as_Load()->barrier_data() != 0);
799 effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr);
800 ins_cost(INSN_COST * 2);
801 format %{ "ldrw $dst, $mem\t# decode(load(n))" %}
802 ins_encode %{
803 bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
804
805 // Loads compressed pointer
806 __ ldrw($dst$$Register, $mem$$Register);
807
808 // Eagerly decode since both barriers below would decode it anyway
809 __ decode_heap_oop($tmp2$$Register, $dst$$Register);
810
811 // Loads gc_state
812 Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
813 __ ldrb($tmp1$$Register, gc_state);
814
815 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
816 ShenandoahBarrierSet::assembler()->satb_barrier_c3(this, masm,
817 noreg /* obj */,
818 $tmp2$$Register /* pre_val */,
819 $tmp1$$Register /* gc_state */);
820 }
821
822 ShenandoahBarrierSet::assembler()->load_ref_barrier_c3(this, masm,
823 $dst$$Register /* obj */,
824 $mem$$Register /* addr */,
825 $tmp2$$Register /* tmp1 */,
826 true /* narrow */,
827 maybe_null,
828 $tmp1$$Register /* gc_state */);
829
830 __ decode_heap_oop($dst$$Register, $dst$$Register);
831 %}
832 ins_pipe(ialu_reg);
833 %}
834
835 instruct loadN_shenandoah(iRegNNoSp dst, indirect mem, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr) %{
836 match(Set dst (LoadN mem));
837 predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
838 effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr);
839 ins_cost(INSN_COST * 4);
840 format %{ "ldrw $dst, $mem\t# compressed ptr" %}
841 ins_encode %{
842 bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
843
844 // Loads compressed pointer
845 __ ldrw($dst$$Register, $mem$$Register);
846
847 // Eagerly decode since both barriers below would decode it anyway
848 __ decode_heap_oop($tmp1$$Register, $dst$$Register);
849
850 // Loads gc_state
851 Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
852 __ ldrb($tmp2$$Register, gc_state);
853
854 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
855 ShenandoahBarrierSet::assembler()->satb_barrier_c3(this, masm,
856 noreg /* obj */,
857 $tmp1$$Register /* pre_val */,
858 $tmp2$$Register /* gc_state */);
859 }
860
861 ShenandoahBarrierSet::assembler()->load_ref_barrier_c3(this, masm,
862 $dst$$Register /* obj */,
863 $mem$$Register /* addr */,
864 $tmp1$$Register /* tmp1 */,
865 true /* narrow */,
866 maybe_null,
867 $tmp2$$Register /* gc_state */);
868 %}
869 ins_pipe(ialu_reg);
870 %}
871
872 instruct loadN_volatile_shenandoah(iRegNNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr) %{
873 predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
874 match(Set dst (LoadN mem));
875 effect(TEMP_DEF dst, TEMP tmp, KILL cr);
876 ins_cost(INSN_COST * 3);
877 format %{ "ldarw $dst, $mem\t# ptr"
878 "decode_heap_oop $dst, $dst"
879 %}
880 ins_encode %{
881 __ ldarw($dst$$Register, $mem$$Register);
882 if (ShenandoahSATBBarrierStubC2::needs_barrier(this)) {
883 __ decode_heap_oop($tmp$$Register, $dst$$Register);
884 ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
885 noreg /* obj */,
886 $tmp$$Register /* pre_val */);
887 }
888
889 bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
890 ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
891 $dst$$Register /* obj */,
892 $mem$$Register /* addr */,
893 $tmp$$Register /* tmp */,
894 true /* narrow */,
895 maybe_null);
896 %}
897 ins_pipe(ialu_reg);
898 %}