# HG changeset patch # User rkennke # Date 1479477746 0 # Fri Nov 18 14:02:26 2016 +0000 # Node ID 0b9bf12a63fb8a58900a81acc48358523d77356a # Parent 1fb95b185cc3b62a6f74319de4858a32532df9b9 [mq]: casfixes.patch diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad --- a/src/cpu/aarch64/vm/aarch64.ad +++ b/src/cpu/aarch64/vm/aarch64.ad @@ -4282,13 +4282,12 @@ %} - enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegLNoSp oldval, iRegLNoSp newval, iRegP tmp) %{ + enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Register tmp = $tmp$$Register; - __ shenandoah_store_check($mem$$base$$Register, $newval$$Register); __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - __ cmpxchg_oop_shenandoah($mem$$base$$Register, tmp, $newval$$Register, + __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, Assembler::xword, /*acquire*/ false, /*release*/ true, /*weak*/ false); %} @@ -4315,13 +4314,12 @@ %} - enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegLNoSp oldval, iRegLNoSp newval, iRegP tmp) %{ + enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); Register tmp = $tmp$$Register; - __ shenandoah_store_check($mem$$base$$Register, $newval$$Register); __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - __ cmpxchg_oop_shenandoah($mem$$base$$Register, tmp, $newval$$Register, + __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, Assembler::xword, /*acquire*/ true, /*release*/ true, /*weak*/ false); %} @@ -9649,7 +9647,7 @@ ins_pipe(pipe_slow); %} -instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegP tmp, rFlagsReg cr) %{ +instruct compareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (CompareAndSwapP mem (Binary oldval newval))); @@ -9687,7 +9685,7 @@ ins_pipe(pipe_slow); %} -instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, iRegP tmp, rFlagsReg cr) %{ +instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (CompareAndSwapN mem (Binary oldval newval))); @@ -9695,6 +9693,126 @@ effect(TEMP tmp, KILL cr); + format %{ + "cmpxchg_narrow_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode %{ + Register tmp = $tmp$$Register; + __ mov(tmp, $oldval$$Register); // Must not clobber oldval. + __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, Assembler::word, /*acquire*/ false, /*release*/ true, /*weak*/ false); + __ cset($res$$Register, Assembler::EQ); + %} + + ins_pipe(pipe_slow); +%} + +// alternative CompareAndSwapX when we are eliding barriers + +instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n)); + match(Set res (CompareAndSwapI mem (Binary oldval newval))); + ins_cost(VOLATILE_REF_COST); + + effect(KILL cr); + + format %{ + "cmpxchgw_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval), + aarch64_enc_cset_eq(res)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n)); + match(Set res (CompareAndSwapL mem (Binary oldval newval))); + ins_cost(VOLATILE_REF_COST); + + effect(KILL cr); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval), + aarch64_enc_cset_eq(res)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n) && (!UseShenandoahGC || n->in(3)->in(1)->bottom_type() == TypePtr::NULL_PTR)); + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + ins_cost(VOLATILE_REF_COST); + + effect(KILL cr); + + format %{ + "cmpxchg_acq $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval), + aarch64_enc_cset_eq(res)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n) && UseShenandoahGC); + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + ins_cost(2 * VOLATILE_REF_COST); + + effect(TEMP tmp, KILL cr); + + format %{ + "cmpxchg_acq_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp), + aarch64_enc_cset_eq(res)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n) && ! UseShenandoahGC); + match(Set res (CompareAndSwapN mem (Binary oldval newval))); + ins_cost(VOLATILE_REF_COST); + + effect(KILL cr); + + format %{ + "cmpxchgw_acq $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval" + "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" + %} + + ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval), + aarch64_enc_cset_eq(res)); + + ins_pipe(pipe_slow); +%} + +instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ + + predicate(needs_acquiring_load_exclusive(n) && UseShenandoahGC); + match(Set res (CompareAndSwapN mem (Binary oldval newval))); + ins_cost(3 * VOLATILE_REF_COST); + + effect(TEMP tmp, KILL cr); + format %{ "cmpxchg_narrow_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" @@ -9703,127 +9821,7 @@ ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - __ cmpxchg_oop_shenandoah($mem$$base$$Register, tmp, $newval$$Register, Assembler::word, /*acquire*/ false, /*release*/ true, /*weak*/ false); - __ cset($res$$Register, Assembler::EQ); - %} - - ins_pipe(pipe_slow); -%} - -// alternative CompareAndSwapX when we are eliding barriers - -instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n)); - match(Set res (CompareAndSwapI mem (Binary oldval newval))); - ins_cost(VOLATILE_REF_COST); - - effect(KILL cr); - - format %{ - "cmpxchgw_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval), - aarch64_enc_cset_eq(res)); - - ins_pipe(pipe_slow); -%} - -instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n)); - match(Set res (CompareAndSwapL mem (Binary oldval newval))); - ins_cost(VOLATILE_REF_COST); - - effect(KILL cr); - - format %{ - "cmpxchg_acq $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval), - aarch64_enc_cset_eq(res)); - - ins_pipe(pipe_slow); -%} - -instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n) && (!UseShenandoahGC || n->in(3)->in(1)->bottom_type() == TypePtr::NULL_PTR)); - match(Set res (CompareAndSwapP mem (Binary oldval newval))); - ins_cost(VOLATILE_REF_COST); - - effect(KILL cr); - - format %{ - "cmpxchg_acq $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval), - aarch64_enc_cset_eq(res)); - - ins_pipe(pipe_slow); -%} - -instruct compareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegP tmp, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n) && UseShenandoahGC); - match(Set res (CompareAndSwapP mem (Binary oldval newval))); - ins_cost(2 * VOLATILE_REF_COST); - - effect(TEMP tmp, KILL cr); - - format %{ - "cmpxchg_acq_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode(aarch64_enc_cmpxchg_acq_oop_shenandoah(mem, oldval, newval, tmp), - aarch64_enc_cset_eq(res)); - - ins_pipe(pipe_slow); -%} - -instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n) && ! UseShenandoahGC); - match(Set res (CompareAndSwapN mem (Binary oldval newval))); - ins_cost(VOLATILE_REF_COST); - - effect(KILL cr); - - format %{ - "cmpxchgw_acq $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval), - aarch64_enc_cset_eq(res)); - - ins_pipe(pipe_slow); -%} - -instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, iRegP tmp, rFlagsReg cr) %{ - - predicate(needs_acquiring_load_exclusive(n) && UseShenandoahGC); - match(Set res (CompareAndSwapN mem (Binary oldval newval))); - ins_cost(3 * VOLATILE_REF_COST); - - effect(TEMP tmp, KILL cr); - - format %{ - "cmpxchg_narrow_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" - "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)" - %} - - ins_encode %{ - Register tmp = $tmp$$Register; - __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - __ cmpxchg_oop_shenandoah($mem$$base$$Register, tmp, $newval$$Register, Assembler::word, /*acquire*/ true, /*release*/ true, /*weak*/ false); + __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, Assembler::word, /*acquire*/ true, /*release*/ true, /*weak*/ false); __ cset($res$$Register, Assembler::EQ); %} @@ -9844,7 +9842,7 @@ instruct compareAndExchangeB(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{ match(Set res (CompareAndExchangeB mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9861,7 +9859,7 @@ instruct compareAndExchangeS(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{ match(Set res (CompareAndExchangeS mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9878,7 +9876,7 @@ instruct compareAndExchangeI(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{ match(Set res (CompareAndExchangeI mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9893,7 +9891,7 @@ instruct compareAndExchangeL(iRegL_R0 res, indirect mem, iRegL_R2 oldval, iRegL_R3 newval, rFlagsReg cr) %{ match(Set res (CompareAndExchangeL mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9909,7 +9907,7 @@ predicate(! UseShenandoahGC); match(Set res (CompareAndExchangeN mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9921,11 +9919,11 @@ ins_pipe(pipe_slow); %} -instruct compareAndExchangeN_shenandoah(iRegN_R0 res, indirect mem, iRegN_R2 oldval, iRegN_R3 newval, iRegP tmp, rFlagsReg cr) %{ +instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (CompareAndExchangeN mem (Binary oldval newval))); ins_cost(3 * VOLATILE_REF_COST); - effect(TEMP tmp, KILL cr); + effect(TEMP_DEF res, TEMP tmp, KILL cr); format %{ "cmpxchg_oop_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9933,8 +9931,7 @@ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::word, /*acquire*/ false, /*release*/ true, /*weak*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -9943,7 +9940,7 @@ predicate(!UseShenandoahGC || n->in(3)->in(1)->bottom_type() == TypePtr::NULL_PTR); match(Set res (CompareAndExchangeP mem (Binary oldval newval))); ins_cost(2 * VOLATILE_REF_COST); - effect(KILL cr); + effect(TEMP_DEF res, KILL cr); format %{ "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval" %} @@ -9955,11 +9952,11 @@ ins_pipe(pipe_slow); %} -instruct compareAndExchangeP_shenandoah(iRegP_R0 res, indirect mem, iRegP_R2 oldval, iRegP_R3 newval, iRegP tmp, rFlagsReg cr) %{ +instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (CompareAndExchangeP mem (Binary oldval newval))); ins_cost(3 * VOLATILE_REF_COST); - effect(TEMP tmp, KILL cr); + effect(TEMP_DEF res, TEMP tmp, KILL cr); format %{ "cmpxchg_oop_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval with temp $tmp" %} @@ -9967,8 +9964,7 @@ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ false, $res$$Register); + Assembler::xword, /*acquire*/ false, /*release*/ true, /*weak*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -10061,7 +10057,7 @@ ins_pipe(pipe_slow); %} -instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegP tmp, rFlagsReg cr) %{ +instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (WeakCompareAndSwapN mem (Binary oldval newval))); ins_cost(3 * VOLATILE_REF_COST); @@ -10074,8 +10070,7 @@ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, - Assembler::word, /*acquire*/ false, /*release*/ true, - /*weak*/ true); + Assembler::word, /*acquire*/ false, /*release*/ true, /*weak*/ true); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); @@ -10099,7 +10094,7 @@ ins_pipe(pipe_slow); %} -instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegP tmp, rFlagsReg cr) %{ +instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ predicate(UseShenandoahGC); match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); ins_cost(3 * VOLATILE_REF_COST); @@ -10112,8 +10107,7 @@ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. __ cmpxchg_oop_shenandoah($mem$$Register, tmp, $newval$$Register, - Assembler::xword, /*acquire*/ false, /*release*/ true, - /*weak*/ true); + Assembler::xword, /*acquire*/ false, /*release*/ true, /*weak*/ true); __ csetw($res$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); diff --git a/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp --- a/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -1617,7 +1617,7 @@ Register t2 = op->tmp2()->as_register(); __ encode_heap_oop(t2, newval); newval = t2; - __ cmpxchg_oop_shenandoah(addr, cmpval, newval, Assembler::word, true, true, false); + __ cmpxchg_oop_shenandoah(addr, cmpval, newval, Assembler::word, /*acquire*/ false, /*release*/ true, /*weak*/ false); __ csetw(res, Assembler::EQ); } else { __ encode_heap_oop(t1, cmpval); @@ -1629,7 +1629,7 @@ } } else { if (UseShenandoahGC) { - __ cmpxchg_oop_shenandoah(addr, cmpval, newval, Assembler::xword, true, true, false); + __ cmpxchg_oop_shenandoah(addr, cmpval, newval, Assembler::xword, /*acquire*/ false, /*release*/ true, /*weak*/ false); __ csetw(res, Assembler::EQ); } else { casl(addr, newval, cmpval); diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -2200,24 +2200,34 @@ void MacroAssembler::cmpxchg_oop_shenandoah(Register addr, Register expected, Register new_val, enum operand_size size, - bool acquire, bool release, + bool acquire, bool release, bool weak, - Register res, Register tmp2) { + Register result, Register tmp2) { assert(UseShenandoahGC, "only for shenandoah"); - Register result = res; - if (result == noreg) result = rscratch1; + bool is_cae = (result != noreg); + bool is_narrow = (size == word); + + if (! is_cae) result = rscratch1; assert_different_registers(addr, expected, new_val, result, tmp2); + if (ShenandoahStoreCheck) { + if (is_narrow) { + decode_heap_oop(tmp2, new_val); + shenandoah_store_check(addr, tmp2); + } else { + shenandoah_store_check(addr, new_val); + } + } Label retry, done, fail; // CAS, using LL/SC pair. bind(retry); load_exclusive(result, addr, size, acquire); - if (size == xword) { + if (is_narrow) { + cmpw(result, expected); + } else { cmp(result, expected); - } else { - cmpw(result, expected); } br(Assembler::NE, fail); store_exclusive(tmp2, new_val, addr, size, release); @@ -2233,7 +2243,7 @@ // Shuffle registers so that we have memory value ready for next expected. mov(tmp2, expected); mov(expected, result); - if (size == word) { + if (is_narrow) { decode_heap_oop(result, result); decode_heap_oop(tmp2, tmp2); } @@ -2242,9 +2252,9 @@ cmp(result, tmp2); // Retry with expected now being the value we just loaded from addr. br(Assembler::EQ, retry); - if (size == word && res != noreg) { + if (is_narrow && is_cae) { // For cmp-and-exchange and narrow oops, we need to restore - // the compressed old-value. + // the compressed old-value. We moved it to 'expected' a few lines up. mov(result, expected); } bind(done);