< prev index next >

src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad

Print this page
@@ -20,240 +20,1042 @@
  // or visit www.oracle.com if you need additional information or have any
  // questions.
  //
  //
  
- source_hpp %{
+ source %{
  #include "gc/shenandoah/shenandoahBarrierSet.hpp"
- #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
+ #include "gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp"
+ #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  %}
  
- encode %{
-   enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
-     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
-   %}
  
-   enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
-     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
+ // BEGIN This section of the file is automatically generated from shenandoah_aarch64.m4.
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct store_P_Normal_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreP mem src));
+   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
+   effect(TEMP tmp, KILL cr);
+   ins_cost(3*INSN_COST);
+   format %{ "str  $src, $mem" %}
+   ins_encode %{
+     bool is_narrow = false;
+     bool is_volatile = false;
+ 
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ is_narrow,
+       $src$$Register, /* src_narrow  = */ is_narrow,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
    %}
+   ins_pipe(pipe_class_memory);
  %}
  
- instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct store_P_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreP mem src));
+   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
+   effect(TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST);
+   format %{ "str  $src, $mem" %}
+   ins_encode %{
+     bool is_narrow = false;
+     bool is_volatile = true;
  
-   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ is_narrow,
+       $src$$Register, /* src_narrow  = */ is_narrow,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
+   %}
+   ins_pipe(pipe_class_memory);
+ %}
  
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct store_N_Normal_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreN mem src));
+   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
    effect(TEMP tmp, KILL cr);
+   ins_cost(3*INSN_COST);
+   format %{ "str  $src, $mem" %}
+   ins_encode %{
+     bool is_narrow = true;
+     bool is_volatile = false;
  
-   format %{
-     "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ is_narrow,
+       $src$$Register, /* src_narrow  = */ is_narrow,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
    %}
+   ins_pipe(pipe_class_memory);
+ %}
  
-   ins_encode(aarch64_enc_cmpxchg_oop_shenandoah(mem, oldval, newval, tmp, res));
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct store_N_Volatile_shenandoah(indirect mem, iRegN src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreN mem src));
+   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
+   effect(TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST);
+   format %{ "str  $src, $mem" %}
+   ins_encode %{
+     bool is_narrow = true;
+     bool is_volatile = true;
  
-   ins_pipe(pipe_slow);
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ is_narrow,
+       $src$$Register, /* src_narrow  = */ is_narrow,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
+   %}
+   ins_pipe(pipe_class_memory);
  %}
  
- instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
  
-   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
  
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct encodePAndStoreN_Normal_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreN mem (EncodeP src)));
+   predicate(UseShenandoahGC && !needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
    effect(TEMP tmp, KILL cr);
+   ins_cost(4*INSN_COST);
+   format %{ "encode_heap_oop $tmp, $src\n\t"
+             "str  $tmp, $mem\t# compressed ptr" %}
+   ins_encode %{
+     bool is_volatile = false;
  
-   format %{
-     "cmpxchgw_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ true,
+       $src$$Register, /* src_narrow  = */ false,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
    %}
+   ins_pipe(pipe_class_memory);
+ %}
  
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct encodePAndStoreN_Volatile_shenandoah(indirect mem, iRegP src, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set mem (StoreN mem (EncodeP src)));
+   predicate(UseShenandoahGC && needs_releasing_store(n) && n->as_Store()->barrier_data() != 0);
+   effect(TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST);
+   format %{ "encode_heap_oop $tmp, $src\n\t"
+             "str  $tmp, $mem\t# compressed ptr" %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
-   %}
+     bool is_volatile = true;
  
-   ins_pipe(pipe_slow);
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $mem$$Register, /* dst_narrow  = */ true,
+       $src$$Register, /* src_narrow  = */ false,
+       $tmp$$Register, /* pre_val     = */ noreg,
+                       /* is_volatile = */ is_volatile);
+   %}
+   ins_pipe(pipe_class_memory);
  %}
  
- instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
  
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndSwap_P_Normal_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
    ins_cost(VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+   format %{
+     "cmpxchg_P_Normal_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
+   %}
+   ins_encode %{
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
  
-   effect(TEMP tmp, KILL cr);
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val, only used in slow path */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,    /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
+   %}
  
+   ins_pipe(pipe_slow);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndSwap_N_Normal_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchg_acq_shenandoah_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
+     "cmpxchg_N_Normal_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
    %}
