Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 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
31 changes: 19 additions & 12 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ static size_t CreateDispatchTokenForMethod(MethodDesc* pMD)
void InvokeManagedMethod(ManagedMethodParam *pParam);
void InvokeUnmanagedMethod(MethodDesc *targetMethod, int8_t *pArgs, int8_t *pRet, PCODE callTarget);
void InvokeCalliStub(CalliStubParam* pParam);
void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet);
void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet);
void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam);
void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD);
InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD);
extern "C" PCODE CID_VirtualOpenDelegateDispatch(TransitionBlock * pTransitionBlock);

// Filter to ignore SEH exceptions representing C++ exceptions.
Expand Down Expand Up @@ -287,7 +287,7 @@ void InvokeUnmanagedMethodWithTransition(UnmanagedMethodWithTransitionParam *pPa
}

NOINLINE
void InvokeUnmanagedCalliWithTransition(PCODE ftn, void *cookie, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet)
void InvokeUnmanagedCalliWithTransition(PCODE ftn, InterpreterCalliCookie cookie, int8_t *stack, InterpMethodContextFrame *pFrame, int8_t *pArgs, int8_t *pRet)
{
CONTRACTL
{
Expand Down Expand Up @@ -349,15 +349,15 @@ static CallStubHeader *UpdateCallStubForMethod(MethodDesc *pMD, PCODE target)
header->SetTarget(target);
}

if (pMD->SetCallStub(header))
if (pMD->SetCalliCookie(header))
{
amTracker.SuppressRelease();
}
else
{
// We have lost the race for generating the header, use the one that was generated by another thread
// and let the amTracker release the memory of the one we generated.
header = pMD->GetCallStub();
header = pMD->GetCalliCookie();
}

return header;
Expand Down Expand Up @@ -408,7 +408,7 @@ void InvokeManagedMethod(ManagedMethodParam* pParam)
PCODE target = pParam->target;
Object** pContinuationRet = pParam->pContinuationRet;

CallStubHeader *pHeader = pParam->pMD->GetCallStub();
CallStubHeader *pHeader = pParam->pMD->GetCalliCookie();
if (pHeader == NULL)
{
pHeader = UpdateCallStubForMethod(pMD, target == (PCODE)NULL ? pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY) : target);
Comment thread
radekdoulik marked this conversation as resolved.
Expand Down Expand Up @@ -467,7 +467,7 @@ void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam)
PCODE target = pParam->target;
Object** pContinuationRet = pParam->pContinuationRet;

CallStubHeader *stubHeaderTemplate = pMDDelegateInvoke->GetCallStub();
CallStubHeader *stubHeaderTemplate = pMDDelegateInvoke->GetCalliCookie();
if (stubHeaderTemplate == NULL)
{
stubHeaderTemplate = UpdateCallStubForMethod(pMDDelegateInvoke, (PCODE)pMDDelegateInvoke->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY));
Expand All @@ -490,7 +490,7 @@ void InvokeDelegateInvokeMethod(DelegateInvokeMethodParam* pParam)
pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize, pContinuationRet);
}

void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet)
void InvokeUnmanagedCalli(PCODE ftn, InterpreterCalliCookie cookie, int8_t *pArgs, int8_t *pRet)
{
CONTRACTL
{
Expand Down Expand Up @@ -549,7 +549,7 @@ void InvokeCalliStub(CalliStubParam* pParam)
pHeader->Invoke(pHeader->Routines, pArgs, pRet, pHeader->TotalStackSize, pContinuationRet);
}

void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD)
InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD)
{
STANDARD_VM_CONTRACT;

Expand Down Expand Up @@ -3123,7 +3123,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
int32_t calliCookie = ip[4];
int32_t flags = ip[5];

void* cookie = pMethod->pDataItems[calliCookie];
InterpreterCalliCookie cookie = (InterpreterCalliCookie)pMethod->pDataItems[calliCookie];
ip += 6;

// Save current execution state for when we return from called method
Expand Down Expand Up @@ -3167,8 +3167,15 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
if (PortableEntryPoint::PrefersInterpreterEntryPoint(calliFunctionPointer) || !PortableEntryPoint::HasNativeEntryPoint(calliFunctionPointer))
goto CALL_INTERP_METHOD;

MetaSig sig(targetMethod);
cookie = GetCookieForCalliSig(sig, NULL);
cookie = targetMethod->GetCalliCookie();
if (cookie == NULL)
{
MetaSig sig(targetMethod);
cookie = GetCookieForCalliSig(sig, NULL);
_ASSERTE(cookie != NULL);
targetMethod->SetCalliCookie(cookie);
cookie = targetMethod->GetCalliCookie();
}
#endif // FEATURE_PORTABLE_ENTRYPOINTS
frameNeedsTailcallUpdate = false;
CalliStubParam param = { calliFunctionPointer, cookie, callArgsAddress, returnValueAddress, pInterpreterFrame->GetContinuationPtr() };
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/vm/interpexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,16 @@ struct ManagedMethodParam

void InvokeManagedMethod(ManagedMethodParam *pParam);

#ifdef FEATURE_INTERPRETER
struct CalliStubParam
{
PCODE ftn;
void* cookie;
InterpreterCalliCookie cookie;
int8_t *pArgs;
int8_t *pRet;
Comment thread
radekdoulik marked this conversation as resolved.
Object** pContinuationRet;
};
Comment thread
radekdoulik marked this conversation as resolved.
#endif // FEATURE_INTERPRETER

struct DelegateInvokeMethodParam
{
Expand Down
43 changes: 27 additions & 16 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11490,25 +11490,13 @@ LPVOID CEEInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* szMetaSig)
#ifdef FEATURE_INTERPRETER

// Forward declare the function for mapping MetaSig to a cookie.
void* GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD);
InterpreterCalliCookie GetCookieForCalliSig(MetaSig metaSig, MethodDesc *pContextMD);

LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* szMetaSig)
{
void* result = NULL;
InterpreterCalliCookie result = NULL;
JIT_TO_EE_TRANSITION();

Instantiation classInst = Instantiation((TypeHandle*) szMetaSig->sigInst.classInst, szMetaSig->sigInst.classInstCount);
Instantiation methodInst = Instantiation((TypeHandle*) szMetaSig->sigInst.methInst, szMetaSig->sigInst.methInstCount);
SigTypeContext typeContext = SigTypeContext(classInst, methodInst);
Module* mod = GetModule(szMetaSig->scope);

MetaSig sig(szMetaSig->pSig, szMetaSig->cbSig, mod, &typeContext);

if (szMetaSig->isAsyncCall())
sig.SetIsAsyncCall();

_ASSERTE(szMetaSig->isAsyncCall() == sig.IsAsyncCall());

// When compiling a calli inside an IL stub for a P/Invoke, pass the target
// P/Invoke MethodDesc so ComputeCallStub can detect the Swift calling convention.
MethodDesc* pContextMD = nullptr;
Expand All @@ -11518,12 +11506,35 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz
if (pTargetMD != nullptr)
{
pContextMD = pTargetMD;
result = pTargetMD->GetCalliCookie();
}
}

if (result == NULL)
{
Instantiation classInst = Instantiation((TypeHandle*) szMetaSig->sigInst.classInst, szMetaSig->sigInst.classInstCount);
Instantiation methodInst = Instantiation((TypeHandle*) szMetaSig->sigInst.methInst, szMetaSig->sigInst.methInstCount);
SigTypeContext typeContext = SigTypeContext(classInst, methodInst);
Module* mod = GetModule(szMetaSig->scope);

MetaSig sig(szMetaSig->pSig, szMetaSig->cbSig, mod, &typeContext);

if (szMetaSig->isAsyncCall())
sig.SetIsAsyncCall();

_ASSERTE(szMetaSig->isAsyncCall() == sig.IsAsyncCall());

result = GetCookieForCalliSig(sig, pContextMD);

if (pContextMD != nullptr)
{
pContextMD->SetCalliCookie(result);
result = pContextMD->GetCalliCookie();
Comment thread
radekdoulik marked this conversation as resolved.
Comment thread
radekdoulik marked this conversation as resolved.
}
}
result = GetCookieForCalliSig(sig, pContextMD);

EE_TO_JIT_TRANSITION();
return result;
return (void*)result;
Comment thread
radekdoulik marked this conversation as resolved.
}

void CInterpreterJitInfo::allocMem(AllocMemArgs *pArgs)
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,26 +300,26 @@ PatchpointInfo* MethodDesc::GetMethodDescAltJitPatchpointInfo()
#endif // FEATURE_CODE_VERSIONING

#ifdef FEATURE_INTERPRETER
// Set the call stub for the interpreter to JIT/AOT calls
// Returns true if the current call set the stub, false if it was already set
bool MethodDesc::SetCallStub(CallStubHeader *pHeader)
// Cache the calli cookie on the MethodDesc
// Returns true if the current call set the cookie, false if it was already set
bool MethodDesc::SetCalliCookie(InterpreterCalliCookie cookie)
{
STANDARD_VM_CONTRACT;

IfFailThrow(EnsureCodeDataExists(NULL));

_ASSERTE(m_codeData != NULL);
return InterlockedCompareExchangeT(&m_codeData->CallStub, pHeader, NULL) == NULL;
return InterlockedCompareExchangeT((void**)&m_codeData->CalliCookie, (void*)cookie, (void*)NULL) == NULL;
}
Comment thread
radekdoulik marked this conversation as resolved.
Comment thread
radekdoulik marked this conversation as resolved.

