From e7e471455810a18bb4d3b70fdd5cf43a76ea2c8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 17:57:48 +0000 Subject: [PATCH 1/8] Initial plan From 61e591849836029ea8bfa6a01024b8d7959e3aa8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:21:49 +0000 Subject: [PATCH 2/8] Optimize allocheap.cpp: use new/delete and 4KB blocks with embedded metadata Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 41 +++++++++++---------- src/coreclr/nativeaot/Runtime/allocheap.h | 14 +++---- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index f03a34c946189f..71976d256e45ad 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -50,12 +50,13 @@ bool AllocHeap::Init( { ASSERT(!m_fIsInit); - BlockListElem *pBlock = new (nothrow) BlockListElem(pbInitialMem, cbInitialMemReserve); - if (pBlock == NULL) - return false; + BlockListElem *pBlock = reinterpret_cast(pbInitialMem); + pBlock->m_pNext = NULL; + pBlock->m_cbMem = cbInitialMemReserve; m_blockList.PushHead(pBlock); - if (!_UpdateMemPtrs(pbInitialMem, + uint8_t* dataStart = pBlock->GetDataStart(); + if (!_UpdateMemPtrs(dataStart, pbInitialMem + cbInitialMemCommit, pbInitialMem + cbInitialMemReserve)) { @@ -76,8 +77,7 @@ AllocHeap::~AllocHeap() { BlockListElem *pCur = m_blockList.PopHead(); if (pCur->GetStart() != m_pbInitialMem || m_fShouldFreeInitialMem) - PalVirtualFree(pCur->GetStart(), pCur->GetLength()); - delete pCur; + delete[] pCur->GetStart(); } } @@ -88,7 +88,7 @@ uint8_t * AllocHeap::_Alloc( ) { ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 only. - ASSERT(alignment <= OS_PAGE_SIZE); // Can't handle this right now. + ASSERT(alignment <= BLOCK_SIZE); // Can't handle this right now. CrstHolder lock(&m_lock); @@ -124,8 +124,8 @@ uint8_t * AllocHeap::AllocAligned( //------------------------------------------------------------------------------------------------- bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd, uint8_t* pFreeReserveEnd) { - ASSERT(ALIGN_DOWN(pFreeCommitEnd, OS_PAGE_SIZE) == pFreeCommitEnd); - ASSERT(ALIGN_DOWN(pFreeReserveEnd, OS_PAGE_SIZE) == pFreeReserveEnd); + ASSERT(ALIGN_DOWN(pFreeCommitEnd, BLOCK_SIZE) == pFreeCommitEnd); + ASSERT(ALIGN_DOWN(pFreeReserveEnd, BLOCK_SIZE) == pFreeReserveEnd); m_pNextFree = pNextFree; m_pFreeCommitEnd = pFreeCommitEnd; @@ -148,27 +148,28 @@ bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree) //------------------------------------------------------------------------------------------------- bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) { - cbMem = ALIGN_UP(cbMem, OS_PAGE_SIZE); + // Calculate block size: ensure it's at least BLOCK_SIZE and aligned to BLOCK_SIZE + // Also need room for BlockListElem header + uintptr_t cbBlockSize = ALIGN_UP(cbMem + sizeof(BlockListElem), BLOCK_SIZE); + if (cbBlockSize < BLOCK_SIZE) + cbBlockSize = BLOCK_SIZE; - uint8_t * pbMem = reinterpret_cast - (PalVirtualAlloc(cbMem, PAGE_READWRITE)); + uint8_t * pbMem = new (nothrow) uint8_t[cbBlockSize]; if (pbMem == NULL) return false; - BlockListElem *pBlockListElem = new (nothrow) BlockListElem(pbMem, cbMem); - if (pBlockListElem == NULL) - { - PalVirtualFree(pbMem, cbMem); - return false; - } + BlockListElem *pBlockListElem = reinterpret_cast(pbMem); + pBlockListElem->m_pNext = NULL; + pBlockListElem->m_cbMem = cbBlockSize; // Add to the list. While there is no race for writers (we hold the lock) we have the // possibility of simultaneous readers, and using the interlocked version creates a // memory barrier to make sure any reader sees a consistent list. m_blockList.PushHeadInterlocked(pBlockListElem); - return _UpdateMemPtrs(pbMem, pbMem + cbMem, pbMem + cbMem); + uint8_t* dataStart = pBlockListElem->GetDataStart(); + return _UpdateMemPtrs(dataStart, pbMem + cbBlockSize, pbMem + cbBlockSize); } //------------------------------------------------------------------------------------------------- @@ -201,7 +202,7 @@ bool AllocHeap::_CommitFromCurBlock(uintptr_t cbMem) if (m_pNextFree + cbMem <= m_pFreeReserveEnd) { - uintptr_t cbMemToCommit = ALIGN_UP(cbMem, OS_PAGE_SIZE); + uintptr_t cbMemToCommit = ALIGN_UP(cbMem, BLOCK_SIZE); return _UpdateMemPtrs(m_pNextFree, m_pFreeCommitEnd + cbMemToCommit); } diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 7da47eda6e4130..8e2cc0a52c0278 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -39,18 +39,16 @@ class AllocHeap bool _UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd); bool _UpdateMemPtrs(uint8_t* pNextFree); + static const uintptr_t BLOCK_SIZE = 4096; + struct BlockListElem { - BlockListElem(uint8_t * pbMem, uintptr_t cbMem) - : m_pbMem(pbMem), m_cbMem(cbMem), m_pNext(NULL) - {} + BlockListElem* m_pNext; + uintptr_t m_cbMem; - uint8_t* GetStart() const { return m_pbMem; } + uint8_t* GetStart() const { return (uint8_t*)this; } uintptr_t GetLength() const { return m_cbMem; } - - uint8_t * m_pbMem; - uintptr_t m_cbMem; - BlockListElem* m_pNext; + uint8_t* GetDataStart() const { return (uint8_t*)this + sizeof(BlockListElem); } }; typedef SList BlockList; From a79ccef217fc1f531409e98a75f7cc2ac2e2a230 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:33:03 +0000 Subject: [PATCH 3/8] Remove dead code: InitialMemReserve support Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 37 +-------------------- src/coreclr/nativeaot/Runtime/allocheap.h | 8 ----- 2 files changed, 1 insertion(+), 44 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 71976d256e45ad..96b7a1bc2ab8a2 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -22,8 +22,6 @@ AllocHeap::AllocHeap() m_pNextFree(NULL), m_pFreeCommitEnd(NULL), m_pFreeReserveEnd(NULL), - m_pbInitialMem(NULL), - m_fShouldFreeInitialMem(false), m_lock(CrstAllocHeap) COMMA_INDEBUG(m_fIsInit(false)) { @@ -38,46 +36,13 @@ bool AllocHeap::Init() return true; } -//------------------------------------------------------------------------------------------------- -// This is for using pre-allocated memory on heap construction. -// Should never use this more than once, and should always follow construction of heap. - -bool AllocHeap::Init( - uint8_t * pbInitialMem, - uintptr_t cbInitialMemCommit, - uintptr_t cbInitialMemReserve, - bool fShouldFreeInitialMem) -{ - ASSERT(!m_fIsInit); - - BlockListElem *pBlock = reinterpret_cast(pbInitialMem); - pBlock->m_pNext = NULL; - pBlock->m_cbMem = cbInitialMemReserve; - m_blockList.PushHead(pBlock); - - uint8_t* dataStart = pBlock->GetDataStart(); - if (!_UpdateMemPtrs(dataStart, - pbInitialMem + cbInitialMemCommit, - pbInitialMem + cbInitialMemReserve)) - { - return false; - } - - m_pbInitialMem = pbInitialMem; - m_fShouldFreeInitialMem = fShouldFreeInitialMem; - - INDEBUG(m_fIsInit = true;) - return true; -} - //------------------------------------------------------------------------------------------------- AllocHeap::~AllocHeap() { while (!m_blockList.IsEmpty()) { BlockListElem *pCur = m_blockList.PopHead(); - if (pCur->GetStart() != m_pbInitialMem || m_fShouldFreeInitialMem) - delete[] pCur->GetStart(); + delete[] pCur->GetStart(); } } diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 8e2cc0a52c0278..91c60bd903af38 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -9,11 +9,6 @@ class AllocHeap bool Init(); - bool Init(uint8_t * pbInitialMem, - uintptr_t cbInitialMemCommit, - uintptr_t cbInitialMemReserve, - bool fShouldFreeInitialMem); - ~AllocHeap(); // If AllocHeap was created with a MemAccessMgr, pRWAccessHolder must be non-NULL. @@ -58,9 +53,6 @@ class AllocHeap uint8_t * m_pFreeCommitEnd; uint8_t * m_pFreeReserveEnd; - uint8_t * m_pbInitialMem; - bool m_fShouldFreeInitialMem; - Crst m_lock; INDEBUG(bool m_fIsInit;) From def48b052a5dcfe1b66d00060c60f59efc805d76 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 18:34:23 +0000 Subject: [PATCH 4/8] Address code review feedback: remove redundant condition Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 96b7a1bc2ab8a2..117850fc6919ab 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -116,8 +116,6 @@ bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) // Calculate block size: ensure it's at least BLOCK_SIZE and aligned to BLOCK_SIZE // Also need room for BlockListElem header uintptr_t cbBlockSize = ALIGN_UP(cbMem + sizeof(BlockListElem), BLOCK_SIZE); - if (cbBlockSize < BLOCK_SIZE) - cbBlockSize = BLOCK_SIZE; uint8_t * pbMem = new (nothrow) uint8_t[cbBlockSize]; From 5a9a9e8afbeeb8d05cec2b64ccf0268a3148767c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 20:32:59 +0000 Subject: [PATCH 5/8] Address feedback: simplify state tracking and remove obsolete code Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 81 +++++---------------- src/coreclr/nativeaot/Runtime/allocheap.h | 12 +-- 2 files changed, 19 insertions(+), 74 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 117850fc6919ab..8f03e532a70de8 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -19,9 +19,8 @@ //------------------------------------------------------------------------------------------------- AllocHeap::AllocHeap() : m_blockList(), - m_pNextFree(NULL), - m_pFreeCommitEnd(NULL), - m_pFreeReserveEnd(NULL), + m_pCurBlock(NULL), + m_cbCurBlockUsed(0), m_lock(CrstAllocHeap) COMMA_INDEBUG(m_fIsInit(false)) { @@ -42,7 +41,7 @@ AllocHeap::~AllocHeap() while (!m_blockList.IsEmpty()) { BlockListElem *pCur = m_blockList.PopHead(); - delete[] pCur->GetStart(); + delete[] (uint8_t*)pCur; } } @@ -86,39 +85,12 @@ uint8_t * AllocHeap::AllocAligned( return _Alloc(cbMem, alignment); } -//------------------------------------------------------------------------------------------------- -bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd, uint8_t* pFreeReserveEnd) -{ - ASSERT(ALIGN_DOWN(pFreeCommitEnd, BLOCK_SIZE) == pFreeCommitEnd); - ASSERT(ALIGN_DOWN(pFreeReserveEnd, BLOCK_SIZE) == pFreeReserveEnd); - - m_pNextFree = pNextFree; - m_pFreeCommitEnd = pFreeCommitEnd; - m_pFreeReserveEnd = pFreeReserveEnd; - return true; -} - -//------------------------------------------------------------------------------------------------- -bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd) -{ - return _UpdateMemPtrs(pNextFree, pFreeCommitEnd, m_pFreeReserveEnd); -} - -//------------------------------------------------------------------------------------------------- -bool AllocHeap::_UpdateMemPtrs(uint8_t* pNextFree) -{ - return _UpdateMemPtrs(pNextFree, m_pFreeCommitEnd); -} - //------------------------------------------------------------------------------------------------- bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) { - // Calculate block size: ensure it's at least BLOCK_SIZE and aligned to BLOCK_SIZE - // Also need room for BlockListElem header uintptr_t cbBlockSize = ALIGN_UP(cbMem + sizeof(BlockListElem), BLOCK_SIZE); uint8_t * pbMem = new (nothrow) uint8_t[cbBlockSize]; - if (pbMem == NULL) return false; @@ -126,13 +98,12 @@ bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) pBlockListElem->m_pNext = NULL; pBlockListElem->m_cbMem = cbBlockSize; - // Add to the list. While there is no race for writers (we hold the lock) we have the - // possibility of simultaneous readers, and using the interlocked version creates a - // memory barrier to make sure any reader sees a consistent list. - m_blockList.PushHeadInterlocked(pBlockListElem); + m_blockList.PushHead(pBlockListElem); + + m_pCurBlock = pBlockListElem; + m_cbCurBlockUsed = sizeof(BlockListElem); - uint8_t* dataStart = pBlockListElem->GetDataStart(); - return _UpdateMemPtrs(dataStart, pbMem + cbBlockSize, pbMem + cbBlockSize); + return true; } //------------------------------------------------------------------------------------------------- @@ -140,36 +111,18 @@ uint8_t * AllocHeap::_AllocFromCurBlock( uintptr_t cbMem, uintptr_t alignment) { - uint8_t * pbMem = NULL; - - cbMem += (uint8_t *)ALIGN_UP(m_pNextFree, alignment) - m_pNextFree; - - if (m_pNextFree + cbMem <= m_pFreeCommitEnd || - _CommitFromCurBlock(cbMem)) - { - ASSERT(cbMem + m_pNextFree <= m_pFreeCommitEnd); - - pbMem = ALIGN_UP(m_pNextFree, alignment); - - if (!_UpdateMemPtrs(m_pNextFree + cbMem)) - return NULL; - } - - return pbMem; -} + if (m_pCurBlock == NULL) + return NULL; -//------------------------------------------------------------------------------------------------- -bool AllocHeap::_CommitFromCurBlock(uintptr_t cbMem) -{ - ASSERT(m_pFreeCommitEnd < m_pNextFree + cbMem); + uint8_t* pBlockStart = (uint8_t*)m_pCurBlock; + uint8_t* pAlloc = (uint8_t*)ALIGN_UP(pBlockStart + m_cbCurBlockUsed, alignment); + uintptr_t cbAllocEnd = pAlloc + cbMem - pBlockStart; - if (m_pNextFree + cbMem <= m_pFreeReserveEnd) - { - uintptr_t cbMemToCommit = ALIGN_UP(cbMem, BLOCK_SIZE); - return _UpdateMemPtrs(m_pNextFree, m_pFreeCommitEnd + cbMemToCommit); - } + if (cbAllocEnd > m_pCurBlock->m_cbMem) + return NULL; - return false; + m_cbCurBlockUsed = cbAllocEnd; + return pAlloc; } //------------------------------------------------------------------------------------------------- diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 91c60bd903af38..9a9aef4d56df44 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -27,12 +27,6 @@ class AllocHeap uint8_t* _Alloc(uintptr_t cbMem, uintptr_t alignment); bool _AllocNewBlock(uintptr_t cbMem); uint8_t* _AllocFromCurBlock(uintptr_t cbMem, uintptr_t alignment); - bool _CommitFromCurBlock(uintptr_t cbMem); - - // Access protection helpers - bool _UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd, uint8_t* pFreeReserveEnd); - bool _UpdateMemPtrs(uint8_t* pNextFree, uint8_t* pFreeCommitEnd); - bool _UpdateMemPtrs(uint8_t* pNextFree); static const uintptr_t BLOCK_SIZE = 4096; @@ -41,7 +35,6 @@ class AllocHeap BlockListElem* m_pNext; uintptr_t m_cbMem; - uint8_t* GetStart() const { return (uint8_t*)this; } uintptr_t GetLength() const { return m_cbMem; } uint8_t* GetDataStart() const { return (uint8_t*)this + sizeof(BlockListElem); } }; @@ -49,9 +42,8 @@ class AllocHeap typedef SList BlockList; BlockList m_blockList; - uint8_t * m_pNextFree; - uint8_t * m_pFreeCommitEnd; - uint8_t * m_pFreeReserveEnd; + BlockListElem * m_pCurBlock; + uintptr_t m_cbCurBlockUsed; Crst m_lock; From b14fecaa846b1b9817ecb5f56d8abdb61fa01e2a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 2 Jan 2026 12:42:48 -0800 Subject: [PATCH 6/8] Update src/coreclr/nativeaot/Runtime/allocheap.cpp --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 8f03e532a70de8..73205f7a47b9d6 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -95,7 +95,6 @@ bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) return false; BlockListElem *pBlockListElem = reinterpret_cast(pbMem); - pBlockListElem->m_pNext = NULL; pBlockListElem->m_cbMem = cbBlockSize; m_blockList.PushHead(pBlockListElem); From d83538c32d25312be375c086e719bfeaf14fdbe0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:14:01 +0000 Subject: [PATCH 7/8] Remove m_pCurBlock, use m_blockList.GetHead() instead Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- src/coreclr/nativeaot/Runtime/allocheap.cpp | 10 ++++------ src/coreclr/nativeaot/Runtime/allocheap.h | 1 - 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 73205f7a47b9d6..5753df521895d6 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -19,7 +19,6 @@ //------------------------------------------------------------------------------------------------- AllocHeap::AllocHeap() : m_blockList(), - m_pCurBlock(NULL), m_cbCurBlockUsed(0), m_lock(CrstAllocHeap) COMMA_INDEBUG(m_fIsInit(false)) @@ -98,8 +97,6 @@ bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) pBlockListElem->m_cbMem = cbBlockSize; m_blockList.PushHead(pBlockListElem); - - m_pCurBlock = pBlockListElem; m_cbCurBlockUsed = sizeof(BlockListElem); return true; @@ -110,14 +107,15 @@ uint8_t * AllocHeap::_AllocFromCurBlock( uintptr_t cbMem, uintptr_t alignment) { - if (m_pCurBlock == NULL) + BlockListElem *pCurBlock = m_blockList.GetHead(); + if (pCurBlock == NULL) return NULL; - uint8_t* pBlockStart = (uint8_t*)m_pCurBlock; + uint8_t* pBlockStart = (uint8_t*)pCurBlock; uint8_t* pAlloc = (uint8_t*)ALIGN_UP(pBlockStart + m_cbCurBlockUsed, alignment); uintptr_t cbAllocEnd = pAlloc + cbMem - pBlockStart; - if (cbAllocEnd > m_pCurBlock->m_cbMem) + if (cbAllocEnd > pCurBlock->m_cbMem) return NULL; m_cbCurBlockUsed = cbAllocEnd; diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 9a9aef4d56df44..0b7606244941fd 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -42,7 +42,6 @@ class AllocHeap typedef SList BlockList; BlockList m_blockList; - BlockListElem * m_pCurBlock; uintptr_t m_cbCurBlockUsed; Crst m_lock; From 5eb738af20dce2c96fe6cfd5647ae478404cee26 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 2 Jan 2026 21:45:02 +0000 Subject: [PATCH 8/8] Address feedback: rename to AllocAligned, account for alignment, use static g_allocHeap Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../Runtime/CachedInterfaceDispatch_Aot.cpp | 12 ++---- src/coreclr/nativeaot/Runtime/allocheap.cpp | 40 ++++++++----------- src/coreclr/nativeaot/Runtime/allocheap.h | 7 ++-- 3 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp index 9a8be1bfd69e29..32147f1597aa61 100644 --- a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp +++ b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp @@ -7,15 +7,11 @@ #include "CachedInterfaceDispatch.h" // The base memory allocator. -static AllocHeap * g_pAllocHeap = NULL; +static AllocHeap g_allocHeap; bool InterfaceDispatch_InitializePal() { - g_pAllocHeap = new (nothrow) AllocHeap(); - if (g_pAllocHeap == NULL) - return false; - - if (!g_pAllocHeap->Init()) + if (!g_allocHeap.Init()) return false; return true; @@ -24,14 +20,14 @@ bool InterfaceDispatch_InitializePal() // Allocate memory aligned at sizeof(void*)*2 boundaries void *InterfaceDispatch_AllocDoublePointerAligned(size_t size) { - return g_pAllocHeap->AllocAligned(size, sizeof(void*) * 2); + return g_allocHeap.AllocAligned(size, sizeof(void*) * 2); } // Allocate memory aligned at sizeof(void*) boundaries void *InterfaceDispatch_AllocPointerAligned(size_t size) { - return g_pAllocHeap->AllocAligned(size, sizeof(void*)); + return g_allocHeap.AllocAligned(size, sizeof(void*)); } FCIMPL4(PCODE, RhpUpdateDispatchCellCache, InterfaceDispatchCell * pCell, PCODE pTargetCode, MethodTable* pInstanceType, DispatchCellInfo *pNewCellInfo) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.cpp b/src/coreclr/nativeaot/Runtime/allocheap.cpp index 5753df521895d6..be924529ce5d59 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.cpp +++ b/src/coreclr/nativeaot/Runtime/allocheap.cpp @@ -19,8 +19,7 @@ //------------------------------------------------------------------------------------------------- AllocHeap::AllocHeap() : m_blockList(), - m_cbCurBlockUsed(0), - m_lock(CrstAllocHeap) + m_cbCurBlockUsed(0) COMMA_INDEBUG(m_fIsInit(false)) { } @@ -29,26 +28,34 @@ AllocHeap::AllocHeap() bool AllocHeap::Init() { ASSERT(!m_fIsInit); + m_lock.Init(CrstAllocHeap); INDEBUG(m_fIsInit = true;) return true; } //------------------------------------------------------------------------------------------------- -AllocHeap::~AllocHeap() +void AllocHeap::Destroy() { while (!m_blockList.IsEmpty()) { BlockListElem *pCur = m_blockList.PopHead(); delete[] (uint8_t*)pCur; } + m_lock.Destroy(); } //------------------------------------------------------------------------------------------------- -uint8_t * AllocHeap::_Alloc( +uint8_t * AllocHeap::Alloc( + uintptr_t cbMem) +{ + return AllocAligned(cbMem, 1); +} + +//------------------------------------------------------------------------------------------------- +uint8_t * AllocHeap::AllocAligned( uintptr_t cbMem, - uintptr_t alignment - ) + uintptr_t alignment) { ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 only. ASSERT(alignment <= BLOCK_SIZE); // Can't handle this right now. @@ -60,7 +67,7 @@ uint8_t * AllocHeap::_Alloc( return pbMem; // Must allocate new block - if (!_AllocNewBlock(cbMem)) + if (!_AllocNewBlock(cbMem, alignment)) return NULL; pbMem = _AllocFromCurBlock(cbMem, alignment); @@ -70,24 +77,9 @@ uint8_t * AllocHeap::_Alloc( } //------------------------------------------------------------------------------------------------- -uint8_t * AllocHeap::Alloc( - uintptr_t cbMem) -{ - return _Alloc(cbMem, 1); -} - -//------------------------------------------------------------------------------------------------- -uint8_t * AllocHeap::AllocAligned( - uintptr_t cbMem, - uintptr_t alignment) -{ - return _Alloc(cbMem, alignment); -} - -//------------------------------------------------------------------------------------------------- -bool AllocHeap::_AllocNewBlock(uintptr_t cbMem) +bool AllocHeap::_AllocNewBlock(uintptr_t cbMem, uintptr_t alignment) { - uintptr_t cbBlockSize = ALIGN_UP(cbMem + sizeof(BlockListElem), BLOCK_SIZE); + uintptr_t cbBlockSize = ALIGN_UP(cbMem + sizeof(BlockListElem) + alignment, BLOCK_SIZE); uint8_t * pbMem = new (nothrow) uint8_t[cbBlockSize]; if (pbMem == NULL) diff --git a/src/coreclr/nativeaot/Runtime/allocheap.h b/src/coreclr/nativeaot/Runtime/allocheap.h index 0b7606244941fd..5a9538d2cdca02 100644 --- a/src/coreclr/nativeaot/Runtime/allocheap.h +++ b/src/coreclr/nativeaot/Runtime/allocheap.h @@ -9,7 +9,7 @@ class AllocHeap bool Init(); - ~AllocHeap(); + void Destroy(); // If AllocHeap was created with a MemAccessMgr, pRWAccessHolder must be non-NULL. // On return, the holder will permit R/W access to the allocated memory until it @@ -24,8 +24,7 @@ class AllocHeap private: // Allocation Helpers - uint8_t* _Alloc(uintptr_t cbMem, uintptr_t alignment); - bool _AllocNewBlock(uintptr_t cbMem); + bool _AllocNewBlock(uintptr_t cbMem, uintptr_t alignment); uint8_t* _AllocFromCurBlock(uintptr_t cbMem, uintptr_t alignment); static const uintptr_t BLOCK_SIZE = 4096; @@ -44,7 +43,7 @@ class AllocHeap uintptr_t m_cbCurBlockUsed; - Crst m_lock; + CrstStatic m_lock; INDEBUG(bool m_fIsInit;) };