Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 1 addition & 89 deletions src/coreclr/vm/callcounting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,6 @@ const PCODE CallCountingStub::TargetForThresholdReached = (PCODE)GetEEFuncEntryP

#ifndef DACCESS_COMPILE

CallCountingManager::CallCountingInfo::CallCountingInfo(NativeCodeVersion codeVersion)
: m_codeVersion(codeVersion),
m_callCountingStub(nullptr),
m_remainingCallCount(0),
m_stage(Stage::Disabled)
{
WRAPPER_NO_CONTRACT;
_ASSERTE(!codeVersion.IsNull());
}

CallCountingManager::CallCountingInfo *
CallCountingManager::CallCountingInfo::CreateWithCallCountingDisabled(NativeCodeVersion codeVersion)
{
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;

return new CallCountingInfo(codeVersion);
}

CallCountingManager::CallCountingInfo::CallCountingInfo(NativeCodeVersion codeVersion, CallCount callCountThreshold)
: m_codeVersion(codeVersion),
m_callCountingStub(nullptr),
Expand Down Expand Up @@ -88,7 +64,6 @@ NativeCodeVersion CallCountingManager::CallCountingInfo::GetCodeVersion() const
const CallCountingStub *CallCountingManager::CallCountingInfo::GetCallCountingStub() const
{
WRAPPER_NO_CONTRACT;
_ASSERTE(m_stage != Stage::Disabled);

return m_callCountingStub;
}
Expand Down Expand Up @@ -118,7 +93,6 @@ void CallCountingManager::CallCountingInfo::ClearCallCountingStub()
PTR_CallCount CallCountingManager::CallCountingInfo::GetRemainingCallCountCell()
{
WRAPPER_NO_CONTRACT;
_ASSERTE(m_stage != Stage::Disabled);
//_ASSERTE(m_callCountingStub != nullptr);

return &m_remainingCallCount;
Expand All @@ -136,7 +110,6 @@ CallCountingManager::CallCountingInfo::Stage CallCountingManager::CallCountingIn
FORCEINLINE void CallCountingManager::CallCountingInfo::SetStage(Stage stage)
{
WRAPPER_NO_CONTRACT;
_ASSERTE(m_stage != Stage::Disabled);
_ASSERTE(stage <= Stage::Complete);

switch (stage)
Expand Down Expand Up @@ -482,59 +455,8 @@ void CallCountingManager::StaticInitialize()
}
#endif

bool CallCountingManager::IsCallCountingEnabled(NativeCodeVersion codeVersion)
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;

_ASSERTE(!codeVersion.IsNull());
_ASSERTE(codeVersion.IsDefaultVersion());
_ASSERTE(codeVersion.GetMethodDesc()->IsEligibleForTieredCompilation());

CodeVersionManager::LockHolder codeVersioningLockHolder;

PTR_CallCountingInfo callCountingInfo = m_callCountingInfoByCodeVersionHash.Lookup(codeVersion);
return callCountingInfo == NULL || callCountingInfo->GetStage() != CallCountingInfo::Stage::Disabled;
}

#ifndef DACCESS_COMPILE

