6161import com .oracle .svm .core .heap .GCCause ;
6262import com .oracle .svm .core .heap .Heap ;
6363import com .oracle .svm .core .heap .ReferenceAccess ;
64+ import com .oracle .svm .core .heap .SuspendSerialGCMaxHeapSize ;
6465import com .oracle .svm .core .heap .VMOperationInfos ;
6566import com .oracle .svm .core .log .Log ;
6667import com .oracle .svm .core .log .StringBuilderLog ;
8586import jdk .graal .compiler .api .replacements .Fold ;
8687import jdk .graal .compiler .core .common .NumUtil ;
8788import jdk .graal .compiler .core .common .util .TypeConversion ;
89+ import jdk .graal .compiler .nodes .UnreachableNode ;
8890import jdk .graal .compiler .options .Option ;
8991import jdk .graal .compiler .word .BarrieredAccess ;
9092import jdk .graal .compiler .word .Word ;
@@ -797,53 +799,51 @@ public static UnsignedWord lazyDeoptStubPrimitiveReturn(Pointer framePointer, Un
797799 @ Uninterruptible (reason = "frame will hold objects in unmanaged storage" )
798800 private static UnsignedWord lazyDeoptStubCore (Pointer framePointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue , boolean hasException , Object gpReturnValueObject ) {
799801 DeoptimizedFrame deoptFrame ;
800- Pointer newSp ;
801802
802- StackOverflowCheck .singleton ().makeYellowZoneAvailable ();
803- try {
804- /* The original return address is at offset 0 from the stack pointer */
805- CodePointer originalReturnAddress = framePointer .readWord (0 );
806- assert originalReturnAddress .isNonNull ();
803+ /* The original return address is at offset 0 from the stack pointer */
804+ CodePointer originalReturnAddress = framePointer .readWord (0 );
805+ VMError .guarantee (originalReturnAddress .isNonNull ());
806+
807+ /* Clear the deoptimization slot. */
808+ framePointer .writeWord (0 , Word .nullPointer ());
807809
808- /* Clear the deoptimization slot. */
809- framePointer .writeWord (0 , Word .nullPointer ());
810+ /*
811+ * Write the old return address to the return address slot, so that stack walks see a
812+ * consistent stack.
813+ */
814+ FrameAccess .singleton ().writeReturnAddress (CurrentIsolate .getCurrentThread (), framePointer , originalReturnAddress );
810815
816+ try {
817+ deoptFrame = constructLazilyDeoptimizedFrameInterruptibly (framePointer , originalReturnAddress , hasException );
818+ } catch (OutOfMemoryError ex ) {
811819 /*
812- * Write the old return address to the return address slot, so that stack walks see a
813- * consistent stack.
820+ * If a OutOfMemoryError occurs during lazy deoptimization, we cannot let the frame
821+ * being deoptimized handle the exception, because it might have been invalidated due to
822+ * incorrect assumptions. Note that since unwindExceptionSkippingCaller does not return,
823+ * this try...catch must not have a finally block, as it will not be executed.
814824 */
815- FrameAccess .singleton ().writeReturnAddress (CurrentIsolate .getCurrentThread (), framePointer , originalReturnAddress );
825+ ExceptionUnwind .unwindExceptionSkippingCaller (ex , framePointer );
826+ throw UnreachableNode .unreachable ();
827+ }
816828
817- UntetheredCodeInfo untetheredInfo = CodeInfoTable .lookupCodeInfo (originalReturnAddress );
818- Object tether = CodeInfoAccess .acquireTether (untetheredInfo );
819- try {
820- CodeInfo info = CodeInfoAccess .convert (untetheredInfo , tether );
821- deoptFrame = constructLazilyDeoptimizedFrameInterruptibly (framePointer , info , originalReturnAddress , hasException );
822- } finally {
823- CodeInfoAccess .releaseTether (untetheredInfo , tether );
824- }
829+ DeoptimizationCounters .counters ().deoptCount .inc ();
830+ VMError .guarantee (deoptFrame != null , "was not able to lazily construct a deoptimized frame" );
825831
826- DeoptimizationCounters .counters ().deoptCount .inc ();
827- assert deoptFrame != null : "was not able to lazily construct a deoptimized frame" ;
832+ Pointer newSp = computeNewFramePointer (framePointer , deoptFrame );
828833
829- newSp = computeNewFramePointer (framePointer , deoptFrame );
834+ /* Build the content of the deopt target stack frames. */
835+ deoptFrame .buildContent (newSp );
830836
831- /* Build the content of the deopt target stack frames. */
832- deoptFrame .buildContent (newSp );
837+ /*
838+ * We fail fatally if eager deoptimization is invoked when the lazy deopt stub is executing,
839+ * because eager deoptimization should only be invoked through stack introspection, which
840+ * can only be called from the current thread. Thus, there is no use case for eager
841+ * deoptimization to happen if the current thread is executing the lazy deopt stub.
842+ */
843+ VMError .guarantee (framePointer .readWord (0 ) == Word .nullPointer (), "Eager deoptimization should not occur when lazy deoptimization is in progress" );
833844
834- /*
835- * We fail fatally if eager deoptimization is invoked when the lazy deopt stub is
836- * executing, because eager deoptimization should only be invoked through stack
837- * introspection, which can only be called from the current thread. Thus, there is no
838- * use case for eager deoptimization to happen if the current thread is executing the
839- * lazy deopt stub.
840- */
841- VMError .guarantee (framePointer .readWord (0 ) == Word .nullPointer (), "Eager deoptimization should not occur when lazy deoptimization is in progress" );
845+ recentDeoptimizationEvents .append (deoptFrame .getCompletedMessage ());
842846
843- recentDeoptimizationEvents .append (deoptFrame .getCompletedMessage ());
844- } finally {
845- StackOverflowCheck .singleton ().protectYellowZone ();
846- }
847847 // From this point on, only uninterruptible code may be executed.
848848 UnsignedWord updatedGpReturnValue = gpReturnValue ;
849849 if (gpReturnValueObject != null ) {
@@ -855,8 +855,23 @@ private static UnsignedWord lazyDeoptStubCore(Pointer framePointer, UnsignedWord
855855 }
856856
857857 @ Uninterruptible (reason = "Wrapper to call interruptible methods" , calleeMustBe = false )
858- private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly (Pointer sourceSp , CodeInfo info , CodePointer ip , boolean hasException ) {
859- return constructLazilyDeoptimizedFrameInterruptibly0 (sourceSp , info , ip , hasException );
858+ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly (Pointer sourceSp , CodePointer ip , boolean hasException ) {
859+ StackOverflowCheck .singleton ().makeYellowZoneAvailable ();
860+ SuspendSerialGCMaxHeapSize .suspendInCurrentThread ();
861+
862+ try {
863+ UntetheredCodeInfo untetheredInfo = CodeInfoTable .lookupCodeInfo (ip );
864+ Object tether = CodeInfoAccess .acquireTether (untetheredInfo );
865+ try {
866+ CodeInfo info = CodeInfoAccess .convert (untetheredInfo , tether );
867+ return constructLazilyDeoptimizedFrameInterruptibly0 (sourceSp , info , ip , hasException );
868+ } finally {
869+ CodeInfoAccess .releaseTether (untetheredInfo , tether );
870+ }
871+ } finally {
872+ SuspendSerialGCMaxHeapSize .resumeInCurrentThread ();
873+ StackOverflowCheck .singleton ().protectYellowZone ();
874+ }
860875 }
861876
862877 private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0 (Pointer sourceSp , CodeInfo info , CodePointer ip , boolean hasException ) {
0 commit comments