< prev index next >
src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
Print this page
rev 12202 : AArch64: Add remaining (weak / exchange) CAS-obj intrinsics for Shenandoah.
@@ -2195,50 +2195,61 @@
bind(done);
BLOCK_COMMENT("} cmpxchg");
}
}
-void MacroAssembler::cmpxchg_oop_shenandoah(Register res, Register addr, Register expected,
+void MacroAssembler::cmpxchg_oop_shenandoah(Register addr, Register expected,
Register new_val,
- bool narrow,
+ enum operand_size size,
bool acquire, bool release,
- Register tmp1, Register tmp2) {
+ bool weak,
+ Register res, Register tmp2) {
assert(UseShenandoahGC, "only for shenandoah");
- assert_different_registers(res, addr, expected, new_val, tmp1, tmp2);
+ Register result = res;
+ if (result == noreg) result = rscratch1;
- Label retry, done, fail;
+ assert_different_registers(addr, expected, new_val, result, tmp2);
- mov(res, 0);
+ Label retry, done, fail;
// CAS, using LL/SC pair.
bind(retry);
- load_exclusive(tmp1, addr, narrow ? word : xword, true);
- if (narrow) cmpw(tmp1, expected);
- else cmp(tmp1, expected);
+ load_exclusive(result, addr, size, acquire);
+ if (size == xword) {
+ cmp(result, expected);
+ } else {
+ cmpw(result, expected);
+ }
br(Assembler::NE, fail);
- store_exclusive(tmp2, new_val, addr, narrow ? word : xword, true);
+ store_exclusive(tmp2, new_val, addr, size, release);
+ if (weak) {
+ cmpw(tmp2, 0u); // If the store fails, return NE to our caller
+ } else {
cbnzw(tmp2, retry);
- mov(res, 1);
+ }
b(done);
bind(fail);
- // Check if rb(expected)==rb(tmp1)
+ // Check if rb(expected)==rb(result)
// Shuffle registers so that we have memory value ready for next expected.
mov(tmp2, expected);
- mov(expected, tmp1);
- if (narrow) {
- decode_heap_oop(tmp1, tmp1);
+ mov(expected, result);
+ if (size == word) {
+ decode_heap_oop(result, result);
decode_heap_oop(tmp2, tmp2);
}
- oopDesc::bs()->interpreter_read_barrier(this, tmp1);
+ oopDesc::bs()->interpreter_read_barrier(this, result);
oopDesc::bs()->interpreter_read_barrier(this, tmp2);
- cmp(tmp1, tmp2);
+ cmp(result, tmp2);
// Retry with expected now being the value we just loaded from addr.
br(Assembler::EQ, retry);
-
+ if (size == word && res != noreg) {
+ // For cmp-and-exchange and narrow oops, we need to restore
+ // the compressed old-value.
+ mov(result, expected);
+ }
bind(done);
- membar(AnyAny);
}
static bool different(Register a, RegisterOrConstant b, Register c) {
if (b.is_constant())
return a != c;
< prev index next >