@@ -4916,6 +4916,9 @@ HCIMPLEND
4916
4916
4917
4917
void JIT_Patchpoint (int * counter, int ilOffset)
4918
4918
{
4919
+ // BEGIN_PRESERVE_LAST_ERROR;
4920
+ DWORD dwLastError = ::GetLastError ();
4921
+
4919
4922
// This method may not return normally
4920
4923
STATIC_CONTRACT_GC_NOTRIGGER;
4921
4924
STATIC_CONTRACT_MODE_COOPERATIVE;
@@ -4929,6 +4932,8 @@ void JIT_Patchpoint(int* counter, int ilOffset)
4929
4932
LoaderAllocator* allocator = pMD->GetLoaderAllocator ();
4930
4933
OnStackReplacementManager* manager = allocator->GetOnStackReplacementManager ();
4931
4934
PerPatchpointInfo * ppInfo = manager->GetPerPatchpointInfo (ip);
4935
+ PCODE osrMethodCode = NULL ;
4936
+ bool isNewMethod = false ;
4932
4937
4933
4938
// In the current prototype, counter is shared by all patchpoints
4934
4939
// 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)
4955
4960
{
4956
4961
LOG ((LF_TIEREDCOMPILATION, LL_INFO1000, " Jit_Patchpoint: invalid patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n " ,
4957
4962
ppId, ip, pMD, pMD->m_pszDebugClassName , pMD->m_pszDebugMethodName , ilOffset));
4958
- return ;
4963
+
4964
+ goto DONE;
4959
4965
}
4960
4966
4961
4967
// 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 ;
4964
4969
4965
4970
if (osrMethodCode == NULL )
4966
4971
{
@@ -4983,7 +4988,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
4983
4988
{
4984
4989
LOG ((LF_TIEREDCOMPILATION, LL_INFO10, " Jit_Patchpoint: ignoring patchpoint [%d] (0x%p) in Method=0x%pM (%s::%s) at offset %d\n " ,
4985
4990
ppId, ip, pMD, pMD->m_pszDebugClassName , pMD->m_pszDebugMethodName , ilOffset));
4986
- return ;
4991
+ goto DONE ;
4987
4992
}
4988
4993
#endif
4989
4994
@@ -5024,15 +5029,15 @@ void JIT_Patchpoint(int* counter, int ilOffset)
5024
5029
// Defer, if we haven't yet reached the limit
5025
5030
if (hitCount < hitLimit)
5026
5031
{
5027
- return ;
5032
+ goto DONE ;
5028
5033
}
5029
5034
5030
5035
// Third, make sure no other thread is trying to create the OSR method.
5031
5036
LONG oldFlags = ppInfo->m_flags ;
5032
5037
if ((oldFlags & PerPatchpointInfo::patchpoint_triggered) == PerPatchpointInfo::patchpoint_triggered)
5033
5038
{
5034
5039
LOG ((LF_TIEREDCOMPILATION, LL_INFO1000, " Jit_Patchpoint: AWAITING OSR method for patchpoint [%d] (0x%p)\n " , ppId, ip));
5035
- return ;
5040
+ goto DONE ;
5036
5041
}
5037
5042
5038
5043
LONG newFlags = oldFlags | PerPatchpointInfo::patchpoint_triggered;
@@ -5041,7 +5046,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
5041
5046
if (!triggerTransition)
5042
5047
{
5043
5048
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 ;
5045
5050
}
5046
5051
5047
5052
// Time to create the OSR method.
@@ -5071,7 +5076,7 @@ void JIT_Patchpoint(int* counter, int ilOffset)
5071
5076
" marking patchpoint invalid for Method=0x%pM il offset %d\n " , ip, pMD, ilOffset);
5072
5077
5073
5078
InterlockedOr (&ppInfo->m_flags , (LONG)PerPatchpointInfo::patchpoint_invalid);
5074
- return ;
5079
+ goto DONE ;
5075
5080
}
5076
5081
5077
5082
// We've successfully created the osr method; make it available.
@@ -5083,115 +5088,126 @@ void JIT_Patchpoint(int* counter, int ilOffset)
5083
5088
// If we get here, we have code to transition to...
5084
5089
_ASSERTE (osrMethodCode != NULL );
5085
5090
5086
- Thread *pThread = GetThread ();
5091
+ {
5092
+ Thread *pThread = GetThread ();
5087
5093
5088
5094
#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 ();
5093
5099
#endif
5094
5100
5095
- // Find context for the original method
5096
- CONTEXT *pFrameContext = NULL ;
5101
+ // Find context for the original method
5102
+ CONTEXT *pFrameContext = NULL ;
5097
5103
#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
+ }
5106
5112
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);
5111
5117
5112
- _ASSERTE (!success && (GetLastError () == ERROR_INSUFFICIENT_BUFFER));
5118
+ _ASSERTE (!success && (GetLastError () == ERROR_INSUFFICIENT_BUFFER));
5113
5119
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);
5119
5125
#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;
5123
5129
#endif // TARGET_WINDOWS && TARGET_AMD64
5124
5130
5125
- // Find context for the original method
5126
- RtlCaptureContext (pFrameContext);
5131
+ // Find context for the original method
5132
+ RtlCaptureContext (pFrameContext);
5127
5133
5128
5134
#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
+ }
5135
5141
#endif // TARGET_WINDOWS && TARGET_AMD64
5136
5142
5137
- // Walk back to the original method frame
5138
- pThread->VirtualUnwindToFirstManagedCallFrame (pFrameContext);
5143
+ // Walk back to the original method frame
5144
+ pThread->VirtualUnwindToFirstManagedCallFrame (pFrameContext);
5139
5145
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);
5143
5149
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
+ }
5152
5158
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 );
5159
5165
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.
5165
5171
5166
5172
#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 ;
5171
5177
5172
5178
#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
+ }
5178
5184
#endif // TARGET_WINDOWS
5179
5185
5180
- pFrameContext->Rbp = currentFP;
5186
+ pFrameContext->Rbp = currentFP;
5181
5187
#endif // TARGET_AMD64
5182
5188
5183
- SetSP (pFrameContext, currentSP);
5189
+ SetSP (pFrameContext, currentSP);
5184
5190
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));
5189
5195
5190
- // Install new entry point as IP
5191
- SetIP (pFrameContext, osrMethodCode);
5196
+ // Install new entry point as IP
5197
+ SetIP (pFrameContext, osrMethodCode);
5192
5198
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);
5195
5211
}
5196
5212
5197
5213
// Jit helper invoked at a partial compilation patchpoint.
@@ -5205,6 +5221,9 @@ void JIT_Patchpoint(int* counter, int ilOffset)
5205
5221
//
5206
5222
void JIT_PartialCompilationPatchpoint (int ilOffset)
5207
5223
{
5224
+ // BEGIN_PRESERVE_LAST_ERROR;
5225
+ DWORD dwLastError = ::GetLastError ();
5226
+
5208
5227
// This method will not return normally
5209
5228
STATIC_CONTRACT_GC_NOTRIGGER;
5210
5229
STATIC_CONTRACT_MODE_COOPERATIVE;
@@ -5356,6 +5375,10 @@ void JIT_PartialCompilationPatchpoint(int ilOffset)
5356
5375
// Install new entry point as IP
5357
5376
SetIP (&frameContext, osrMethodCode);
5358
5377
5378
+ // Restore last error (since call below does not return)
5379
+ // END_PRESERVE_LAST_ERROR;
5380
+ ::SetLastError (dwLastError);
5381
+
5359
5382
// Transition!
5360
5383
RtlRestoreContext (&frameContext, NULL );
5361
5384
}
0 commit comments