Skip to content

Commit 07b8faf

Browse files
committed
Avoid use scratch register in ZGC CAS
1 parent d019d3d commit 07b8faf

File tree

3 files changed

+100
-24
lines changed

3 files changed

+100
-24
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.hotspot.test;
26+
27+
import java.io.IOException;
28+
29+
import org.junit.Assert;
30+
import org.junit.Assume;
31+
import org.junit.Before;
32+
import org.junit.Test;
33+
34+
import jdk.graal.compiler.core.test.GraalCompilerTest;
35+
import jdk.graal.compiler.core.test.SubprocessTest;
36+
import jdk.graal.compiler.replacements.test.UnsafeSubstitutionsTest;
37+
import jdk.graal.compiler.test.SubprocessUtil;
38+
import jdk.vm.ci.aarch64.AArch64;
39+
40+
public class UnsafeSubstitutionsWithoutLSETest extends SubprocessTest {
41+
@Before
42+
public void before() {
43+
Assume.assumeTrue("AArch64-specific test", getArchitecture() instanceof AArch64);
44+
}
45+
46+
public void testWithoutLSE(Class<? extends GraalCompilerTest> testClass) {
47+
Runnable nopRunnable = () -> {
48+
/*
49+
* The runnable is only relevant when running a test in the same class as the parent
50+
* process.
51+
*/
52+
};
53+
SubprocessUtil.Subprocess subprocess = null;
54+
try {
55+
subprocess = launchSubprocess(testClass, ALL_TESTS, nopRunnable, "-XX:-UseLSE");
56+
} catch (IOException | InterruptedException e) {
57+
Assert.fail("subprocess exception: " + e);
58+
}
59+
Assert.assertEquals("subprocess exit code", 0, subprocess.exitCode);
60+
}
61+
62+
@Test
63+
public void unsafeSubstitutions() {
64+
testWithoutLSE(UnsafeSubstitutionsTest.class);
65+
}
66+
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/z/AArch64HotSpotZBarrierSetLIRGenerator.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ static void emitStoreBarrier(CompilationResultBuilder crb,
120120
LIRInstruction op,
121121
GraalHotSpotVMConfig config,
122122
AArch64Address address,
123-
Register result,
123+
Register tmp,
124124
StoreKind storeKind,
125125
ForeignCallLinkage callTarget,
126126
LIRFrameState state) {
@@ -130,9 +130,9 @@ static void emitStoreBarrier(CompilationResultBuilder crb,
130130
Register rscratch1 = sc1.getRegister();
131131
Register rscratch2 = sc2.getRegister();
132132

133-
Assembler.guaranteeDifferentRegisters(address.getBase(), result, rscratch1);
134-
Assembler.guaranteeDifferentRegisters(address.getOffset(), result, rscratch1);
135-
Assembler.guaranteeDifferentRegisters(result, rscratch1);
133+
Assembler.guaranteeDifferentRegisters(address.getBase(), tmp, rscratch1);
134+
Assembler.guaranteeDifferentRegisters(address.getOffset(), tmp, rscratch1);
135+
Assembler.guaranteeDifferentRegisters(tmp, rscratch1);
136136

137137
if (storeKind == StoreKind.Atomic) {
138138
if (state != null) {
@@ -182,7 +182,7 @@ static void emitStoreBarrier(CompilationResultBuilder crb,
182182
storeBarrierMedium(crb, masm, config,
183183
address,
184184
rscratch2,
185-
result,
185+
tmp,
186186
rscratch1,
187187
storeKind,
188188
continuation,
@@ -423,10 +423,11 @@ public void emitCompareAndSwapOp(LIRGeneratorTool tool,
423423
AllocatableValue allocatableNewValue,
424424
BarrierType barrierType) {
425425
ForeignCallLinkage callTarget = getWriteBarrierStub(barrierType, StoreKind.Atomic);
426-
AllocatableValue temp = tool.newVariable(tool.toRegisterKind(LIRKind.value(memKind)));
426+
AllocatableValue tmp = tool.newVariable(tool.toRegisterKind(LIRKind.value(memKind)));
427+
AllocatableValue tmp2 = tool.newVariable(tool.toRegisterKind(LIRKind.value(memKind)));
427428
tool.getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention());
428429
tool.append(new AArch64HotSpotZCompareAndSwapOp(isLogicVariant, memKind, memoryOrder, isLogicVariant, result,
429-
allocatableExpectedValue, allocatableNewValue, tool.asAllocatable(address), config, callTarget, temp));
430+
allocatableExpectedValue, allocatableNewValue, tool.asAllocatable(address), config, callTarget, tmp, tmp2));
430431
}
431432

432433
@Override

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/z/AArch64HotSpotZCompareAndSwapOp.java

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,37 +51,46 @@ public final class AArch64HotSpotZCompareAndSwapOp extends AArch64AtomicMove.Com
5151
private final boolean isLogic;
5252
private final GraalHotSpotVMConfig config;
5353
private final ForeignCallLinkage callTarget;
54-
@Temp protected AllocatableValue tmp;
54+
@Temp private AllocatableValue tmp;
55+
@Temp private AllocatableValue tmp2;
5556

56-
public AArch64HotSpotZCompareAndSwapOp(boolean isLogic, AArch64Kind accessKind, MemoryOrderMode memoryOrder, boolean setConditionFlags, AllocatableValue result, Value expectedValue,
57+
public AArch64HotSpotZCompareAndSwapOp(boolean isLogic,
58+
AArch64Kind accessKind,
59+
MemoryOrderMode memoryOrder,
60+
boolean setConditionFlags,
61+
AllocatableValue result,
62+
Value expectedValue,
5763
AllocatableValue newValue,
58-
AllocatableValue addressValue, GraalHotSpotVMConfig config, ForeignCallLinkage callTarget, AllocatableValue tmp) {
64+
AllocatableValue addressValue,
65+
GraalHotSpotVMConfig config,
66+
ForeignCallLinkage callTarget,
67+
AllocatableValue tmp, AllocatableValue tmp2) {
5968
super(TYPE, accessKind, memoryOrder, setConditionFlags, result, expectedValue, newValue, addressValue);
6069
this.isLogic = isLogic;
6170
this.config = config;
6271
this.callTarget = callTarget;
6372
this.tmp = tmp;
73+
this.tmp2 = tmp2;
6474
}
6575

6676
@Override
6777
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
6878
// Use ANY_SIZE here because the store barrier performs 16 and 64 access for atomics.
6979
AArch64Address location = AArch64Address.createBaseRegisterOnlyAddress(AArch64Address.ANY_SIZE, asRegister(addressValue));
70-
AArch64HotSpotZBarrierSetLIRGenerator.emitStoreBarrier(crb, masm, this, config, location, asRegister(tmp), ZWriteBarrierSetLIRGeneratorTool.StoreKind.Atomic,
80+
Register tmpRegister = asRegister(tmp);
81+
AArch64HotSpotZBarrierSetLIRGenerator.emitStoreBarrier(crb, masm, this, config, location, tmpRegister, ZWriteBarrierSetLIRGeneratorTool.StoreKind.Atomic,
7182
callTarget, null);
72-
try (AArch64MacroAssembler.ScratchRegister sc1 = masm.getScratchRegister()) {
73-
Register rscratch1 = sc1.getRegister();
74-
// Color newValue and expectedValue into a temporary registers
75-
AArch64HotSpotZBarrierSetLIRGenerator.zColor(crb, masm, config, asRegister(tmp), asRegister(newValue));
76-
AArch64HotSpotZBarrierSetLIRGenerator.zColor(crb, masm, config, rscratch1, asRegister(expectedValue));
77-
Register address = asRegister(addressValue);
78-
// Produce the colored result into a temporary register
79-
Register result = asRegister(resultValue);
80-
Register expected = rscratch1;
81-
emitCompareAndSwap(masm, accessKind, address, result, expected, asRegister(tmp), memoryOrder, setConditionFlags);
82-
if (!isLogic) {
83-
AArch64HotSpotZBarrierSetLIRGenerator.zUncolor(masm, config, asRegister(resultValue));
84-
}
83+
Register tmp2Register = asRegister(tmp2);
84+
// Color newValue and expectedValue into a temporary registers
85+
AArch64HotSpotZBarrierSetLIRGenerator.zColor(crb, masm, config, tmpRegister, asRegister(newValue));
86+
AArch64HotSpotZBarrierSetLIRGenerator.zColor(crb, masm, config, tmp2Register, asRegister(expectedValue));
87+
Register address = asRegister(addressValue);
88+
// Produce the colored result into a temporary register
89+
Register result = asRegister(resultValue);
90+
Register expected = tmp2Register;
91+
emitCompareAndSwap(masm, accessKind, address, result, expected, tmpRegister, memoryOrder, setConditionFlags);
92+
if (!isLogic) {
93+
AArch64HotSpotZBarrierSetLIRGenerator.zUncolor(masm, config, asRegister(resultValue));
8594
}
8695
}
8796
}

0 commit comments

Comments
 (0)