summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKoundinya Veluri <kouvel@users.noreply.github.com>2019-05-02 13:48:13 -0700
committerGitHub <noreply@github.com>2019-05-02 13:48:13 -0700
commit607c8db3931cc4f4afe086f2cd4dd957d35ef0ac (patch)
tree511c45c80e528ca2b2b249213fd7a15a64191652 /src
parentee8c00f18b0230fa92bed627ebd0dbe26d30b721 (diff)
downloadcoreclr-607c8db3931cc4f4afe086f2cd4dd957d35ef0ac.tar.gz
coreclr-607c8db3931cc4f4afe086f2cd4dd957d35ef0ac.tar.bz2
coreclr-607c8db3931cc4f4afe086f2cd4dd957d35ef0ac.zip
When QuickJit is enabled, disable it for methods that contain loops by default (#24252)
When QuickJit is enabled, disable it for methods that contain loops by default Fixes https://github.com/dotnet/coreclr/issues/19751 by default when QuickJit is enabled - Added config variable TC_QuickJitForLoops. When disabled (the default), the JIT identifies loops and explicit tail calls and switches to tier 1 JIT. - This would prevent the possibility of spending too long in QuickJit code, but may decrease startup time a bit when QuickJit is enabled - Removed TC_StartupTier_OptimizeCode, as now that there is TC_QuickJit, I didn't see a good use for it - Removed references to "StartupTier" in config variables because we had previously decided not to call it that. - When QuickJit is disabled, avoid creating native code slots for methods in non-R2R'ed modules, as tiering would be disabled for those anyway - Marked TC_QuickJit config var as external
Diffstat (limited to 'src')
-rw-r--r--src/inc/clrconfigvalues.h13
-rw-r--r--src/inc/corinfo.h3
-rw-r--r--src/jit/compiler.cpp8
-rw-r--r--src/jit/compiler.h7
-rw-r--r--src/jit/flowgraph.cpp97
-rw-r--r--src/vm/callcounter.cpp4
-rw-r--r--src/vm/eeconfig.cpp42
-rw-r--r--src/vm/eeconfig.h16
-rw-r--r--src/vm/jitinterface.cpp15
-rw-r--r--src/vm/methodtablebuilder.cpp5
-rw-r--r--src/vm/prestub.cpp15
-rw-r--r--src/vm/tieredcompilation.cpp17
12 files changed, 193 insertions, 49 deletions
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index 3d8c26929d..ab4b8e4a05 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -647,13 +647,12 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent,
///
#ifdef FEATURE_TIERED_COMPILATION
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJit, W("TC_QuickJit"), 0, "For methods that would be jitted, enable using quick JIT when appropriate.")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_StartupTier_CallCountThreshold, W("TC_StartupTier_CallCountThreshold"), 30, "Number of times a method must be called in the startup tier after which it is promoted to the next tier.")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_StartupTier_CallCountingDelayMs, W("TC_StartupTier_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in the startup tier and jitting at higher tiers, while there is startup-like activity.")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_StartupTier_DelaySingleProcMultiplier, W("TC_StartupTier_DelaySingleProcMultiplier"), 10, "Multiplier for TC_StartupTier_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.")
-
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_StartupTier_CallCounting, W("TC_StartupTier_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers")
-RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_StartupTier_OptimizeCode, W("TC_StartupTier_OptimizeCode"), 0, "Use optimized codegen (normally used by the optimized tier) in the startup tier")
+RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 0, "For methods that would be jitted, enable using quick JIT when appropriate.")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), 30, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), 10, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers")
#endif
///
diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h
index df6adfe154..1a223a1f8b 100644
--- a/src/inc/corinfo.h
+++ b/src/inc/corinfo.h
@@ -832,7 +832,7 @@ enum CorInfoFlag
CORINFO_FLG_INTRINSIC = 0x00400000, // This method MAY have an intrinsic ID
CORINFO_FLG_CONSTRUCTOR = 0x00800000, // This method is an instance or type initializer
CORINFO_FLG_AGGRESSIVE_OPT = 0x01000000, // The method may contain hot code and should be aggressively optimized if possible
-// CORINFO_FLG_UNUSED = 0x02000000,
+ CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS = 0x02000000, // Indicates that tier 0 JIT should not be used for a method that contains a loop
CORINFO_FLG_NOSECURITYWRAP = 0x04000000, // The method requires no security checks
CORINFO_FLG_DONT_INLINE = 0x10000000, // The method should not be inlined
CORINFO_FLG_DONT_INLINE_CALLER = 0x20000000, // The method should not be inlined, nor should its callers. It cannot be tail called.
@@ -864,6 +864,7 @@ enum CorInfoMethodRuntimeFlags
CORINFO_FLG_BAD_INLINEE = 0x00000001, // The method is not suitable for inlining
CORINFO_FLG_VERIFIABLE = 0x00000002, // The method has verifiable code
CORINFO_FLG_UNVERIFIABLE = 0x00000004, // The method has unverifiable code
+ CORINFO_FLG_SWITCHED_TO_TIER1 = 0x00000008, // The JIT decided to switch to tier 1 for this method, when a different tier was requested
};
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 378d83bd1f..6b6a64c25e 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -5814,6 +5814,8 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr,
info.compTotalHotCodeSize = 0;
info.compTotalColdCodeSize = 0;
+ fgHasBackwardJump = false;
+
#ifdef DEBUG
compCurBB = nullptr;
lvaTable = nullptr;
@@ -5946,6 +5948,12 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr,
goto _Next;
}
+ if (fgHasBackwardJump && (info.compFlags & CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS) != 0 && fgCanSwitchToTier1())
+ {
+ // Method likely has a loop, switch to the OptimizedTier to avoid spending too much time running slower code
+ fgSwitchToTier1();
+ }
+
compSetOptimizationLevel();
#if COUNT_BASIC_BLOCKS
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index fed7003faa..d10f34de0c 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -5296,6 +5296,13 @@ protected:
void fgInitBBLookup();
BasicBlock* fgLookupBB(unsigned addr);
+ bool fgHasBackwardJump;
+
+ bool fgCanSwitchToTier1();
+ void fgSwitchToTier1();
+
+ bool fgMayExplicitTailCall();
+
void fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, FixedBitVect* jumpTarget);
void fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock);
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index 236302cca5..c9348d88af 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -4253,6 +4253,94 @@ private:
};
//------------------------------------------------------------------------
+// fgCanSwitchToTier1: Determines if conditions are met to allow switching the opt level to tier 1
+//
+// Return Value:
+// True if the opt level may be switched to tier 1, false otherwise
+//
+// Assumptions:
+// - compInitOptions() has been called
+// - compSetOptimizationLevel() has not been called
+//
+// Notes:
+// This method is to be called at some point before compSetOptimizationLevel() to determine if the opt level may be
+// changed based on information gathered in early phases.
+
+bool Compiler::fgCanSwitchToTier1()
+{
+ bool result = opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0) && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_MIN_OPT) &&
+ !opts.compDbgCode && !compIsForInlining();
+ if (result)
+ {
+ // Ensure that it would be safe to change the opt level
+ assert(opts.compFlags == CLFLG_MINOPT);
+ assert(!opts.IsMinOptsSet());
+ }
+
+ return result;
+}
+
+//------------------------------------------------------------------------
+// fgSwitchToTier1: Switch the opt level to tier 1
+//
+// Assumptions:
+// - fgCanSwitchToTier1() is true
+// - compSetOptimizationLevel() has not been called
+//
+// Notes:
+// This method is to be called at some point before compSetOptimizationLevel() to switch the opt level to tier 1
+// based on information gathered in early phases.
+
+void Compiler::fgSwitchToTier1()
+{
+ assert(fgCanSwitchToTier1());
+
+ // Switch to tier 1 and re-init options
+ assert(opts.jitFlags->IsSet(JitFlags::JIT_FLAG_TIER0));
+ opts.jitFlags->Clear(JitFlags::JIT_FLAG_TIER0);
+ opts.jitFlags->Set(JitFlags::JIT_FLAG_TIER1);
+ compInitOptions(opts.jitFlags);
+
+ // Notify the VM of the change
+ info.compCompHnd->setMethodAttribs(info.compMethodHnd, CORINFO_FLG_SWITCHED_TO_TIER1);
+}
+
+//------------------------------------------------------------------------
+// fgMayExplicitTailCall: Estimates conservatively for an explicit tail call, if the importer may actually use a tail
+// call.
+//
+// Return Value:
+// - False if a tail call will not be generated
+// - True if a tail call *may* be generated
+//
+// Assumptions:
+// - compInitOptions() has been called
+// - info.compIsVarArgs has been initialized
+// - An explicit tail call has been seen
+// - compSetOptimizationLevel() has not been called
+
+bool Compiler::fgMayExplicitTailCall()
+{
+ assert(!compIsForInlining());
+
+ if (info.compFlags & CORINFO_FLG_SYNCH)
+ {
+ // Caller is synchronized
+ return false;
+ }
+
+#if !FEATURE_FIXED_OUT_ARGS
+ if (info.compIsVarArgs)
+ {
+ // Caller is varargs
+ return false;
+ }
+#endif // FEATURE_FIXED_OUT_ARGS
+
+ return true;
+}
+
+//------------------------------------------------------------------------
// fgFindJumpTargets: walk the IL stream, determining jump target offsets
//
// Arguments:
@@ -5137,6 +5225,7 @@ void Compiler::fgMarkBackwardJump(BasicBlock* startBlock, BasicBlock* endBlock)
if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
{
block->bbFlags |= BBF_BACKWARD_JUMP;
+ fgHasBackwardJump = true;
}
}
}
@@ -5516,6 +5605,14 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, F
#endif // !FEATURE_CORECLR && _TARGET_AMD64_
}
+ if (fgCanSwitchToTier1() && fgMayExplicitTailCall())
+ {
+ // Method has an explicit tail call that may run like a loop or may not be generated as a tail
+ // call in tier 0, switch to tier 1 to avoid spending too much time running slower code and to
+ // avoid stack overflow from recursion
+ fgSwitchToTier1();
+ }
+
#if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_)
if (isCallPopAndRet)
{
diff --git a/src/vm/callcounter.cpp b/src/vm/callcounter.cpp
index 4130345da0..d360f1227c 100644
--- a/src/vm/callcounter.cpp
+++ b/src/vm/callcounter.cpp
@@ -39,7 +39,7 @@ bool CallCounter::IsEligibleForTier0CallCounting(MethodDesc* pMethodDesc)
_ASSERTE(pMethodDesc != NULL);
_ASSERTE(pMethodDesc->IsEligibleForTieredCompilation());
- return g_pConfig->TieredCompilation_StartupTier_CallCounting() && !pMethodDesc->RequestedAggressiveOptimization();
+ return g_pConfig->TieredCompilation_CallCounting() && !pMethodDesc->RequestedAggressiveOptimization();
}
bool CallCounter::IsTier0CallCountingEnabled(MethodDesc* pMethodDesc)
@@ -131,7 +131,7 @@ void CallCounter::OnMethodCalled(
if (pEntry == NULL)
{
isFirstTier0Call = true;
- tier0CallCountLimit = (int)g_pConfig->TieredCompilation_StartupTier_CallCountThreshold() - 1;
+ tier0CallCountLimit = (int)g_pConfig->TieredCompilation_CallCountThreshold() - 1;
_ASSERTE(tier0CallCountLimit >= 0);
m_methodToCallCount.Add(CallCounterEntry(pMethodDesc, tier0CallCountLimit));
}
diff --git a/src/vm/eeconfig.cpp b/src/vm/eeconfig.cpp
index 0d4021fc88..a4b8e1d196 100644
--- a/src/vm/eeconfig.cpp
+++ b/src/vm/eeconfig.cpp
@@ -351,10 +351,10 @@ HRESULT EEConfig::Init()
#if defined(FEATURE_TIERED_COMPILATION)
fTieredCompilation = false;
fTieredCompilation_QuickJit = false;
- fTieredCompilation_StartupTier_CallCounting = false;
- fTieredCompilation_StartupTier_OptimizeCode = false;
- tieredCompilation_StartupTier_CallCountThreshold = 1;
- tieredCompilation_StartupTier_CallCountingDelayMs = 0;
+ fTieredCompilation_QuickJitForLoops = false;
+ fTieredCompilation_CallCounting = false;
+ tieredCompilation_CallCountThreshold = 1;
+ tieredCompilation_CallCountingDelayMs = 0;
#endif
#ifndef CROSSGEN_COMPILE
@@ -1207,29 +1207,30 @@ HRESULT EEConfig::sync()
dwSleepOnExit = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_SleepOnExit);
#if defined(FEATURE_TIERED_COMPILATION)
- fTieredCompilation = Configuration::GetKnobBooleanValue(W("System.Runtime.TieredCompilation"), CLRConfig::EXTERNAL_TieredCompilation) != 0;
+ fTieredCompilation = Configuration::GetKnobBooleanValue(W("System.Runtime.TieredCompilation"), CLRConfig::EXTERNAL_TieredCompilation);
fTieredCompilation_QuickJit =
Configuration::GetKnobBooleanValue(
W("System.Runtime.TieredCompilation.QuickJit"),
- CLRConfig::UNSUPPORTED_TC_QuickJit) != 0;
+ CLRConfig::EXTERNAL_TC_QuickJit);
+ fTieredCompilation_QuickJitForLoops =
+ Configuration::GetKnobBooleanValue(
+ W("System.Runtime.TieredCompilation.QuickJitForLoops"),
+ CLRConfig::UNSUPPORTED_TC_QuickJitForLoops);
- fTieredCompilation_StartupTier_CallCounting = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_StartupTier_CallCounting) != 0;
- fTieredCompilation_StartupTier_OptimizeCode = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_StartupTier_OptimizeCode) != 0;
+ fTieredCompilation_CallCounting = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCounting) != 0;
- tieredCompilation_StartupTier_CallCountThreshold =
- CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_CallCountThreshold);
- if (tieredCompilation_StartupTier_CallCountThreshold < 1)
+ tieredCompilation_CallCountThreshold = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCountThreshold);
+ if (tieredCompilation_CallCountThreshold < 1)
{
- tieredCompilation_StartupTier_CallCountThreshold = 1;
+ tieredCompilation_CallCountThreshold = 1;
}
- else if (tieredCompilation_StartupTier_CallCountThreshold > INT_MAX) // CallCounter uses 'int'
+ else if (tieredCompilation_CallCountThreshold > INT_MAX) // CallCounter uses 'int'
{
- tieredCompilation_StartupTier_CallCountThreshold = INT_MAX;
+ tieredCompilation_CallCountThreshold = INT_MAX;
}
- tieredCompilation_StartupTier_CallCountingDelayMs =
- CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_CallCountingDelayMs);
+ tieredCompilation_CallCountingDelayMs = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_CallCountingDelayMs);
#ifndef FEATURE_PAL
bool hadSingleProcessorAtStartup = CPUGroupInfo::HadSingleProcessorAtStartup();
@@ -1239,14 +1240,13 @@ HRESULT EEConfig::sync()
if (hadSingleProcessorAtStartup)
{
- DWORD delayMultiplier =
- CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_DelaySingleProcMultiplier);
+ DWORD delayMultiplier = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TC_DelaySingleProcMultiplier);
if (delayMultiplier > 1)
{
- DWORD newDelay = tieredCompilation_StartupTier_CallCountingDelayMs * delayMultiplier;
- if (newDelay / delayMultiplier == tieredCompilation_StartupTier_CallCountingDelayMs)
+ DWORD newDelay = tieredCompilation_CallCountingDelayMs * delayMultiplier;
+ if (newDelay / delayMultiplier == tieredCompilation_CallCountingDelayMs)
{
- tieredCompilation_StartupTier_CallCountingDelayMs = newDelay;
+ tieredCompilation_CallCountingDelayMs = newDelay;
}
}
}
diff --git a/src/vm/eeconfig.h b/src/vm/eeconfig.h
index aef34b3236..f96a5a214c 100644
--- a/src/vm/eeconfig.h
+++ b/src/vm/eeconfig.h
@@ -285,10 +285,10 @@ public:
#if defined(FEATURE_TIERED_COMPILATION)
bool TieredCompilation(void) const { LIMITED_METHOD_CONTRACT; return fTieredCompilation; }
bool TieredCompilation_QuickJit() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_QuickJit; }
- bool TieredCompilation_StartupTier_CallCounting() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_StartupTier_CallCounting; }
- bool TieredCompilation_StartupTier_OptimizeCode() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_StartupTier_OptimizeCode; }
- DWORD TieredCompilation_StartupTier_CallCountThreshold() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_StartupTier_CallCountThreshold; }
- DWORD TieredCompilation_StartupTier_CallCountingDelayMs() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_StartupTier_CallCountingDelayMs; }
+ bool TieredCompilation_QuickJitForLoops() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_QuickJitForLoops; }
+ bool TieredCompilation_CallCounting() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_CallCounting; }
+ DWORD TieredCompilation_CallCountThreshold() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_CallCountThreshold; }
+ DWORD TieredCompilation_CallCountingDelayMs() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_CallCountingDelayMs; }
#endif
#ifndef CROSSGEN_COMPILE
@@ -1018,10 +1018,10 @@ private: //----------------------------------------------------------------
#if defined(FEATURE_TIERED_COMPILATION)
bool fTieredCompilation;
bool fTieredCompilation_QuickJit;
- bool fTieredCompilation_StartupTier_CallCounting;
- bool fTieredCompilation_StartupTier_OptimizeCode;
- DWORD tieredCompilation_StartupTier_CallCountThreshold;
- DWORD tieredCompilation_StartupTier_CallCountingDelayMs;
+ bool fTieredCompilation_QuickJitForLoops;
+ bool fTieredCompilation_CallCounting;
+ DWORD tieredCompilation_CallCountThreshold;
+ DWORD tieredCompilation_CallCountingDelayMs;
#endif
#ifndef CROSSGEN_COMPILE
diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp
index 11d5039210..1b260b3c58 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -6849,6 +6849,13 @@ DWORD CEEInfo::getMethodAttribsInternal (CORINFO_METHOD_HANDLE ftn)
result |= CORINFO_FLG_DELEGATE_INVOKE;
}
+#ifndef CROSSGEN_COMPILE
+ if (!g_pConfig->TieredCompilation_QuickJitForLoops())
+ {
+ result |= CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS;
+ }
+#endif
+
return result;
}
@@ -6901,6 +6908,14 @@ void CEEInfo::setMethodAttribs (
}
}
+#ifdef FEATURE_TIERED_COMPILATION
+ if (attribs & CORINFO_FLG_SWITCHED_TO_TIER1)
+ {
+ _ASSERTE(ftn->IsEligibleForTieredCompilation());
+ ftn->GetCallCounter()->DisableTier0CallCounting(ftn);
+ }
+#endif
+
EE_TO_JIT_TRANSITION();
}
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index 5b094f6555..b2e7a07859 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -6959,6 +6959,11 @@ MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
#ifdef FEATURE_TIERED_COMPILATION
// Keep in-sync with MethodDesc::DetermineAndSetIsEligibleForTieredCompilation()
if (g_pConfig->TieredCompilation() &&
+
+ // Policy - If QuickJit is disabled and the module is not ReadyToRun, the method would be ineligible for tiering
+ // currently to avoid some unnecessary overhead
+ (g_pConfig->TieredCompilation_QuickJit() || GetModule()->IsReadyToRun()) &&
+
(pMDMethod->GetMethodType() == METHOD_TYPE_NORMAL || pMDMethod->GetMethodType() == METHOD_TYPE_INSTANTIATED))
{
return TRUE;
diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp
index 4adf32ede1..17174ad79f 100644
--- a/src/vm/prestub.cpp
+++ b/src/vm/prestub.cpp
@@ -998,6 +998,21 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEn
return pOtherCode;
}
+#ifdef FEATURE_TIERED_COMPILATION
+ if (pFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0))
+ {
+ MethodDesc *methodDesc = pConfig->GetMethodDesc();
+ _ASSERTE(methodDesc->IsEligibleForTieredCompilation());
+
+ // Update the tier in the code version. The JIT may have decided to switch from tier 0 to tier 1, in which case call
+ // counting would have been disabled for the method.
+ if (!methodDesc->GetCallCounter()->IsTier0CallCountingEnabled(methodDesc))
+ {
+ pConfig->GetCodeVersion().SetOptimizationTier(NativeCodeVersion::OptimizationTier1);
+ }
+ }
+#endif
+
#if defined(FEATURE_JIT_PITCHING)
SavePitchingCandidate(this, *pSizeOfCode);
#endif
diff --git a/src/vm/tieredcompilation.cpp b/src/vm/tieredcompilation.cpp
index 467125f065..91cfff4c00 100644
--- a/src/vm/tieredcompilation.cpp
+++ b/src/vm/tieredcompilation.cpp
@@ -84,8 +84,6 @@ void TieredCompilationManager::Init()
MODE_PREEMPTIVE;
}
CONTRACTL_END;
-
- CrstHolder holder(&m_lock);
}
#endif // FEATURE_TIERED_COMPILATION && !DACCESS_COMPILE
@@ -109,7 +107,7 @@ NativeCodeVersion::OptimizationTier TieredCompilationManager::GetInitialOptimiza
return NativeCodeVersion::OptimizationTier1;
}
- if (!g_pConfig->TieredCompilation_StartupTier_CallCounting())
+ if (!g_pConfig->TieredCompilation_CallCounting())
{
// Call counting is disabled altogether through config, the intention is to remain at the initial tier
return NativeCodeVersion::OptimizationTier0;
@@ -150,7 +148,7 @@ void TieredCompilationManager::OnTier0MethodCalled(
// Stop call counting when the delay is in effect
IsTieringDelayActive() ||
// Initiate the delay on tier 0 activity (when a new eligible method is called the first time)
- (isFirstCall && g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs() != 0) ||
+ (isFirstCall && g_pConfig->TieredCompilation_CallCountingDelayMs() != 0) ||
// Stop call counting when ready for tier 1 promotion
currentCallCountLimit <= 0;
@@ -168,7 +166,7 @@ void TieredCompilationManager::OnMethodCallCountingStoppedWithoutTierPromotion(M
_ASSERTE(pMethodDesc != nullptr);
_ASSERTE(pMethodDesc->IsEligibleForTieredCompilation());
- if (g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs() == 0 ||
+ if (g_pConfig->TieredCompilation_CallCountingDelayMs() == 0 ||
!pMethodDesc->GetCallCounter()->IsCallCountingEnabled(pMethodDesc))
{
return;
@@ -314,7 +312,7 @@ bool TieredCompilationManager::TryInitiateTieringDelay()
{
WRAPPER_NO_CONTRACT;
_ASSERTE(g_pConfig->TieredCompilation());
- _ASSERTE(g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs() != 0);
+ _ASSERTE(g_pConfig->TieredCompilation_CallCountingDelayMs() != 0);
NewHolder<SArray<MethodDesc*>> methodsPendingCountingHolder = new(nothrow) SArray<MethodDesc*>();
if (methodsPendingCountingHolder == nullptr)
@@ -364,7 +362,7 @@ bool TieredCompilationManager::TryInitiateTieringDelay()
&m_tieringDelayTimerHandle,
TieringDelayTimerCallback,
timerContextHolder,
- g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs(),
+ g_pConfig->TieredCompilation_CallCountingDelayMs(),
(DWORD)-1 /* Period, non-repeating */,
0 /* flags */))
{
@@ -448,7 +446,7 @@ void TieredCompilationManager::TieringDelayTimerCallbackWorker()
{
if (ThreadpoolMgr::ChangeTimerQueueTimer(
tieringDelayTimerHandle,
- g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs(),
+ g_pConfig->TieredCompilation_CallCountingDelayMs(),
(DWORD)-1 /* Period, non-repeating */))
{
success = true;
@@ -818,8 +816,7 @@ CORJIT_FLAGS TieredCompilationManager::GetJitFlags(NativeCodeVersion nativeCodeV
return flags;
}
- if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0 &&
- !g_pConfig->TieredCompilation_StartupTier_OptimizeCode())
+ if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0)
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_TIER0);
}