Skip to content

Commit e5655ea

Browse files
committed
Catch all exceptions in deopt stubs and use correct address for tracing.
1 parent 1df9e1b commit e5655ea

File tree

2 files changed

+69
-42
lines changed

2 files changed

+69
-42
lines changed

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

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

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ private static boolean checkDeoptimizedThenRegisterSpeculationFailure(boolean de
575575
* or we are in the thread to which the frame belongs, and with lazy deoptimization
576576
* enabled, only that thread may deoptimize it eagerly.
577577
*/
578-
CodePointer originalReturnAddress = sp.readWord(0);
578+
CodePointer originalReturnAddress = readLazyDeoptOriginalReturnAddress(targetThread, sp);
579579
SubstrateInstalledCode installedCode = CodeInfoTable.lookupInstalledCode(originalReturnAddress);
580580
registerSpeculationFailure(installedCode, speculation);
581581
return true;
@@ -675,7 +675,7 @@ public static void invalidateMethodOfFrame(IsolateThread thread, Pointer sp, Spe
675675
* only the thread to which the frame belongs to may deoptimize it eagerly, which is the
676676
* current thread.
677677
*/
678-
ip = sp.readWord(0);
678+
ip = readLazyDeoptOriginalReturnAddress(thread, sp);
679679
}
680680
SubstrateInstalledCode installedCode = CodeInfoTable.lookupInstalledCode(ip);
681681
/*
@@ -812,37 +812,49 @@ private static boolean isNonNullValue(UnsignedWord pointer) {
812812
}
813813

814814
@DeoptStub(stubType = StubType.LazyEntryStub)
815-
@Uninterruptible(reason = "gpReturnValue may hold unmanaged reference")
815+
@Uninterruptible(reason = "Rewriting stack; gpReturnValue holds object reference.")
816816
public static UnsignedWord lazyDeoptStubObjectReturn(Pointer framePointer, UnsignedWord gpReturnValue, UnsignedWord fpReturnValue) {
817-
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
818-
assert Options.LazyDeoptimization.getValue();
819-
assert VMThreads.StatusSupport.isStatusJava() : "Deopt stub execution must not be visible to other threads.";
817+
try {
818+
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
819+
assert Options.LazyDeoptimization.getValue();
820+
assert VMThreads.StatusSupport.isStatusJava() : "Deopt stub execution must not be visible to other threads.";
820821

821-
boolean hasException = ExceptionUnwind.getLazyDeoptStubShouldReturnToExceptionHandler();
822-
if (hasException) {
823-
ExceptionUnwind.setLazyDeoptStubShouldReturnToExceptionHandler(false);
824-
}
825-
Object gpReturnValueObject = null;
826-
if (isNonNullValue(gpReturnValue)) {
827-
gpReturnValueObject = ((Pointer) gpReturnValue).toObject();
828-
}
822+
boolean hasException = ExceptionUnwind.getLazyDeoptStubShouldReturnToExceptionHandler();
823+
if (hasException) {
824+
ExceptionUnwind.setLazyDeoptStubShouldReturnToExceptionHandler(false);
825+
}
826+
Object gpReturnValueObject = null;
827+
if (isNonNullValue(gpReturnValue)) {
828+
gpReturnValueObject = ((Pointer) gpReturnValue).toObject();
829+
}
830+
831+
lazyDeoptStubCore(framePointer, gpReturnValue, fpReturnValue, hasException, gpReturnValueObject);
832+
throw UnreachableNode.unreachable();
829833

830-
return lazyDeoptStubCore(framePointer, gpReturnValue, fpReturnValue, hasException, gpReturnValueObject);
834+
} catch (Throwable t) {
835+
throw VMError.shouldNotReachHere("Exception in lazy deopt stub", t);
836+
}
831837
}
832838

833839
@DeoptStub(stubType = StubType.LazyEntryStub)
834-
@Uninterruptible(reason = "gpReturnValue may hold unmanaged reference")
840+
@Uninterruptible(reason = "Rewriting stack.")
835841
public static UnsignedWord lazyDeoptStubPrimitiveReturn(Pointer framePointer, UnsignedWord gpReturnValue, UnsignedWord fpReturnValue) {
836842
/*
837843
* Note: when we dispatch an exception, we enter lazyDeoptStubObjectReturn instead, since
838844
* that involves returning an exception object.
839845
*/
840-
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
841-
assert Options.LazyDeoptimization.getValue();
842-
assert VMThreads.StatusSupport.isStatusJava() : "Deopt stub execution must not be visible to other threads.";
843-
assert !ExceptionUnwind.getLazyDeoptStubShouldReturnToExceptionHandler();
846+
try {
847+
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
848+
assert Options.LazyDeoptimization.getValue();
849+
assert VMThreads.StatusSupport.isStatusJava() : "Deopt stub execution must not be visible to other threads.";
850+
assert !ExceptionUnwind.getLazyDeoptStubShouldReturnToExceptionHandler();
844851

845-
return lazyDeoptStubCore(framePointer, gpReturnValue, fpReturnValue, false, null);
852+
lazyDeoptStubCore(framePointer, gpReturnValue, fpReturnValue, false, null);
853+
throw UnreachableNode.unreachable();
854+
855+
} catch (Throwable t) {
856+
throw VMError.shouldNotReachHere("Exception in lazy deopt stub", t);
857+
}
846858
}
847859

