diff --git a/src/coreclr/vm/codeversion.cpp b/src/coreclr/vm/codeversion.cpp index 8fa82da46db6e2..e6ff66cfac9df8 100644 --- a/src/coreclr/vm/codeversion.cpp +++ b/src/coreclr/vm/codeversion.cpp @@ -1637,7 +1637,8 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( MethodDesc* pMethodDesc, CallerGCMode callerGCMode, bool *doBackpatchRef, - bool *doFullBackpatchRef) + bool *doFullBackpatchRef, + Module* pModule) { STANDARD_VM_CONTRACT; _ASSERTE(!IsLockOwnedByCurrentThread()); @@ -1698,7 +1699,7 @@ PCODE CodeVersionManager::PublishVersionableCodeIfNecessary( // Record the caller's GC mode. config->SetCallerGCMode(callerGCMode); - pCode = pMethodDesc->PrepareCode(config); + pCode = pMethodDesc->PrepareCode(config, pModule); #ifdef FEATURE_CODE_VERSIONING if (config->ProfilerMayHaveActivatedNonDefaultCodeVersion()) diff --git a/src/coreclr/vm/codeversion.h b/src/coreclr/vm/codeversion.h index bacc5305d9bb6c..b3ec3345114168 100644 --- a/src/coreclr/vm/codeversion.h +++ b/src/coreclr/vm/codeversion.h @@ -594,7 +594,8 @@ class CodeVersionManager MethodDesc* pMethodDesc, CallerGCMode callerGCMode, bool *doBackpatchRef, - bool *doFullBackpatchRef); + bool *doFullBackpatchRef, + Module* pModule = NULL); HRESULT PublishNativeCodeVersion(MethodDesc* pMethodDesc, NativeCodeVersion nativeCodeVersion); HRESULT GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodDescVersioningState); HRESULT GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState); diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 5bdea982a7591f..29459a973877bf 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -1792,7 +1792,7 @@ class MethodDesc // PCODE DoBackpatch(MethodTable * pMT, MethodTable * pDispatchingMT, BOOL fFullBackPatch); - PCODE DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMode = CallerGCMode::Unknown); + PCODE DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMode = CallerGCMode::Unknown, Module* pModule = NULL); VOID GetMethodInfo(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); VOID GetMethodInfoWithNewSig(SString &namespaceOrClassName, SString &methodName, SString &methodSignature); @@ -2019,13 +2019,13 @@ class MethodDesc #ifndef DACCESS_COMPILE public: PCODE PrepareInitialCode(CallerGCMode callerGCMode = CallerGCMode::Unknown); - PCODE PrepareCode(PrepareCodeConfig* pConfig); + PCODE PrepareCode(PrepareCodeConfig* pConfig, Module* pModule = NULL); private: - PCODE PrepareILBasedCode(PrepareCodeConfig* pConfig); - PCODE GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier); + PCODE PrepareILBasedCode(PrepareCodeConfig* pConfig, Module* pModule = NULL); + PCODE GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier, Module* pModule = NULL); PCODE GetPrecompiledNgenCode(PrepareCodeConfig* pConfig); - PCODE GetPrecompiledR2RCode(PrepareCodeConfig* pConfig); + PCODE GetPrecompiledR2RCode(PrepareCodeConfig* pConfig, Module* pModule_probe = NULL); PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0Jit); COR_ILMETHOD_DECODER* GetAndVerifyILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory); COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory); diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 01fa3287d3f702..12a8d3e613f569 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -322,7 +322,7 @@ PCODE MethodDesc::PrepareInitialCode(CallerGCMode callerGCMode) return PrepareCode(&config); } -PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig) +PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig, Module* pModule) { STANDARD_VM_CONTRACT; @@ -333,7 +333,7 @@ PCODE MethodDesc::PrepareCode(PrepareCodeConfig* pConfig) // If other kinds of code need multi-versioning we could add more cases here, // but for now generation of all other code/stubs occurs in other code paths _ASSERTE(IsIL() || IsNoMetadata()); - PCODE pCode = PrepareILBasedCode(pConfig); + PCODE pCode = PrepareILBasedCode(pConfig, pModule); #if defined(FEATURE_GDBJIT) && defined(TARGET_UNIX) && !defined(CROSSGEN_COMPILE) NotifyGdb::MethodPrepared(this); @@ -356,7 +356,7 @@ bool MayUsePrecompiledILStub() return true; } -PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) +PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig, Module* pModule) { STANDARD_VM_CONTRACT; PCODE pCode = NULL; @@ -406,7 +406,7 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) MethodDesc* pTargetMD = stubMethodDesc->GetILStubResolver()->GetStubTargetMethodDesc(); if (pTargetMD != NULL) { - pCode = pTargetMD->GetPrecompiledR2RCode(pConfig); + pCode = pTargetMD->GetPrecompiledR2RCode(pConfig, pModule); if (pCode != NULL) { LOG_USING_R2R_CODE(this); @@ -421,7 +421,7 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) if (pCode == NULL) { - pCode = GetPrecompiledCode(pConfig, shouldTier); + pCode = GetPrecompiledCode(pConfig, shouldTier, pModule); } #ifdef FEATURE_PERFMAP @@ -447,7 +447,7 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) return pCode; } -PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier) +PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier, Module* pModule) { STANDARD_VM_CONTRACT; PCODE pCode = NULL; @@ -465,7 +465,7 @@ PCODE MethodDesc::GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier #ifdef FEATURE_READYTORUN else { - pCode = GetPrecompiledR2RCode(pConfig); + pCode = GetPrecompiledR2RCode(pConfig, pModule); if (pCode != NULL) { LOG_USING_R2R_CODE(this); @@ -578,7 +578,7 @@ PCODE MethodDesc::GetPrecompiledNgenCode(PrepareCodeConfig* pConfig) } -PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) +PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig, Module* pModule_probe) { STANDARD_VM_CONTRACT; @@ -600,6 +600,20 @@ PCODE MethodDesc::GetPrecompiledR2RCode(PrepareCodeConfig* pConfig) { pCode = pModule->GetReadyToRunInfo()->GetEntryPoint(this, pConfig, TRUE /* fFixups */); } + + if (!pCode) + { + if (pModule_probe) + { + if (pModule_probe->IsReadyToRun()) + { + if (pModule_probe->IsInSameVersionBubble(GetModule())) + { + pCode = pModule_probe->GetReadyToRunInfo()->GetEntryPoint(this, pConfig, TRUE /* fFixups */); + } + } + } + } } #endif return pCode; @@ -1852,7 +1866,8 @@ extern "C" MethodDesc * STDCALL PreStubGetMethodDescForCompactEntryPoint (PCODE static PCODE PreStubWorker_Preemptive( _In_ TransitionBlock* pTransitionBlock, _In_ MethodDesc* pMD, - _In_opt_ Thread* currentThread) + _In_opt_ Thread* currentThread, + Module* pModule = NULL) { _ASSERTE(pMD->HasUnmanagedCallersOnlyAttribute()); @@ -1885,7 +1900,7 @@ static PCODE PreStubWorker_Preemptive( pMD->CheckRestore(); CONSISTENCY_CHECK(GetAppDomain()->CheckCanExecuteManagedCode(pMD)); - pbRetVal = pMD->DoPrestub(NULL, CallerGCMode::Preemptive); + pbRetVal = pMD->DoPrestub(NULL, CallerGCMode::Preemptive, pModule); UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; @@ -1910,6 +1925,11 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method { PCODE pbRetVal = NULL; + Module* pModule = NULL; + FrameWithCookie frame(pTransitionBlock); + ExternalMethodFrame * pEMFrame = &frame; + pModule = ExecutionManager::FindReadyToRunModule((TADDR)(((BYTE*)pEMFrame->GetReturnAddress())-1)); + BEGIN_PRESERVE_LAST_ERROR; STATIC_CONTRACT_THROWS; @@ -1927,7 +1947,7 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method if (CURRENT_THREAD == NULL || !CURRENT_THREAD->PreemptiveGCDisabled()) { - pbRetVal = PreStubWorker_Preemptive(pTransitionBlock, pMD, CURRENT_THREAD); + pbRetVal = PreStubWorker_Preemptive(pTransitionBlock, pMD, CURRENT_THREAD, pModule); } else { @@ -1995,7 +2015,7 @@ extern "C" PCODE STDCALL PreStubWorker(TransitionBlock* pTransitionBlock, Method auto jitWriteEnableHolder = PAL_JITWriteEnable(true); #endif // defined(HOST_OSX) && defined(HOST_ARM64) - pbRetVal = pMD->DoPrestub(pDispatchingMT, CallerGCMode::Coop); + pbRetVal = pMD->DoPrestub(pDispatchingMT, CallerGCMode::Coop, pModule); } UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; @@ -2064,7 +2084,7 @@ static void TestSEHGuardPageRestore() // the case of methods that require stubs to be executed first (e.g., remoted methods // that require remoting stubs to be executed first), this stable entrypoint would be a // pointer to the stub, and not a pointer directly to the JITted code. -PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMode) +PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMode, Module* pModule) { CONTRACT(PCODE) { @@ -2169,7 +2189,7 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT, CallerGCMode callerGCMo { bool doBackpatch = true; bool doFullBackpatch = false; - pCode = GetCodeVersionManager()->PublishVersionableCodeIfNecessary(this, callerGCMode, &doBackpatch, &doFullBackpatch); + pCode = GetCodeVersionManager()->PublishVersionableCodeIfNecessary(this, callerGCMode, &doBackpatch, &doFullBackpatch, pModule); if (doBackpatch) {