Skip to content

Commit b2fcb9b

Browse files
committed
[GR-68134] In deoptimization stub, save registers again and restore return address.
PullRequest: graal/21677
2 parents 41825fe + 6714e8b commit b2fcb9b

File tree

4 files changed

+184
-182
lines changed

4 files changed

+184
-182
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
7373
/* No need to restore anything in the frame of the new stack pointer. */
7474
masm.mov(64, AArch64.sp, asRegister(sp));
7575
returnTo(asRegister(ip), masm);
76+
return;
7677
}
7778

7879
/*

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

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -487,27 +487,19 @@ public SubstrateLIRGenerationResult(CompilationIdentifier compilationId, LIR lir
487487
super(compilationId, lir, frameMapBuilder, registerAllocationConfig, callingConvention);
488488
this.method = method;
489489

490-
/*
491-
* Besides for methods with callee saved registers, we reserve additional stack space
492-
* for lazyDeoptStub too. This is necessary because the lazy deopt stub might read
493-
* callee-saved register values in the callee of the function to be deoptimized, thus
494-
* that stack space must not be overwritten by the lazy deopt stub.
495-
*/
496-
if (method.hasCalleeSavedRegisters() || method.getDeoptStubType() == Deoptimizer.StubType.LazyEntryStub) {
490+
if (method.hasCalleeSavedRegisters()) {
497491
AArch64CalleeSavedRegisters calleeSavedRegisters = AArch64CalleeSavedRegisters.singleton();
498492
FrameMap frameMap = ((FrameMapBuilderTool) frameMapBuilder).getFrameMap();
499493
int registerSaveAreaSizeInBytes = calleeSavedRegisters.getSaveAreaSize();
500494
StackSlot calleeSaveArea = frameMap.allocateStackMemory(registerSaveAreaSizeInBytes, frameMap.getTarget().wordSize);
501495

502-
if (method.hasCalleeSavedRegisters()) {
503-
/*
504-
* The offset of the callee save area must be fixed early during image
505-
* generation. It is accessed when compiling methods that have a call with
506-
* callee-saved calling convention. Here we verify that offset computed earlier
507-
* is the same as the offset actually reserved.
508-
*/
509-
calleeSavedRegisters.verifySaveAreaOffsetInFrame(calleeSaveArea.getRawOffset());
510-
}
496+
/*
497+
* The offset of the callee save area must be fixed early during image generation.
498+
* It is accessed when compiling methods that have a call with callee-saved calling
499+
* convention. Here we verify that offset computed earlier is the same as the offset
500+
* actually reserved.
501+
*/
502+
calleeSavedRegisters.verifySaveAreaOffsetInFrame(calleeSaveArea.getRawOffset());
511503
}
512504

513505
if (method.canDeoptimize() || method.isDeoptTarget()) {
@@ -1042,9 +1034,8 @@ public void returned(CompilationResultBuilder crb) {
10421034
}
10431035

10441036
/**
1045-
* Generates the prologue of a
1046-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} or
1047-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#LazyEntryStub} method.
1037+
* Generates the prologue of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EntryStub}
1038+
* method.
10481039
*/
10491040
protected static class DeoptEntryStubContext extends SubstrateAArch64FrameContext {
10501041
protected final CallingConvention callingConvention;
@@ -1058,9 +1049,18 @@ protected DeoptEntryStubContext(SharedMethod method, CallingConvention callingCo
10581049
public void enter(CompilationResultBuilder crb) {
10591050
AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm;
10601051
RegisterConfig registerConfig = crb.frameMap.getRegisterConfig();
1052+
Register frameRegister = registerConfig.getFrameRegister();
10611053
Register gpReturnReg = registerConfig.getReturnRegister(JavaKind.Object);
10621054
Register fpReturnReg = registerConfig.getReturnRegister(JavaKind.Double);
10631055

1056+
/* Create the frame. */
1057+
super.enter(crb);
1058+
1059+
/*
1060+
* Synthesize the parameters for the deopt stub. This needs to be done after enter() to
1061+
* avoid overwriting register values that it might save to the stack.
1062+
*/
1063+
10641064
/* Pass the general purpose and floating point registers to the deopt stub. */
10651065
Register secondParameter = ValueUtil.asRegister(callingConvention.getArgument(1));
10661066
masm.mov(64, secondParameter, gpReturnReg);
@@ -1073,9 +1073,7 @@ public void enter(CompilationResultBuilder crb) {
10731073
* the first argument register may overlap with the object return register.
10741074
*/
10751075
Register firstParameter = ValueUtil.asRegister(callingConvention.getArgument(0));
1076-
masm.mov(64, firstParameter, registerConfig.getFrameRegister());
1077-
1078-
super.enter(crb);
1076+
masm.add(64, firstParameter, frameRegister, crb.frameMap.totalFrameSize());
10791077
}
10801078
}
10811079

@@ -1343,7 +1341,7 @@ public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult
13431341
}
13441342

13451343
protected FrameContext createFrameContext(SharedMethod method, Deoptimizer.StubType stubType, CallingConvention callingConvention) {
1346-
if (stubType == Deoptimizer.StubType.EagerEntryStub || stubType == Deoptimizer.StubType.LazyEntryStub) {
1344+
if (stubType == Deoptimizer.StubType.EntryStub) {
13471345
return new DeoptEntryStubContext(method, callingConvention);
13481346
} else if (stubType == Deoptimizer.StubType.ExitStub) {
13491347
return new DeoptExitStubContext(method, callingConvention);

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

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -564,27 +564,19 @@ public SubstrateLIRGenerationResult(CompilationIdentifier compilationId, LIR lir
564564
super(compilationId, lir, frameMapBuilder, registerAllocationConfig, callingConvention);
565565
this.method = method;
566566

567-
/*
568-
* Besides for methods with callee saved registers, we reserve additional stack space
569-
* for lazyDeoptStub too. This is necessary because the lazy deopt stub might read
570-
* callee-saved register values in the callee of the function to be deoptimized, thus
571-
* that stack space must not be overwritten by the lazy deopt stub.
572-
*/
573-
if (method.hasCalleeSavedRegisters() || method.getDeoptStubType() == Deoptimizer.StubType.LazyEntryStub) {
567+
if (method.hasCalleeSavedRegisters()) {
574568
AMD64CalleeSavedRegisters calleeSavedRegisters = AMD64CalleeSavedRegisters.singleton();
575569
FrameMap frameMap = ((FrameMapBuilderTool) frameMapBuilder).getFrameMap();
576570
int registerSaveAreaSizeInBytes = calleeSavedRegisters.getSaveAreaSize();
577571
StackSlot calleeSaveArea = frameMap.allocateStackMemory(registerSaveAreaSizeInBytes, frameMap.getTarget().wordSize);
578572

579-
if (method.hasCalleeSavedRegisters()) {
580-
/*
581-
* The offset of the callee save area must be fixed early during image
582-
* generation. It is accessed when compiling methods that have a call with
583-
* callee-saved calling convention. Here we verify that offset computed earlier
584-
* is the same as the offset actually reserved.
585-
*/
586-
calleeSavedRegisters.verifySaveAreaOffsetInFrame(calleeSaveArea.getRawOffset());
587-
}
573+
/*
574+
* The offset of the callee save area must be fixed early during image generation.
575+
* It is accessed when compiling methods that have a call with callee-saved calling
576+
* convention. Here we verify that offset computed earlier is the same as the offset
577+
* actually reserved.
578+
*/
579+
calleeSavedRegisters.verifySaveAreaOffsetInFrame(calleeSaveArea.getRawOffset());
588580
}
589581

590582
if (method.canDeoptimize() || method.isDeoptTarget()) {
@@ -1344,9 +1336,8 @@ public void returned(CompilationResultBuilder crb) {
13441336
}
13451337

13461338
/**
1347-
* Generates the prologue of a
1348-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub} or
1349-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#LazyEntryStub} method.
1339+
* Generates the prologue of a {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EntryStub}
1340+
* method.
13501341
*/
13511342
protected static class DeoptEntryStubContext extends SubstrateAMD64FrameContext {
13521343
protected DeoptEntryStubContext(SharedMethod method, CallingConvention callingConvention) {
@@ -1357,33 +1348,39 @@ protected DeoptEntryStubContext(SharedMethod method, CallingConvention callingCo
13571348
public void enter(CompilationResultBuilder tasm) {
13581349
AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
13591350
RegisterConfig registerConfig = tasm.frameMap.getRegisterConfig();
1351+
Register frameRegister = registerConfig.getFrameRegister();
13601352
Register gpReturnReg = registerConfig.getReturnRegister(JavaKind.Long);
13611353
Register fpReturnReg = registerConfig.getReturnRegister(JavaKind.Double);
1362-
13631354
Register firstArgument = ValueUtil.asRegister(callingConvention.getArgument(0));
13641355
assert !firstArgument.equals(gpReturnReg) : "overwriting return register";
1356+
13651357
/*
13661358
* Since this is the target for all deoptimizations we must mark the start of this
13671359
* routine as an indirect target.
13681360
*/
13691361
asm.maybeEmitIndirectTargetMarker();
13701362

1371-
/* Pass the address of the frame to deoptimize as first argument. */
1372-
asm.movq(firstArgument, registerConfig.getFrameRegister());
1373-
1374-
/* Copy the original return registers values into the argument registers. */
1375-
asm.movq(ValueUtil.asRegister(callingConvention.getArgument(1)), gpReturnReg);
1376-
asm.movdq(ValueUtil.asRegister(callingConvention.getArgument(2)), fpReturnReg);
1377-
13781363
/*
1379-
* Keep the return address slot. This keeps the stack walkable, which is crucial for the
1380-
* interruptible phase of lazy deoptimization. (The return address points to the deopt
1381-
* stub, while the original return address is stored in the deopt slot.)
1364+
* Keep the return address slot. The correct return address is written in the stub
1365+
* itself (read more there). The original return address is stored in the deopt slot.
13821366
*
1383-
* This also ensures that the stack pointer is aligned properly.
1367+
* Keeping this slot also ensures that the stack pointer is aligned properly.
13841368
*/
13851369
asm.subq(registerConfig.getFrameRegister(), FrameAccess.returnAddressSize());
1370+
13861371
super.enter(tasm);
1372+
1373+
/*
1374+
* Synthesize the parameters for the deopt stub. This needs to be done after enter() to
1375+
* avoid overwriting register values that it might save to the stack.
1376+
*/
1377+
1378+
/* Pass the address of the frame to deoptimize as first argument. */
1379+
asm.leaq(firstArgument, new AMD64Address(frameRegister, tasm.frameMap.totalFrameSize()));
1380+
1381+
/* Copy the original return registers values into the argument registers. */
1382+
asm.movq(ValueUtil.asRegister(callingConvention.getArgument(1)), gpReturnReg);
1383+
asm.movdq(ValueUtil.asRegister(callingConvention.getArgument(2)), fpReturnReg);
13871384
}
13881385
}
13891386

@@ -1392,7 +1389,7 @@ public void enter(CompilationResultBuilder tasm) {
13921389
* method.
13931390
*
13941391
* Note no special handling is necessary for CFI as this will be a direct call from the
1395-
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EagerEntryStub}.
1392+
* {@link com.oracle.svm.core.deopt.Deoptimizer.StubType#EntryStub}.
13961393
*/
13971394
protected static class DeoptExitStubContext extends SubstrateAMD64FrameContext {
13981395
protected DeoptExitStubContext(SharedMethod method, CallingConvention callingConvention) {
@@ -1918,7 +1915,7 @@ protected AMD64MacroAssembler createAssembler(OptionValues options) {
19181915
}
19191916

19201917
protected FrameContext createFrameContext(SharedMethod method, Deoptimizer.StubType stubType, CallingConvention callingConvention) {
1921-
if (stubType == Deoptimizer.StubType.EagerEntryStub || stubType == Deoptimizer.StubType.LazyEntryStub) {
1918+
if (stubType == Deoptimizer.StubType.EntryStub) {
19221919
return new DeoptEntryStubContext(method, callingConvention);
19231920
} else if (stubType == Deoptimizer.StubType.ExitStub) {
19241921
return new DeoptExitStubContext(method, callingConvention);

0 commit comments

Comments
 (0)