diff options
author | David Wrighton <davidwr@microsoft.com> | 2019-06-11 13:13:09 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-11 13:13:09 -0700 |
commit | 93675fbf467f54ab0f1f5d183c70750c9822c9ca (patch) | |
tree | 9fc2f0d0e6507da062ce55f371c46402da2a2f8f | |
parent | 118711549ecdc024719d5023a004a2250705cdf9 (diff) | |
download | coreclr-93675fbf467f54ab0f1f5d183c70750c9822c9ca.tar.gz coreclr-93675fbf467f54ab0f1f5d183c70750c9822c9ca.tar.bz2 coreclr-93675fbf467f54ab0f1f5d183c70750c9822c9ca.zip |
R2R ilstubs (#24823)
* Basic support for precompiled pinvoke stubs
* Generate R2R file with multiple references to same IL stub (one per method which the IL stub is associated with)
* Not all il stubs are p/invokes. Don't fail when they aren't.
* Consistently use IsDynamicScope and GetModule to avoid unsafe memory access in IL stub compilation paths
* Enable full p/invoke il stubs when compiling System.Private.Corelib
* Disable IL Stub generation in crossgen for ARM32.
- The cross bitness logic is not correct for IL Stub generation
-rw-r--r-- | src/inc/corcompile.h | 5 | ||||
-rw-r--r-- | src/vm/compile.cpp | 114 | ||||
-rw-r--r-- | src/vm/compile.h | 4 | ||||
-rw-r--r-- | src/vm/dllimport.cpp | 30 | ||||
-rw-r--r-- | src/vm/ilstubresolver.cpp | 6 | ||||
-rw-r--r-- | src/vm/ilstubresolver.h | 1 | ||||
-rw-r--r-- | src/vm/prestub.cpp | 52 | ||||
-rw-r--r-- | src/vm/stubgen.cpp | 2 | ||||
-rw-r--r-- | src/vm/zapsig.cpp | 93 | ||||
-rw-r--r-- | src/zap/zapinfo.cpp | 12 | ||||
-rw-r--r-- | src/zap/zapreadytorun.cpp | 38 |
11 files changed, 313 insertions, 44 deletions
diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h index 5f39c65f79..755c846f51 100644 --- a/src/inc/corcompile.h +++ b/src/inc/corcompile.h @@ -1756,6 +1756,11 @@ class ICorCompileInfo virtual int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token) = 0; virtual int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle) = 0; + + virtual BOOL EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator) = 0; + virtual BOOL EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod) = 0; + virtual void EnumCloseForStubEnumerator(void *enumerator) = 0; + #endif virtual BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName) = 0; diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp index f6dd83e99a..321abae729 100644 --- a/src/vm/compile.cpp +++ b/src/vm/compile.cpp @@ -69,9 +69,13 @@ #include "versionresilienthashcode.h" #include "inlinetracking.h" #include "jithost.h" +#include "stubgen.h" #ifdef CROSSGEN_COMPILE CompilationDomain * theDomain; +#ifdef FEATURE_READYTORUN_COMPILER +MapSHash<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE> s_stubMethodsOfMethod; +#endif // FEATURE_READYTORUN_COMPILER #endif VerboseLevel g_CorCompileVerboseLevel = CORCOMPILE_NO_LOG; @@ -6192,11 +6196,17 @@ void CEEPreloader::GenerateMethodStubs( MethodDesc* pMD = GetMethod(hMethod); MethodDesc* pStubMD = NULL; - // Do not generate IL stubs when generating ReadyToRun images + // Do not generate IL stubs when generating ReadyToRun images except for System.Private.Corelib // This prevents versionability concerns around IL stubs exposing internal // implementation details of the CLR. + if (IsReadyToRunCompilation() && (!GetAppDomain()->ToCompilationDomain()->GetTargetModule()->IsSystem() || !pMD->IsNDirect())) + return; + +#if defined(_TARGET_ARM_) && defined(FEATURE_PAL) + // Cross-bitness compilation of il stubs does not work. Disable here. if (IsReadyToRunCompilation()) return; +#endif // defined(_TARGET_ARM_) && defined(FEATURE_PAL) DWORD dwNGenStubFlags = NDIRECTSTUB_FL_NGENEDSTUB; @@ -6285,8 +6295,14 @@ void CEEPreloader::GenerateMethodStubs( // that we can recover the stub MethodDesc at prestub time, do the fixups, and wire up the native code if (pStubMD != NULL) { - SetStubMethodDescOnInteropMethodDesc(pMD, pStubMD, false /* fReverseStub */); - pStubMD = NULL; +#ifdef FEATURE_READYTORUN_COMPILER + if (IsReadyToRunCompilation()) + { + s_stubMethodsOfMethod.Add(CORINFO_METHOD_HANDLE(pStubMD), CORINFO_METHOD_HANDLE(pMD)); + } +#endif // FEATURE_READYTORUN_COMPILER + SetStubMethodDescOnInteropMethodDesc(pMD, pStubMD, false /* fReverseStub */); + pStubMD = NULL; } } @@ -6297,6 +6313,10 @@ void CEEPreloader::GenerateMethodStubs( } EX_END_CATCH(RethrowTransientExceptions); + // Only P/Invoke stubs are eligible to be created in R2R + if (IsReadyToRunCompilation()) + return; + // // Now take care of reverse P/Invoke stubs for delegates // @@ -7290,6 +7310,94 @@ HRESULT CompilationDomain::SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths) return S_OK; } + +#ifdef FEATURE_READYTORUN_COMPILER + +class MethodsForStubEnumerator +{ + SHash<NoRemoveSHashTraits<MapSHashTraits<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE>>>::KeyIterator current; + SHash<NoRemoveSHashTraits<MapSHashTraits<CORINFO_METHOD_HANDLE, CORINFO_METHOD_HANDLE>>>::KeyIterator end; + bool started = false; + bool complete = false; + +public: + MethodsForStubEnumerator(CORINFO_METHOD_HANDLE hMethod) : + current(s_stubMethodsOfMethod.Begin(hMethod)), + end(s_stubMethodsOfMethod.End(hMethod)) + { + complete = current == end; + } + + bool Next() + { + if (complete) + return false; + + if (started) + { + ++current; + } + else + { + started = true; + } + + if (current == end) + { + complete = true; + return false; + } + return true; + } + + CORINFO_METHOD_HANDLE Current() + { + return current->Value(); + } +}; +#endif // FEATURE_READYTORUN_COMPILER + +BOOL CEECompileInfo::EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator) +{ +#ifdef FEATURE_READYTORUN_COMPILER + *enumerator = NULL; + if (s_stubMethodsOfMethod.LookupPtr(hMethod) == NULL) + return FALSE; + + *enumerator = new MethodsForStubEnumerator(hMethod); + return TRUE; +#else + return FALSE; +#endif // FEATURE_READYTORUN_COMPILER +} + +BOOL CEECompileInfo::EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod) +{ + *hMethod = NULL; +#ifdef FEATURE_READYTORUN_COMPILER + auto stubEnum = (MethodsForStubEnumerator*)enumerator; + if (stubEnum->Next()) + { + *hMethod = stubEnum->Current(); + return TRUE; + } + else + { + return FALSE; + } +#else + return FALSE; +#endif // FEATURE_READYTORUN_COMPILER +} + +void CEECompileInfo::EnumCloseForStubEnumerator(void *enumerator) +{ +#ifdef FEATURE_READYTORUN_COMPILER + auto stubEnum = (MethodsForStubEnumerator*)enumerator; + delete stubEnum; +#endif // FEATURE_READYTORUN_COMPILER +} + #endif // CROSSGEN_COMPILE diff --git a/src/vm/compile.h b/src/vm/compile.h index 8b13af6ecb..d8935c41d1 100644 --- a/src/vm/compile.h +++ b/src/vm/compile.h @@ -372,6 +372,10 @@ class CEECompileInfo : public ICorCompileInfo int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token); int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle); + + BOOL EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator); + BOOL EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod); + void EnumCloseForStubEnumerator(void *enumerator); #endif BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName); diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index 469a06e887..aca871d789 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -801,7 +801,7 @@ public: DWORD dwMethodDescLocalNum = (DWORD)-1; // Notify the profiler of call out of the runtime - if (!SF_IsReverseCOMStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || SF_IsNGENedStubForProfiling(m_dwStubFlags))) + if (!SF_IsReverseCOMStub(m_dwStubFlags) && (CORProfilerTrackTransitions() || (!IsReadyToRunCompilation() && SF_IsNGENedStubForProfiling(m_dwStubFlags)))) { dwMethodDescLocalNum = m_slIL.EmitProfilerBeginTransitionCallback(pcsDispatch, m_dwStubFlags); _ASSERTE(dwMethodDescLocalNum != (DWORD)-1); @@ -2295,27 +2295,23 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth #endif // FEATURE_COMINTEROP { EmitLoadStubContext(pcsEmit, dwStubFlags); + // pcsEmit->EmitCALL(METHOD__STUBHELPERS__GET_NDIRECT_TARGET, 1, 1); + pcsEmit->EmitLDC(offsetof(NDirectMethodDesc, ndirect.m_pWriteableData)); + pcsEmit->EmitADD(); + if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative) { - // Perf: inline the helper for now - //pcsEmit->EmitCALL(METHOD__STUBHELPERS__GET_NDIRECT_TARGET, 1, 1); - pcsEmit->EmitLDC(offsetof(NDirectMethodDesc, ndirect.m_pWriteableData)); - pcsEmit->EmitADD(); - - if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative) - { - pcsEmit->EmitDUP(); - } + pcsEmit->EmitDUP(); + } - pcsEmit->EmitLDIND_I(); + pcsEmit->EmitLDIND_I(); - if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative) - { - pcsEmit->EmitADD(); - } - - pcsEmit->EmitLDIND_I(); + if (decltype(NDirectMethodDesc::ndirect.m_pWriteableData)::isRelative) + { + pcsEmit->EmitADD(); } + + pcsEmit->EmitLDIND_I(); } #ifdef FEATURE_COMINTEROP else diff --git a/src/vm/ilstubresolver.cpp b/src/vm/ilstubresolver.cpp index 4d429626eb..7f5964b927 100644 --- a/src/vm/ilstubresolver.cpp +++ b/src/vm/ilstubresolver.cpp @@ -233,6 +233,11 @@ bool ILStubResolver::IsNativeToCLRInteropStub() return (m_type == NativeToCLRInteropStub); } +bool ILStubResolver::IsCLRToNativeInteropStub() +{ + return (m_type == CLRToNativeInteropStub); +} + void ILStubResolver::SetStubType(ILStubType stubType) { LIMITED_METHOD_CONTRACT; @@ -393,7 +398,6 @@ COR_ILMETHOD_SECT_EH* ILStubResolver::AllocEHSect(size_t nClauses) } } - void ILStubResolver::FreeCompileTimeState() { CONTRACTL diff --git a/src/vm/ilstubresolver.h b/src/vm/ilstubresolver.h index 8eeb510dbb..6f49398a96 100644 --- a/src/vm/ilstubresolver.h +++ b/src/vm/ilstubresolver.h @@ -47,6 +47,7 @@ public: // ILStubResolver-specific methods // ----------------------------------- bool IsNativeToCLRInteropStub(); + bool IsCLRToNativeInteropStub(); MethodDesc* GetStubMethodDesc(); MethodDesc* GetStubTargetMethodDesc(); void SetStubTargetMethodDesc(MethodDesc* pStubTargetMD); diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index d83c419e22..45ee0f02df 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -358,6 +358,20 @@ PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig) return PrepareILBasedCode(pConfig); } +bool MayUsePrecompiledILStub() +{ + if (g_pConfig->InteropValidatePinnedObjects()) + return false; + + if (CORProfilerTrackTransitions()) + return false; + + if (g_pConfig->InteropLogArguments()) + return false; + + return true; +} + PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) { STANDARD_VM_CONTRACT; @@ -365,7 +379,39 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) if (pConfig->MayUsePrecompiledCode()) { - pCode = GetPrecompiledCode(pConfig); +#ifdef FEATURE_READYTORUN + if (this->IsDynamicMethod() && GetLoaderModule()->IsSystem() && MayUsePrecompiledILStub()) + { + DynamicMethodDesc *stubMethodDesc = this->AsDynamicMethodDesc(); + if (stubMethodDesc->IsILStub() && stubMethodDesc->IsPInvokeStub()) + { + ILStubResolver *pStubResolver = stubMethodDesc->GetILStubResolver(); + if (pStubResolver->IsCLRToNativeInteropStub()) + { + MethodDesc *pTargetMD = stubMethodDesc->GetILStubResolver()->GetStubTargetMethodDesc(); + if (pTargetMD != NULL) + { + pCode = pTargetMD->GetPrecompiledR2RCode(pConfig); + if (pCode != NULL) + { + LOG((LF_ZAP, LL_INFO10000, + "ZAP: Using R2R precompiled code" FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n", + DBG_ADDR(pCode), + m_pszDebugClassName, + m_pszDebugMethodName, + m_pszDebugMethodSignature, + GetMemberDef())); + + pConfig->SetNativeCode(pCode, &pCode); + } + } + } + } + } +#endif // FEATURE_READYTORUN + + if (pCode == NULL) + pCode = GetPrecompiledCode(pConfig); } if (pCode == NULL) @@ -412,7 +458,7 @@ PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig) if (pCode != NULL) { LOG((LF_ZAP, LL_INFO10000, - "ZAP: Using R2R precompiled code" FMT_ADDR "for %s.%s sig=\"%s\" (token %x).\n", + "ZAP: Using R2R precompiled code" FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n", DBG_ADDR(pCode), m_pszDebugClassName, m_pszDebugMethodName, @@ -471,7 +517,7 @@ PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig) if (pCode != NULL) { LOG((LF_ZAP, LL_INFO10000, - "ZAP: Using NGEN precompiled code" FMT_ADDR "for %s.%s sig=\"%s\" (token %x).\n", + "ZAP: Using NGEN precompiled code " FMT_ADDR " for %s.%s sig=\"%s\" (token %x).\n", DBG_ADDR(pCode), m_pszDebugClassName, m_pszDebugMethodName, diff --git a/src/vm/stubgen.cpp b/src/vm/stubgen.cpp index ab054a5c3f..60d1dea340 100644 --- a/src/vm/stubgen.cpp +++ b/src/vm/stubgen.cpp @@ -2921,4 +2921,4 @@ void ILCodeStream::ClearCode() { LIMITED_METHOD_CONTRACT; m_uCurInstrIdx = 0; -} +}
\ No newline at end of file diff --git a/src/vm/zapsig.cpp b/src/vm/zapsig.cpp index 08d9228c40..125ff7e7bc 100644 --- a/src/vm/zapsig.cpp +++ b/src/vm/zapsig.cpp @@ -1324,9 +1324,11 @@ BOOL ZapSig::EncodeMethod( { Module * pReferencingModule = pMethod->IsNDirect() ? pMethod->GetModule() : - (Module *)pResolvedToken->tokenScope; + IsDynamicScope(pResolvedToken->tokenScope) ? NULL: GetModule(pResolvedToken->tokenScope); - if (!pReferencingModule->IsInCurrentVersionBubble()) + // pReferencingModule may be NULL if the method is a dynamic method. + + if (pReferencingModule != NULL && !pReferencingModule->IsInCurrentVersionBubble()) { // FUTURE: Encoding of new cross-module references for ReadyToRun // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise. @@ -1334,9 +1336,54 @@ BOOL ZapSig::EncodeMethod( ThrowHR(E_FAIL); } - methodToken = pMethod->IsNDirect() ? - pMethod->GetMemberDef_NoLogging() : - pResolvedToken->token; + if (pMethod->IsNDirect()) + { + methodToken = pMethod->GetMemberDef_NoLogging(); + } + else if (!IsDynamicScope(pResolvedToken->tokenScope)) + { + // Normal case for IL code + methodToken = pResolvedToken->token; + } + else + { + // Dynamic scope case. IL Stubs only + if (!pMethod->GetModule()->IsSystem()) + { + _ASSERTE(FALSE); // IL stubs are expected to only have references to System. + ThrowHR(E_FAIL); + } + + if (pInfoModule == pMethod->GetModule()) + { + // This is assuming that the current module being compiled is the same as the module + // associated with the method being called. If so, we can identify the method by a MethodDef + // token. Otherwise, a more complex operation would be necessary. + methodToken = pMethod->GetMemberDef_NoLogging(); + } + else + { + // Attempt to compile IL stub with use of helper function outside of CoreLib + _ASSERTE(FALSE); + ThrowHR(E_FAIL); + } + + if (!ownerType.IsTypicalTypeDefinition() || pMethod->HasMethodInstantiation()) + { + _ASSERTE(FALSE); // IL Stubs are not expected to have use of generic functions + ThrowHR(E_FAIL); // Attempt to compile IL stub with use of generic function. This encoding does not support that. + } + } + + if (TypeFromToken(methodToken) != mdtMethodDef) + { + if (pReferencingModule == NULL) + { + // Invalid situation. Null pReferencingModule can only happen with a dynamic scope, + // and in that case the reference can only be a methoddef. + ThrowHR(E_FAIL); + } + } if (TypeFromToken(methodToken) == mdtMethodSpec) { @@ -1447,9 +1494,14 @@ BOOL ZapSig::EncodeMethod( _ASSERTE(pResolvedToken->cbTypeSpec > 0); DWORD moduleIndex = MODULE_INDEX_NONE; - if ((IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope)) + if ((IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != GetModule(pResolvedToken->tokenScope))) { - moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope); + if (IsDynamicScope(pResolvedToken->tokenScope)) + { + _ASSERTE(FALSE); // IL stubs aren't expected to call methods which need this + ThrowHR(E_FAIL); + } + moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) GetModule(pResolvedToken->tokenScope)); } SigParser sigParser(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); @@ -1492,10 +1544,16 @@ BOOL ZapSig::EncodeMethod( IfFailThrow(sigParser.GetData(&numGenArgs)); pSigBuilder->AppendData(numGenArgs); + if (IsDynamicScope(pResolvedToken->tokenScope)) + { + _ASSERTE(FALSE); // IL stubs aren't expected to call methods which need this + ThrowHR(E_FAIL); + } + DWORD moduleIndex = MODULE_INDEX_NONE; - if ((IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope)) + if (IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != GetModule(pResolvedToken->tokenScope)) { - moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope); + moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, GetModule(pResolvedToken->tokenScope)); } while (numGenArgs != 0) @@ -1531,9 +1589,14 @@ BOOL ZapSig::EncodeMethod( _ASSERTE(pConstrainedResolvedToken->cbTypeSpec > 0); DWORD moduleIndex = MODULE_INDEX_NONE; - if (IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pConstrainedResolvedToken->tokenScope) + if (IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != GetModule(pConstrainedResolvedToken->tokenScope)) { - moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pConstrainedResolvedToken->tokenScope); + if (IsDynamicScope(pConstrainedResolvedToken->tokenScope)) + { + _ASSERTE(FALSE); // IL stubs aren't expected to call methods which need this + ThrowHR(E_FAIL); + } + moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, GetModule(pConstrainedResolvedToken->tokenScope)); } SigParser sigParser(pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec); @@ -1584,7 +1647,13 @@ void ZapSig::EncodeField( // Encode the referencing field type pMT = (MethodTable *)(pResolvedToken->hClass); - Module * pReferencingModule = (Module *)pResolvedToken->tokenScope; + if (IsDynamicScope(pResolvedToken->tokenScope)) + { + _ASSERTE(FALSE); // IL stubs aren't expected to need to access this sort of field + ThrowHR(E_FAIL); + } + + Module * pReferencingModule = GetModule(pResolvedToken->tokenScope); if (!pReferencingModule->IsInCurrentVersionBubble()) { diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index f57556b830..007765b3ab 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -2228,6 +2228,18 @@ void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, } else { + if (pResult->methodFlags & CORINFO_FLG_INTRINSIC) + { + bool unused; + CorInfoIntrinsics intrinsic = getIntrinsicID(pResult->hMethod, &unused); + if ((intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContext) + || (intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr) + ) + { + // These intrinsics are always expanded directly in the jit and do not correspond to external methods + return; + } + } pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken); } diff --git a/src/zap/zapreadytorun.cpp b/src/zap/zapreadytorun.cpp index cb41a1a4d7..73670bdc16 100644 --- a/src/zap/zapreadytorun.cpp +++ b/src/zap/zapreadytorun.cpp @@ -222,12 +222,6 @@ void ZapImage::OutputEntrypointsTableForReadyToRun() { ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(pMethod->GetHandle()); - CORINFO_SIG_INFO sig; - GetJitInfo()->getMethodSig(pMethod->GetHandle(), &sig); - - int rid = RidFromToken(token); - _ASSERTE(rid != 0); BlobVertex * pFixupBlob = NULL; @@ -250,8 +244,16 @@ void ZapImage::OutputEntrypointsTableForReadyToRun() } } + CORINFO_SIG_INFO sig; + GetJitInfo()->getMethodSig(pMethod->GetHandle(), &sig); + + mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(pMethod->GetHandle()); + int rid = RidFromToken(token); + if (sig.sigInst.classInstCount > 0 || sig.sigInst.methInstCount > 0) { + _ASSERTE(rid != 0); + CORINFO_MODULE_HANDLE module = GetJitInfo()->getClassModule(pMethod->GetClassHandle()); _ASSERTE(GetCompileInfo()->IsInCurrentVersionBubble(module)); SigBuilder sigBuilder; @@ -273,7 +275,29 @@ void ZapImage::OutputEntrypointsTableForReadyToRun() } else { - vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); + int rid = RidFromToken(token); + if (rid != 0) + { + vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); + } + else + { + // This is a p/invoke stub, get the list of methods associated with the stub, and put this code in that set of rids + void *targetMethodEnum; + BOOL isStubWithTargetMethods = GetCompileInfo()->EnumMethodsForStub(pMethod->GetHandle(), &targetMethodEnum); + _ASSERTE(isStubWithTargetMethods); + + CORINFO_METHOD_HANDLE hTargetMethod; + while (GetCompileInfo()->EnumNextMethodForStub(targetMethodEnum, &hTargetMethod)) + { + mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(hTargetMethod); + int rid = RidFromToken(token); + _ASSERTE(rid != 0); + vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); + } + + GetCompileInfo()->EnumCloseForStubEnumerator(targetMethodEnum); + } } fEmpty = false; |