diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java index e933e17ffb3f..b04a39584988 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java @@ -1069,7 +1069,7 @@ public enum SystemRegister { FPCR(0b11, 0b011, 0b0100, 0b0100, 0b000), FPSR(0b11, 0b011, 0b0100, 0b0100, 0b001), /* Counter-timer Virtual Count register */ - CNTVCT_EL0(0b11, 0b011, 0b110, 0b0000, 0b010); + CNTVCT_EL0(0b11, 0b011, 0b1110, 0b0000, 0b010); SystemRegister(int op0, int op1, int crn, int crm, int op2) { this.op0 = op0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java index ee480f6762b6..913218113bec 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java @@ -89,6 +89,7 @@ import jdk.graal.compiler.lir.aarch64.AArch64Move; import jdk.graal.compiler.lir.aarch64.AArch64Move.MembarOp; import jdk.graal.compiler.lir.aarch64.AArch64PauseOp; +import jdk.graal.compiler.lir.aarch64.AArch64ReadTimestampCounter; import jdk.graal.compiler.lir.aarch64.AArch64SHA1Op; import jdk.graal.compiler.lir.aarch64.AArch64SHA256Op; import jdk.graal.compiler.lir.aarch64.AArch64SHA3Op; @@ -384,6 +385,13 @@ public void emitCompareBranch(PlatformKind cmpKind, Value left, final Value righ append(new BranchOp(cmpCondition, trueDestination, falseDestination, trueDestinationProbability)); } + @Override + public Value emitTimeStamp() { + Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); + append(new AArch64ReadTimestampCounter(result)); + return result; + } + private static ConditionFlag toConditionFlag(boolean isInt, Condition cond, boolean unorderedIsTrue) { return isInt ? toIntConditionFlag(cond) : toFloatConditionFlag(cond, unorderedIsTrue); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java index 8ff803ce83a2..9a386039a530 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java @@ -120,6 +120,7 @@ import jdk.graal.compiler.lir.amd64.AMD64Move.MembarOp; import jdk.graal.compiler.lir.amd64.AMD64Move.StackLeaOp; import jdk.graal.compiler.lir.amd64.AMD64PauseOp; +import jdk.graal.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid; import jdk.graal.compiler.lir.amd64.AMD64SHA1Op; import jdk.graal.compiler.lir.amd64.AMD64SHA256AVX2Op; import jdk.graal.compiler.lir.amd64.AMD64SHA256Op; @@ -1215,4 +1216,22 @@ public boolean useCountLeadingZerosInstruction() { public boolean useCountTrailingZerosInstruction() { return supportsCPUFeature(CPUFeature.BMI1); } + + @Override + public Value emitTimeStamp() { + AMD64ReadTimestampCounterWithProcid timestamp = new AMD64ReadTimestampCounterWithProcid(); + append(timestamp); + // Combine RDX and RAX into a single 64-bit register. + AllocatableValue lo = timestamp.getLowResult(); + Value hi = getArithmetic().emitZeroExtend(timestamp.getHighResult(), 32, 64); + return combineLoAndHi(lo, hi); + } + + /** + * Combines two 32 bit values to a 64 bit value: ( (hi << 32) | lo ). + */ + protected Value combineLoAndHi(Value lo, Value hi) { + Value shiftedHi = getArithmetic().emitShl(hi, emitConstant(LIRKind.value(AMD64Kind.DWORD), JavaConstant.forInt(32))); + return getArithmetic().emitOr(shiftedHi, lo); + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 74fa7dbaa13a..04414791e04b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -75,7 +75,6 @@ import jdk.graal.compiler.lir.amd64.AMD64Move; import jdk.graal.compiler.lir.amd64.AMD64Move.MoveFromRegOp; import jdk.graal.compiler.lir.amd64.AMD64PrefetchOp; -import jdk.graal.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid; import jdk.graal.compiler.lir.amd64.AMD64RestoreRegistersOp; import jdk.graal.compiler.lir.amd64.AMD64SaveRegistersOp; import jdk.graal.compiler.lir.amd64.AMD64VZeroUpper; @@ -624,24 +623,6 @@ protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, Label return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp); } - @Override - public Value emitTimeStamp() { - AMD64ReadTimestampCounterWithProcid timestamp = new AMD64ReadTimestampCounterWithProcid(); - append(timestamp); - // Combine RDX and RAX into a single 64-bit register. - AllocatableValue lo = timestamp.getLowResult(); - Value hi = getArithmetic().emitZeroExtend(timestamp.getHighResult(), 32, 64); - return combineLoAndHi(lo, hi); - } - - /** - * Combines two 32 bit values to a 64 bit value: ( (hi << 32) | lo ). - */ - private Value combineLoAndHi(Value lo, Value hi) { - Value shiftedHi = getArithmetic().emitShl(hi, emitConstant(LIRKind.value(AMD64Kind.DWORD), JavaConstant.forInt(32))); - return getArithmetic().emitOr(shiftedHi, lo); - } - @Override public int getArrayLengthOffset() { return config.arrayOopDescLengthOffset(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java index 0a3786a0a194..131a0bf97b0b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java @@ -33,6 +33,7 @@ import jdk.graal.compiler.lir.LIRInstructionClass; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; /** * Reads the CNTVCT_EL0 generic timer register. Note that two reads to this system register from the @@ -48,8 +49,13 @@ public AArch64ReadTimestampCounter(AllocatableValue result) { this.result = result; } + public Value getResult() { + return result; + } + @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + masm.isb(); masm.mrs(asRegister(result), AArch64Assembler.SystemRegister.CNTVCT_EL0); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java index 100bbef9441a..1b567dac64ec 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java @@ -57,6 +57,8 @@ public abstract class AbstractCompareAndSwapNode extends FixedAccessNode impleme @OptionalInput(State) FrameState stateAfter; protected final MemoryOrderMode memoryOrder; + private final boolean hasSideEffect; + @Override public FrameState stateAfter() { return stateAfter; @@ -71,7 +73,7 @@ public void setStateAfter(FrameState x) { @Override public boolean hasSideEffect() { - return true; + return hasSideEffect; } public ValueNode getExpectedValue() { @@ -89,11 +91,18 @@ public final MemoryOrderMode getMemoryOrder() { public AbstractCompareAndSwapNode(NodeClass c, AddressNode address, LocationIdentity location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType, Stamp stamp, MemoryOrderMode memoryOrder) { + this(c, address, location, expectedValue, newValue, barrierType, stamp, memoryOrder, true); + + } + + protected AbstractCompareAndSwapNode(NodeClass c, AddressNode address, LocationIdentity location, ValueNode expectedValue, ValueNode newValue, + BarrierType barrierType, Stamp stamp, MemoryOrderMode memoryOrder, boolean hasSideEffect) { super(c, address, location, stamp, barrierType); assert expectedValue.getStackKind() == newValue.getStackKind() : Assertions.errorMessageContext("c", c, "adr", address, "loc", location, "expected", expectedValue, "newVal", newValue); this.expectedValue = expectedValue; this.newValue = newValue; this.memoryOrder = memoryOrder; + this.hasSideEffect = hasSideEffect; } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java index 4022c488c1f3..7b06707d3f41 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java @@ -54,7 +54,12 @@ public final class LogicCompareAndSwapNode extends AbstractCompareAndSwapNode { public static final NodeClass TYPE = NodeClass.create(LogicCompareAndSwapNode.class); public LogicCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType, MemoryOrderMode memoryOrder) { - super(TYPE, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder); + this(TYPE, address, expectedValue, newValue, location, barrierType, memoryOrder, true); + } + + private LogicCompareAndSwapNode(NodeClass type, AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, + BarrierType barrierType, MemoryOrderMode memoryOrder, boolean hasSideEffect) { + super(type, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder, hasSideEffect); } @Override @@ -70,4 +75,15 @@ public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, result); } + + /** + * This is a special form of {@link LogicCompareAndSwapNode} that does not have a side effect to + * the interpreter, i.e., it does not modify memory that is visible to other threads or modifies + * state beyond what is captured in {@code FrameState} nodes. Thus, it should only be used with + * caution in suitable scenarios. + */ + public static LogicCompareAndSwapNode createWithoutSideEffect(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location) { + return new LogicCompareAndSwapNode(TYPE, address, expectedValue, newValue, location, BarrierType.NONE, MemoryOrderMode.PLAIN, false); + } + } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index 7e330886f8f6..0ed747f3668b 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it