void CallCountingManager::DisableCallCounting(NativeCodeVersion codeVersion)
{
CONTRACTL
{
THROWS;
GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;

_ASSERTE(!codeVersion.IsNull());
_ASSERTE(codeVersion.IsDefaultVersion());
_ASSERTE(codeVersion.GetMethodDesc()->IsEligibleForTieredCompilation());

CodeVersionManager::LockHolder codeVersioningLockHolder;

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();
}

// Returns true if the code entry point was updated to reflect the active code version, false otherwise. In normal paths, the
// code entry point is not updated only when the use of call counting stubs is disabled, as in that case returning to the
// prestub is necessary for further call counting. On exception, the code entry point may or may not have been updated and it's
Expand Down Expand Up @@ -566,12 +488,7 @@ bool CallCountingManager::SetCodeEntryPoint(
_ASSERTE(createTieringBackgroundWorkerRef == nullptr || !*createTieringBackgroundWorkerRef);

if (!methodDesc->IsEligibleForTieredCompilation() ||
(
// For a default code version that is not tier 0, call counting will have been disabled by this time (checked
// below). Avoid the redundant and not-insignificant expense of GetOptimizationTier() on a default code version.
!activeCodeVersion.IsDefaultVersion() &&
activeCodeVersion.IsFinalTier()
) ||
activeCodeVersion.IsFinalTier() ||
!g_pConfig->TieredCompilation_CallCounting())
{
methodDesc->SetCodeEntryPoint(codeEntryPoint);
Expand Down Expand Up @@ -1148,11 +1065,6 @@ void CallCountingManager::DeleteAllCallCountingStubs()
{
CallCountingInfo *callCountingInfo = *it;
CallCountingInfo::Stage callCountingStage = callCountingInfo->GetStage();
if (callCountingStage == CallCountingInfo::Stage::Disabled)
{
continue;
}

if (callCountingInfo->GetCallCountingStub() != nullptr)
{
callCountingInfo->ClearCallCountingStub();
Expand Down
12 changes: 0 additions & 12 deletions src/coreclr/vm/callcounting.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,6 @@ class CallCountingManager

// Stub is not active and will not become active, call counting complete, promoted, stub may be deleted
Complete,

// Call counting is disabled, only used for the default code version to indicate that it is to be optimized
Disabled
};

private:
Expand All @@ -208,10 +205,7 @@ class CallCountingManager
Stage m_stage;

#ifndef DACCESS_COMPILE
private:
CallCountingInfo(NativeCodeVersion codeVersion);
public:
static CallCountingInfo *CreateWithCallCountingDisabled(NativeCodeVersion codeVersion);
CallCountingInfo(NativeCodeVersion codeVersion, CallCount callCountThreshold);
~CallCountingInfo();
#endif
Expand Down Expand Up @@ -336,13 +330,7 @@ class CallCountingManager
static void StaticInitialize();
#endif // !DACCESS_COMPILE

public:
bool IsCallCountingEnabled(NativeCodeVersion codeVersion);

#ifndef DACCESS_COMPILE
public:
void DisableCallCounting(NativeCodeVersion codeVersion);

public:
static bool SetCodeEntryPoint(
NativeCodeVersion activeCodeVersion,
Expand Down
14 changes: 10 additions & 4 deletions src/coreclr/vm/codeversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,22 +346,28 @@ NativeCodeVersion::OptimizationTier NativeCodeVersion::GetOptimizationTier() con
}
else
{
return TieredCompilationManager::GetInitialOptimizationTier(GetMethodDesc());
PTR_MethodDesc pMethodDesc = GetMethodDesc();
OptimizationTier tier = pMethodDesc->GetMethodDescOptimizationTier();
if (tier == OptimizationTier::OptimizationTierUnknown)
{
tier = TieredCompilationManager::GetInitialOptimizationTier(pMethodDesc);
}
return tier;
}
}

#ifndef DACCESS_COMPILE
void NativeCodeVersion::SetOptimizationTier(OptimizationTier tier)
{
WRAPPER_NO_CONTRACT;
STANDARD_VM_CONTRACT;

if (m_storageKind == StorageKind::Explicit)
{
AsNode()->SetOptimizationTier(tier);
}
else
{
// State changes should have been made previously such that the initial tier is the new tier
_ASSERTE(TieredCompilationManager::GetInitialOptimizationTier(GetMethodDesc()) == tier);
GetMethodDesc()->SetMethodDescOptimizationTier(tier);
}
}
#endif
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/codeversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class NativeCodeVersion
OptimizationTierOptimized, // may do less optimizations than tier 1
OptimizationTier0Instrumented,
OptimizationTier1Instrumented,
OptimizationTierUnknown = 0xFFFFFFFF
};
#ifdef FEATURE_TIERED_COMPILATION
OptimizationTier GetOptimizationTier() const;
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/vm/eeconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,11 +789,35 @@ HRESULT EEConfig::sync()
}
#endif

#ifdef FEATURE_PGO
if (fTieredPGO)
{
// Initial tier for R2R is always just OptimizationTier0
// For ILOnly it depends on TieredPGO_InstrumentOnlyHotCode:
// OptimizationTier0 as we don't want to instrument the initial version (will only instrument hot Tier0)
// OptimizationTier0Instrumented - instrument all ILOnly code
if (g_pConfig->TieredPGO_InstrumentOnlyHotCode())
{
tieredCompilation_DefaultTier = (DWORD)NativeCodeVersion::OptimizationTier0;
}
else
{
tieredCompilation_DefaultTier = (DWORD)NativeCodeVersion::OptimizationTier0Instrumented;
}
}
else
#endif
{
tieredCompilation_DefaultTier = (DWORD)NativeCodeVersion::OptimizationTier0;
}

if (ETW::CompilationLog::TieredCompilation::Runtime::IsEnabled())
{
ETW::CompilationLog::TieredCompilation::Runtime::SendSettings();
}
}
#else // !FEATURE_TIERED_COMPILATION
tieredCompilation_DefaultTier = NativeCodeVersion::OptimizationTierOptimized;
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the !FEATURE_TIERED_COMPILATION branch, tieredCompilation_DefaultTier (a DWORD) is assigned an enum value without an explicit cast, while other assignments in this method cast to DWORD. Using a consistent explicit cast here helps avoid compiler warnings (and matches the nearby code style).

Suggested change
tieredCompilation_DefaultTier = NativeCodeVersion::OptimizationTierOptimized;
tieredCompilation_DefaultTier = (DWORD)NativeCodeVersion::OptimizationTierOptimized;

Copilot uses AI. Check for mistakes.
#endif

