@@ -4916,6 +4916,9 @@ HCIMPLEND
49164916
49174917void JIT_Patchpoint (int * counter, int ilOffset)
49184918{
4919+ // BEGIN_PRESERVE_LAST_ERROR;
4920+ DWORD dwLastError = ::GetLastError ();
4921+
49194922 // This method may not return normally
49204923 STATIC_CONTRACT_GC_NOTRIGGER;
49214924 STATIC_CONTRACT_MODE_COOPERATIVE;
@@ -4929,6 +4932,8 @@ void JIT_Patchpoint(int* counter, int ilOffset)
49294932 LoaderAllocator* allocator = pMD->GetLoaderAllocator ();
49304933 OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager ();
49314934 PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo (ip);
4935+ PCODE osrMethodCode = NULL ;
4936+ bool isNewMethod = false ;
49324937
49334938 // In the current prototype, counter is shared by all patchpoints
49344939 // in a method, so no matter what happens below, we don't want to
@@ -4955,12 +4960,12 @@ void JIT_Patchpoint(int* counter, int ilOffset)
49554960 {
49564961 LOG ((LF_TIEREDCOMPILATION, LL_INFO1000, " Jit_Patchpoint: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n " ,
49574962 ppId, ip, pMD, pMD->m_pszDebugClassName , pMD->m_pszDebugMethodName , ilOffset));
4958- return ;
4963+
4964+ goto DONE;
49594965 }
49604966
49614967 // See if we have an OSR method for this patchpoint.
4962- PCODE osrMethodCode = ppInfo->m_osrMethodCode ;
4963- bool isNewMethod = false ;
4968+ osrMethodCode = ppInfo->m_osrMethodCode ;
49644969
49654970 if (osrMethodCode == NULL )
49664971 {
@@ -4983,7 +4988,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
49834988 {
49844989 LOG ((LF_TIEREDCOMPILATION, LL_INFO10, " Jit_Patchpoint: ignoring patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n " ,
49854990 ppId, ip, pMD, pMD->m_pszDebugClassName , pMD->m_pszDebugMethodName , ilOffset));
4986- return ;
4991+ goto DONE ;
49874992 }
49884993#endif
49894994
@@ -5024,15 +5029,15 @@ void JIT_Patchpoint(int* counter, int ilOffset)
50245029 // Defer, if we haven't yet reached the limit
50255030 if (hitCount < hitLimit)
50265031 {
5027- return ;
5032+ goto DONE ;
50285033 }
50295034
50305035 // Third, make sure no other thread is trying to create the OSR method.
50315036 LONG oldFlags = ppInfo->m_flags ;
50325037 if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered)
50335038 {
50345039 LOG ((LF_TIEREDCOMPILATION, LL_INFO1000, " Jit_Patchpoint: AWAITING OSR method for patchpoint [%d] (0x%p)\n " , ppId, ip));
5035- return ;
5040+ goto DONE ;
50365041 }
50375042
50385043 LONG newFlags = oldFlags | PerPatchpointInfo::patchpoint_triggered;
@@ -5041,7 +5046,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
50415046 if (!triggerTransition)
50425047 {
50435048 LOG ((LF_TIEREDCOMPILATION, LL_INFO1000, " Jit_Patchpoint: (lost race) AWAITING OSR method for patchpoint [%d] (0x%p)\n " , ppId, ip));
5044- return ;
5049+ goto DONE ;
50455050 }
50465051
50475052 // Time to create the OSR method.
@@ -5071,7 +5076,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
50715076 " marking patchpoint invalid for Method=0x%pM il offset %d\n " , ip, pMD, ilOffset);
50725077
50735078 InterlockedOr (&ppInfo->m_flags , (LONG)PerPatchpointInfo::patchpoint_invalid);
5074- return ;
5079+ goto DONE ;
50755080 }
50765081
50775082 // We've successfully created the osr method; make it available.
@@ -5083,115 +5088,126 @@ void JIT_Patchpoint(int* counter, int ilOffset)
50835088 // If we get here, we have code to transition to...
50845089 _ASSERTE (osrMethodCode != NULL );
50855090
5086- Thread *pThread = GetThread ();
5091+ {
5092+ Thread *pThread = GetThread ();
50875093
50885094#ifdef FEATURE_HIJACK
5089- // We can't crawl the stack of a thread that currently has a hijack pending
5090- // (since the hijack routine won't be recognized by any code manager). So we
5091- // Undo any hijack, the EE will re-attempt it later.
5092- pThread->UnhijackThread ();
5095+ // We can't crawl the stack of a thread that currently has a hijack pending
5096+ // (since the hijack routine won't be recognized by any code manager). So we
5097+ // Undo any hijack, the EE will re-attempt it later.
5098+ pThread->UnhijackThread ();
50935099#endif
50945100
5095- // Find context for the original method
5096- CONTEXT *pFrameContext = NULL ;
5101+ // Find context for the original method
5102+ CONTEXT *pFrameContext = NULL ;
50975103#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
5098- DWORD contextSize = 0 ;
5099- ULONG64 xStateCompactionMask = 0 ;
5100- DWORD contextFlags = CONTEXT_FULL;
5101- if (Thread::AreCetShadowStacksEnabled ())
5102- {
5103- xStateCompactionMask = XSTATE_MASK_CET_U;
5104- contextFlags |= CONTEXT_XSTATE;
5105- }
5104+ DWORD contextSize = 0 ;
5105+ ULONG64 xStateCompactionMask = 0 ;
5106+ DWORD contextFlags = CONTEXT_FULL;
5107+ if (Thread::AreCetShadowStacksEnabled ())
5108+ {
5109+ xStateCompactionMask = XSTATE_MASK_CET_U;
5110+ contextFlags |= CONTEXT_XSTATE;
5111+ }
51065112
5107- // The initialize call should fail but return contextSize
5108- BOOL success = g_pfnInitializeContext2 ?
5109- g_pfnInitializeContext2 (NULL , contextFlags, NULL , &contextSize, xStateCompactionMask) :
5110- InitializeContext (NULL , contextFlags, NULL , &contextSize);
5113+ // The initialize call should fail but return contextSize
5114+ BOOL success = g_pfnInitializeContext2 ?
5115+ g_pfnInitializeContext2 (NULL , contextFlags, NULL , &contextSize, xStateCompactionMask) :
5116+ InitializeContext (NULL , contextFlags, NULL , &contextSize);
51115117
5112- _ASSERTE (!success && (GetLastError () == ERROR_INSUFFICIENT_BUFFER));
5118+ _ASSERTE (!success && (GetLastError () == ERROR_INSUFFICIENT_BUFFER));
51135119
5114- PVOID pBuffer = _alloca (contextSize);
5115- success = g_pfnInitializeContext2 ?
5116- g_pfnInitializeContext2 (pBuffer, contextFlags, &pFrameContext, &contextSize, xStateCompactionMask) :
5117- InitializeContext (pBuffer, contextFlags, &pFrameContext, &contextSize);
5118- _ASSERTE (success);
5120+ PVOID pBuffer = _alloca (contextSize);
5121+ success = g_pfnInitializeContext2 ?
5122+ g_pfnInitializeContext2 (pBuffer, contextFlags, &pFrameContext, &contextSize, xStateCompactionMask) :
5123+ InitializeContext (pBuffer, contextFlags, &pFrameContext, &contextSize);
5124+ _ASSERTE (success);
51195125#else // TARGET_WINDOWS && TARGET_AMD64
5120- CONTEXT frameContext;
5121- frameContext.ContextFlags = CONTEXT_FULL;
5122- pFrameContext = &frameContext;
5126+ CONTEXT frameContext;
5127+ frameContext.ContextFlags = CONTEXT_FULL;
5128+ pFrameContext = &frameContext;
51235129#endif // TARGET_WINDOWS && TARGET_AMD64
51245130
5125- // Find context for the original method
5126- RtlCaptureContext (pFrameContext);
5131+ // Find context for the original method
5132+ RtlCaptureContext (pFrameContext);
51275133
51285134#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
5129- if (Thread::AreCetShadowStacksEnabled ())
5130- {
5131- pFrameContext->ContextFlags |= CONTEXT_XSTATE;
5132- SetXStateFeaturesMask (pFrameContext, xStateCompactionMask);
5133- SetSSP (pFrameContext, _rdsspq ());
5134- }
5135+ if (Thread::AreCetShadowStacksEnabled ())
5136+ {
5137+ pFrameContext->ContextFlags |= CONTEXT_XSTATE;
5138+ SetXStateFeaturesMask (pFrameContext, xStateCompactionMask);
5139+ SetSSP (pFrameContext, _rdsspq ());
5140+ }
51355141#endif // TARGET_WINDOWS && TARGET_AMD64
51365142
5137- // Walk back to the original method frame
5138- pThread->VirtualUnwindToFirstManagedCallFrame (pFrameContext);
5143+ // Walk back to the original method frame
5144+ pThread->VirtualUnwindToFirstManagedCallFrame (pFrameContext);
51395145
5140- // Remember original method FP and SP because new method will inherit them.
5141- UINT_PTR currentSP = GetSP (pFrameContext);
5142- UINT_PTR currentFP = GetFP (pFrameContext);
5146+ // Remember original method FP and SP because new method will inherit them.
5147+ UINT_PTR currentSP = GetSP (pFrameContext);
5148+ UINT_PTR currentFP = GetFP (pFrameContext);
51435149
5144- // We expect to be back at the right IP
5145- if ((UINT_PTR)ip != GetIP (pFrameContext))
5146- {
5147- // Should be fatal
5148- STRESS_LOG2 (LF_TIEREDCOMPILATION, LL_FATALERROR, " Jit_Patchpoint: patchpoint (0x%p) TRANSITION"
5149- " unexpected context IP 0x%p\n " , ip, GetIP (pFrameContext));
5150- EEPOLICY_HANDLE_FATAL_ERROR (COR_E_EXECUTIONENGINE);
5151- }
5150+ // We expect to be back at the right IP
5151+ if ((UINT_PTR)ip != GetIP (pFrameContext))
5152+ {
5153+ // Should be fatal
5154+ STRESS_LOG2 (LF_TIEREDCOMPILATION, LL_FATALERROR, " Jit_Patchpoint: patchpoint (0x%p) TRANSITION"
5155+ " unexpected context IP 0x%p\n " , ip, GetIP (pFrameContext));
5156+ EEPOLICY_HANDLE_FATAL_ERROR (COR_E_EXECUTIONENGINE);
5157+ }
51525158
5153- // Now unwind back to the original method caller frame.
5154- EECodeInfo callerCodeInfo (GetIP (pFrameContext));
5155- ULONG_PTR establisherFrame = 0 ;
5156- PVOID handlerData = NULL ;
5157- RtlVirtualUnwind (UNW_FLAG_NHANDLER, callerCodeInfo.GetModuleBase (), GetIP (pFrameContext), callerCodeInfo.GetFunctionEntry (),
5158- pFrameContext, &handlerData, &establisherFrame, NULL );
5159+ // Now unwind back to the original method caller frame.
5160+ EECodeInfo callerCodeInfo (GetIP (pFrameContext));
5161+ ULONG_PTR establisherFrame = 0 ;
5162+ PVOID handlerData = NULL ;
5163+ RtlVirtualUnwind (UNW_FLAG_NHANDLER, callerCodeInfo.GetModuleBase (), GetIP (pFrameContext), callerCodeInfo.GetFunctionEntry (),
5164+ pFrameContext, &handlerData, &establisherFrame, NULL );
51595165
5160- // Now, set FP and SP back to the values they had just before this helper was called,
5161- // since the new method must have access to the original method frame.
5162- //
5163- // TODO: if we access the patchpointInfo here, we can read out the FP-SP delta from there and
5164- // use that to adjust the stack, likely saving some stack space.
5166+ // Now, set FP and SP back to the values they had just before this helper was called,
5167+ // since the new method must have access to the original method frame.
5168+ //
5169+ // TODO: if we access the patchpointInfo here, we can read out the FP-SP delta from there and
5170+ // use that to adjust the stack, likely saving some stack space.
51655171
51665172#if defined(TARGET_AMD64)
5167- // If calls push the return address, we need to simulate that here, so the OSR
5168- // method sees the "expected" SP misalgnment on entry.
5169- _ASSERTE (currentSP % 16 == 0 );
5170- currentSP -= 8 ;
5173+ // If calls push the return address, we need to simulate that here, so the OSR
5174+ // method sees the "expected" SP misalgnment on entry.
5175+ _ASSERTE (currentSP % 16 == 0 );
5176+ currentSP -= 8 ;
51715177
51725178#if defined(TARGET_WINDOWS)
5173- DWORD64 ssp = GetSSP (pFrameContext);
5174- if (ssp != 0 )
5175- {
5176- SetSSP (pFrameContext, ssp - 8 );
5177- }
5179+ DWORD64 ssp = GetSSP (pFrameContext);
5180+ if (ssp != 0 )
5181+ {
5182+ SetSSP (pFrameContext, ssp - 8 );
5183+ }
51785184#endif // TARGET_WINDOWS
51795185
5180- pFrameContext->Rbp = currentFP;
5186+ pFrameContext->Rbp = currentFP;
51815187#endif // TARGET_AMD64
51825188
5183- SetSP (pFrameContext, currentSP);
5189+ SetSP (pFrameContext, currentSP);
51845190
5185- // Note we can get here w/o triggering, if there is an existing OSR method and
5186- // we hit the patchpoint.
5187- const int transitionLogLevel = isNewMethod ? LL_INFO10 : LL_INFO1000;
5188- LOG ((LF_TIEREDCOMPILATION, transitionLogLevel, " Jit_Patchpoint: patchpoint [%d] (0x%p) TRANSITION to ip 0x%p\n " , ppId, ip, osrMethodCode));
5191+ // Note we can get here w/o triggering, if there is an existing OSR method and
5192+ // we hit the patchpoint.
5193+ const int transitionLogLevel = isNewMethod ? LL_INFO10 : LL_INFO1000;
5194+ LOG ((LF_TIEREDCOMPILATION, transitionLogLevel, " Jit_Patchpoint: patchpoint [%d] (0x%p) TRANSITION to ip 0x%p\n " , ppId, ip, osrMethodCode));
51895195
5190- // Install new entry point as IP
5191- SetIP (pFrameContext, osrMethodCode);
5196+ // Install new entry point as IP
5197+ SetIP (pFrameContext, osrMethodCode);
51925198
5193- // Transition!
5194- ClrRestoreNonvolatileContext (pFrameContext);
5199+ // Restore last error (since call below does not return)
5200+ // END_PRESERVE_LAST_ERROR;
5201+ ::SetLastError (dwLastError);
5202+
5203+ // Transition!
5204+ ClrRestoreNonvolatileContext (pFrameContext);
5205+ }
5206+
5207+ DONE:
5208+
5209+ // END_PRESERVE_LAST_ERROR;
5210+ ::SetLastError (dwLastError);
51955211}
51965212
51975213// Jit helper invoked at a partial compilation patchpoint.
@@ -5205,6 +5221,9 @@ void JIT_Patchpoint(int* counter, int ilOffset)
52055221//
52065222void JIT_PartialCompilationPatchpoint (int ilOffset)
52075223{
5224+ // BEGIN_PRESERVE_LAST_ERROR;
5225+ DWORD dwLastError = ::GetLastError ();
5226+
52085227 // This method will not return normally
52095228 STATIC_CONTRACT_GC_NOTRIGGER;
52105229 STATIC_CONTRACT_MODE_COOPERATIVE;
@@ -5356,6 +5375,10 @@ void JIT_PartialCompilationPatchpoint(int ilOffset)
53565375 // Install new entry point as IP
53575376 SetIP (&frameContext, osrMethodCode);
53585377
5378+ // Restore last error (since call below does not return)
5379+ // END_PRESERVE_LAST_ERROR;
5380+ ::SetLastError (dwLastError);
5381+
53595382 // Transition!
53605383 RtlRestoreContext (&frameContext, NULL );
53615384}
0 commit comments