diff --git a/src/coreclr/vm/dllimport.cpp b/src/coreclr/vm/dllimport.cpp index f9d5924c94a517..0c5e85018240c5 100644 --- a/src/coreclr/vm/dllimport.cpp +++ b/src/coreclr/vm/dllimport.cpp @@ -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) @@ -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 @@ -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; } @@ -6011,8 +6025,6 @@ VOID PInvokeMethodDesc::SetPInvokeTarget(LPVOID pTarget) //========================================================================== EXTERN_C void* PInvokeImportWorker(PInvokeMethodDesc* pMD) { - LPVOID ret = NULL; - PreserveLastErrorHolder preserveLastError; CONTRACTL @@ -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(); } //=========================================================================== diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 79040c69c9e08b..9f5dd3d17e6a8e 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -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(); diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 73ae13ab6e5ac9..532c285d4fab46 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -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(this)); - } } // end else if (IsIL() || IsNoMetadata() || (IsPInvoke() && !IsVarArg())) else if (IsPInvoke()) {