+   ins_encode %{
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
  
-   ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp, res));
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val, only used in slow path */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,    /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
+   %}
  
    ins_pipe(pipe_slow);
  %}
  
- instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndSwap_P_Volatile_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+   format %{
+     "cmpxchg_P_Volatile_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
+   %}
+   ins_encode %{
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
  
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-   ins_cost(VOLATILE_REF_COST);
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
  
-   effect(TEMP tmp, KILL cr);
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val, only used in slow path */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
  
-  format %{
-     "cmpxchgw_acq_shenandoah_narrow_oop $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
-  %}
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,    /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
+   %}
+ 
+   ins_pipe(pipe_slow);
+ %}
  
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndSwap_N_Volatile_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndSwapN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+   format %{
+     "cmpxchg_N_Volatile_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
+   %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val, only used in slow path */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,    /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
    %}
  
    ins_pipe(pipe_slow);
  %}
  
- instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
-   effect(TEMP_DEF res, TEMP tmp, KILL cr);
+ 
+ 
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndExchange_N_Normal_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(2*VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_N_Normal_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,        /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ true);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                            $res$$Register     /* obj */,
+                                                            $mem$$Register     /* addr */,
+                                                            is_narrow          /* narrow */,
+                                                            maybe_null,
+                                                            $tmp1$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register         /* addr */,
+                                                        $tmp1$$Register        /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
-   effect(TEMP_DEF res, TEMP tmp, KILL cr);
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndExchange_P_Normal_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(2*VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
+     "cmpxchg_P_Normal_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,        /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ true);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                            $res$$Register     /* obj */,
+                                                            $mem$$Register     /* addr */,
+                                                            is_narrow          /* narrow */,
+                                                            maybe_null,
+                                                            $tmp1$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register         /* addr */,
+                                                        $tmp1$$Register        /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
-   ins_cost(VOLATILE_REF_COST);
-   effect(TEMP_DEF res, TEMP tmp, KILL cr);
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndExchange_N_Volatile_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_N_Volatile_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,        /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ true);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                            $res$$Register     /* obj */,
+                                                            $mem$$Register     /* addr */,
+                                                            is_narrow          /* narrow */,
+                                                            maybe_null,
+                                                            $tmp1$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register         /* addr */,
+                                                        $tmp1$$Register        /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
-   ins_cost(VOLATILE_REF_COST);
-   effect(TEMP_DEF res, TEMP tmp, KILL cr);
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct compareAndExchange_P_Volatile_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchg_acq_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp"
+     "cmpxchg_P_Volatile_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,        /* gc_state */
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ false,
+                                                         /*is_cae*/ true);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                            $res$$Register     /* obj */,
+                                                            $mem$$Register     /* addr */,
+                                                            is_narrow          /* narrow */,
+                                                            maybe_null,
+                                                            $tmp1$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register         /* addr */,
+                                                        $tmp1$$Register        /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
-   effect(TEMP tmp, KILL cr);
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct weakCompareAndSwap_N_Normal_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchgw_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_oop_c2 $res = $mem, $oldval, $newval\t# (N, weak, Normal) if $mem == $oldval then $mem <-- $newval\n\t"
      "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ true,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
-   ins_cost(2 * VOLATILE_REF_COST);
-   effect(TEMP tmp, KILL cr);
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct weakCompareAndSwap_P_Normal_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   ins_cost(VOLATILE_REF_COST);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchg_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_oop_c2 $res = $mem, $oldval, $newval\t# (P, weak, Normal) if $mem == $oldval then $mem <-- $newval\n\t"
+     "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = false;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ true,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct weakCompareAndSwap_N_Volatile_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegN newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
    ins_cost(VOLATILE_REF_COST);
-   effect(TEMP tmp, KILL cr);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_oop_c2 $res = $mem, $oldval, $newval\t# (N, weak, Volatile) if $mem == $oldval then $mem <-- $newval\n\t"
      "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ true,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
  
- instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{
-   predicate(needs_acquiring_load_exclusive(n));
-   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct weakCompareAndSwap_P_Volatile_shenandoah(iRegINoSp res, indirect mem, iRegPNoSp oldval, iRegP newval, iRegPNoSp tmp1, iRegPNoSp tmp2, rFlagsReg cr)
+ %{
+   match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
    ins_cost(VOLATILE_REF_COST);
-   effect(TEMP tmp, KILL cr);
+   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
    format %{
-     "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
+     "cmpxchg_oop_c2 $res = $mem, $oldval, $newval\t# (P, weak, Volatile) if $mem == $oldval then $mem <-- $newval\n\t"
      "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
    %}
    ins_encode %{
-     Register tmp = $tmp$$Register;
-     __ mov(tmp, $oldval$$Register); // Must not clobber oldval.
-     // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, $mem$$Register, tmp, $newval$$Register,
-                                                    /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register);
+     assert_different_registers($tmp1$$Register, $tmp2$$Register);
+     guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp1$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $oldval$$Register /* pre_val */,
+                                                         $tmp1$$Register   /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool is_acquire = true;
+     ShenandoahBarrierSet::assembler()->cmpxchg_oop_c2(this, masm,
+                                                         $mem$$base$$Register,
+                                                         $oldval$$Register,
+                                                         $newval$$Register,
+                                                         $res$$Register,
+                                                         $tmp1$$Register,
+                                                         $tmp2$$Register,
+                                                         /*acquire*/ is_acquire,
+                                                         /*release*/ true,
+                                                         /*weak*/ true,
+                                                         /*is_cae*/ false);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register /* addr */,
+                                                        $tmp1$$Register /* tmp */);
    %}
    ins_pipe(pipe_slow);
  %}
