Skip to content

Commit b1b10b0

Browse files
committed
Capture the hidden argument in TheUMEntryPrestubWorker for interpreted reverse p/invoke stubs and ensure that the worker runs on every reverse p/invoke, so that the interpreter can recover the hidden argument and make it available via GetStubContext.
Add INTOP_GETSTUBCONTEXT and always generate it for the GetStubContext intrinsic, even if other intrinsics are disabled
1 parent 491bcb5 commit b1b10b0

File tree

8 files changed

+58
-7
lines changed

8 files changed

+58
-7
lines changed

src/coreclr/interpreter/compiler.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2306,6 +2306,14 @@ bool InterpCompiler::EmitNamedIntrinsicCall(NamedIntrinsic ni, CORINFO_CLASS_HAN
23062306
AddIns(INTOP_THROW_PNSE);
23072307
return true;
23082308

2309+
case NI_System_StubHelpers_GetStubContext:
2310+
{
2311+
AddIns(INTOP_GETSTUBCONTEXT);
2312+
PushStackType(StackTypeI, NULL);
2313+
m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
2314+
return true;
2315+
}
2316+
23092317
case NI_System_Runtime_CompilerServices_StaticsHelpers_VolatileReadAsByref:
23102318
{
23112319
CHECK_STACK(1);
@@ -2817,7 +2825,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
28172825
// intrinsics for the recursive call. Otherwise we will just recurse infinitely and overflow stack.
28182826
// This expansion can produce value that is inconsistent with the value seen by JIT/R2R code that can
28192827
// cause user code to misbehave. This is by design. One-off method Interpretation is for internal use only.
2820-
bool isMustExpand = (callInfo.hMethod == m_methodHnd);
2828+
bool isMustExpand = (callInfo.hMethod == m_methodHnd) || (ni == NI_System_StubHelpers_GetStubContext);
28212829
if ((InterpConfig.InterpMode() == 3) || isMustExpand)
28222830
{
28232831
if (EmitNamedIntrinsicCall(ni, resolvedCallToken.hClass, callInfo.hMethod, callInfo.sig))

src/coreclr/interpreter/intops.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ OPDEF(INTOP_LOAD_FRAMEVAR, "load.framevar", 2, 1, 0, InterpOpNoArgs)
415415
// Intrinsics
416416
OPDEF(INTOP_COMPARE_EXCHANGE_I4, "compare.exchange.i4", 5, 1, 3, InterpOpNoArgs)
417417
OPDEF(INTOP_COMPARE_EXCHANGE_I8, "compare.exchange.i8", 5, 1, 3, InterpOpNoArgs)
418+
OPDEF(INTOP_GETSTUBCONTEXT, "getstubcontext", 2, 1, 0, InterpOpNoArgs)
418419

419420
// All instructions after this point are IROPS, instructions that are not emitted/executed
420421
OPDEF(INTOP_NOP, "nop", 1, 0, 0, InterpOpNoArgs)

src/coreclr/interpreter/intrinsics.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp
4444
{
4545
if (!strcmp(methodName, "NextCallReturnAddress"))
4646
return NI_System_StubHelpers_NextCallReturnAddress;
47+
else if (!strcmp(methodName, "GetStubContext"))
48+
return NI_System_StubHelpers_GetStubContext;
4749
}
4850
}
4951
else if (!strcmp(namespaceName, "System.Numerics"))

src/coreclr/vm/dllimportcallback.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,15 @@ VOID CallbackOnCollectedDelegate(UMEntryThunkData* pEntryThunkData)
210210
EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode());
211211
}
212212

213+
PLATFORM_THREAD_LOCAL UMEntryThunkData * t_MostRecentUMEntryThunkData;
214+
215+
UMEntryThunkData * GetMostRecentUMEntryThunkData()
216+
{
217+
UMEntryThunkData * result = t_MostRecentUMEntryThunkData;
218+
t_MostRecentUMEntryThunkData = nullptr;
219+
return result;
220+
}
221+
213222
PCODE TheUMEntryPrestubWorker(UMEntryThunkData * pUMEntryThunkData)
214223
{
215224
STATIC_CONTRACT_THROWS;
@@ -229,18 +238,23 @@ PCODE TheUMEntryPrestubWorker(UMEntryThunkData * pUMEntryThunkData)
229238
if (pUMEntryThunkData->IsCollectedDelegate())
230239
CallbackOnCollectedDelegate(pUMEntryThunkData);
231240

241+
PCODE result = 0;
242+
232243
INSTALL_MANAGED_EXCEPTION_DISPATCHER;
233244
// this method is called by stubs which are called by managed code,
234245
// so we need an unwind and continue handler so that our internal
235246
// exceptions don't leak out into managed code.
236247
INSTALL_UNWIND_AND_CONTINUE_HANDLER;
237248

238-
pUMEntryThunkData->RunTimeInit();
249+
// HACK: Stash the entry thunk data address so that the interpreter can recover it.
250+
// The InterpreterStub overwrites the register that normally would contain this address.
251+
t_MostRecentUMEntryThunkData = pUMEntryThunkData;
252+
result = pUMEntryThunkData->RunTimeInit();
239253

240254
UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
241255
UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;
242256

243-
return (PCODE)pUMEntryThunkData->GetCode();
257+
return result;
244258
}
245259

