Skip to content

Commit ea31dbc

Browse files
committed
[GR-64981] Reliably detect pending deoptimization and correctly handle speculations and invalidation.
PullRequest: graal/20814
2 parents 57e5328 + 742925d commit ea31dbc

File tree

10 files changed

+205
-118
lines changed

10 files changed

+205
-118
lines changed

substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/AArch64FarReturnOp.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static com.oracle.svm.core.graal.aarch64.SubstrateAArch64RegisterConfig.fp;
2828
import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
2929
import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.REG;
30+
import static jdk.vm.ci.aarch64.AArch64.lr;
3031
import static jdk.vm.ci.code.ValueUtil.asRegister;
3132

3233
import com.oracle.svm.core.CalleeSavedRegisters;
@@ -67,6 +68,16 @@ public AArch64FarReturnOp(AllocatableValue result, AllocatableValue sp, Allocata
6768
public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
6869
assert sp.getPlatformKind().getSizeInBytes() == FrameAccess.wordSize() && FrameAccess.wordSize() == Long.BYTES : Assertions.errorMessage(sp.getPlatformKind().getSizeInBytes(),
6970
FrameAccess.wordSize());
71+
/*
72+
* Set lr to the new instruction pointer like a regular return does.
73+
*
74+
* For dispatching an exception into a frame pending deoptimization, we farReturn into a
75+
* deopt stub which will do a regular enter and thus push lr. This keeps the stack walkable
76+
* and the frame can be recognized as pending deoptimization due to the return address from
77+
* lr matching the deopt stub entry point.
78+
*/
79+
masm.mov(64, lr, asRegister(ip));
80+
7081
if (!SubstrateOptions.PreserveFramePointer.getValue() && !fromMethodWithCalleeSavedRegisters) {
7182
/* No need to restore anything in the frame of the new stack pointer. */
7283
masm.mov(64, AArch64.sp, asRegister(sp));

substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,8 +1033,9 @@ public void returned(CompilationResultBuilder crb) {
10331033
}
10341034

10351035
/**
1036-
* Generates the prolog of a
1037-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} method.
1036+
* Generates the prologue of a
1037+
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} or
1038+
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#LazyEntryStub} method.
10381039
*/
10391040
protected static class DeoptEntryStubContext extends SubstrateAArch64FrameContext {
10401041
protected final CallingConvention callingConvention;
@@ -1059,8 +1060,8 @@ public void enter(CompilationResultBuilder crb) {
10591060
masm.fmov(64, thirdParameter, fpReturnReg);
10601061

10611062
/*
1062-
* Load DeoptimizedFrame. Perform this operation last, because the first argument
1063-
* register may overlap with the object return register.
1063+
* Pass the address of the frame to deoptimize as first argument. Do this last, because
1064+
* the first argument register may overlap with the object return register.
10641065
*/
10651066
Register firstParameter = ValueUtil.asRegister(callingConvention.getArgument(0));
10661067
masm.mov(64, firstParameter, registerConfig.getFrameRegister());
@@ -1070,7 +1071,7 @@ public void enter(CompilationResultBuilder crb) {
10701071
}
10711072

10721073
/**
1073-
* Generates the epilog of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#ExitStub}
1074+
* Generates the epilogue of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#ExitStub}
10741075
* method.
10751076
*/
10761077
protected static class DeoptExitStubContext extends SubstrateAArch64FrameContext {

substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64FarReturnOp.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
7272
if (!SubstrateOptions.PreserveFramePointer.getValue() && !fromMethodWithCalleeSavedRegisters) {
7373
/* No need to restore anything in the frame of the new stack pointer. */
7474
masm.movq(AMD64.rsp, asRegister(sp));
75+
masm.movq(masm.makeAddress(AMD64.rsp, -FrameAccess.returnAddressSize()), asRegister(ip));
7576
masm.jmp(asRegister(ip));
7677
return;
7778
}

substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,8 +1342,9 @@ public void returned(CompilationResultBuilder crb) {
13421342
}
13431343

13441344
/**
1345-
* Generates the prolog of a
1346-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} method.
1345+
* Generates the prologue of a
1346+
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} or
1347+
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#LazyEntryStub} method.
13471348
*/
13481349
protected static class DeoptEntryStubContext extends SubstrateAMD64FrameContext {
13491350
protected DeoptEntryStubContext(SharedMethod method, CallingConvention callingConvention) {
@@ -1357,28 +1358,35 @@ public void enter(CompilationResultBuilder tasm) {
13571358
Register gpReturnReg = registerConfig.getReturnRegister(JavaKind.Long);
13581359
Register fpReturnReg = registerConfig.getReturnRegister(JavaKind.Double);
13591360

1360-
/* Move the DeoptimizedFrame into the first calling convention register. */
1361-
Register deoptimizedFrame = ValueUtil.asRegister(callingConvention.getArgument(0));
1362-
assert !deoptimizedFrame.equals(gpReturnReg) : "overwriting return reg";
1361+
Register firstArgument = ValueUtil.asRegister(callingConvention.getArgument(0));
1362+
assert !firstArgument.equals(gpReturnReg) : "overwriting return register";
13631363
/*
13641364
* Since this is the target for all deoptimizations we must mark the start of this
13651365
* routine as an indirect target.
13661366
*/
13671367
asm.maybeEmitIndirectTargetMarker();
1368-
asm.movq(deoptimizedFrame, registerConfig.getFrameRegister());
1368+
1369+
/* Pass the address of the frame to deoptimize as first argument. */
1370+
asm.movq(firstArgument, registerConfig.getFrameRegister());
13691371

13701372
/* Copy the original return registers values into the argument registers. */
13711373
asm.movq(ValueUtil.asRegister(callingConvention.getArgument(1)), gpReturnReg);
13721374
asm.movdq(ValueUtil.asRegister(callingConvention.getArgument(2)), fpReturnReg);
13731375

1374-
/* Add a dummy return address to the stack so that RSP is properly aligned. */
1376+
/*
1377+
* Keep the return address slot. This keeps the stack walkable, which is crucial for the
1378+
* interruptible phase of lazy deoptimization. (The return address points to the deopt
1379+
* stub, while the original return address is stored in the deopt slot.)
1380+
*
1381+
* This also ensures that the stack pointer is aligned properly.
1382+
*/
13751383
asm.subq(registerConfig.getFrameRegister(), FrameAccess.returnAddressSize());
13761384
super.enter(tasm);
13771385
}
13781386
}
13791387

13801388
/**
1381-
* Generates the epilog of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#ExitStub}
1389+
* Generates the epilogue of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#ExitStub}
13821390
* method.
13831391
*
13841392
* Note no special handling is necessary for CFI as this will be a direct call from the

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/DeoptimizationRuntime.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ private static void deoptimize(long actionAndReason, SpeculationReason speculati
7171

7272
if (Deoptimizer.Options.TraceDeoptimization.getValue()) {
7373
CodePointer ip = KnownIntrinsics.readReturnAddress();
74+
if (Deoptimizer.checkLazyDeoptimized(ip)) {
75+
ip = Deoptimizer.readLazyDeoptOriginalReturnAddress(CurrentIsolate.getCurrentThread(), sp);
76+
}
7477
traceDeoptimization(actionAndReason, speculation, action, sp, ip);
7578
}
7679

0 commit comments

Comments
 (0)