2525package com .oracle .svm .core .deopt ;
2626
2727import static com .oracle .svm .core .Uninterruptible .CALLED_FROM_UNINTERRUPTIBLE_CODE ;
28+ import static com .oracle .svm .core .stack .JavaFrameAnchors .verifyTopFrameAnchor ;
2829
2930import java .lang .annotation .ElementType ;
3031import java .lang .annotation .Retention ;
@@ -813,7 +814,7 @@ private static boolean isNonNullValue(UnsignedWord pointer) {
813814
814815 @ DeoptStub (stubType = StubType .LazyEntryStub )
815816 @ Uninterruptible (reason = "Rewriting stack; gpReturnValue holds object reference." )
816- public static UnsignedWord lazyDeoptStubObjectReturn (Pointer framePointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
817+ public static UnsignedWord lazyDeoptStubObjectReturn (Pointer originalStackPointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
817818 try {
818819 assert PointerUtils .isAMultiple (KnownIntrinsics .readStackPointer (), Word .unsigned (ConfigurationValues .getTarget ().stackAlignment ));
819820 assert Options .LazyDeoptimization .getValue ();
@@ -828,7 +829,7 @@ public static UnsignedWord lazyDeoptStubObjectReturn(Pointer framePointer, Unsig
828829 gpReturnValueObject = ((Pointer ) gpReturnValue ).toObject ();
829830 }
830831
831- lazyDeoptStubCore (framePointer , gpReturnValue , fpReturnValue , hasException , gpReturnValueObject );
832+ lazyDeoptStubCore (originalStackPointer , gpReturnValue , fpReturnValue , hasException , gpReturnValueObject );
832833 throw UnreachableNode .unreachable ();
833834
834835 } catch (Throwable t ) {
@@ -838,7 +839,7 @@ public static UnsignedWord lazyDeoptStubObjectReturn(Pointer framePointer, Unsig
838839
839840 @ DeoptStub (stubType = StubType .LazyEntryStub )
840841 @ Uninterruptible (reason = "Rewriting stack." )
841- public static UnsignedWord lazyDeoptStubPrimitiveReturn (Pointer framePointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
842+ public static UnsignedWord lazyDeoptStubPrimitiveReturn (Pointer originalStackPointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
842843 /*
843844 * Note: when we dispatch an exception, we enter lazyDeoptStubObjectReturn instead, since
844845 * that involves returning an exception object.
@@ -849,7 +850,7 @@ public static UnsignedWord lazyDeoptStubPrimitiveReturn(Pointer framePointer, Un
849850 assert VMThreads .StatusSupport .isStatusJava () : "Deopt stub execution must not be visible to other threads." ;
850851 assert !ExceptionUnwind .getLazyDeoptStubShouldReturnToExceptionHandler ();
851852
852- lazyDeoptStubCore (framePointer , gpReturnValue , fpReturnValue , false , null );
853+ lazyDeoptStubCore (originalStackPointer , gpReturnValue , fpReturnValue , false , null );
853854 throw UnreachableNode .unreachable ();
854855
855856 } catch (Throwable t ) {
@@ -864,32 +865,32 @@ public static UnsignedWord lazyDeoptStubPrimitiveReturn(Pointer framePointer, Un
864865 * the code info, and construct the {@link DeoptimizedFrame}.
865866 */
866867 @ Uninterruptible (reason = "Rewriting stack." )
867- private static UnsignedWord lazyDeoptStubCore (Pointer framePointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue , boolean hasException , Object gpReturnValueObject ) {
868- CodePointer deoptStubAddress = FrameAccess .singleton ().readReturnAddress (CurrentIsolate .getCurrentThread (), framePointer );
868+ private static UnsignedWord lazyDeoptStubCore (Pointer originalStackPointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue , boolean hasException , Object gpReturnValueObject ) {
869+ CodePointer deoptStubAddress = FrameAccess .singleton ().readReturnAddress (CurrentIsolate .getCurrentThread (), originalStackPointer );
869870 assert isLazyDeoptStub (deoptStubAddress );
870871
871872 /* The original return address is at offset 0 from the stack pointer */
872- CodePointer originalReturnAddress = framePointer .readWord (0 );
873+ CodePointer originalReturnAddress = originalStackPointer .readWord (0 );
873874 VMError .guarantee (originalReturnAddress .isNonNull ());
874875
875876 DeoptimizedFrame deoptFrame ;
876877 try {
877- deoptFrame = constructLazilyDeoptimizedFrameInterruptibly (framePointer , originalReturnAddress , hasException );
878+ deoptFrame = constructLazilyDeoptimizedFrameInterruptibly (originalStackPointer , originalReturnAddress , hasException );
878879 } catch (OutOfMemoryError ex ) {
879880 /*
880881 * If a OutOfMemoryError occurs during lazy deoptimization, we cannot let the frame
881882 * being deoptimized handle the exception, because it might have been invalidated due to
882883 * incorrect assumptions. Note that since unwindExceptionSkippingCaller does not return,
883884 * this try...catch must not have a finally block, as it will not be executed.
884885 */
885- ExceptionUnwind .unwindExceptionSkippingCaller (ex , framePointer );
886+ ExceptionUnwind .unwindExceptionSkippingCaller (ex , originalStackPointer );
886887 throw UnreachableNode .unreachable ();
887888 }
888889
889890 DeoptimizationCounters .counters ().deoptCount .inc ();
890891 VMError .guarantee (deoptFrame != null , "was not able to lazily construct a deoptimized frame" );
891892
892- Pointer newSp = computeNewFramePointer ( framePointer , deoptFrame );
893+ Pointer newSp = computeNewStackPointer ( originalStackPointer , deoptFrame );
893894
894895 /* Build the content of the deopt target stack frames. */
895896 deoptFrame .buildContent (newSp );
@@ -900,9 +901,9 @@ private static UnsignedWord lazyDeoptStubCore(Pointer framePointer, UnsignedWord
900901 * can only be called from the current thread. Thus, there is no use case for eager
901902 * deoptimization to happen if the current thread is executing the lazy deopt stub.
902903 */
903- VMError .guarantee (framePointer .readWord (0 ) == originalReturnAddress , "Eager deoptimization should not occur when lazy deoptimization is in progress" );
904+ VMError .guarantee (originalStackPointer .readWord (0 ) == originalReturnAddress , "Eager deoptimization should not occur when lazy deoptimization is in progress" );
904905
905- CodePointer returnAddressAfter = FrameAccess .singleton ().readReturnAddress (CurrentIsolate .getCurrentThread (), framePointer );
906+ CodePointer returnAddressAfter = FrameAccess .singleton ().readReturnAddress (CurrentIsolate .getCurrentThread (), originalStackPointer );
906907 VMError .guarantee (returnAddressAfter == deoptStubAddress , "Return address must remain unchanged during deoptimization" );
907908
908909 recentDeoptimizationEvents .append (deoptFrame .getCompletedMessage ());
@@ -962,7 +963,7 @@ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0(Po
962963 * When {@link #eagerDeoptStub} is "called", the stack looks like this:
963964 *
964965 * <pre>
965- * : :
966+ * : : highest stack address
966967 * | |
967968 * | | frame of the
968969 * +--------------------------------+ deoptimized method
@@ -977,9 +978,8 @@ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0(Po
977978 * The instructions to compute the parameters must be generated in this method's prologue by a
978979 * backend-specific FrameContext class.
979980 *
980- * @param framePointer This is a pointer to the reference which was written in
981- * {@link #deoptimizeInRange} on the stack (the slot above the original return
982- * address).
981+ * @param originalStackPointer the original stack pointer of the deoptimized method (points to
982+ * the {@link DeoptimizedFrame} object).
983983 * @param gpReturnValue This is the value which was stored in the general purpose return
984984 * register when the deopt stub was reached. It must be restored to the register
985985 * before completion of the stub.
@@ -989,18 +989,19 @@ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0(Po
989989 */
990990 @ DeoptStub (stubType = StubType .EagerEntryStub )
991991 @ Uninterruptible (reason = "Frame holds Objects in unmanaged storage." )
992- public static UnsignedWord eagerDeoptStub (Pointer framePointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
992+ public static UnsignedWord eagerDeoptStub (Pointer originalStackPointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
993993 try {
994994 assert PointerUtils .isAMultiple (KnownIntrinsics .readStackPointer (), Word .unsigned (ConfigurationValues .getTarget ().stackAlignment ));
995995 VMError .guarantee (VMThreads .StatusSupport .isStatusJava (), "Deopt stub execution must not be visible to other threads." );
996- DeoptimizedFrame frame = (DeoptimizedFrame ) ReferenceAccess .singleton ().readObjectAt (framePointer , true );
996+
997+ DeoptimizedFrame frame = (DeoptimizedFrame ) ReferenceAccess .singleton ().readObjectAt (originalStackPointer , true );
997998
998999 DeoptimizationCounters .counters ().deoptCount .inc ();
9991000 if (DeoptimizationCounters .Options .ProfileDeoptimization .getValue ()) {
10001001 DeoptimizationCounters .startTime .set (System .nanoTime ());
10011002 }
10021003
1003- final Pointer newSp = computeNewFramePointer ( framePointer , frame );
1004+ final Pointer newSp = computeNewStackPointer ( originalStackPointer , frame );
10041005
10051006 /* Build the content of the deopt target stack frames. */
10061007 frame .buildContent (newSp );
@@ -1023,13 +1024,15 @@ public static UnsignedWord eagerDeoptStub(Pointer framePointer, UnsignedWord gpR
10231024 }
10241025
10251026 @ Uninterruptible (reason = CALLED_FROM_UNINTERRUPTIBLE_CODE , mayBeInlined = true )
1026- private static Pointer computeNewFramePointer (Pointer originalFramePointer , DeoptimizedFrame deoptimizedFrame ) {
1027- /* Computation of the new stack pointer: we start with the stack pointer of this frame. */
1028- return originalFramePointer
1029- /* Remove the size of the frame that gets deoptimized. */
1030- .add (Word .unsigned (deoptimizedFrame .getSourceTotalFrameSize ()))
1031- /* Add the size of the deoptimization target frames. */
1032- .subtract (deoptimizedFrame .getTargetContent ().getSize ());
1027+ private static Pointer computeNewStackPointer (Pointer originalStackPointer , DeoptimizedFrame deoptimizedFrame ) {
1028+ /* Remove the size of the frame that gets deoptimized. */
1029+ Pointer callerStackPointer = originalStackPointer .add (Word .unsigned (deoptimizedFrame .getSourceTotalFrameSize ()));
1030+
1031+ /* Verify that the top frame anchor is in a part of the stack that is not rewritten. */
1032+ verifyTopFrameAnchor (callerStackPointer );
1033+
1034+ /* Add the size of the deoptimization target frames. */
1035+ return callerStackPointer .subtract (deoptimizedFrame .getTargetContent ().getSize ());
10331036 }
10341037
10351038 /**
@@ -1054,7 +1057,6 @@ private static UnsignedWord rewriteStackStub(Pointer newSp, UnsignedWord gpRetur
10541057 if (DeoptimizationCounters .Options .ProfileDeoptimization .getValue ()) {
10551058 DeoptimizationCounters .counters ().timeSpentInDeopt .add (System .nanoTime () - DeoptimizationCounters .startTime .get ());
10561059 }
1057-
10581060 return gpReturnValue ;
10591061 }
10601062
0 commit comments