< 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 >