#if defined(FEATURE_ON_STACK_REPLACEMENT)
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/eeconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class EEConfig
bool TieredCompilation_UseCallCountingStubs() const { LIMITED_METHOD_CONTRACT; return fTieredCompilation_UseCallCountingStubs; }
DWORD TieredCompilation_DeleteCallCountingStubsAfter() const { LIMITED_METHOD_CONTRACT; return tieredCompilation_DeleteCallCountingStubsAfter; }
#endif // FEATURE_TIERED_COMPILATION
DWORD TieredCompilation_DefaultTier() const
{
LIMITED_METHOD_CONTRACT;
return tieredCompilation_DefaultTier;
}

#if defined(FEATURE_PGO)
bool TieredPGO(void) const { LIMITED_METHOD_CONTRACT; return fTieredPGO; }
Expand Down Expand Up @@ -607,6 +612,7 @@ class EEConfig
DWORD tieredCompilation_CallCountingDelayMs;
DWORD tieredCompilation_DeleteCallCountingStubsAfter;
#endif
DWORD tieredCompilation_DefaultTier;

#if defined(FEATURE_PGO)
bool fTieredPGO;
Expand Down
23 changes: 23 additions & 0 deletions src/coreclr/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ HRESULT MethodDesc::EnsureCodeDataExists(AllocMemTracker *pamTracker)
if (alloc == NULL)
return E_OUTOFMEMORY;

#ifdef FEATURE_CODE_VERSIONING
alloc->OptimizationTier = NativeCodeVersion::OptimizationTierUnknown;
#endif

// Try to set the field. Suppress clean-up if we win the race.
if (InterlockedCompareExchangeT(&m_codeData, (MethodDescCodeData*)alloc, NULL) == NULL)
amTracker.SuppressRelease();
Expand All @@ -260,6 +264,16 @@ HRESULT MethodDesc::SetMethodDescVersionState(PTR_MethodDescVersioningState stat

return S_OK;
}

void MethodDesc::SetMethodDescOptimizationTier(NativeCodeVersion::OptimizationTier tier)
{
STANDARD_VM_CONTRACT;

IfFailThrow(EnsureCodeDataExists(NULL));

_ASSERTE(m_codeData != NULL);
VolatileStoreWithoutBarrier(&m_codeData->OptimizationTier, tier);
}
#endif // FEATURE_CODE_VERSIONING

#ifdef FEATURE_INTERPRETER
Expand Down Expand Up @@ -297,6 +311,15 @@ PTR_MethodDescVersioningState MethodDesc::GetMethodDescVersionState()
return NULL;
return VolatileLoadWithoutBarrier(&codeData->VersioningState);
}

NativeCodeVersion::OptimizationTier MethodDesc::GetMethodDescOptimizationTier()
{
WRAPPER_NO_CONTRACT;
PTR_MethodDescCodeData codeData = VolatileLoadWithoutBarrier(&m_codeData);
if (codeData == NULL)
return NativeCodeVersion::OptimizationTierUnknown;
return VolatileLoadWithoutBarrier(&codeData->OptimizationTier);
}
#endif // FEATURE_CODE_VERSIONING

//*******************************************************************************
Expand Down
18 changes: 3 additions & 15 deletions src/coreclr/vm/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ struct MethodDescCodeData final
{
#ifdef FEATURE_CODE_VERSIONING
PTR_MethodDescVersioningState VersioningState;
NativeCodeVersion::OptimizationTier OptimizationTier;
#endif // FEATURE_CODE_VERSIONING
PCODE TemporaryEntryPoint;
#ifdef FEATURE_INTERPRETER
Expand Down Expand Up @@ -1936,8 +1937,10 @@ class MethodDesc
#ifdef FEATURE_CODE_VERSIONING
#ifndef DACCESS_COMPILE
HRESULT SetMethodDescVersionState(PTR_MethodDescVersioningState state);
void SetMethodDescOptimizationTier(NativeCodeVersion::OptimizationTier tier);
#endif // !DACCESS_COMPILE
PTR_MethodDescVersioningState GetMethodDescVersionState();
NativeCodeVersion::OptimizationTier GetMethodDescOptimizationTier();
#endif // FEATURE_CODE_VERSIONING

public:
Expand Down Expand Up @@ -2319,20 +2322,6 @@ class PrepareCodeConfig

#ifdef FEATURE_TIERED_COMPILATION
public:
bool WasTieringDisabledBeforeJitting() const
{
WRAPPER_NO_CONTRACT;
return m_wasTieringDisabledBeforeJitting;
}

void SetWasTieringDisabledBeforeJitting()
{
WRAPPER_NO_CONTRACT;
_ASSERTE(GetMethodDesc()->IsEligibleForTieredCompilation());

m_wasTieringDisabledBeforeJitting = true;
}

bool ShouldCountCalls() const
{
WRAPPER_NO_CONTRACT;
Expand Down Expand Up @@ -2441,7 +2430,6 @@ class PrepareCodeConfig

#ifdef FEATURE_TIERED_COMPILATION
private:
bool m_wasTieringDisabledBeforeJitting;
bool m_shouldCountCalls;
#endif

Expand Down
Loading