Replace CoreCLR SList with NativeAOT-style design#126949
Conversation
|
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
Replaces CoreCLR’s sentinel-based SList with a NativeAOT-style, traits-based design (no sentinel; NULL = empty) and migrates affected consumers and DAC/cDAC descriptors to point directly at the owning objects.
Changes:
- Reworked
src/coreclr/inc/slist.hto a traits-based intrusive list with optional tail tracking andSListElem<T>for non-intrusive usage. - Migrated multiple CoreCLR consumers from
SLink m_Linktom_pNext(DAC-safe pointer types) and updated list operations accordingly. - Updated DAC/cDAC contracts, descriptors, and mocks so list heads/links now point directly to objects (no offset subtraction /
CONTAINING_RECORD).
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.Thread.cs | Updates mock thread store/list wiring to use direct Thread.Address links. |
| src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.SyncBlock.cs | Updates mock cleanup list to use direct SyncBlock.Address links. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Thread_1.cs | Removes SLink offset logic; treats thread links as direct thread pointers. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/SyncBlock_1.cs | Removes link-offsetof subtraction; iterates cleanup list via direct pointers. |
| src/coreclr/vm/tieredcompilation.h | Introduces OptimizationQueue typedef using tail-enabled SList for optimization queue. |
| src/coreclr/vm/threads.h | Replaces SLink m_Link with PTR_Thread m_pNext; updates ThreadList and cdac offsets. |
| src/coreclr/vm/threads.cpp | Updates FindAndRemove usage to new boolean-return API. |
| src/coreclr/vm/syncblk.h | Replaces SLink usage with PTR_SyncBlock m_pNext; updates cdac offsets and cache list types. |
| src/coreclr/vm/syncblk.cpp | Removes offsetof(SyncBlock, m_Link) arithmetic; cleanup/free lists now store SyncBlock* directly. |
| src/coreclr/vm/loaderallocator.hpp | Replaces SLink with m_pNext in cleanup list items; adds tail-enabled list typedefs. |
| src/coreclr/vm/loaderallocator.cpp | Updates list iteration/removal to match new next-pointer layout. |
| src/coreclr/vm/datadescriptor/datadescriptor.inc | Removes SLink type and switches FirstThreadLink descriptor to a pointer. |
| src/coreclr/vm/comconnectionpoints.h | Replaces SLink with m_pNext in ConnectionCookie; updates list typedef. |
| src/coreclr/vm/comconnectionpoints.cpp | Removes CONTAINING_RECORD/InsertAfter usage; performs direct pointer chaining. |
| src/coreclr/vm/callcounting.h | Replaces SLink with m_pNext; introduces tail-enabled CallCountingManagerList. |
| src/coreclr/vm/callcounting.cpp | Updates static list declaration and iteration to new list type/API. |
| src/coreclr/vm/cachelinealloc.h | Replaces SLink with m_pNext; updates list typedefs and initialization. |
| src/coreclr/vm/cachelinealloc.cpp | Removes now-unneeded SList::Init() calls in allocator ctor. |
| src/coreclr/inc/slist.h | Core redesign: traits-based next-pointer access, optional tail tracking, SListElem<T>, and updated iterator/API. |
| src/coreclr/inc/profilepriv.h | Migrates StoredProfilerNode to m_pNext; updates profiler list typedef. |
| src/coreclr/debug/daccess/request.cpp | Updates DAC traversal of syncblock lists to use direct m_pNext pointers. |
| docs/design/datacontracts/SyncBlock.md | Updates docs to reflect cleanup list head now points to SyncBlock objects directly. |
This comment has been minimized.
This comment has been minimized.
cb65de6 to
84d3e34
Compare
4e843f7 to
b73b3b5
Compare
This comment has been minimized.
This comment has been minimized.
b73b3b5 to
b5cad54
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jkotas
left a comment
There was a problem hiding this comment.
@AaronRobinsonMSFT Any feedback about the C++ specifics?
-nostdlib only affects linking, not header inclusion. std::forward from <utility> is header-only with no link dependency, so it works fine under NativeAOT's -nostdlib flag. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Inline the single rh::std::count usage in threadstore.cpp as a debug-only loop. Remove rh::std::find/count/SList-find helpers from slist.inl, making it a plain forwarder to ../../inc/slist.inl. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Aaron R Robinson <arobins@microsoft.com>
Co-authored-by: Aaron R Robinson <arobins@microsoft.com>
🤖 Copilot Code Review — PR #126949Note This review was generated by GitHub Copilot using multi-model analysis (Claude Opus 4.6, Claude Sonnet 4.5, GPT-5.3-Codex). All three models contributed findings. Holistic AssessmentMotivation: The PR is well-justified. Maintaining two divergent SList implementations (CoreCLR's sentinel-based Approach: The traits-based design with Summary: Detailed Findings✅ InsertHeadInterlocked CAS loop — CorrectThe CAS loop in ✅ Tail pointer maintenance — CorrectAll four mutation operations correctly handle
Edge cases (empty, single-element, multi-element) all handled. (Confirmed by all 3 models) ✅ SyncBlock free/cleanup list migration — CorrectThe elimination of ✅ cDAC contract simplification — Correct
✅ NativeAOT redirect — Complete
✅ static_assert guards — ComprehensiveAll mode-incompatible operations are gated:
|
Include Pal.h (NativeAOT) and utilcode.h (CoreCLR) directly in slist.inl so consumers don't need to worry about include order. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Match the declaration guard in slist.h so slist.inl is safe to include in DAC builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- SyncBlock.md: remove offset subtraction from pseudocode (links now point directly to objects, not embedded SLink nodes) - daccess.h: update SList description to reflect intrusive m_pNext design instead of removed SLink/CONTAINING_RECORD pattern Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per review feedback, the two NativeAOT InsertHeadInterlocked call sites run single-threaded, so lock-free support is unnecessary. The volatile m_pHead was also insufficient for weak memory models. - Remove SListMode::Interlocked, IsInterlocked, FailFastPolicy - Remove DoNothingFailFastPolicy, SListThin alias, SListInterlocked alias - Remove all IsInterlocked static_asserts - Remove InsertHeadInterlocked declaration and volatile m_pHead - Delete inc/slist.inl and nativeaot/Runtime/slist.inl - NativeAOT: InsertHeadInterlocked → InsertHead, remove volatile m_pNext Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/ba-g
|
Note
This PR was authored with the assistance of GitHub Copilot.
Summary
Unify the CoreCLR and NativeAOT
SListimplementations into a single shared header atsrc/coreclr/inc/slist.h. NativeAOT'sslist.hbecomes a redirect to this shared header. The old sentinel-basedSLink/SListdesign is replaced with the NativeAOT-style design: no sentinel node,NULLmeans empty, traits-based next-pointer access.Design
SListTraits and SListMode
A single
SListTraits<T, Mode>template replaces the oldDefaultSListTraits/DefaultSListTraitsWithTailclasses. TheSListModeenum controls which operations are permitted:Thin(default)TailConvenience Alias
Other Features
Begin()/End(),Insert/Removeat position, debug validationSListElem<T>wrapper for non-intrusive list usage (available to both CoreCLR and NativeAOT)SListTailBaseconditional storage —m_pTailonly exists whenHasTailis trueConsumer Migrations
All method names preserved:
InsertHead,InsertTail,RemoveHead,FindAndRemove,GetHead,GetNext,IsEmpty.m_pNexttypeDPTR(CacheLine)SList<CacheLine>DPTR(CallCountingManager)SListTail<CallCountingManager>DPTR(ConnectionCookie)SList<ConnectionCookie>DPTR(StoredProfilerNode)SList<StoredProfilerNode>PTR_ThreadSListTail<Thread>PTR_SyncBlockDPTR(...)SListTail<HandleCleanupListItem>DPTR(...)SListTail<FailedTypeInitCleanupListItem>DPTR(SListElem)SListTail<SListElem<NativeCodeVersion>>PTR_OsModuleEntrySList<OsModuleEntry>TypeManagerEntry*SList<TypeManagerEntry>DAC / cDAC Changes
SyncBlock_1.cs,Thread_1.cs: Removed SLink offset subtraction (links now point directly to objects)datadescriptor.inc: RemovedSLinktype definition,ThreadStore.FirstThreadLinkchanged fromTYPE(SLink)toT_POINTERLinkAddress/CleanupLinkAddresspropertiesSyncBlock.md: Updated pseudocode to remove offset subtractiondaccess.h: Updated stale SLink comments to reflect intrusivem_pNextdesignNativeAOT Unification
nativeaot/Runtime/slist.hredirects to../../inc/slist.hInsertHeadInterlocked— the two call sites run single-threaded; the previous volatile/CAS approach was also insufficient for weak memory modelsslist.inlfiles (no longer needed without interlocked support)rh::std::find/counthelpers (single usage inlined)InsertHead/RemoveHead/Begin/End)