CallStubHeader *MethodDesc::GetCallStub()
InterpreterCalliCookie MethodDesc::GetCalliCookie()
{
LIMITED_METHOD_CONTRACT;

PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData);
if (codeData == NULL)
return NULL;
return VolatileLoadWithoutBarrier(&codeData->CallStub);
return (InterpreterCalliCookie)VolatileLoadWithoutBarrier(&codeData->CalliCookie);
}
#endif // FEATURE_INTERPRETER

Expand Down
14 changes: 11 additions & 3 deletions src/coreclr/vm/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ enum MethodDescFlags
};

// Used for storing additional items related to native code
#ifdef FEATURE_INTERPRETER
#ifdef FEATURE_PORTABLE_ENTRYPOINTS
typedef void(*InterpreterCalliCookie)(PCODE, int8_t*, int8_t*);
#else
typedef CallStubHeader* InterpreterCalliCookie;
#endif // FEATURE_PORTABLE_ENTRYPOINTS
Comment thread
radekdoulik marked this conversation as resolved.
Comment thread
radekdoulik marked this conversation as resolved.
#endif // FEATURE_INTERPRETER

struct MethodDescCodeData final
{
#ifdef FEATURE_CODE_VERSIONING
Expand All @@ -257,7 +265,7 @@ struct MethodDescCodeData final
#endif // FEATURE_CODE_VERSIONING
PCODE TemporaryEntryPoint;
#ifdef FEATURE_INTERPRETER
CallStubHeader *CallStub;
InterpreterCalliCookie CalliCookie;
Comment thread
radekdoulik marked this conversation as resolved.
#endif // FEATURE_INTERPRETER
#if defined(_DEBUG) && defined(ALLOW_SXS_JIT)
PatchpointInfo *AltJitPatchpointInfo;
Expand Down Expand Up @@ -1976,8 +1984,8 @@ class MethodDesc
#endif //!DACCESS_COMPILE

#if defined(FEATURE_INTERPRETER) && !defined(DACCESS_COMPILE)
bool SetCallStub(CallStubHeader *pHeader);
CallStubHeader *GetCallStub();
bool SetCalliCookie(InterpreterCalliCookie cookie);
InterpreterCalliCookie GetCalliCookie();
#endif // FEATURE_INTERPRETER && !DACCESS_COMPILE

#ifdef FEATURE_CODE_VERSIONING
Expand Down
18 changes: 16 additions & 2 deletions src/coreclr/vm/precode_portable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,27 @@
#ifndef FEATURE_PORTABLE_ENTRYPOINTS
#error Requires FEATURE_PORTABLE_ENTRYPOINTS to be set
#endif // !FEATURE_PORTABLE_ENTRYPOINTS

#ifndef _PRECODE_PORTABLE_MINIMAL
Comment thread
radekdoulik marked this conversation as resolved.
Outdated
#include "cdacdata.h"
#endif

// _PRECODE_PORTABLE_MINIMAL: When defined, only the PortableEntryPoint::GetActualCode
// declaration below is emitted. Used by the WASM app-level relink
// build (wasm_m2n_invoke.g.cpp) which compiles outside the full CoreCLR build context
// and only needs to resolve entry points to actual code pointers.

class PortableEntryPoint final
{
public: // static
static void* GetActualCode(PCODE addr);
#ifndef _PRECODE_PORTABLE_MINIMAL
static void SetActualCode(PCODE addr, PCODE actualCode);

// Returns true if the _pActualCode field of a given PortableEntryPoint is set to a non-null address and that address is the preferred entry point instead of preferring InterpreterCode usage.
static bool HasNativeEntryPoint(PCODE addr);
static bool HasInterpreterData(PCODE addr);

static void* GetActualCode(PCODE addr);
static void SetActualCode(PCODE addr, PCODE actualCode);
static MethodDesc* GetMethodDesc(PCODE addr);
static void* GetInterpreterData(PCODE addr);
static void SetInterpreterData(PCODE addr, PCODE interpreterData);
Expand Down Expand Up @@ -115,7 +125,10 @@ class PortableEntryPoint final
}

friend struct ::cdac_data<PortableEntryPoint>;
#endif // !_PRECODE_PORTABLE_MINIMAL
};

#ifndef _PRECODE_PORTABLE_MINIMAL
template<>
struct cdac_data<PortableEntryPoint>
{
Expand Down Expand Up @@ -162,4 +175,5 @@ BOOL DoesSlotCallPrestub(PCODE pCode);

class PrecodeMachineDescriptor { };

#endif // !_PRECODE_PORTABLE_MINIMAL
#endif // __PRECODE_PORTABLE_H__
Loading
Loading