+ 
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct getAndSet_P_Normal_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set preval (GetAndSetP mem newval));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
+   ins_cost(2*VOLATILE_REF_COST);
+   format %{ "atomic_xchg $preval, $newval, [$mem]" %}
+   ins_encode %{
+     __ atomic_xchg($preval$$Register, $newval$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $preval$$Register /* pre_val */,
+                                                         $tmp$$Register    /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $preval$$Register /* obj */,
+                                                         $mem$$Register    /* addr */,
+                                                         is_narrow         /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register     /* addr */,
+                                                        $tmp$$Register     /* tmp */);
+   %}
+   ins_pipe(pipe_serial);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct getAndSet_P_Volatile_shenandoah(indirect mem, iRegP newval, iRegPNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set preval (GetAndSetP mem newval));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   format %{ "atomic_xchgal $preval, $newval, [$mem]" %}
+   ins_encode %{
+     __ atomic_xchgal($preval$$Register, $newval$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $preval$$Register /* pre_val */,
+                                                         $tmp$$Register    /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $preval$$Register /* obj */,
+                                                         $mem$$Register    /* addr */,
+                                                         is_narrow         /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register     /* addr */,
+                                                        $tmp$$Register     /* tmp */);
+   %}
+   ins_pipe(pipe_serial);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct getAndSet_N_Normal_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set preval (GetAndSetN mem newval));
+   predicate(UseShenandoahGC && !needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
+   ins_cost(2*VOLATILE_REF_COST);
+   format %{ "atomic_xchgw $preval, $newval, [$mem]" %}
+   ins_encode %{
+     __ atomic_xchgw($preval$$Register, $newval$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $preval$$Register /* pre_val */,
+                                                         $tmp$$Register    /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $preval$$Register /* obj */,
+                                                         $mem$$Register    /* addr */,
+                                                         is_narrow         /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register     /* addr */,
+                                                        $tmp$$Register     /* tmp */);
+   %}
+   ins_pipe(pipe_serial);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct getAndSet_N_Volatile_shenandoah(indirect mem, iRegN newval, iRegNNoSp preval, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set preval (GetAndSetN mem newval));
+   predicate(UseShenandoahGC && needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() != 0);
+   effect(TEMP_DEF preval, TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST + 3*INSN_COST);
+   format %{ "atomic_xchgalw $preval, $newval, [$mem]" %}
+   ins_encode %{
+     __ atomic_xchgalw($preval$$Register, $newval$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg             /* addr */,
+                                                         $preval$$Register /* pre_val */,
+                                                         $tmp$$Register    /* gc_state */,
+                                                         is_narrow         /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $preval$$Register /* obj */,
+                                                         $mem$$Register    /* addr */,
+                                                         is_narrow         /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register    /* gc_state */);
+ 
+     ShenandoahBarrierSet::assembler()->card_barrier_c2(this, masm,
+                                                        $mem$$Register     /* addr */,
+                                                        $tmp$$Register     /* tmp */);
+   %}
+   ins_pipe(pipe_serial);
+ %}
+ 
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct load_P_Normal_shenandoah(iRegPNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set dst (LoadP mem));
+   predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
+   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
+   ins_cost(3*INSN_COST);
+   format %{ "ldr  $dst, $mem\t# ptr" %}
+   ins_encode %{
+     __ ldr($dst$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg            /* obj */,
+                                                         $dst$$Register   /* pre_val, in this case it will be only used in the slowpath as tmp. */,
+                                                         $tmp$$Register   /* gc_state */,
+                                                         is_narrow        /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $dst$$Register /* obj */,
+                                                         $mem$$Register /* addr */,
+                                                         is_narrow      /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register /* gc_state */);
+   %}
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct load_P_Volatile_shenandoah(iRegPNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set dst (LoadP mem));
+   predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
+   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST);
+   format %{ "ldar  $dst, $mem\t# ptr" %}
+   ins_encode %{
+     __ ldar($dst$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = false;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg            /* obj */,
+                                                         $dst$$Register   /* pre_val, in this case it will be only used in the slowpath as tmp. */,
+                                                         $tmp$$Register   /* gc_state */,
+                                                         is_narrow        /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $dst$$Register /* obj */,
+                                                         $mem$$Register /* addr */,
+                                                         is_narrow      /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register /* gc_state */);
+   %}
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct load_N_Normal_shenandoah(iRegNNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set dst (LoadN mem));
+   predicate(UseShenandoahGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
+   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
+   ins_cost(3*INSN_COST);
+   format %{ "ldrw  $dst, $mem\t# ptr" %}
+   ins_encode %{
+     __ ldrw($dst$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg            /* obj */,
+                                                         $dst$$Register   /* pre_val, in this case it will be only used in the slowpath as tmp. */,
+                                                         $tmp$$Register   /* gc_state */,
+                                                         is_narrow        /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $dst$$Register /* obj */,
+                                                         $mem$$Register /* addr */,
+                                                         is_narrow      /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register /* gc_state */);
+   %}
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ // This pattern is generated automatically from shenandoah_aarch64.m4.
+ // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
+ instruct load_N_Volatile_shenandoah(iRegNNoSp dst, indirect mem, iRegPNoSp tmp, rFlagsReg cr)
+ %{
+   match(Set dst (LoadN mem));
+   predicate(UseShenandoahGC && needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
+   effect(TEMP_DEF dst, TEMP tmp, KILL cr);
+   ins_cost(VOLATILE_REF_COST);
+   format %{ "ldarw  $dst, $mem\t# ptr" %}
+   ins_encode %{
+     __ ldarw($dst$$Register, $mem$$Register);
+ 
+     Address gcs_addr(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+     __ ldrb($tmp$$Register, gcs_addr);
+ 
+     bool is_narrow = true;
+     ShenandoahBarrierSet::assembler()->satb_barrier_c2(this, masm,
+                                                         noreg            /* obj */,
+                                                         $dst$$Register   /* pre_val, in this case it will be only used in the slowpath as tmp. */,
+                                                         $tmp$$Register   /* gc_state */,
+                                                         is_narrow        /* encoded_preval */);
+ 
+     bool maybe_null = (this->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull);
+     ShenandoahBarrierSet::assembler()->load_ref_barrier_c2(this, masm,
+                                                         $dst$$Register /* obj */,
+                                                         $mem$$Register /* addr */,
+                                                         is_narrow      /* narrow */,
+                                                         maybe_null,
+                                                         $tmp$$Register /* gc_state */);
+   %}
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ // END This section of the file is automatically generated from shenandoah_aarch64.m4.
< prev index next >