Skip to content
28 changes: 19 additions & 9 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1298,7 +1298,8 @@ class PInvoke_StackArgumentSize_ILStubState final : public ILStubState

void MarshalArgument(MarshalInfo* pInfo, int argOffset)
{
LIMITED_METHOD_CONTRACT;
STANDARD_VM_CONTRACT;
pInfo->SetupArgumentSizes();
}

void MarshalLCID(int argIdx)
Expand Down Expand Up @@ -2391,9 +2392,21 @@ void PInvokeStubLinker::DoPInvoke(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
{
_ASSERTE(pMD->IsPInvoke());
PInvokeMethodDesc* pTargetMD = (PInvokeMethodDesc*)pMD;
pcsEmit->EmitLDC((DWORD_PTR)&pTargetMD->m_pPInvokeTarget);
pcsEmit->EmitCONV_I();
pcsEmit->EmitLDIND_I();

// Resolve the P/Invoke target now if our P/Invoke is one that must be resolved eagerly
// (ie SuppressGCTransition)
void* pInvokeTarget = nullptr;
if (PInvokeMethodDesc::TryGetResolvedPInvokeTarget(pTargetMD, &pInvokeTarget))
{
pcsEmit->EmitLDC((DWORD_PTR)pInvokeTarget);
pcsEmit->EmitCONV_I();
}
else
{
pcsEmit->EmitLDC((DWORD_PTR)&pTargetMD->m_pPInvokeTarget);
pcsEmit->EmitCONV_I();
pcsEmit->EmitLDIND_I();
}
}
}
else // native-to-managed
Expand Down Expand Up @@ -4759,6 +4772,7 @@ COR_ILMETHOD_DECODER* PInvoke::CreatePInvokeMethodIL(PInvokeMethodDesc* pMD, Dyn
pResolver->SetStubMethodDesc(pMD);

COR_ILMETHOD_DECODER* pIL = CreatePInvokeStubWorker(&stubState, pResolver, &sigDesc, sigInfo.GetCharSet(), sigInfo.GetLinkFlags(), sigInfo.GetCallConv(), stubState.GetFlags(), pMD, pParamTokenArray, iLCIDArg);

*ppResolver = pResolver.Extract();
return pIL;
}
Expand Down Expand Up @@ -6011,8 +6025,6 @@ VOID PInvokeMethodDesc::SetPInvokeTarget(LPVOID pTarget)
//==========================================================================
EXTERN_C void* PInvokeImportWorker(PInvokeMethodDesc* pMD)
{
LPVOID ret = NULL;

PreserveLastErrorHolder preserveLastError;

CONTRACTL
Expand All @@ -6031,12 +6043,10 @@ EXTERN_C void* PInvokeImportWorker(PInvokeMethodDesc* pMD)

PInvoke::ResolvePInvokeTarget(pMD);

ret = pMD->GetPInvokeTarget();

UNINSTALL_UNWIND_AND_CONTINUE_HANDLER;
UNINSTALL_MANAGED_EXCEPTION_DISPATCHER;

return ret;
return pMD->GetPInvokeTarget();
}

//===========================================================================
Expand Down
12 changes: 9 additions & 3 deletions src/coreclr/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3543,11 +3543,17 @@ BOOL PInvokeMethodDesc::TryGetResolvedPInvokeTarget(_In_ PInvokeMethodDesc* pMD,
return TRUE;
}

// We only resolve P/Invoke targets early for SuppressGCTransition inlined P/Invokes.
// We do so because we cannot resolve the target of a SuppressGCTransition inlined P/Invoke at the time of the call
// as the resolution logic violates the rules of SuppressGCTransition (this behavior is documented).
// We only resolve P/Invoke targets early in two cases:
// - SuppressGCTransition inlined P/Invokes.
// We do so because we cannot resolve the target of a SuppressGCTransition inlined P/Invoke at the time of the call
// as the resolution logic violates the rules of SuppressGCTransition (this behavior is documented).
// - Platforms with no P/Invoke import precode:
// On these platforms, there is no mechanism to lazily resolve the target of a P/Invoke,
// so we must resolve it eagerly in order for the call to succeed.
#ifdef HAS_PINVOKE_IMPORT_PRECODE
if (!pMD->ShouldSuppressGCTransition())
return FALSE;
#endif

PInvoke::ResolvePInvokeTarget(pMD);
*ndirectTarget = pMD->GetPInvokeTarget();
Expand Down
12 changes: 0 additions & 12 deletions src/coreclr/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2402,18 +2402,6 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo
}
#endif // !FEATURE_PORTABLE_ENTRYPOINTS
pCode = PrepareInitialCode(callerGCMode);

// We need to resolve the P/Invoke target in the prestub in the following cases:
// - SuppressGCTransition
// - The logic to resolve the P/Invoke target does not meet the requirements for SuppressGCTransition usage.
// - No P/Invoke import thunk
// - If there's no P/Invoke import thunk, then there's no later time to resolve the P/Invoke target.
//
// For simplicity, we will resolve all P/Invoke targets here for non-inlined P/Invokes.
if (IsPInvoke())
{
PInvoke::ResolvePInvokeTarget(static_cast<PInvokeMethodDesc*>(this));
}
} // end else if (IsIL() || IsNoMetadata() || (IsPInvoke() && !IsVarArg()))
else if (IsPInvoke())
{
Expand Down