848860
/**
@@ -851,7 +863,7 @@ public static UnsignedWord lazyDeoptStubPrimitiveReturn(Pointer framePointer, Un
851863
* Despite being marked Uninterruptible, this contains interruptible sections when we look up
852864
* the code info, and construct the {@link DeoptimizedFrame}.
853865
*/
854-
@Uninterruptible(reason = "frame will hold objects in unmanaged storage")
866+
@Uninterruptible(reason = "Rewriting stack.")
855867
private static UnsignedWord lazyDeoptStubCore(Pointer framePointer, UnsignedWord gpReturnValue, UnsignedWord fpReturnValue, boolean hasException, Object gpReturnValueObject) {
856868
CodePointer deoptStubAddress = FrameAccess.singleton().readReturnAddress(CurrentIsolate.getCurrentThread(), framePointer);
857869
assert isLazyDeoptStub(deoptStubAddress);
@@ -978,30 +990,36 @@ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0(Po
978990
@DeoptStub(stubType = StubType.EagerEntryStub)
979991
@Uninterruptible(reason = "Frame holds Objects in unmanaged storage.")
980992
public static UnsignedWord eagerDeoptStub(Pointer framePointer, UnsignedWord gpReturnValue, UnsignedWord fpReturnValue) {
981-
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
982-
VMError.guarantee(VMThreads.StatusSupport.isStatusJava(), "Deopt stub execution must not be visible to other threads.");
983-
DeoptimizedFrame frame = (DeoptimizedFrame) ReferenceAccess.singleton().readObjectAt(framePointer, true);
993+
try {
994+
assert PointerUtils.isAMultiple(KnownIntrinsics.readStackPointer(), Word.unsigned(ConfigurationValues.getTarget().stackAlignment));
995+
VMError.guarantee(VMThreads.StatusSupport.isStatusJava(), "Deopt stub execution must not be visible to other threads.");
996+
DeoptimizedFrame frame = (DeoptimizedFrame) ReferenceAccess.singleton().readObjectAt(framePointer, true);
984997

985-
DeoptimizationCounters.counters().deoptCount.inc();
986-
if (DeoptimizationCounters.Options.ProfileDeoptimization.getValue()) {
987-
DeoptimizationCounters.startTime.set(System.nanoTime());
988-
}
998+
DeoptimizationCounters.counters().deoptCount.inc();
999+
if (DeoptimizationCounters.Options.ProfileDeoptimization.getValue()) {
1000+
DeoptimizationCounters.startTime.set(System.nanoTime());
1001+
}
9891002

990-
final Pointer newSp = computeNewFramePointer(framePointer, frame);
1003+
final Pointer newSp = computeNewFramePointer(framePointer, frame);
9911004

992-
/* Build the content of the deopt target stack frames. */
993-
frame.buildContent(newSp);
1005+
/* Build the content of the deopt target stack frames. */
1006+
frame.buildContent(newSp);
9941007

995-
/*
996-
* The frame was pinned to keep it from moving during construction. I can unpin it now that
997-
* I am uninterruptible. (And I have to unpin it.)
998-
*/
999-
frame.unpin();
1008+
/*
1009+
* The frame was pinned to keep it from moving during construction. I can unpin it now
1010+
* that I am uninterruptible. (And I have to unpin it.)
1011+
*/
1012+
frame.unpin();
10001013

1001-
recentDeoptimizationEvents.append(frame.getCompletedMessage());
1014+
recentDeoptimizationEvents.append(frame.getCompletedMessage());
10021015

1003-
/* Do the stack rewriting. Return directly to the deopt target. */
1004-
return rewriteStackStub(newSp, gpReturnValue, fpReturnValue, frame);
1016+
/* Do the stack rewriting. Return directly to the deopt target. */
1017+
rewriteStackStub(newSp, gpReturnValue, fpReturnValue, frame);
1018+
throw UnreachableNode.unreachable();
1019+
1020+
} catch (Throwable t) {
1021+
throw VMError.shouldNotReachHere("Exception in eager deopt stub", t);
1022+
}
10051023
}
10061024

10071025
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
@@ -1111,7 +1129,7 @@ public DeoptimizedFrame deoptimizeEagerly() {
11111129
private static void installLazyDeoptStubReturnAddress(boolean returnValueIsObject, Pointer sourceSp, IsolateThread targetThread) {
11121130
assert Options.LazyDeoptimization.getValue();
11131131
assert VMOperation.isInProgressAtSafepoint();
1114-
CodePointer oldReturnAddress = FrameAccess.singleton().readReturnAddress(targetThread, sourceSp);
1132+
CodePointer originalReturnAddress = FrameAccess.singleton().readReturnAddress(targetThread, sourceSp);
11151133

11161134
/*
11171135
* Replace the return address to the deoptimized method with the entry point of the lazy
@@ -1126,7 +1144,13 @@ private static void installLazyDeoptStubReturnAddress(boolean returnValueIsObjec
11261144
* Write the original return address into the slot where the DeoptimizedFrame would go in
11271145
* the case of eager deoptimization.
11281146
*/
1129-
sourceSp.writeWord(0, oldReturnAddress);
1147+
sourceSp.writeWord(0, originalReturnAddress);
1148+
}
1149+
1150+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
1151+
static CodePointer readLazyDeoptOriginalReturnAddress(IsolateThread thread, Pointer sp) {
1152+
assert checkLazyDeoptimized(thread, sp);
1153+
return sp.readWord(0);
11301154
}
11311155

11321156
@Uninterruptible(reason = "Prevent stack walks from seeing an inconsistent stack.")

0 commit comments

Comments
 (0)