Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,19 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
}
else
{
InvokeCalliStub(LOCAL_VAR(calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
PCODE calliFunctionPointer = LOCAL_VAR(calliFunctionPointerVar, PCODE);
#ifdef FEATURE_PORTABLE_ENTRYPOINTS
// WASMTODO: We may end up here with native JIT helper entrypoint without MethodDesc
// that CALL_INTERP_METHOD is not able to handle. This is a potential problem for
// interpreter<->native code stub generator.
// https://github.com/dotnet/runtime/pull/119516#discussion_r2337631271
if (!PortableEntryPoint::HasNativeEntryPoint(calliFunctionPointer))
{
targetMethod = PortableEntryPoint::GetMethodDesc(calliFunctionPointer);
goto CALL_INTERP_METHOD;
}
#endif // FEATURE_PORTABLE_ENTRYPOINTS
InvokeCalliStub(calliFunctionPointer, cookie, stack + callArgsOffset, stack + returnOffset);
}

break;
Expand Down
111 changes: 58 additions & 53 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10749,7 +10749,7 @@ CEECodeGenInfo::CEECodeGenInfo(PrepareCodeConfig* config, MethodDesc* fd, COR_IL

void CEECodeGenInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */
CORINFO_CONST_LOOKUP* pNativeEntrypoint, /* OUT */
CORINFO_METHOD_HANDLE* pMethod) /* OUT */
CORINFO_METHOD_HANDLE* pMethodHandle) /* OUT */
{
CONTRACTL
{
Expand All @@ -10765,61 +10765,27 @@ void CEECodeGenInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN

InfoAccessType accessType;
LPVOID targetAddr;

MethodDesc* helperMD = NULL;
VMHELPDEF const& helperDef = hlpFuncTable[ftnNum];
PCODE pfnHelper = helperDef.pfnHelper;

VMHELPDEF const& helperDef = hlpFuncTable[ftnNum];
DynamicCorInfoHelpFunc dynamicFtnNum;

#ifdef FEATURE_PORTABLE_ENTRYPOINTS

accessType = IAT_VALUE;
targetAddr = (LPVOID)VolatileLoad(&hlpFuncEntryPoints[ftnNum]);
if (targetAddr != NULL)
{
// If the target address is already cached, but the caller asked for the method handle
// then we verify the helper is an IL based dynamic helper and load the method handle for it.
if (pMethod != NULL
&& helperDef.IsDynamicHelper(&dynamicFtnNum)
&& HasILBasedDynamicJitHelper(dynamicFtnNum))
{
helperMD = GetMethodDescForILBasedDynamicJitHelper(dynamicFtnNum);
_ASSERTE(PortableEntryPoint::GetMethodDesc((PCODE)targetAddr) == helperMD);
}
}
else
{
if (helperDef.IsDynamicHelper(&dynamicFtnNum))
{
pfnHelper = LoadDynamicJitHelper(dynamicFtnNum);
if (HasILBasedDynamicJitHelper(dynamicFtnNum))
helperMD = GetMethodDescForILBasedDynamicJitHelper(dynamicFtnNum);
}

// LoadDynamicJitHelper returns PortableEntryPoint for helpers backed by managed methods. We need to wrap
// the code address by PortableEntryPoint in all other cases.
if (helperMD == NULL)
{
_ASSERTE(pfnHelper != NULL);
AllocMemHolder<PortableEntryPoint> portableEntryPoint = SystemDomain::GetGlobalLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T{ sizeof(PortableEntryPoint) });
portableEntryPoint->Init((void*)pfnHelper);
pfnHelper = (PCODE)(PortableEntryPoint*)(portableEntryPoint);

if (InterlockedCompareExchangeT<PCODE>(&hlpFuncEntryPoints[ftnNum], pfnHelper, (PCODE)NULL) == (PCODE)NULL)
portableEntryPoint.SuppressRelease();
pfnHelper = hlpFuncEntryPoints[ftnNum];
}
else
{
VolatileStore(&hlpFuncEntryPoints[ftnNum], pfnHelper);
}
targetAddr = (LPVOID)getHelperFtnStatic(ftnNum);

targetAddr = (LPVOID)pfnHelper;
// If the caller asked for the method handle then we verify the helper is
// an IL based dynamic helper and get the method handle for it.
if (pMethodHandle != NULL
&& helperDef.IsDynamicHelper(&dynamicFtnNum)
&& HasILBasedDynamicJitHelper(dynamicFtnNum))
{
helperMD = GetMethodDescForILBasedDynamicJitHelper(dynamicFtnNum);
_ASSERTE(PortableEntryPoint::GetMethodDesc((PCODE)targetAddr) == helperMD);
}

#else // !FEATURE_PORTABLE_ENTRYPOINTS

PCODE pfnHelper = helperDef.pfnHelper;
if (helperDef.IsDynamicHelper(&dynamicFtnNum))
{
#if defined(TARGET_AMD64)
Expand Down Expand Up @@ -10853,7 +10819,7 @@ void CEECodeGenInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN
{
accessType = IAT_VALUE;
targetAddr = finalTierAddr;
if (pMethod != NULL && HasILBasedDynamicJitHelper(dynamicFtnNum))
if (pMethodHandle != NULL && HasILBasedDynamicJitHelper(dynamicFtnNum))
{
helperMD = GetMethodDescForILBasedDynamicJitHelper(dynamicFtnNum);
_ASSERT(helperMD != NULL);
Expand Down Expand Up @@ -10939,30 +10905,69 @@ exit: ;
pNativeEntrypoint->addr = targetAddr;
}

if (pMethod != NULL)
*pMethod = (CORINFO_METHOD_HANDLE)helperMD;
if (pMethodHandle != NULL)
*pMethodHandle = (CORINFO_METHOD_HANDLE)helperMD;

EE_TO_JIT_TRANSITION();
}

PCODE CEECodeGenInfo::getHelperFtnStatic(CorInfoHelpFunc ftnNum)
{
CONTRACTL {
CONTRACTL
{
THROWS;
GC_TRIGGERS;
MODE_PREEMPTIVE;
} CONTRACTL_END;
}
CONTRACTL_END;

VMHELPDEF const& helperDef = hlpFuncTable[ftnNum];
PCODE pfnHelper = helperDef.pfnHelper;

PCODE pfnHelper;
DynamicCorInfoHelpFunc dynamicFtnNum;

#ifdef FEATURE_PORTABLE_ENTRYPOINTS
pfnHelper = VolatileLoad(&hlpFuncEntryPoints[ftnNum]);
if (pfnHelper == (PCODE)NULL)
{
MethodDesc* helperMD = NULL;
pfnHelper = helperDef.pfnHelper;
if (helperDef.IsDynamicHelper(&dynamicFtnNum))
{
pfnHelper = LoadDynamicJitHelper(dynamicFtnNum);
if (HasILBasedDynamicJitHelper(dynamicFtnNum))
helperMD = GetMethodDescForILBasedDynamicJitHelper(dynamicFtnNum);
}

// LoadDynamicJitHelper returns PortableEntryPoint for helpers backed by managed methods. We need to wrap
// the code address by PortableEntryPoint in all other cases.
if (helperMD == NULL)
{
_ASSERTE(pfnHelper != NULL);
AllocMemHolder<PortableEntryPoint> portableEntryPoint = SystemDomain::GetGlobalLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T{ sizeof(PortableEntryPoint) });
portableEntryPoint->Init((void*)pfnHelper);
pfnHelper = (PCODE)(PortableEntryPoint*)(portableEntryPoint);

if (InterlockedCompareExchangeT<PCODE>(&hlpFuncEntryPoints[ftnNum], pfnHelper, (PCODE)NULL) == (PCODE)NULL)
portableEntryPoint.SuppressRelease();
pfnHelper = hlpFuncEntryPoints[ftnNum];
}
else
{
VolatileStore(&hlpFuncEntryPoints[ftnNum], pfnHelper);
}
}

#else // !FEATURE_PORTABLE_ENTRYPOINTS
pfnHelper = helperDef.pfnHelper;

// In this case we need to find the actual pfnHelper
// using an extra indirection.
DynamicCorInfoHelpFunc dynamicFtnNum;
if (helperDef.IsDynamicHelper(&dynamicFtnNum))
{
pfnHelper = LoadDynamicJitHelper(dynamicFtnNum);
}
#endif // FEATURE_PORTABLE_ENTRYPOINTS

_ASSERTE(pfnHelper != (PCODE)NULL);

Expand Down
Loading
Loading