RFR: 8360654: AArch64: Remove redundant dmb from C1 compareAndSet

Aleksey Shipilev shade at openjdk.org
Fri Jun 27 07:33:40 UTC 2025


On Thu, 26 Jun 2025 12:13:19 GMT, Samuel Chee <duke at openjdk.org> wrote:

> AtomicLong.CompareAndSet has the following assembly dump snippet which gets emitted from the intermediary LIRGenerator::atomic_cmpxchg:
> 
> ;; cmpxchg {
>   0x0000e708d144cf60:   mov	x8, x2
>   0x0000e708d144cf64:   casal	x8, x3, [x0]
>   0x0000e708d144cf68:   cmp	x8, x2
>  ;; 0x1F1F1F1F1F1F1F1F
>   0x0000e708d144cf6c:   mov	x8, #0x1f1f1f1f1f1f1f1f
>  ;; } cmpxchg
>   0x0000e708d144cf70:   cset	x8, ne  // ne = any
>   0x0000e708d144cf74:   dmb	ish
> 
> 
> According to the Oracle Java Specification, AtomicLong.CompareAndSet [1] has the same memory effects as specified by VarHandle.compareAndSet which has the following effects: [2]
> 
>> Atomically sets the value of a variable to the
>> newValue with the memory semantics of setVolatile if
>> the variable's current value, referred to as the witness
>> value, == the expectedValue, as accessed with the memory
>> semantics of getVolatile.
> 
> 
> 
> Hence the release on the store due to setVolatile only occurs if the compare is successful. Since casal already satisfies these requirements, the dmb does not need to occur to ensure memory ordering in case the compare fails and a release does not happen.
> 
> Hence we remove the dmb from both casl and casw (same logic applies to the non-long variant)
> 
> This is also reflected by C2 not having a dmb for the same respective method.
> 
> [1] https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html#compareAndSet(long,long)
> [2] https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/lang/invoke/VarHandle.html#compareAndSet(java.lang.Object...)

I heavily suspect some of these extra barriers has to do with compatibility across different barrier schemes in interpreter, C1 and C2, especially when `cmpxchg` is expanded to LL/SC (happens, AFAICS, without LSE). That, and that is historically we believed CAS should has release memory semantics even on failure. There are other instances of this, see e.g. `MacroAssembler::cmpxchg*`: https://github.com/openjdk/jdk/blob/master/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp#L3380

You need to verify that jcstress does not fail with this patch, also with `-XX:-UseLSE`. Take the latest bundle from here: https://builds.shipilev.net/jcstress/

-------------

PR Review: https://git.openjdk.org/jdk/pull/26000#pullrequestreview-2965119245


More information about the hotspot-compiler-dev mailing list