Skip to content

Commit

Permalink
Fix tiering assertion failures from concurrent or reentering JIT of t…
Browse files Browse the repository at this point in the history
…he same native code version (#39643)

Fix tiering assertion failures from concurrent or reentering JIT of the same native code version

Allowed disabling call counting multiple times.

Fixes #39604
  • Loading branch information
kouvel authored Jul 20, 2020
1 parent 874399a commit 36041c5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 3 deletions.
11 changes: 10 additions & 1 deletion src/coreclr/src/vm/callcounting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,16 @@ void CallCountingManager::DisableCallCounting(NativeCodeVersion codeVersion)

CodeVersionManager::LockHolder codeVersioningLockHolder;

_ASSERTE(m_callCountingInfoByCodeVersionHash.Lookup(codeVersion) == nullptr);
CallCountingInfo *callCountingInfo = m_callCountingInfoByCodeVersionHash.Lookup(codeVersion);
if (callCountingInfo != nullptr)
{
// Call counting may already have been disabled due to the possibility of concurrent or reentering JIT of the same
// native code version of a method. The call counting info is created with call counting enabled or disabled and it
// cannot be changed thereafter for consistency in dependents of the info.
_ASSERTE(callCountingInfo->GetStage() == CallCountingInfo::Stage::Disabled);
return;
}

NewHolder<CallCountingInfo> callCountingInfoHolder = CallCountingInfo::CreateWithCallCountingDisabled(codeVersion);
m_callCountingInfoByCodeVersionHash.Add(callCountingInfoHolder);
callCountingInfoHolder.SuppressRelease();
Expand Down
14 changes: 12 additions & 2 deletions src/coreclr/src/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1063,11 +1063,21 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEn
bool shouldCountCalls = false;
if (pFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_TIER0))
{
_ASSERTE(pConfig->GetCodeVersion().GetOptimizationTier() == NativeCodeVersion::OptimizationTier0);
_ASSERTE(pConfig->GetMethodDesc()->IsEligibleForTieredCompilation());

if (pConfig->JitSwitchedToOptimized())
{
#ifdef _DEBUG
// Call counting may already have been disabled due to the possibility of concurrent or reentering JIT of the same
// native code version of a method. The current optimization tier should be consistent with the change being made
// (Tier 0 to Optimized), such that the tier is not changed in an unexpected way or at an unexpected time. Since
// changes to the optimization tier are unlocked, this assertion is just a speculative check on possible values.
NativeCodeVersion::OptimizationTier previousOptimizationTier = pConfig->GetCodeVersion().GetOptimizationTier();
_ASSERTE(
previousOptimizationTier == NativeCodeVersion::OptimizationTier0 ||
previousOptimizationTier == NativeCodeVersion::OptimizationTierOptimized);
#endif // _DEBUG

// Update the tier in the code version. The JIT may have decided to switch from tier 0 to optimized, in which case
// call counting would have to be disabled for the method.
NativeCodeVersion codeVersion = pConfig->GetCodeVersion();
Expand All @@ -1082,7 +1092,7 @@ PCODE MethodDesc::JitCompileCodeLocked(PrepareCodeConfig* pConfig, JitListLockEn
shouldCountCalls = true;
}
}
#endif
#endif // FEATURE_TIERED_COMPILATION

// Aside from rejit, performing a SetNativeCodeInterlocked at this point
// generally ensures that there is only one winning version of the native
Expand Down

0 comments on commit 36041c5

Please sign in to comment.