diff options
author | Jan Vorlicek <jan.vorlicek@volny.cz> | 2021-05-20 12:02:22 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-20 12:02:22 +0300 |
commit | 636f89d78efeda58e938534f9b1da1981e6c8575 (patch) | |
tree | 2db3eaa9328a8a3f60fcff818b3fd6f7fe02f668 /src/coreclr/utilcode | |
parent | 542ef8ba780303a63e628bbcd67d97586428be77 (diff) |
Move metadata off the executable heaps (#52912)
* Move metadata off the executable heaps
This change moves metadata structures that manage blocks of heap memory
out of the heaps in preparation for the W^X changes that will make the
heap memory read-execute only and modifying the metadata would require
unnecessary mappings and unmappings of the memory as read-write.
The structures moved in this change are the following:
* LoaderHeapBlock
* FreeBlock
* HeapList
* Remove unnecessary m_pCurBlock from the UnlockedLoaderHeap
Diffstat (limited to 'src/coreclr/utilcode')
-rw-r--r-- | src/coreclr/utilcode/loaderheap.cpp | 74 |
1 files changed, 30 insertions, 44 deletions
diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp index 8cfbba75659..33974b9e290 100644 --- a/src/coreclr/utilcode/loaderheap.cpp +++ b/src/coreclr/utilcode/loaderheap.cpp @@ -910,7 +910,6 @@ UnlockedLoaderHeap::UnlockedLoaderHeap(DWORD dwReserveBlockSize, } CONTRACTL_END; - m_pCurBlock = NULL; m_pFirstBlock = NULL; m_dwReserveBlockSize = dwReserveBlockSize; @@ -982,6 +981,8 @@ UnlockedLoaderHeap::~UnlockedLoaderHeap() fSuccess = ClrVirtualFree(pVirtualAddress, 0, MEM_RELEASE); _ASSERTE(fSuccess); } + + delete pSearch; } if (m_reservedBlock.m_fReleaseMemory) @@ -1047,12 +1048,22 @@ size_t UnlockedLoaderHeap::GetBytesAvailReservedRegion() #define SETUP_NEW_BLOCK(pData, dwSizeToCommit, dwSizeToReserve) \ m_pPtrToEndOfCommittedRegion = (BYTE *) (pData) + (dwSizeToCommit); \ - m_pAllocPtr = (BYTE *) (pData) + sizeof(LoaderHeapBlock); \ + m_pAllocPtr = (BYTE *) (pData); \ m_pEndReservedRegion = (BYTE *) (pData) + (dwSizeToReserve); #ifndef DACCESS_COMPILE +void ReleaseReservedMemory(BYTE* value) +{ + if (value) + { + ClrVirtualFree(value, 0, MEM_RELEASE); + } +} + +using ReservedMemoryHolder = SpecializedWrapper<BYTE, ReleaseReservedMemory>; + BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) { CONTRACTL @@ -1065,13 +1076,10 @@ BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) size_t dwSizeToReserve; - // Add sizeof(LoaderHeapBlock) - dwSizeToCommit += sizeof(LoaderHeapBlock); - // Round to page size again dwSizeToCommit = ALIGN_UP(dwSizeToCommit, GetOsPageSize()); - void *pData = NULL; + ReservedMemoryHolder pData = NULL; BOOL fReleaseMemory = TRUE; // We were provided with a reserved memory block at instance creation time, so use it if it's big enough. @@ -1079,7 +1087,7 @@ BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) m_reservedBlock.dwVirtualSize >= dwSizeToCommit) { // Get the info out of the block. - pData = m_reservedBlock.pVirtualAddress; + pData = (PTR_BYTE)m_reservedBlock.pVirtualAddress; dwSizeToReserve = m_reservedBlock.dwVirtualSize; fReleaseMemory = m_reservedBlock.m_fReleaseMemory; @@ -1126,16 +1134,17 @@ BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) return FALSE; } + if (!fReleaseMemory) + { + pData.SuppressRelease(); + } + // Commit first set of pages, since it will contain the LoaderHeapBlock void *pTemp = ClrVirtualAlloc(pData, dwSizeToCommit, MEM_COMMIT, (m_Options & LHF_EXECUTABLE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); if (pTemp == NULL) { //_ASSERTE(!"Unable to ClrVirtualAlloc commit in a loaderheap"); - // Unable to commit - release pages - if (fReleaseMemory) - ClrVirtualFree(pData, 0, MEM_RELEASE); - return FALSE; } @@ -1147,44 +1156,27 @@ BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) ((const BYTE *) pData) + dwSizeToReserve, (void *) this)) { - - if (fReleaseMemory) - ClrVirtualFree(pData, 0, MEM_RELEASE); - return FALSE; } } - m_dwTotalAlloc += dwSizeToCommit; - - LoaderHeapBlock *pNewBlock; + LoaderHeapBlock *pNewBlock = new (nothrow) LoaderHeapBlock; + if (pNewBlock == NULL) + { + return FALSE; + } -#if defined(HOST_OSX) && defined(HOST_ARM64) - // Always assume we are touching executable heap - auto jitWriteEnableHolder = PAL_JITWriteEnable(true); -#endif // defined(HOST_OSX) && defined(HOST_ARM64) + m_dwTotalAlloc += dwSizeToCommit; - pNewBlock = (LoaderHeapBlock *) pData; + pData.SuppressRelease(); pNewBlock->dwVirtualSize = dwSizeToReserve; pNewBlock->pVirtualAddress = pData; - pNewBlock->pNext = NULL; + pNewBlock->pNext = m_pFirstBlock; pNewBlock->m_fReleaseMemory = fReleaseMemory; - LoaderHeapBlock *pCurBlock = m_pCurBlock; - - // Add to linked list - while (pCurBlock != NULL && - pCurBlock->pNext != NULL) - pCurBlock = pCurBlock->pNext; - - if (pCurBlock != NULL) - m_pCurBlock->pNext = pNewBlock; - else - m_pFirstBlock = pNewBlock; - - // If we want to use the memory immediately... - m_pCurBlock = pNewBlock; + // Add to the linked list + m_pFirstBlock = pNewBlock; SETUP_NEW_BLOCK(pData, dwSizeToCommit, dwSizeToReserve); @@ -1827,16 +1819,11 @@ void UnlockedLoaderHeap::DumpFreeList() size_t dwsize = pBlock->m_dwSize; BOOL ccbad = FALSE; BOOL sizeunaligned = FALSE; - BOOL sizesmall = FALSE; if ( 0 != (dwsize & ALLOC_ALIGN_CONSTANT) ) { sizeunaligned = TRUE; } - if ( dwsize < sizeof(LoaderHeapBlock)) - { - sizesmall = TRUE; - } for (size_t i = sizeof(LoaderHeapFreeBlock); i < dwsize; i++) { @@ -1850,7 +1837,6 @@ void UnlockedLoaderHeap::DumpFreeList() printf("Addr = %pxh, Size = %lxh", pBlock, ((ULONG)dwsize)); if (ccbad) printf(" *** ERROR: NOT CC'd ***"); if (sizeunaligned) printf(" *** ERROR: size not a multiple of ALLOC_ALIGN_CONSTANT ***"); - if (sizesmall) printf(" *** ERROR: size smaller than sizeof(LoaderHeapFreeBlock) ***"); printf("\n"); pBlock = pBlock->m_pNext; |