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
13 changes: 11 additions & 2 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,8 +1215,13 @@ InterpMethod* InterpCompiler::CreateInterpMethod()
pDataItems[i] = m_dataItems.Get(i);

bool initLocals = (m_methodInfo->options & CORINFO_OPT_INIT_LOCALS) != 0;
CORJIT_FLAGS corJitFlags;
DWORD jitFlagsSize = m_compHnd->getJitFlags(&corJitFlags, sizeof(corJitFlags));
assert(jitFlagsSize == sizeof(corJitFlags));

InterpMethod *pMethod = new InterpMethod(m_methodHnd, m_totalVarsStackSize, pDataItems, initLocals);
bool unmanagedCallersOnly = corJitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_REVERSE_PINVOKE);

InterpMethod *pMethod = new InterpMethod(m_methodHnd, m_totalVarsStackSize, pDataItems, initLocals, unmanagedCallersOnly);

return pMethod;
}
Expand Down Expand Up @@ -3038,9 +3043,13 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
CORINFO_CONST_LOOKUP lookup;
m_compHnd->getAddressOfPInvokeTarget(callInfo.hMethod, &lookup);
m_pLastNewIns->data[1] = GetDataItemIndex(lookup.addr);
m_pLastNewIns->data[2] = lookup.accessType == IAT_PVALUE;
if (lookup.accessType == IAT_PPVALUE)
NO_WAY("IAT_PPVALUE pinvokes not implemented in interpreter");
bool suppressGCTransition = false;
m_compHnd->getUnmanagedCallConv(callInfo.hMethod, nullptr, &suppressGCTransition);
m_pLastNewIns->data[2] =
((lookup.accessType == IAT_PVALUE) ? (int32_t)PInvokeCallFlags::Indirect : 0) |
(suppressGCTransition ? (int32_t)PInvokeCallFlags::SuppressGCTransition : 0);
}
}
break;
Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/interpreter/interpretershared.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ struct InterpMethod
// This stub is used for calling the interpreted method from JITted/AOTed code
CallStubHeader *pCallStub;
bool initLocals;
bool unmanagedCallersOnly;

InterpMethod(CORINFO_METHOD_HANDLE methodHnd, int32_t allocaSize, void** pDataItems, bool initLocals)
InterpMethod(CORINFO_METHOD_HANDLE methodHnd, int32_t allocaSize, void** pDataItems, bool initLocals, bool unmanagedCallersOnly)
{
#if DEBUG
this->self = this;
Expand All @@ -45,6 +46,7 @@ struct InterpMethod
this->allocaSize = allocaSize;
this->pDataItems = pDataItems;
this->initLocals = initLocals;
this->unmanagedCallersOnly = unmanagedCallersOnly;
pCallStub = NULL;
}

Expand Down Expand Up @@ -157,4 +159,11 @@ struct InterpGenericLookup
uint16_t offsets[InterpGenericLookup_MaxIndirections];
};

enum class PInvokeCallFlags : int32_t
{
None = 0,
Indirect = 1 << 0, // The call target address is indirect
SuppressGCTransition = 1 << 1, // The pinvoke is marked by the SuppressGCTransition attribute
};

#endif
6 changes: 3 additions & 3 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1855,11 +1855,11 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
callArgsOffset = ip[2];
methodSlot = ip[3];
int32_t targetAddrSlot = ip[4];
int32_t indirectFlag = ip[5];
int32_t flags = ip[5];

ip += 6;
targetMethod = (MethodDesc*)pMethod->pDataItems[methodSlot];
PCODE callTarget = indirectFlag
PCODE callTarget = (flags & (int32_t)PInvokeCallFlags::Indirect)
? *(PCODE *)pMethod->pDataItems[targetAddrSlot]
: (PCODE)pMethod->pDataItems[targetAddrSlot];

Expand All @@ -1872,7 +1872,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr
inlinedCallFrame.Push();

{
GCX_PREEMP();
GCX_MAYBE_PREEMP(!(flags & (int32_t)PInvokeCallFlags::SuppressGCTransition));
InvokeCompiledMethod(targetMethod, stack + callArgsOffset, stack + returnOffset, callTarget);
}

Expand Down
17 changes: 17 additions & 0 deletions src/coreclr/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2001,13 +2001,30 @@ static InterpThreadContext* GetInterpThreadContext()
return threadContext;
}

EXTERN_C void STDCALL ReversePInvokeBadTransition();

extern "C" void* STDCALL ExecuteInterpretedMethod(TransitionBlock* pTransitionBlock, TADDR byteCodeAddr, void* retBuff)
{
// Argument registers are in the TransitionBlock
// The stack arguments are right after the pTransitionBlock
InterpThreadContext *threadContext = GetInterpThreadContext();
int8_t *sp = threadContext->pStackPointer;

InterpByteCodeStart* pInterpreterCode = dac_cast<PTR_InterpByteCodeStart>(byteCodeAddr);

if (pInterpreterCode->Method->unmanagedCallersOnly)
{
Thread* thread = GetThreadNULLOk();
if (thread == NULL)
CREATETHREAD_IF_NULL_FAILFAST(thread, W("Failed to setup new thread during reverse P/Invoke"));

// Verify the current thread isn't in COOP mode.
if (thread->PreemptiveGCDisabled())
ReversePInvokeBadTransition();
}

GCX_MAYBE_COOP(pInterpreterCode->Method->unmanagedCallersOnly);

// This construct ensures that the InterpreterFrame is always stored at a higher address than the
// InterpMethodContextFrame. This is important for the stack walking code.
struct Frames
Expand Down