1 //
  2 // Copyright (c) 2024, Oracle and/or its affiliates. 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 source_hpp %{
 25 
 26 #include "gc/g1/c2/g1BarrierSetC2.hpp"
 27 #include "gc/shared/gc_globals.hpp"
 28 
 29 %}
 30 
 31 source %{
 32 
 33 #include "gc/g1/g1BarrierSetAssembler_aarch64.hpp"
 34 #include "gc/g1/g1BarrierSetRuntime.hpp"
 35 
 36 static void write_barrier_pre(MacroAssembler* masm,
 37                               const MachNode* node,
 38                               Register obj,
 39                               Register pre_val,
 40                               Register tmp1,
 41                               Register tmp2,
 42                               RegSet preserve = RegSet(),
 43                               RegSet no_preserve = RegSet()) {
 44   if (!G1PreBarrierStubC2::needs_barrier(node)) {
 45     return;
 46   }
 47   Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
 48   G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
 49   G1PreBarrierStubC2* const stub = G1PreBarrierStubC2::create(node);
 50   for (RegSetIterator<Register> reg = preserve.begin(); *reg != noreg; ++reg) {
 51     stub->preserve(*reg);
 52   }
 53   for (RegSetIterator<Register> reg = no_preserve.begin(); *reg != noreg; ++reg) {
 54     stub->dont_preserve(*reg);
 55   }
 56   g1_asm->g1_write_barrier_pre_c2(masm, obj, pre_val, rthread, tmp1, tmp2, stub);
 57 }
 58 
 59 static void write_barrier_post(MacroAssembler* masm,
 60                                const MachNode* node,
 61                                Register store_addr,
 62                                Register new_val,
 63                                Register tmp1,
 64                                Register tmp2,
 65                                RegSet preserve = RegSet()) {
 66   if (!G1PostBarrierStubC2::needs_barrier(node)) {
 67     return;
 68   }
 69   Assembler::InlineSkippedInstructionsCounter skip_counter(masm);
 70   G1BarrierSetAssembler* g1_asm = static_cast<G1BarrierSetAssembler*>(BarrierSet::barrier_set()->barrier_set_assembler());
 71   G1PostBarrierStubC2* const stub = G1PostBarrierStubC2::create(node);
 72   for (RegSetIterator<Register> reg = preserve.begin(); *reg != noreg; ++reg) {
 73     stub->preserve(*reg);
 74   }
 75   g1_asm->g1_write_barrier_post_c2(masm, store_addr, new_val, rthread, tmp1, tmp2, stub);
 76 }
 77 
 78 %}
 79 
 80 // TODO 8350865 (same applies to g1StoreLSpecialTwoOops)
 81 // - Can we use an unbound register for src?
 82 // - Do no set/overwrite barrier data here, also handle G1C2BarrierPostNotNull
 83 // - Is the zero-extend really required in all the places?
 84 // - Move this into the .m4?
 85 instruct g1StoreLSpecialOneOop(indirect mem, iRegL_R11 src, immI off, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr)
 86 %{
 87   predicate(UseG1GC);
 88   match(Set mem (StoreLSpecial mem (Binary src off)));
 89   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, KILL cr);
 90   ins_cost(INSN_COST);
 91   format %{ "str  $src, $mem\t# g1StoreLSpecialOneOop" %}
 92   ins_encode %{
 93     ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost);
 94 
 95     // Adjust address to point to narrow oop
 96     __ add($tmp4$$Register, $mem$$Register, $off$$constant);
 97     write_barrier_pre(masm, this,
 98                       $tmp4$$Register /* obj */,
 99                       $tmp1$$Register /* pre_val */,
100                       $tmp2$$Register /* tmp1 */,
101                       $tmp3$$Register /* tmp2 */,
102                       RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */);
103 
104     __ str($src$$Register, $mem$$Register);
105 
106     // Shift long value to extract the narrow oop field value and zero-extend it
107     __ lsr($src$$Register, $src$$Register, $off$$constant << LogBitsPerByte);
108     __ ubfm($src$$Register, $src$$Register, 0, 31);
109 
110     write_barrier_post(masm, this,
111                        $tmp4$$Register /* store_addr */,
112                        $src$$Register /* new_val */,
113                        $tmp2$$Register /* tmp1 */,
114                        $tmp3$$Register /* tmp2 */);
115   %}
116   ins_pipe(istore_reg_mem);
117 %}
118 
119 instruct g1StoreLSpecialTwoOops(indirect mem, iRegL_R11 src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegPNoSp tmp4, rFlagsReg cr)
120 %{
121   predicate(UseG1GC);
122   match(Set mem (StoreLSpecial mem src));
123   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, KILL cr);
124   ins_cost(INSN_COST);
125   format %{ "str  $src, $mem\t# g1StoreLSpecialTwoOops" %}
126   ins_encode %{
127     ((MachNode*)this)->set_barrier_data(G1C2BarrierPre | G1C2BarrierPost);
128 
129     write_barrier_pre(masm, this,
130                       $mem$$Register /* obj */,
131                       $tmp1$$Register /* pre_val */,
132                       $tmp2$$Register /* tmp1 */,
133                       $tmp3$$Register /* tmp2 */,
134                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
135     // Adjust address to point to the second narrow oop in the long value
136     __ add($tmp4$$Register, $mem$$Register, 4);
137     write_barrier_pre(masm, this,
138                       $tmp4$$Register /* obj */,
139                       $tmp1$$Register /* pre_val */,
140                       $tmp2$$Register /* tmp1 */,
141                       $tmp3$$Register /* tmp2 */,
142                       RegSet::of($mem$$Register, $src$$Register, $tmp4$$Register) /* preserve */);
143 
144     __ str($src$$Register, $mem$$Register);
145 
146     // Zero-extend first narrow oop to long
147     __ ubfm($tmp1$$Register, $src$$Register, 0, 31);
148 
149     // Shift long value to extract the second narrow oop field value
150     __ lsr($src$$Register, $src$$Register, 32);
151     write_barrier_post(masm, this,
152                        $mem$$Register /* store_addr */,
153                        $tmp1$$Register /* new_val */,
154                        $tmp2$$Register /* tmp1 */,
155                        $tmp3$$Register /* tmp2 */,
156                        RegSet::of($src$$Register, $tmp4$$Register) /* preserve */);
157     write_barrier_post(masm, this,
158                        $tmp4$$Register /* store_addr */,
159                        $src$$Register /* new_val */,
160                        $tmp2$$Register /* tmp1 */,
161                        $tmp3$$Register /* tmp2 */);
162   %}
163   ins_pipe(istore_reg_mem);
164 %}
165 
166 
167 // BEGIN This section of the file is automatically generated. Do not edit --------------
168 
169 // This section is generated from g1_aarch64.m4
170 
171 
172 // This pattern is generated automatically from g1_aarch64.m4.
173 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
174 instruct g1StoreP(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
175 %{
176   predicate(UseG1GC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
177   match(Set mem (StoreP mem src));
178   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
179   ins_cost(INSN_COST);
180   format %{ "str  $src, $mem\t# ptr" %}
181   ins_encode %{
182     write_barrier_pre(masm, this,
183                       $mem$$Register /* obj */,
184                       $tmp1$$Register /* pre_val */,
185                       $tmp2$$Register /* tmp1 */,
186                       $tmp3$$Register /* tmp2 */,
187                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
188     __ str($src$$Register, $mem$$Register);
189     write_barrier_post(masm, this,
190                        $mem$$Register /* store_addr */,
191                        $src$$Register /* new_val */,
192                        $tmp2$$Register /* tmp1 */,
193                        $tmp3$$Register /* tmp2 */);
194   %}
195   ins_pipe(istore_reg_mem);
196 %}
197 
198 // This pattern is generated automatically from g1_aarch64.m4.
199 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
200 instruct g1StorePVolatile(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
201 %{
202   predicate(UseG1GC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
203   match(Set mem (StoreP mem src));
204   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
205   ins_cost(VOLATILE_REF_COST);
206   format %{ "stlr  $src, $mem\t# ptr" %}
207   ins_encode %{
208     write_barrier_pre(masm, this,
209                       $mem$$Register /* obj */,
210                       $tmp1$$Register /* pre_val */,
211                       $tmp2$$Register /* tmp1 */,
212                       $tmp3$$Register /* tmp2 */,
213                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
214     __ stlr($src$$Register, $mem$$Register);
215     write_barrier_post(masm, this,
216                        $mem$$Register /* store_addr */,
217                        $src$$Register /* new_val */,
218                        $tmp2$$Register /* tmp1 */,
219                        $tmp3$$Register /* tmp2 */);
220   %}
221   ins_pipe(pipe_class_memory);
222 %}
223 
224 // This pattern is generated automatically from g1_aarch64.m4.
225 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
226 instruct g1StoreN(indirect mem, iRegN src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
227 %{
228   predicate(UseG1GC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
229   match(Set mem (StoreN mem src));
230   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
231   ins_cost(INSN_COST);
232   format %{ "strw  $src, $mem\t# compressed ptr" %}
233   ins_encode %{
234     write_barrier_pre(masm, this,
235                       $mem$$Register /* obj */,
236                       $tmp1$$Register /* pre_val */,
237                       $tmp2$$Register /* tmp1 */,
238                       $tmp3$$Register /* tmp2 */,
239                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
240     __ strw($src$$Register, $mem$$Register);
241     if ((barrier_data() & G1C2BarrierPost) != 0) {
242       if ((barrier_data() & G1C2BarrierPostNotNull) == 0) {
243         __ decode_heap_oop($tmp1$$Register, $src$$Register);
244       } else {
245         __ decode_heap_oop_not_null($tmp1$$Register, $src$$Register);
246       }
247     }
248     write_barrier_post(masm, this,
249                        $mem$$Register /* store_addr */,
250                        $tmp1$$Register /* new_val */,
251                        $tmp2$$Register /* tmp1 */,
252                        $tmp3$$Register /* tmp2 */);
253   %}
254   ins_pipe(istore_reg_mem);
255 %}
256 
257 // This pattern is generated automatically from g1_aarch64.m4.
258 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
259 instruct g1StoreNVolatile(indirect mem, iRegN src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
260 %{
261   predicate(UseG1GC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
262   match(Set mem (StoreN mem src));
263   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
264   ins_cost(VOLATILE_REF_COST);
265   format %{ "stlrw  $src, $mem\t# compressed ptr" %}
266   ins_encode %{
267     write_barrier_pre(masm, this,
268                       $mem$$Register /* obj */,
269                       $tmp1$$Register /* pre_val */,
270                       $tmp2$$Register /* tmp1 */,
271                       $tmp3$$Register /* tmp2 */,
272                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
273     __ stlrw($src$$Register, $mem$$Register);
274     if ((barrier_data() & G1C2BarrierPost) != 0) {
275       if ((barrier_data() & G1C2BarrierPostNotNull) == 0) {
276         __ decode_heap_oop($tmp1$$Register, $src$$Register);
277       } else {
278         __ decode_heap_oop_not_null($tmp1$$Register, $src$$Register);
279       }
280     }
281     write_barrier_post(masm, this,
282                        $mem$$Register /* store_addr */,
283                        $tmp1$$Register /* new_val */,
284                        $tmp2$$Register /* tmp1 */,
285                        $tmp3$$Register /* tmp2 */);
286   %}
287   ins_pipe(pipe_class_memory);
288 %}
289 
290 // This pattern is generated automatically from g1_aarch64.m4.
291 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
292 instruct g1EncodePAndStoreN(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
293 %{
294   predicate(UseG1GC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
295   match(Set mem (StoreN mem (EncodeP src)));
296   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
297   ins_cost(INSN_COST);
298   format %{ "encode_heap_oop $tmp1, $src\n\t"
299             "strw  $tmp1, $mem\t# compressed ptr" %}
300   ins_encode %{
301     write_barrier_pre(masm, this,
302                       $mem$$Register /* obj */,
303                       $tmp1$$Register /* pre_val */,
304                       $tmp2$$Register /* tmp1 */,
305                       $tmp3$$Register /* tmp2 */,
306                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
307     if ((barrier_data() & G1C2BarrierPostNotNull) == 0) {
308       __ encode_heap_oop($tmp1$$Register, $src$$Register);
309     } else {
310       __ encode_heap_oop_not_null($tmp1$$Register, $src$$Register);
311     }
312     __ strw($tmp1$$Register, $mem$$Register);
313     write_barrier_post(masm, this,
314                        $mem$$Register /* store_addr */,
315                        $src$$Register /* new_val */,
316                        $tmp2$$Register /* tmp1 */,
317                        $tmp3$$Register /* tmp2 */);
318   %}
319   ins_pipe(istore_reg_mem);
320 %}
321 
322 // This pattern is generated automatically from g1_aarch64.m4.
323 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
324 instruct g1EncodePAndStoreNVolatile(indirect mem, iRegP src, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
325 %{
326   predicate(UseG1GC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
327   match(Set mem (StoreN mem (EncodeP src)));
328   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
329   ins_cost(VOLATILE_REF_COST);
330   format %{ "encode_heap_oop $tmp1, $src\n\t"
331             "stlrw  $tmp1, $mem\t# compressed ptr" %}
332   ins_encode %{
333     write_barrier_pre(masm, this,
334                       $mem$$Register /* obj */,
335                       $tmp1$$Register /* pre_val */,
336                       $tmp2$$Register /* tmp1 */,
337                       $tmp3$$Register /* tmp2 */,
338                       RegSet::of($mem$$Register, $src$$Register) /* preserve */);
339     if ((barrier_data() & G1C2BarrierPostNotNull) == 0) {
340       __ encode_heap_oop($tmp1$$Register, $src$$Register);
341     } else {
342       __ encode_heap_oop_not_null($tmp1$$Register, $src$$Register);
343     }
344     __ stlrw($tmp1$$Register, $mem$$Register);
345     write_barrier_post(masm, this,
346                        $mem$$Register /* store_addr */,
347                        $src$$Register /* new_val */,
348                        $tmp2$$Register /* tmp1 */,
349                        $tmp3$$Register /* tmp2 */);
350   %}
351   ins_pipe(pipe_class_memory);
352 %}
353 
354 // This pattern is generated automatically from g1_aarch64.m4.
355 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
356 instruct g1CompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
357 %{
358   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
359   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
360   effect(TEMP res, TEMP tmp1, TEMP tmp2, KILL cr);
361   ins_cost(2 * VOLATILE_REF_COST);
362   format %{ "cmpxchg $res = $mem, $oldval, $newval\t# ptr" %}
363   ins_encode %{
364     assert_different_registers($oldval$$Register, $mem$$Register);
365     assert_different_registers($newval$$Register, $mem$$Register);
366     // Pass $oldval to the pre-barrier (instead of loading from $mem), because
367     // $oldval is the only value that can be overwritten.
368     // The same holds for g1CompareAndSwapP and its Acq variant.
369     write_barrier_pre(masm, this,
370                       noreg /* obj */,
371                       $oldval$$Register /* pre_val */,
372                       $tmp1$$Register /* tmp1 */,
373                       $tmp2$$Register /* tmp2 */,
374                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
375                       RegSet::of($res$$Register) /* no_preserve */);
376     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
377                false /* acquire */, true /* release */, false /* weak */, $res$$Register);
378     write_barrier_post(masm, this,
379                        $mem$$Register /* store_addr */,
380                        $newval$$Register /* new_val */,
381                        $tmp1$$Register /* tmp1 */,
382                        $tmp2$$Register /* tmp2 */);
383   %}
384   ins_pipe(pipe_slow);
385 %}
386 
387 // This pattern is generated automatically from g1_aarch64.m4.
388 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
389 instruct g1CompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
390 %{
391   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
392   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
393   effect(TEMP res, TEMP tmp1, TEMP tmp2, KILL cr);
394   ins_cost(VOLATILE_REF_COST);
395   format %{ "cmpxchg_acq $res = $mem, $oldval, $newval\t# ptr" %}
396   ins_encode %{
397     assert_different_registers($oldval$$Register, $mem$$Register);
398     assert_different_registers($newval$$Register, $mem$$Register);
399     // Pass $oldval to the pre-barrier (instead of loading from $mem), because
400     // $oldval is the only value that can be overwritten.
401     // The same holds for g1CompareAndSwapP and its Acq variant.
402     write_barrier_pre(masm, this,
403                       noreg /* obj */,
404                       $oldval$$Register /* pre_val */,
405                       $tmp1$$Register /* tmp1 */,
406                       $tmp2$$Register /* tmp2 */,
407                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
408                       RegSet::of($res$$Register) /* no_preserve */);
409     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
410                true /* acquire */, true /* release */, false /* weak */, $res$$Register);
411     write_barrier_post(masm, this,
412                        $mem$$Register /* store_addr */,
413                        $newval$$Register /* new_val */,
414                        $tmp1$$Register /* tmp1 */,
415                        $tmp2$$Register /* tmp2 */);
416   %}
417   ins_pipe(pipe_slow);
418 %}
419 
420 // This pattern is generated automatically from g1_aarch64.m4.
421 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
422 instruct g1CompareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
423 %{
424   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
425   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
426   effect(TEMP res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
427   ins_cost(2 * VOLATILE_REF_COST);
428   format %{ "cmpxchg $res = $mem, $oldval, $newval\t# narrow oop" %}
429   ins_encode %{
430     assert_different_registers($oldval$$Register, $mem$$Register);
431     assert_different_registers($newval$$Register, $mem$$Register);
432     write_barrier_pre(masm, this,
433                       $mem$$Register /* obj */,
434                       $tmp1$$Register /* pre_val */,
435                       $tmp2$$Register /* tmp1 */,
436                       $tmp3$$Register /* tmp2 */,
437                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
438                       RegSet::of($res$$Register) /* no_preserve */);
439     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
440                false /* acquire */, true /* release */, false /* weak */, $res$$Register);
441     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
442     write_barrier_post(masm, this,
443                        $mem$$Register /* store_addr */,
444                        $tmp1$$Register /* new_val */,
445                        $tmp2$$Register /* tmp1 */,
446                        $tmp3$$Register /* tmp2 */);
447   %}
448   ins_pipe(pipe_slow);
449 %}
450 
451 // This pattern is generated automatically from g1_aarch64.m4.
452 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
453 instruct g1CompareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
454 %{
455   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
456   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
457   effect(TEMP res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
458   ins_cost(VOLATILE_REF_COST);
459   format %{ "cmpxchg_acq $res = $mem, $oldval, $newval\t# narrow oop" %}
460   ins_encode %{
461     assert_different_registers($oldval$$Register, $mem$$Register);
462     assert_different_registers($newval$$Register, $mem$$Register);
463     write_barrier_pre(masm, this,
464                       $mem$$Register /* obj */,
465                       $tmp1$$Register /* pre_val */,
466                       $tmp2$$Register /* tmp1 */,
467                       $tmp3$$Register /* tmp2 */,
468                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
469                       RegSet::of($res$$Register) /* no_preserve */);
470     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
471                true /* acquire */, true /* release */, false /* weak */, $res$$Register);
472     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
473     write_barrier_post(masm, this,
474                        $mem$$Register /* store_addr */,
475                        $tmp1$$Register /* new_val */,
476                        $tmp2$$Register /* tmp1 */,
477                        $tmp3$$Register /* tmp2 */);
478   %}
479   ins_pipe(pipe_slow);
480 %}
481 
482 // This pattern is generated automatically from g1_aarch64.m4.
483 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
484 instruct g1CompareAndSwapP(iRegINoSp res, indirect mem, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegP oldval, rFlagsReg cr)
485 %{
486   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
487   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
488   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
489   effect(TEMP res, TEMP tmp1, TEMP tmp2, KILL cr);
490   ins_cost(2 * VOLATILE_REF_COST);
491   format %{ "cmpxchg $mem, $oldval, $newval\t# (ptr)\n\t"
492             "cset $res, EQ" %}
493   ins_encode %{
494     assert_different_registers($oldval$$Register, $mem$$Register);
495     assert_different_registers($newval$$Register, $mem$$Register);
496     write_barrier_pre(masm, this,
497                       noreg /* obj */,
498                       $oldval$$Register /* pre_val */,
499                       $tmp1$$Register /* tmp1 */,
500                       $tmp2$$Register /* tmp2 */,
501                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
502                       RegSet::of($res$$Register) /* no_preserve */);
503     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
504                false /* acquire */, true /* release */, false /* weak */, noreg);
505     __ cset($res$$Register, Assembler::EQ);
506     write_barrier_post(masm, this,
507                        $mem$$Register /* store_addr */,
508                        $newval$$Register /* new_val */,
509                        $tmp1$$Register /* tmp1 */,
510                        $tmp2$$Register /* tmp2 */);
511   %}
512   ins_pipe(pipe_slow);
513 %}
514 
515 // This pattern is generated automatically from g1_aarch64.m4.
516 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
517 instruct g1CompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegP oldval, rFlagsReg cr)
518 %{
519   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
520   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
521   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
522   effect(TEMP res, TEMP tmp1, TEMP tmp2, KILL cr);
523   ins_cost(VOLATILE_REF_COST);
524   format %{ "cmpxchg_acq $mem, $oldval, $newval\t# (ptr)\n\t"
525             "cset $res, EQ" %}
526   ins_encode %{
527     assert_different_registers($oldval$$Register, $mem$$Register);
528     assert_different_registers($newval$$Register, $mem$$Register);
529     write_barrier_pre(masm, this,
530                       noreg /* obj */,
531                       $oldval$$Register /* pre_val */,
532                       $tmp1$$Register /* tmp1 */,
533                       $tmp2$$Register /* tmp2 */,
534                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
535                       RegSet::of($res$$Register) /* no_preserve */);
536     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
537                true /* acquire */, true /* release */, false /* weak */, noreg);
538     __ cset($res$$Register, Assembler::EQ);
539     write_barrier_post(masm, this,
540                        $mem$$Register /* store_addr */,
541                        $newval$$Register /* new_val */,
542                        $tmp1$$Register /* tmp1 */,
543                        $tmp2$$Register /* tmp2 */);
544   %}
545   ins_pipe(pipe_slow);
546 %}
547 
548 // This pattern is generated automatically from g1_aarch64.m4.
549 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
550 instruct g1CompareAndSwapN(iRegINoSp res, indirect mem, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegN oldval, rFlagsReg cr)
551 %{
552   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
553   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
554   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
555   effect(TEMP res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
556   ins_cost(2 * VOLATILE_REF_COST);
557   format %{ "cmpxchg $mem, $oldval, $newval\t# (narrow oop)\n\t"
558             "cset $res, EQ" %}
559   ins_encode %{
560     assert_different_registers($oldval$$Register, $mem$$Register);
561     assert_different_registers($newval$$Register, $mem$$Register);
562     write_barrier_pre(masm, this,
563                       $mem$$Register /* obj */,
564                       $tmp1$$Register /* pre_val */,
565                       $tmp2$$Register /* tmp1 */,
566                       $tmp3$$Register /* tmp2 */,
567                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
568                       RegSet::of($res$$Register) /* no_preserve */);
569     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
570                false /* acquire */, true /* release */, false /* weak */, noreg);
571     __ cset($res$$Register, Assembler::EQ);
572     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
573     write_barrier_post(masm, this,
574                        $mem$$Register /* store_addr */,
575                        $tmp1$$Register /* new_val */,
576                        $tmp2$$Register /* tmp1 */,
577                        $tmp3$$Register /* tmp2 */);
578   %}
579   ins_pipe(pipe_slow);
580 %}
581 
582 // This pattern is generated automatically from g1_aarch64.m4.
583 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
584 instruct g1CompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegN oldval, rFlagsReg cr)
585 %{
586   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
587   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
588   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
589   effect(TEMP res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
590   ins_cost(VOLATILE_REF_COST);
591   format %{ "cmpxchg_acq $mem, $oldval, $newval\t# (narrow oop)\n\t"
592             "cset $res, EQ" %}
593   ins_encode %{
594     assert_different_registers($oldval$$Register, $mem$$Register);
595     assert_different_registers($newval$$Register, $mem$$Register);
596     write_barrier_pre(masm, this,
597                       $mem$$Register /* obj */,
598                       $tmp1$$Register /* pre_val */,
599                       $tmp2$$Register /* tmp1 */,
600                       $tmp3$$Register /* tmp2 */,
601                       RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
602                       RegSet::of($res$$Register) /* no_preserve */);
603     __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
604                true /* acquire */, true /* release */, false /* weak */, noreg);
605     __ cset($res$$Register, Assembler::EQ);
606     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
607     write_barrier_post(masm, this,
608                        $mem$$Register /* store_addr */,
609                        $tmp1$$Register /* new_val */,
610                        $tmp2$$Register /* tmp1 */,
611                        $tmp3$$Register /* tmp2 */);
612   %}
613   ins_pipe(pipe_slow);
614 %}
615 
616 // This pattern is generated automatically from g1_aarch64.m4.
617 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
618 instruct g1GetAndSetP(indirect mem, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp preval, rFlagsReg cr)
619 %{
620   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
621   match(Set preval (GetAndSetP mem newval));
622   effect(TEMP preval, TEMP tmp1, TEMP tmp2, KILL cr);
623   ins_cost(2 * VOLATILE_REF_COST);
624   format %{ "atomic_xchg  $preval, $newval, [$mem]" %}
625   ins_encode %{
626     assert_different_registers($mem$$Register, $newval$$Register);
627     write_barrier_pre(masm, this,
628                       $mem$$Register /* obj */,
629                       $preval$$Register /* pre_val (as a temporary register) */,
630                       $tmp1$$Register /* tmp1 */,
631                       $tmp2$$Register /* tmp2 */,
632                       RegSet::of($mem$$Register, $preval$$Register, $newval$$Register) /* preserve */);
633     __ atomic_xchg($preval$$Register, $newval$$Register, $mem$$Register);
634     write_barrier_post(masm, this,
635                        $mem$$Register /* store_addr */,
636                        $newval$$Register /* new_val */,
637                        $tmp1$$Register /* tmp1 */,
638                        $tmp2$$Register /* tmp2 */);
639   %}
640   ins_pipe(pipe_serial);
641 %}
642 
643 // This pattern is generated automatically from g1_aarch64.m4.
644 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
645 instruct g1GetAndSetPAcq(indirect mem, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp preval, rFlagsReg cr)
646 %{
647   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
648   match(Set preval (GetAndSetP mem newval));
649   effect(TEMP preval, TEMP tmp1, TEMP tmp2, KILL cr);
650   ins_cost(VOLATILE_REF_COST);
651   format %{ "atomic_xchg_acq  $preval, $newval, [$mem]" %}
652   ins_encode %{
653     assert_different_registers($mem$$Register, $newval$$Register);
654     write_barrier_pre(masm, this,
655                       $mem$$Register /* obj */,
656                       $preval$$Register /* pre_val (as a temporary register) */,
657                       $tmp1$$Register /* tmp1 */,
658                       $tmp2$$Register /* tmp2 */,
659                       RegSet::of($mem$$Register, $preval$$Register, $newval$$Register) /* preserve */);
660     __ atomic_xchgal($preval$$Register, $newval$$Register, $mem$$Register);
661     write_barrier_post(masm, this,
662                        $mem$$Register /* store_addr */,
663                        $newval$$Register /* new_val */,
664                        $tmp1$$Register /* tmp1 */,
665                        $tmp2$$Register /* tmp2 */);
666   %}
667   ins_pipe(pipe_serial);
668 %}
669 
670 // This pattern is generated automatically from g1_aarch64.m4.
671 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
672 instruct g1GetAndSetN(indirect mem, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegNNoSp preval, rFlagsReg cr)
673 %{
674   predicate(UseG1GC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
675   match(Set preval (GetAndSetN mem newval));
676   effect(TEMP preval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
677   ins_cost(2 * VOLATILE_REF_COST);
678   format %{ "atomic_xchgw $preval, $newval, [$mem]" %}
679   ins_encode %{
680     assert_different_registers($mem$$Register, $newval$$Register);
681     write_barrier_pre(masm, this,
682                       $mem$$Register /* obj */,
683                       $tmp1$$Register /* pre_val */,
684                       $tmp2$$Register /* tmp1 */,
685                       $tmp3$$Register /* tmp2 */,
686                       RegSet::of($mem$$Register, $preval$$Register, $newval$$Register) /* preserve */);
687     __ atomic_xchgw($preval$$Register, $newval$$Register, $mem$$Register);
688     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
689     write_barrier_post(masm, this,
690                        $mem$$Register /* store_addr */,
691                        $tmp1$$Register /* new_val */,
692                        $tmp2$$Register /* tmp1 */,
693                        $tmp3$$Register /* tmp2 */);
694   %}
695   ins_pipe(pipe_serial);
696 %}
697 
698 // This pattern is generated automatically from g1_aarch64.m4.
699 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
700 instruct g1GetAndSetNAcq(indirect mem, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, iRegNNoSp preval, rFlagsReg cr)
701 %{
702   predicate(UseG1GC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
703   match(Set preval (GetAndSetN mem newval));
704   effect(TEMP preval, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
705   ins_cost(VOLATILE_REF_COST);
706   format %{ "atomic_xchgw_acq $preval, $newval, [$mem]" %}
707   ins_encode %{
708     assert_different_registers($mem$$Register, $newval$$Register);
709     write_barrier_pre(masm, this,
710                       $mem$$Register /* obj */,
711                       $tmp1$$Register /* pre_val */,
712                       $tmp2$$Register /* tmp1 */,
713                       $tmp3$$Register /* tmp2 */,
714                       RegSet::of($mem$$Register, $preval$$Register, $newval$$Register) /* preserve */);
715     __ atomic_xchgalw($preval$$Register, $newval$$Register, $mem$$Register);
716     __ decode_heap_oop($tmp1$$Register, $newval$$Register);
717     write_barrier_post(masm, this,
718                        $mem$$Register /* store_addr */,
719                        $tmp1$$Register /* new_val */,
720                        $tmp2$$Register /* tmp1 */,
721                        $tmp3$$Register /* tmp2 */);
722   %}
723   ins_pipe(pipe_serial);
724 %}
725 
726 // This pattern is generated automatically from g1_aarch64.m4.
727 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
728 instruct g1LoadP(iRegPNoSp dst, indirect mem, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
729 %{
730   // This instruction does not need an acquiring counterpart because it is only
731   // used for reference loading (Reference::get()). The same holds for g1LoadN.
732   predicate(UseG1GC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
733   match(Set dst (LoadP mem));
734   effect(TEMP dst, TEMP tmp1, TEMP tmp2, KILL cr);
735   ins_cost(4 * INSN_COST);
736   format %{ "ldr  $dst, $mem\t# ptr" %}
737   ins_encode %{
738     __ ldr($dst$$Register, $mem$$Register);
739     write_barrier_pre(masm, this,
740                       noreg /* obj */,
741                       $dst$$Register /* pre_val */,
742                       $tmp1$$Register /* tmp1 */,
743                       $tmp2$$Register /* tmp2 */);
744   %}
745   ins_pipe(iload_reg_mem);
746 %}
747 
748 // This pattern is generated automatically from g1_aarch64.m4.
749 // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
750 instruct g1LoadN(iRegNNoSp dst, indirect mem, iRegPNoSp tmp1, iRegPNoSp tmp2, iRegPNoSp tmp3, rFlagsReg cr)
751 %{
752   predicate(UseG1GC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
753   match(Set dst (LoadN mem));
754   effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
755   ins_cost(4 * INSN_COST);
756   format %{ "ldrw  $dst, $mem\t# compressed ptr" %}
757   ins_encode %{
758     __ ldrw($dst$$Register, $mem$$Register);
759     if ((barrier_data() & G1C2BarrierPre) != 0) {
760       __ decode_heap_oop($tmp1$$Register, $dst$$Register);
761       write_barrier_pre(masm, this,
762                         noreg /* obj */,
763                         $tmp1$$Register /* pre_val */,
764                         $tmp2$$Register /* tmp1 */,
765                         $tmp3$$Register /* tmp2 */);
766     }
767   %}
768   ins_pipe(iload_reg_mem);
769 %}
770 
771 // END This section of the file is automatically generated. Do not edit --------------