PCODE GetPrecompiledCode(PrepareCodeConfig* pConfig, bool shouldTier);
PCODE GetPrecompiledNgenCode(PrepareCodeConfig* pConfig);
PCODE GetPrecompiledR2RCode(PrepareCodeConfig* pConfig);
- PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0Jit);
+ PCODE GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0);
COR_ILMETHOD_DECODER* GetAndVerifyILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory);
COR_ILMETHOD_DECODER* GetAndVerifyMetadataILHeader(PrepareCodeConfig* pConfig, COR_ILMETHOD_DECODER* pIlDecoderMemory);
COR_ILMETHOD_DECODER* GetAndVerifyNoMetadataILHeader();
}
}
- bool FinalizeOptimizationTierForTier0Jit();
+ bool FinalizeOptimizationTierForTier0Load();
+ bool FinalizeOptimizationTierForTier0LoadOrJit();
#endif
public:
class MulticoreJitPrepareCodeConfig : public PrepareCodeConfig
{
private:
- bool m_wasTier0Jit;
+ bool m_wasTier0;
public:
MulticoreJitPrepareCodeConfig(MethodDesc* pMethod);
- bool WasTier0Jit() const
+ bool WasTier0() const
{
LIMITED_METHOD_CONTRACT;
- return m_wasTier0Jit;
+ return m_wasTier0;
}
- void SetWasTier0Jit()
+ void SetWasTier0()
{
LIMITED_METHOD_CONTRACT;
- m_wasTier0Jit = true;
+ m_wasTier0 = true;
}
virtual BOOL SetNativeCode(PCODE pCode, PCODE * ppAlternateCodeToUse) override;
}
-void MulticoreJitRecorder::RecordMethodJit(MethodDesc * pMethod, bool application)
+void MulticoreJitRecorder::RecordMethodJitOrLoad(MethodDesc * pMethod, bool application)
{
STANDARD_VM_CONTRACT;
if (!codeInfo.IsNull() && pManager->IsRecorderActive()) // recorder may be off when player is on (e.g. for Appx)
{
- RecordMethodJit(pMethod, false); // JITTed by background thread, returned to application
+ RecordMethodJitOrLoad(pMethod, false); // JITTed by background thread, returned to application
}
return codeInfo;
// Call back from MethodDesc::MakeJitWorker for
// Threading: protected by m_playerLock
-void MulticoreJitManager::RecordMethodJit(MethodDesc * pMethod)
+void MulticoreJitManager::RecordMethodJitOrLoad(MethodDesc * pMethod)
{
STANDARD_VM_CONTRACT;
if (m_pMulticoreJitRecorder != NULL)
{
- m_pMulticoreJitRecorder->RecordMethodJit(pMethod, true);
+ m_pMulticoreJitRecorder->RecordMethodJitOrLoad(pMethod, true);
if (m_pMulticoreJitRecorder->IsAtFullCapacity())
{
enum class TierInfo : TADDR
{
None = 0,
- WasTier0Jit = 1 << 0,
+ WasTier0 = 1 << 0,
JitSwitchedToOptimized = 1 << 1,
- Mask = None | WasTier0Jit | JitSwitchedToOptimized
+ Mask = None | WasTier0 | JitSwitchedToOptimized
};
TADDR m_entryPointAndTierInfo;
return IsNull() ? NULL : PINSTRToPCODE(m_entryPointAndTierInfo & ~(TADDR)TierInfo::Mask);
}
- bool WasTier0Jit() const
+ bool WasTier0() const
{
WRAPPER_NO_CONTRACT;
VerifyIsNotNull();
- return (m_entryPointAndTierInfo & (TADDR)TierInfo::WasTier0Jit) != 0;
+ return (m_entryPointAndTierInfo & (TADDR)TierInfo::WasTier0) != 0;
}
bool JitSwitchedToOptimized() const
MulticoreJitCodeInfo RequestMethodCode(MethodDesc * pMethod);
- void RecordMethodJit(MethodDesc * pMethod);
+ void RecordMethodJitOrLoad(MethodDesc * pMethod);
MulticoreJitPlayerStat & GetStats()
{
(m_ModuleCount >= MAX_MODULES);
}
- void RecordMethodJit(MethodDesc * pMethod, bool application);
+ void RecordMethodJitOrLoad(MethodDesc * pMethod, bool application);
MulticoreJitCodeInfo RequestMethodCode(MethodDesc * pMethod, MulticoreJitManager * pManager);
"%p %p %d %d StoredMethodCode",
pMD,
codeInfo.GetEntryPoint(),
- (int)codeInfo.WasTier0Jit(),
+ (int)codeInfo.WasTier0(),
(int)codeInfo.JitSwitchedToOptimized()));
}
#endif
"%p %p %d %d QueryAndRemoveMethodCode",
pMethod,
codeInfo.GetEntryPoint(),
- (int)codeInfo.WasTier0Jit(),
+ (int)codeInfo.WasTier0(),
(int)codeInfo.JitSwitchedToOptimized()));
}
#endif
#ifndef DACCESS_COMPILE
MulticoreJitPrepareCodeConfig::MulticoreJitPrepareCodeConfig(MethodDesc* pMethod) :
- PrepareCodeConfig(NativeCodeVersion(pMethod), FALSE, FALSE), m_wasTier0Jit(false)
+ // Method code that was pregenerated and loaded is recorded in the multi-core JIT profile, so enable multi-core JIT to also
+ // look up pregenerated code to help parallelize the work
+ PrepareCodeConfig(NativeCodeVersion(pMethod), FALSE, TRUE), m_wasTier0(false)
{
WRAPPER_NO_CONTRACT;
_ASSERTE((m_entryPointAndTierInfo & (TADDR)TierInfo::Mask) == 0);
#ifdef FEATURE_TIERED_COMPILATION
- if (pConfig->WasTier0Jit())
+ if (pConfig->WasTier0())
{
- m_entryPointAndTierInfo |= (TADDR)TierInfo::WasTier0Jit;
+ m_entryPointAndTierInfo |= (TADDR)TierInfo::WasTier0;
}
if (pConfig->JitSwitchedToOptimized())
// Similar to Module::FindMethod + Module::FindMethodThrowing,
// except it calls GetMethodDescFromMemberDefOrRefOrSpec with strictMetadataChecks=FALSE to allow generic instantiation
MethodDesc * pMethod = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, token, NULL, FALSE, FALSE);
-
CompileMethodInfoRecord(pModule, pMethod, false);
}
else
unsigned curdata1 = * (const unsigned *) pCurBuf;
unsigned currcdTyp = curdata1 >> RECORD_TYPE_OFFSET;
unsigned curmoduleIndex = curdata1 & MODULE_MASK;
- unsigned curflags = curdata1 & METHOD_FLAGS_MASK;
if (currcdTyp == MULTICOREJIT_METHOD_RECORD_ID)
{
{
LOG_USING_R2R_CODE(this);
+#ifdef FEATURE_TIERED_COMPILATION
+ // Finalize the optimization tier before SetNativeCode() is called
+ bool shouldCountCalls = shouldTier && pConfig->FinalizeOptimizationTierForTier0Load();
+#endif
+
if (pConfig->SetNativeCode(pCode, &pCode))
{
#ifdef FEATURE_CODE_VERSIONING
pConfig->SetGeneratedOrLoadedNewCode();
#endif
#ifdef FEATURE_TIERED_COMPILATION
- if (shouldTier)
+ if (shouldCountCalls)
{
_ASSERTE(pConfig->GetCodeVersion().GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
pConfig->SetShouldCountCalls();
}
#endif
+
+#ifdef FEATURE_MULTICOREJIT
+ // Multi-core JIT is only applicable to the default code version. A method is recorded in the profile only when
+ // SetNativeCode() above succeeds to avoid recording duplicates in the multi-core JIT profile. Successful loads
+ // of R2R code are also recorded.
+ if (pConfig->NeedsMulticoreJitNotification())
+ {
+ _ASSERTE(pConfig->GetCodeVersion().IsDefaultVersion());
+ _ASSERTE(!pConfig->IsForMulticoreJit());
+
+ MulticoreJitManager & mcJitManager = GetAppDomain()->GetMulticoreJitManager();
+ if (mcJitManager.IsRecorderActive())
+ {
+ if (MulticoreJitManager::IsMethodSupported(this))
+ {
+ mcJitManager.RecordMethodJitOrLoad(this);
+ }
+ }
+ }
+#endif
}
}
}
}
}
#endif
+
return pCode;
}
-PCODE MethodDesc::GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0Jit)
+PCODE MethodDesc::GetMulticoreJitCode(PrepareCodeConfig* pConfig, bool* pWasTier0)
{
STANDARD_VM_CONTRACT;
_ASSERTE(pConfig != NULL);
_ASSERTE(pConfig->GetMethodDesc() == this);
- _ASSERTE(pWasTier0Jit != NULL);
- _ASSERTE(!*pWasTier0Jit);
+ _ASSERTE(pWasTier0 != NULL);
+ _ASSERTE(!*pWasTier0);
MulticoreJitCodeInfo codeInfo;
#ifdef FEATURE_MULTICOREJIT
#ifdef FEATURE_TIERED_COMPILATION
if (!codeInfo.IsNull())
{
- if (codeInfo.WasTier0Jit())
+ if (codeInfo.WasTier0())
{
- *pWasTier0Jit = true;
+ *pWasTier0 = true;
}
if (codeInfo.JitSwitchedToOptimized())
{
NativeCodeVersion codeVersion = pConfig->GetCodeVersion();
if (codeVersion.IsDefaultVersion())
{
- bool wasTier0Jit = false;
- pCode = GetMulticoreJitCode(pConfig, &wasTier0Jit);
+ bool wasTier0 = false;
+ pCode = GetMulticoreJitCode(pConfig, &wasTier0);
if (pCode != NULL)
{
#ifdef FEATURE_TIERED_COMPILATION
// Finalize the optimization tier before SetNativeCode() is called
- bool shouldCountCalls = wasTier0Jit && pConfig->FinalizeOptimizationTierForTier0Jit();
+ bool shouldCountCalls = wasTier0 && pConfig->FinalizeOptimizationTierForTier0LoadOrJit();
#endif
if (pConfig->SetNativeCode(pCode, &pCode))
#ifdef FEATURE_TIERED_COMPILATION
// Finalize the optimization tier before SetNativeCode() is called
- bool shouldCountCalls = pFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0) && pConfig->FinalizeOptimizationTierForTier0Jit();
+ bool shouldCountCalls = pFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0) && pConfig->FinalizeOptimizationTierForTier0LoadOrJit();
#endif
// Aside from rejit, performing a SetNativeCodeInterlocked at this point
{
if (MulticoreJitManager::IsMethodSupported(this))
{
- mcJitManager.RecordMethodJit(this); // Tell multi-core JIT manager to record method on successful JITting
+ mcJitManager.RecordMethodJitOrLoad(this); // Tell multi-core JIT manager to record method on successful JITting
}
}
}
}
#ifdef FEATURE_TIERED_COMPILATION
+// This function should be called before SetNativeCode() for consistency with usage of FinalizeOptimizationTierForTier0Jit
+bool PrepareCodeConfig::FinalizeOptimizationTierForTier0Load()
+{
+ _ASSERTE(GetMethodDesc()->IsEligibleForTieredCompilation());
+ _ASSERTE(!JitSwitchedToOptimized());
+
+ if (!IsForMulticoreJit())
+ {
+ return true; // should count calls if SetNativeCode() succeeds
+ }
+
+ // When using multi-core JIT, the loaded code would not be used until the method is called. Record some information that may
+ // be used later when the method is called.
+ ((MulticoreJitPrepareCodeConfig *)this)->SetWasTier0();
+ return false; // don't count calls
+}
+
// This function should be called before SetNativeCode() to update the optimization tier if necessary before SetNativeCode() is
// called. As soon as SetNativeCode() is called, another thread may get the native code and the optimization tier for that code
// version, and it should have already been finalized.
-bool PrepareCodeConfig::FinalizeOptimizationTierForTier0Jit()
+bool PrepareCodeConfig::FinalizeOptimizationTierForTier0LoadOrJit()
{
_ASSERTE(GetMethodDesc()->IsEligibleForTieredCompilation());
{
// When using multi-core JIT, the jitted code would not be used until the method is called. Don't make changes to the
// optimization tier yet, just record some information that may be used later when the method is called.
- ((MulticoreJitPrepareCodeConfig *)this)->SetWasTier0Jit();
+ ((MulticoreJitPrepareCodeConfig *)this)->SetWasTier0();
return false; // don't count calls
}
if (pCode == NULL)
{
pCode = GetStubForInteropMethod(this);
-#ifdef FEATURE_MULTICOREJIT
- if (pCode)
- {
- MulticoreJitManager & mcJitManager = GetAppDomain()->GetMulticoreJitManager();
- if (mcJitManager.IsRecorderActive())
- {
- if (MulticoreJitManager::IsMethodSupported(this))
- {
- mcJitManager.RecordMethodJit(this); // Tell multi-core JIT manager to record method on successful JITting
- }
- }
- }
-#endif // FEATURE_MULTICOREJIT
}
GetOrCreatePrecode();