RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_LEGACY_TieredCompilation, W("EXPERIMENTAL_TieredCompilation"), 0, "Deprecated - Use COMPLUS_TieredCompilation")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation_Tier1CallCountThreshold, W("TieredCompilation_Tier1CallCountThreshold"), 30, "Number of times a method must be called after which it is promoted to tier 1.")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation_Tier1CallCountingDelayMs, W("TieredCompilation_Tier1CallCountingDelayMs"), 100, "Delay in milliseconds since process startup or the last tier 0 JIT before call counting begins for tier 1 promotion.")
+
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation_Test_CallCounting, W("TieredCompilation_Test_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any tier1 promotion")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredCompilation_Test_OptimizeTier0, W("TieredCompilation_Test_OptimizeTier0"), 0, "Use optimized codegen (normally used by tier1) in tier0")
#endif
#if defined(FEATURE_TIERED_COMPILATION)
fTieredCompilation = false;
+ fTieredCompilation_CallCounting = false;
+ fTieredCompilation_OptimizeTier0 = false;
tieredCompilation_tier1CallCountThreshold = 1;
tieredCompilation_tier1CallCountingDelayMs = 0;
#endif
//this older name is deprecated, but still accepted for a time. Preserving it is a very small overhead not to needlessly break things.
CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_LEGACY_TieredCompilation) != 0;
+ fTieredCompilation_CallCounting = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TieredCompilation_Test_CallCounting) != 0;
+ fTieredCompilation_OptimizeTier0 = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TieredCompilation_Test_OptimizeTier0) != 0;
+
tieredCompilation_tier1CallCountThreshold =
CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TieredCompilation_Tier1CallCountThreshold);
if (tieredCompilation_tier1CallCountThreshold < 1)
// Tiered Compilation config
#if defined(FEATURE_TIERED_COMPILATION)
bool TieredCompilation(void) const {LIMITED_METHOD_CONTRACT; return fTieredCompilation; }
+ bool TieredCompilation_CallCounting() const {LIMITED_METHOD_CONTRACT; return fTieredCompilation_CallCounting; }
+ bool TieredCompilation_OptimizeTier0() const {LIMITED_METHOD_CONTRACT; return fTieredCompilation_OptimizeTier0; }
DWORD TieredCompilation_Tier1CallCountThreshold() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_tier1CallCountThreshold; }
DWORD TieredCompilation_Tier1CallCountingDelayMs() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_tier1CallCountingDelayMs; }
#endif
#if defined(FEATURE_TIERED_COMPILATION)
bool fTieredCompilation;
+ bool fTieredCompilation_CallCounting;
+ bool fTieredCompilation_OptimizeTier0;
DWORD tieredCompilation_tier1CallCountThreshold;
DWORD tieredCompilation_tier1CallCountingDelayMs;
#endif
BOOL MethodDesc::RequiresStableEntryPoint(BOOL fEstimateForChunk /*=FALSE*/)
{
LIMITED_METHOD_CONTRACT;
-
+
+ // Create precodes for versionable methods
+ if (IsVersionableWithPrecode())
+ return TRUE;
+
// Create precodes for edit and continue to make methods updateable
if (IsEnCMethod() || IsEnCAddedMethod())
return TRUE;
}
CONTRACTL_END
- return !MayHaveNativeCode() || IsRemotingInterceptedViaPrestub();
+ return !MayHaveNativeCode() || IsRemotingInterceptedViaPrestub() || IsVersionableWithPrecode();
}
void InterlockedUpdateFlags2(BYTE bMask, BOOL fSet);
// When the TieredCompilationManager has received enough call notifications
// for this method only then do we back-patch it.
BOOL fCanBackpatchPrestub = TRUE;
+ BOOL fEligibleForCallCounting = FALSE;
#ifdef FEATURE_TIERED_COMPILATION
TieredCompilationManager* pTieredCompilationManager = nullptr;
BOOL fEligibleForTieredCompilation = IsEligibleForTieredCompilation();
BOOL fWasPromotedToTier1 = FALSE;
if (fEligibleForTieredCompilation)
{
- pTieredCompilationManager = GetAppDomain()->GetTieredCompilationManager();
- CallCounter * pCallCounter = GetCallCounter();
- pCallCounter->OnMethodCalled(this, pTieredCompilationManager, &fCanBackpatchPrestub, &fWasPromotedToTier1);
+ fEligibleForCallCounting = g_pConfig->TieredCompilation_CallCounting();
+ if (fEligibleForCallCounting)
+ {
+ pTieredCompilationManager = GetAppDomain()->GetTieredCompilationManager();
+ CallCounter * pCallCounter = GetCallCounter();
+ pCallCounter->OnMethodCalled(this, pTieredCompilationManager, &fCanBackpatchPrestub, &fWasPromotedToTier1);
+ }
}
#endif
{
pCode = GetCodeVersionManager()->PublishVersionableCodeIfNecessary(this, fCanBackpatchPrestub);
- if (pTieredCompilationManager != nullptr && fCanBackpatchPrestub && pCode != NULL && !fWasPromotedToTier1)
+ if (pTieredCompilationManager != nullptr && fEligibleForCallCounting && fCanBackpatchPrestub && pCode != NULL && !fWasPromotedToTier1)
{
pTieredCompilationManager->OnMethodCallCountingStoppedWithoutTier1Promotion(this);
}
return flags;
}
- if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0)
+ if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0 &&
+ !g_pConfig->TieredCompilation_OptimizeTier0())
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_TIER0);
}
startInfo.WorkingDirectory = WorkingDirPath;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
- foreach (KeyValuePair<string, string> kv in config.EnvironmentVariables)
+ IEnumerable<KeyValuePair<string, string>> extraEnvVars = config.EnvironmentVariables.Concat(EnvironmentVariables).Append(new KeyValuePair<string, string>("DOTNET_MULTILEVEL_LOOKUP", "0"));
+ foreach (KeyValuePair<string, string> kv in extraEnvVars)
{
startInfo.Environment[kv.Key] = kv.Value;
}
- foreach (KeyValuePair<string, string> kv in EnvironmentVariables)
- {
- startInfo.Environment[kv.Key] = kv.Value;
- }
- startInfo.Environment["DOTNET_MULTILEVEL_LOOKUP"] = "0";
+ output.WriteLine("XUnitPerfHarness doesn't log env vars it uses to run processes. To workaround, logging them here:");
+ output.WriteLine(string.Join(", ", extraEnvVars.Select(kv => kv.Key + "=" + kv.Value)));
BenchmarkRunResult result = new BenchmarkRunResult(this, config);
StringBuilder stderr = new StringBuilder();