## Environment/Registry Configuration Knobs
-This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [d064ffb](https://github.com/dotnet/coreclr/commit/d064ffb6b05c4f7fa44c7ee389e9694e64a76c08) on 15/04/2019. It might be out of date. To generate latest documentation run `{dotnet-script} clr-configuration-knobs.csx` from this file directory.
+This table was machine-generated using `clr-configuration-knobs.csx` script from repository commit [0ae3d02](https://github.com/dotnet/coreclr/commit/0ae3d020f82c3f8650b7e5eeaf9f1030f7e7e785) on 4/25/2019. It might be out of date. To generate latest documentation run `dotnet-script clr-configuration-knobs.csx` from this file directory.
When using these configurations from environment variables, the variables need to have the `COMPlus_` prefix in their names. e.g. To set DumpJittedMethods to 1, add the environment variable `COMPlus_DumpJittedMethods=1`.
Name | Description | Type | Class | Default Value | Flags
-----|-------------|------|-------|---------------|-------
-`TC_QuickJit` | For methods that would be jitted, enable using quick JIT when appropriate. | `DWORD` | `UNSUPPORTED` | `0` |
-`TC_StartupTier_CallCounting` | Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers | `DWORD` | `INTERNAL` | `1` |
-`TC_StartupTier_CallCountingDelayMs` | 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. | `DWORD` | `UNSUPPORTED` | `100` |
-`TC_StartupTier_CallCountThreshold` | Number of times a method must be called in the startup tier after which it is promoted to the next tier. | `DWORD` | `UNSUPPORTED` | `30` |
-`TC_StartupTier_DelaySingleProcMultiplier` | Multiplier for TC_StartupTier_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor. | `DWORD` | `UNSUPPORTED` | `10` |
-`TC_StartupTier_OptimizeCode` | Use optimized codegen (normally used by the optimized tier) in the startup tier | `DWORD` | `INTERNAL` | `0` |
+`TC_CallCounting` | Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers | `DWORD` | `INTERNAL` | `1` |
+`TC_CallCountingDelayMs` | A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity. | `DWORD` | `INTERNAL` | `100` |
+`TC_CallCountThreshold` | Number of times a method must be called in tier 0 after which it is promoted to the next tier. | `DWORD` | `INTERNAL` | `30` |
+`TC_DelaySingleProcMultiplier` | Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor. | `DWORD` | `INTERNAL` | `10` |
+`TC_QuickJit` | For methods that would be jitted, enable using quick JIT when appropriate. | `DWORD` | `EXTERNAL` | `0` |
+`TC_QuickJitForLoops` | When quick JIT is enabled, quick JIT may also be used for methods that contain loops. | `DWORD` | `UNSUPPORTED` | `0` |
`TieredCompilation` | Enables tiered compilation | `DWORD` | `EXTERNAL` | `1` |
#### TypeLoader Configuration Knobs
///
#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
///
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.
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
};
info.compTotalHotCodeSize = 0;
info.compTotalColdCodeSize = 0;
+ fgHasBackwardJump = false;
+
#ifdef DEBUG
compCurBB = nullptr;
lvaTable = nullptr;
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
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);
};
//------------------------------------------------------------------------
+// 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:
if ((block->bbFlags & BBF_BACKWARD_JUMP) == 0)
{
block->bbFlags |= BBF_BACKWARD_JUMP;
+ fgHasBackwardJump = true;
}
}
}
#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)
{
_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)
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));
}
#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
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();
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;
}
}
}
#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
#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
result |= CORINFO_FLG_DELEGATE_INVOKE;
}
+#ifndef CROSSGEN_COMPILE
+ if (!g_pConfig->TieredCompilation_QuickJitForLoops())
+ {
+ result |= CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS;
+ }
+#endif
+
return result;
}
}
}
+#ifdef FEATURE_TIERED_COMPILATION
+ if (attribs & CORINFO_FLG_SWITCHED_TO_TIER1)
+ {
+ _ASSERTE(ftn->IsEligibleForTieredCompilation());
+ ftn->GetCallCounter()->DisableTier0CallCounting(ftn);
+ }
+#endif
+
EE_TO_JIT_TRANSITION();
}
#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;
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
MODE_PREEMPTIVE;
}
CONTRACTL_END;
-
- CrstHolder holder(&m_lock);
}
#endif // FEATURE_TIERED_COMPILATION && !DACCESS_COMPILE
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;
// 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;
_ASSERTE(pMethodDesc != nullptr);
_ASSERTE(pMethodDesc->IsEligibleForTieredCompilation());
- if (g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs() == 0 ||
+ if (g_pConfig->TieredCompilation_CallCountingDelayMs() == 0 ||
!pMethodDesc->GetCallCounter()->IsCallCountingEnabled(pMethodDesc))
{
return;
{
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)
&m_tieringDelayTimerHandle,
TieringDelayTimerCallback,
timerContextHolder,
- g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs(),
+ g_pConfig->TieredCompilation_CallCountingDelayMs(),
(DWORD)-1 /* Period, non-repeating */,
0 /* flags */))
{
{
if (ThreadpoolMgr::ChangeTimerQueueTimer(
tieringDelayTimerHandle,
- g_pConfig->TieredCompilation_StartupTier_CallCountingDelayMs(),
+ g_pConfig->TieredCompilation_CallCountingDelayMs(),
(DWORD)-1 /* Period, non-repeating */))
{
success = true;
return flags;
}
- if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0 &&
- !g_pConfig->TieredCompilation_StartupTier_OptimizeCode())
+ if (nativeCodeVersion.GetOptimizationTier() == NativeCodeVersion::OptimizationTier0)
{
flags.Set(CORJIT_FLAGS::CORJIT_FLAG_TIER0);
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+ .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
+ .ver 4:2:1:0
+}
+.assembly ExplicitTailCallNoSO
+{
+}
+.class private abstract auto ansi sealed beforefieldinit ExplicitTailCallNoSO
+ extends [System.Runtime]System.Object
+{
+ .method private hidebysig static int32
+ Main() cil managed
+ {
+ .entrypoint
+ // Code size 44 (0x2c)
+ .maxstack 2
+ .locals init (int32 V_0,
+ int32 V_1,
+ int32 V_2)
+ IL_0000: ldc.i4 0xf4240 // 1_000_000
+ IL_0005: ldc.i4.0
+ IL_0006: call int32 ExplicitTailCallNoSO::CalculateSumWithTailCall(int32,
+ int32)
+ IL_000b: stloc.0
+ IL_000c: ldc.i4.0
+ IL_000d: stloc.1
+ IL_000e: ldc.i4.1
+ IL_000f: stloc.2
+ IL_0010: br.s IL_001a
+
+ IL_0012: ldloc.1
+ IL_0013: ldloc.2
+ IL_0014: add
+ IL_0015: stloc.1
+ IL_0016: ldloc.2
+ IL_0017: ldc.i4.1
+ IL_0018: add
+ IL_0019: stloc.2
+ IL_001a: ldloc.2
+ IL_001b: ldc.i4 0xf4240 // 1_000_000
+ IL_0020: ble.s IL_0012
+
+ IL_0022: ldloc.0
+ IL_0023: ldloc.1
+ IL_0024: beq.s IL_0029
+
+ IL_0026: ldc.i4.s 101
+ IL_0028: ret
+
+ IL_0029: ldc.i4.s 100
+ IL_002b: ret
+ } // end of method ExplicitTailCallNoSO::Main
+
+ .method private hidebysig static int32
+ CalculateSumWithTailCall(int32 n,
+ [opt] int32 sum) cil managed
+ {
+ .param [2] = int32(0x00000000)
+ // Code size 27 (0x1b)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldc.i4.0
+ IL_0002: bgt.s IL_0006
+
+ IL_0004: ldc.i4.0
+ IL_0005: ret
+
+ IL_0006: ldarg.1
+ IL_0007: ldarg.0
+ IL_0008: add
+ IL_0009: starg.s sum
+ IL_000b: ldarg.0
+ IL_000c: ldc.i4.1
+ IL_000d: bne.un.s IL_0011
+
+ IL_000f: ldarg.1
+ IL_0010: ret
+
+ IL_0011: ldarg.0
+ IL_0012: ldc.i4.1
+ IL_0013: sub
+ IL_0014: ldarg.1
+ IL_0015: tail. call int32 ExplicitTailCallNoSO::CalculateSumWithTailCall(int32,
+ int32)
+ IL_001a: ret
+ } // end of method ExplicitTailCallNoSO::CalculateSumWithTailCall
+
+} // end of class ExplicitTailCallNoSO
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7DFE5715-DC0F-46D5-9D72-6176FE22BB6C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
+ <PropertyGroup>
+ <DebugType>PdbOnly</DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="ExplicitTailCallNoSO.il" />
+ </ItemGroup>
+ <PropertyGroup>
+ <CLRTestBatchPreCommands><![CDATA[
+$(CLRTestBatchPreCommands)
+set COMPlus_TC_QuickJit=1
+set COMPlus_TC_QuickJitForLoops=1
+]]></CLRTestBatchPreCommands>
+ <BashCLRTestPreCommands><![CDATA[
+$(BashCLRTestPreCommands)
+export COMPlus_TC_QuickJit=1
+export COMPlus_TC_QuickJitForLoops=1
+]]></BashCLRTestPreCommands>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
\ No newline at end of file