246260
UMEntryThunkData* UMEntryThunkData::CreateUMEntryThunk()
@@ -263,7 +277,7 @@ UMEntryThunkData* UMEntryThunkData::CreateUMEntryThunk()
263277
LoaderAllocator *pLoaderAllocator = SystemDomain::GetGlobalLoaderAllocator();
264278
AllocMemTracker amTracker;
265279
AllocMemTracker *pamTracker = &amTracker;
266-
280+
267281
pData = (UMEntryThunkData *)pamTracker->Track(pLoaderAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(UMEntryThunkData))));
268282
UMEntryThunk* pThunk = (UMEntryThunk*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocStub());
269283
#ifdef FEATURE_PERFMAP

src/coreclr/vm/dllimportcallback.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class UMEntryThunk : private StubPrecode
134134
PTR_UMEntryThunkData GetData() const
135135
{
136136
LIMITED_METHOD_CONTRACT;
137-
137+
138138
return dac_cast<PTR_UMEntryThunkData>(GetSecretParam());
139139
}
140140
};
@@ -214,7 +214,7 @@ class UMEntryThunkData
214214

215215
void Terminate();
216216

217-
VOID RunTimeInit()
217+
PCODE RunTimeInit()
218218
{
219219
STANDARD_VM_CONTRACT;
220220

@@ -227,11 +227,29 @@ class UMEntryThunkData
227227
if (m_pObjectHandle == NULL && m_pManagedTarget == (TADDR)0)
228228
m_pManagedTarget = m_pMD->GetMultiCallableAddrOfCode();
229229

230-
m_pUMEntryThunk->SetTargetUnconditional(m_pUMThunkMarshInfo->GetExecStubEntryPoint());
230+
#ifdef FEATURE_INTERPRETER
231+
// HACK: For interpreted stubs we need to ensure that TheUMEntryPrestubWorker runs for every
232+
// unmanaged-to-managed invocation in order to populate the TLS variable every time.
233+
PCODE pILStub = m_pUMThunkMarshInfo->GetExecStubEntryPoint();
234+
Precode* pStubPrecode = (Precode*)(void*)pILStub;
235+
if (pStubPrecode->GetType() == PRECODE_INTERPRETER)
236+
{
237+
}
238+
else
239+
#endif
240+
{
241+
m_pUMEntryThunk->SetTargetUnconditional(pILStub);
242+
}
231243

232244
#ifdef _DEBUG
233245
m_state = kRunTimeInited;
234246
#endif // _DEBUG
247+
248+
#ifdef FEATURE_INTERPRETER
249+
if (pStubPrecode->GetType() == PRECODE_INTERPRETER)
250+
return pILStub;
251+
#endif
252+
return GetCode();
235253
}
236254

237255
PCODE GetManagedTarget() const

src/coreclr/vm/interpexec.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,10 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
576576
MemoryBarrier();
577577
ip++;
578578
break;
579+
case INTOP_GETSTUBCONTEXT:
580+
LOCAL_VAR(ip[1], void*) = pFrame->hiddenArgument;
581+
ip += 2;
582+
break;
579583
case INTOP_LDC_I4:
580584
LOCAL_VAR(ip[1], int32_t) = ip[2];
581585
ip += 3;

src/coreclr/vm/interpexec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct InterpMethodContextFrame
3535
int8_t *pRetVal;
3636
const int32_t *ip; // This ip is updated only when execution can leave the frame
3737
PTR_InterpMethodContextFrame pNext;
38+
void *hiddenArgument;
3839

3940
#ifndef DACCESS_COMPILE
4041
void ReInit(InterpMethodContextFrame *pParent, InterpByteCodeStart* startIp, int8_t *pRetVal, int8_t *pStack)

src/coreclr/vm/prestub.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,8 @@ static InterpThreadContext* GetInterpThreadContext()
20162016

20172017
EXTERN_C void STDCALL ReversePInvokeBadTransition();
20182018

2019+
UMEntryThunkData * GetMostRecentUMEntryThunkData();
2020+
20192021
extern "C" void* STDCALL ExecuteInterpretedMethod(TransitionBlock* pTransitionBlock, TADDR byteCodeAddr, void* retBuff)
20202022
{
20212023
// Argument registers are in the TransitionBlock
@@ -2055,6 +2057,7 @@ extern "C" void* STDCALL ExecuteInterpretedMethod(TransitionBlock* pTransitionBl
20552057
frames.interpMethodContextFrame.startIp = dac_cast<PTR_InterpByteCodeStart>(byteCodeAddr);
20562058
frames.interpMethodContextFrame.pStack = sp;
20572059
frames.interpMethodContextFrame.pRetVal = (retBuff != NULL) ? (int8_t*)retBuff : sp;
2060+
frames.interpMethodContextFrame.hiddenArgument = GetMostRecentUMEntryThunkData();
20582061

20592062
InterpExecMethod(&frames.interpreterFrame, &frames.interpMethodContextFrame, threadContext);
20602063

0 commit comments

Comments
 (0)