From f2eec0ae4e1c4148378b0a483bd011e700aad44b Mon Sep 17 00:00:00 2001 From: rcj1 Date: Thu, 9 Apr 2026 11:57:39 -0700 Subject: [PATCH 1/2] replace shash with linked list --- src/coreclr/vm/callcounting.cpp | 62 +++++++++------------------------ src/coreclr/vm/callcounting.h | 32 +++-------------- src/coreclr/vm/ceemain.cpp | 2 +- 3 files changed, 22 insertions(+), 74 deletions(-) diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index 9177036fa5fb0e..ad508d17d9fec1 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -380,33 +380,10 @@ CallCountingManager::MethodDescForwarderStubHashTraits::Hash(const key_t &k) return (count_t)(size_t)k; } -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// CallCountingManager::CallCountingManagerHashTraits - -CallCountingManager::CallCountingManagerHashTraits::key_t -CallCountingManager::CallCountingManagerHashTraits::GetKey(const element_t &e) -{ - WRAPPER_NO_CONTRACT; - return e; -} - -BOOL CallCountingManager::CallCountingManagerHashTraits::Equals(const key_t &k1, const key_t &k2) -{ - WRAPPER_NO_CONTRACT; - return k1 == k2; -} - -CallCountingManager::CallCountingManagerHashTraits::count_t -CallCountingManager::CallCountingManagerHashTraits::Hash(const key_t &k) -{ - WRAPPER_NO_CONTRACT; - return (count_t)dac_cast(k); -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CallCountingManager -CallCountingManager::PTR_CallCountingManagerHash CallCountingManager::s_callCountingManagers = PTR_NULL; +CallCountingManager* CallCountingManager::s_callCountingManagers = nullptr; COUNT_T CallCountingManager::s_callCountingStubCount = 0; COUNT_T CallCountingManager::s_activeCallCountingStubCount = 0; COUNT_T CallCountingManager::s_completedCallCountingStubCount = 0; @@ -423,7 +400,13 @@ CallCountingManager::CallCountingManager() #ifndef DACCESS_COMPILE CodeVersionManager::LockHolder codeVersioningLockHolder; - s_callCountingManagers->Add(this); + m_nextManager = s_callCountingManagers; + m_pPreviousManager = &s_callCountingManagers; + if (s_callCountingManagers != nullptr) + { + s_callCountingManagers->m_pPreviousManager = &m_nextManager; + } + s_callCountingManagers = this; #endif } @@ -448,22 +431,16 @@ CallCountingManager::~CallCountingManager() delete callCountingInfo; } - s_callCountingManagers->Remove(this); + *m_pPreviousManager = m_nextManager; + if (m_nextManager != nullptr) + { + m_nextManager->m_pPreviousManager = m_pPreviousManager; + } #endif } #ifndef DACCESS_COMPILE -void CallCountingManager::StaticInitialize() -{ - WRAPPER_NO_CONTRACT; - s_callCountingManagers = PTR_CallCountingManagerHash(new CallCountingManagerHash()); - CallCountingStub::StaticInitialize(); -} -#endif - -#ifndef DACCESS_COMPILE - // 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 @@ -762,9 +739,8 @@ COUNT_T CallCountingManager::GetCountOfCodeVersionsPendingCompletion() CodeVersionManager::LockHolder codeVersioningLockHolder; - for (auto itEnd = s_callCountingManagers->End(), it = s_callCountingManagers->Begin(); it != itEnd; ++it) + for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) { - CallCountingManager *callCountingManager = *it; count += callCountingManager->m_callCountingInfosPendingCompletion.GetCount(); } @@ -790,9 +766,8 @@ void CallCountingManager::CompleteCallCounting() MethodDescBackpatchInfoTracker::ConditionalLockHolder slotBackpatchLockHolder; CodeVersionManager::LockHolder codeVersioningLockHolder; - for (auto itEnd = s_callCountingManagers->End(), it = s_callCountingManagers->Begin(); it != itEnd; ++it) + for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) { - CallCountingManager *callCountingManager = *it; SArray &callCountingInfosPendingCompletion = callCountingManager->m_callCountingInfosPendingCompletion; COUNT_T callCountingInfoCount = callCountingInfosPendingCompletion.GetCount(); @@ -951,10 +926,8 @@ void CallCountingManager::StopAllCallCounting(TieredCompilationManager *tieredCo _ASSERTE(CodeVersionManager::IsLockOwnedByCurrentThread()); _ASSERTE(tieredCompilationManager != nullptr); - for (auto itEnd = s_callCountingManagers->End(), it = s_callCountingManagers->Begin(); it != itEnd; ++it) + for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) { - CallCountingManager *callCountingManager = *it; - CallCountingInfoByCodeVersionHash &callCountingInfoByCodeVersionHash = callCountingManager->m_callCountingInfoByCodeVersionHash; for (auto itEnd = callCountingInfoByCodeVersionHash.End(), it = callCountingInfoByCodeVersionHash.Begin(); @@ -1039,9 +1012,8 @@ void CallCountingManager::DeleteAllCallCountingStubs() s_callCountingStubCount = 0; s_completedCallCountingStubCount = 0; - for (auto itEnd = s_callCountingManagers->End(), it = s_callCountingManagers->Begin(); it != itEnd; ++it) + for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) { - CallCountingManager *callCountingManager = *it; _ASSERTE(callCountingManager->m_callCountingInfosPendingCompletion.IsEmpty()); // Clear the call counting stub from call counting infos and delete completed infos diff --git a/src/coreclr/vm/callcounting.h b/src/coreclr/vm/callcounting.h index 7db35016307ef1..f448fdc0c8fac3 100644 --- a/src/coreclr/vm/callcounting.h +++ b/src/coreclr/vm/callcounting.h @@ -296,33 +296,11 @@ class CallCountingManager typedef SHash MethodDescForwarderStubHash; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // CallCountingManager::CallCountingManagerHashTraits - -private: - class CallCountingManagerHashTraits : public DefaultSHashTraits - { - private: - typedef DefaultSHashTraits Base; - public: - typedef Base::element_t element_t; - typedef Base::count_t count_t; - typedef PTR_CallCountingManager key_t; - - public: - static key_t GetKey(const element_t &e); - static BOOL Equals(const key_t &k1, const key_t &k2); - static count_t Hash(const key_t &k); - }; - - typedef SHash CallCountingManagerHash; - typedef DPTR(CallCountingManagerHash) PTR_CallCountingManagerHash; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CallCountingManager members private: - static PTR_CallCountingManagerHash s_callCountingManagers; + static CallCountingManager *s_callCountingManagers; static COUNT_T s_callCountingStubCount; static COUNT_T s_activeCallCountingStubCount; static COUNT_T s_completedCallCountingStubCount; @@ -333,15 +311,13 @@ class CallCountingManager MethodDescForwarderStubHash m_methodDescForwarderStubHash; SArray m_callCountingInfosPendingCompletion; + CallCountingManager **m_pPreviousManager = nullptr; + CallCountingManager *m_nextManager = nullptr; + public: CallCountingManager(); ~CallCountingManager(); -#ifndef DACCESS_COMPILE -public: - static void StaticInitialize(); -#endif // !DACCESS_COMPILE - #ifndef DACCESS_COMPILE public: static bool SetCodeEntryPoint( diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 3180399f9ce2cd..bd9c5a2186c30e 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -668,7 +668,7 @@ void EEStartupHelper() #ifdef FEATURE_TIERED_COMPILATION TieredCompilationManager::StaticInitialize(); - CallCountingManager::StaticInitialize(); + CallCountingStub::StaticInitialize(); #endif // FEATURE_TIERED_COMPILATION OnStackReplacementManager::StaticInitialize(); From 12c07824f0b2d8aba2b8ce85691b4dacfe839320 Mon Sep 17 00:00:00 2001 From: rcj1 Date: Fri, 10 Apr 2026 07:24:13 -0700 Subject: [PATCH 2/2] use slist --- src/coreclr/vm/callcounting.cpp | 24 +++++++----------------- src/coreclr/vm/callcounting.h | 8 ++++---- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index ad508d17d9fec1..ee053d81052275 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -383,7 +383,7 @@ CallCountingManager::MethodDescForwarderStubHashTraits::Hash(const key_t &k) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CallCountingManager -CallCountingManager* CallCountingManager::s_callCountingManagers = nullptr; +SList CallCountingManager::s_callCountingManagers; COUNT_T CallCountingManager::s_callCountingStubCount = 0; COUNT_T CallCountingManager::s_activeCallCountingStubCount = 0; COUNT_T CallCountingManager::s_completedCallCountingStubCount = 0; @@ -400,13 +400,7 @@ CallCountingManager::CallCountingManager() #ifndef DACCESS_COMPILE CodeVersionManager::LockHolder codeVersioningLockHolder; - m_nextManager = s_callCountingManagers; - m_pPreviousManager = &s_callCountingManagers; - if (s_callCountingManagers != nullptr) - { - s_callCountingManagers->m_pPreviousManager = &m_nextManager; - } - s_callCountingManagers = this; + s_callCountingManagers.InsertTail(this); #endif } @@ -431,11 +425,7 @@ CallCountingManager::~CallCountingManager() delete callCountingInfo; } - *m_pPreviousManager = m_nextManager; - if (m_nextManager != nullptr) - { - m_nextManager->m_pPreviousManager = m_pPreviousManager; - } + s_callCountingManagers.FindAndRemove(this); #endif } @@ -739,7 +729,7 @@ COUNT_T CallCountingManager::GetCountOfCodeVersionsPendingCompletion() CodeVersionManager::LockHolder codeVersioningLockHolder; - for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) + for (CallCountingManager *callCountingManager = s_callCountingManagers.GetHead(); callCountingManager != nullptr; callCountingManager = SList::GetNext(callCountingManager)) { count += callCountingManager->m_callCountingInfosPendingCompletion.GetCount(); } @@ -766,7 +756,7 @@ void CallCountingManager::CompleteCallCounting() MethodDescBackpatchInfoTracker::ConditionalLockHolder slotBackpatchLockHolder; CodeVersionManager::LockHolder codeVersioningLockHolder; - for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) + for (CallCountingManager *callCountingManager = s_callCountingManagers.GetHead(); callCountingManager != nullptr; callCountingManager = SList::GetNext(callCountingManager)) { SArray &callCountingInfosPendingCompletion = callCountingManager->m_callCountingInfosPendingCompletion; @@ -926,7 +916,7 @@ void CallCountingManager::StopAllCallCounting(TieredCompilationManager *tieredCo _ASSERTE(CodeVersionManager::IsLockOwnedByCurrentThread()); _ASSERTE(tieredCompilationManager != nullptr); - for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) + for (CallCountingManager *callCountingManager = s_callCountingManagers.GetHead(); callCountingManager != nullptr; callCountingManager = SList::GetNext(callCountingManager)) { CallCountingInfoByCodeVersionHash &callCountingInfoByCodeVersionHash = callCountingManager->m_callCountingInfoByCodeVersionHash; @@ -1012,7 +1002,7 @@ void CallCountingManager::DeleteAllCallCountingStubs() s_callCountingStubCount = 0; s_completedCallCountingStubCount = 0; - for (auto* callCountingManager = s_callCountingManagers; callCountingManager != nullptr; callCountingManager = callCountingManager->m_nextManager) + for (CallCountingManager *callCountingManager = s_callCountingManagers.GetHead(); callCountingManager != nullptr; callCountingManager = SList::GetNext(callCountingManager)) { _ASSERTE(callCountingManager->m_callCountingInfosPendingCompletion.IsEmpty()); diff --git a/src/coreclr/vm/callcounting.h b/src/coreclr/vm/callcounting.h index f448fdc0c8fac3..a9600c883cc0ae 100644 --- a/src/coreclr/vm/callcounting.h +++ b/src/coreclr/vm/callcounting.h @@ -299,8 +299,11 @@ class CallCountingManager //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CallCountingManager members +public: + SLink m_Link; + private: - static CallCountingManager *s_callCountingManagers; + static SList s_callCountingManagers; static COUNT_T s_callCountingStubCount; static COUNT_T s_activeCallCountingStubCount; static COUNT_T s_completedCallCountingStubCount; @@ -311,9 +314,6 @@ class CallCountingManager MethodDescForwarderStubHash m_methodDescForwarderStubHash; SArray m_callCountingInfosPendingCompletion; - CallCountingManager **m_pPreviousManager = nullptr; - CallCountingManager *m_nextManager = nullptr; - public: CallCountingManager(); ~CallCountingManager();