diff --git a/src/coreclr/vm/frozenobjectheap.cpp b/src/coreclr/vm/frozenobjectheap.cpp index a1ed1c8b46dc44..eaa23588b09851 100644 --- a/src/coreclr/vm/frozenobjectheap.cpp +++ b/src/coreclr/vm/frozenobjectheap.cpp @@ -77,6 +77,35 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t #endif // !FEATURE_BASICFREEZE } +static void* ReserveMemory(size_t size) +{ +#if defined(TARGET_X86) || defined(TARGET_AMD64) + // We have plenty of space in-range on X86/AMD64 so we can afford keeping + // FOH segments there so e.g. JIT can use relocs for frozen objects. + return ExecutableAllocator::Instance()->Reserve(size); +#else + return ClrVirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE); +#endif +} + +static void* CommitMemory(void* ptr, size_t size) +{ +#if defined(TARGET_X86) || defined(TARGET_AMD64) + return ExecutableAllocator::Instance()->Commit(ptr, size, /*isExecutable*/ false); +#else + return ClrVirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE); +#endif +} + +static void ReleaseMemory(void* ptr) +{ +#if defined(TARGET_X86) || defined(TARGET_AMD64) + ExecutableAllocator::Instance()->Release(ptr); +#else + ClrVirtualFree(ptr, 0, MEM_RELEASE); +#endif +} + // Reserve sizeHint bytes of memory for the given frozen segment. // The requested size can be be ignored in case of memory pressure and FOH_SEGMENT_DEFAULT_SIZE is used instead. FrozenObjectSegment::FrozenObjectSegment(size_t sizeHint) : @@ -90,7 +119,7 @@ FrozenObjectSegment::FrozenObjectSegment(size_t sizeHint) : _ASSERT(m_Size > FOH_COMMIT_SIZE); _ASSERT(m_Size % FOH_COMMIT_SIZE == 0); - void* alloc = ClrVirtualAlloc(nullptr, m_Size, MEM_RESERVE, PAGE_READWRITE); + void* alloc = ReserveMemory(m_Size); if (alloc == nullptr) { // Try again with the default FOH size @@ -99,7 +128,7 @@ FrozenObjectSegment::FrozenObjectSegment(size_t sizeHint) : m_Size = FOH_SEGMENT_DEFAULT_SIZE; _ASSERT(m_Size > FOH_COMMIT_SIZE); _ASSERT(m_Size % FOH_COMMIT_SIZE == 0); - alloc = ClrVirtualAlloc(nullptr, m_Size, MEM_RESERVE, PAGE_READWRITE); + alloc = ReserveMemory(m_Size); } if (alloc == nullptr) @@ -109,15 +138,13 @@ FrozenObjectSegment::FrozenObjectSegment(size_t sizeHint) : } // Commit a chunk in advance - void* committedAlloc = ClrVirtualAlloc(alloc, FOH_COMMIT_SIZE, MEM_COMMIT, PAGE_READWRITE); + void* committedAlloc = CommitMemory(alloc, FOH_COMMIT_SIZE); if (committedAlloc == nullptr) { - ClrVirtualFree(alloc, 0, MEM_RELEASE); + ReleaseMemory(alloc); ThrowOutOfMemory(); } - // ClrVirtualAlloc is expected to be PageSize-aligned so we can expect - // DATA_ALIGNMENT alignment as well _ASSERT(IS_ALIGNED(committedAlloc, DATA_ALIGNMENT)); segment_info si; @@ -130,7 +157,7 @@ FrozenObjectSegment::FrozenObjectSegment(size_t sizeHint) : m_SegmentHandle = GCHeapUtilities::GetGCHeap()->RegisterFrozenSegment(&si); if (m_SegmentHandle == nullptr) { - ClrVirtualFree(alloc, 0, MEM_RELEASE); + ReleaseMemory(alloc); ThrowOutOfMemory(); } @@ -166,9 +193,9 @@ Object* FrozenObjectSegment::TryAllocateObject(PTR_MethodTable type, size_t obje // Make sure we don't go out of bounds during this commit _ASSERT(m_SizeCommitted + FOH_COMMIT_SIZE <= m_Size); - if (ClrVirtualAlloc(m_pStart + m_SizeCommitted, FOH_COMMIT_SIZE, MEM_COMMIT, PAGE_READWRITE) == nullptr) + if (CommitMemory(m_pStart + m_SizeCommitted, FOH_COMMIT_SIZE) == nullptr) { - ClrVirtualFree(m_pStart, 0, MEM_RELEASE); + ReleaseMemory(m_pStart); ThrowOutOfMemory(); } m_SizeCommitted += FOH_COMMIT_SIZE;