ShenandoahGC cmpxchg_oop oldval register *NOT* be clobbered
Leslie Zhai
zhaixiang at loongson.cn
Sun Apr 23 02:26:57 UTC 2023
Hi,
Cui weilong found that Renaissance philosophers thrown ClassCastException[1] with -XX:+UseShenandoahGC for LoongArch.
So I just disabled C2 compiler via -XX:TieredStopAtLevel=3 for fastdebug, then it was not able to reproduce the issue.
At very beginning I thought it might be lack of mov oldval to tmp register in `cmpxchg_oop` by compared with AArch64:
```
enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
MacroAssembler _masm(&cbuf);
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);
%}
```
I thought it was lack of mov oldval to tmp register for LoongArch:
```
enc_class loongarch_enc_cmpxchg_oop_shenandoah(memory mem, mRegP oldval, mRegP newval, mRegI res) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding”);
=> Be lack of move oldval to tmp register
ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, $oldval$$Register, $newval$$Register,
/*acquire*/ false, /*is_cae*/ false, $res$$Register);
%}
```
But I actually fixed the issue by allocating a tmp register for `cmpxchg_oop`, for example:
```
encode %{
enc_class loongarch_enc_cmpxchg_oop_shenandoah(memory mem, mRegP oldval, mRegP newval, mRegP tmp /* allocated tmp register */, mRegI res) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
Register tmp = $tmp$$Register; // allocated tmp register
ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, $oldval$$Register, $newval$$Register, tmp /* allocated tmp register */,
/*acquire*/ false, /*is_cae*/ false, $res$$Register);
%}
...
%}
instruct compareAndSwapP_shenandoah(mRegI res, indirect mem, mRegP oldval, mRegP newval, mRegP tmp) %{
match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
effect(TEMP tmp); // allocated tmp register
predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
&& ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
format %{
"cmpxchg_shenandoah $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
%}
ins_encode(loongarch_enc_cmpxchg_oop_shenandoah(mem, oldval, newval, tmp /* allocated tmp register */, res));
ins_pipe(pipe_slow);
%}
```
Sun guoyun, my colleague, reviewed my patch and found that oldval register *NOT* be clobbered at all, and suggested to remove it for AArch64[2] too, for example:
```
diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad
index 0572e7d8d11..da75df59b6d 100644
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad
@@ -28,233 +28,209 @@ source_hpp %{
%}
encode %{
- enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{
+ enc_class aarch64_enc_cmpxchg_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegINoSp res) %{
MacroAssembler _masm(&cbuf);
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,
+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, $oldval$$Register, $newval$$Register,
/*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register);
%}
```
I only ran jtreg tier1 fastdebug[3] for AArch64 on Mac mini M2:
```
make run-test CONF=fastdebug TEST="tier1" JTREG="VM_OPTIONS=-XX:+UseShenandoahGC;VERBOSE=summary"
```
Do I need to run more tests for AArch64? For example jtreg tier2~3, and some benchmarks such as Renaissance or DaCapo?
Please point out my fault!
1.
[cuiweilong at localhost test]$ jdk-17.0.5/bin/java -XX:+UseShenandoahGC -jar Renaissance/renaissance-gpl-0.14.1.jar philosophers
====== philosophers (scala) [default], iteration 0 started ======
GC before operation: completed in 59.346 ms, heap usage 72.000 MB -> 3.321 MB.
Exception in thread "Thread-3" java.lang.ClassCastException: class scala.concurrent.stm.Txn$Preparing$ cannot be cast to class scala.concurrent.stm.Txn$RolledBack (scala.concurrent.stm.Txn$Preparing$ and scala.concurrent.stm.Txn$RolledBack are in unnamed module of loader java.net.URLClassLoader @12e61fe6)
at scala.concurrent.stm.ccstm.InTxnImpl.topLevelComplete(InTxnImpl.scala:623)
at scala.concurrent.stm.ccstm.InTxnImpl.topLevelAttempt(InTxnImpl.scala:529)
at scala.concurrent.stm.ccstm.InTxnImpl.topLevelAtomicImpl(InTxnImpl.scala:398)
at scala.concurrent.stm.ccstm.InTxnImpl.atomic(InTxnImpl.scala:259)
at scala.concurrent.stm.ccstm.CCSTMExecutor.apply(CCSTMExecutor.scala:24)
at org.renaissance.scala.stm.RealityShowPhilosophers$PhilosopherThread.$anonfun$run$1(RealityShowPhilosophers.scala:29)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:158)
at org.renaissance.scala.stm.RealityShowPhilosophers$PhilosopherThread.run(RealityShowPhilosophers.scala:27)
Exception in thread "Thread-15" java.lang.ClassCastException
Exception in thread "Thread-11" java.lang.ClassCastException
Exception in thread "Thread-6" java.lang.ClassCastException
Exception in thread "Thread-13” java.lang.ClassCastException
2.
ShenandoahGC oldval register *NOT* be clobbered and fix copy_and_paste typo for store_at https://github.com/xiangzhai/jdk/commit/186b0ea48f712bd83cf3f8cc0200a14209679340
3.
Before:
jtreg:test/hotspot/jtreg:tier1 1805 1793 7 5
jtreg:test/jdk:tier1 2314 2306 5 3
jtreg:test/langtools:tier1 4373 2707 1650 16
jtreg:test/jaxp:tier1 0 0 0 0
jtreg:test/lib-test:tier1 28 28 0 0
After:
jtreg:test/hotspot/jtreg:tier1 1805 1793 7 5
jtreg:test/jdk:tier1 2314 2305 6 3
jtreg:test/langtools:tier1 4372 2696 1661 15
jtreg:test/jaxp:tier1 0 0 0 0
jtreg:test/lib-test:tier1 28 28 0 0
Thanks,
Leslie Zhai
More information about the shenandoah-dev
mailing list