SectionAllocWrapper.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #if _WIN32
  7. #if ENABLE_OOP_NATIVE_CODEGEN
  8. namespace Memory
  9. {
  10. struct SectionInfo
  11. {
  12. HANDLE handle;
  13. void * runtimeBaseAddress;
  14. };
  15. // multi level map, modeled after HeapBlockMap
  16. class SectionMap32
  17. {
  18. #if TARGET_64
  19. friend class SectionMap64;
  20. #endif
  21. public:
  22. #if TARGET_64
  23. SectionMap32(__in char * startAddress);
  24. #else
  25. SectionMap32();
  26. #endif
  27. ~SectionMap32();
  28. bool SetSection(void * address, uint pageCount, SectionInfo * section);
  29. SectionInfo * GetSection(void * address);
  30. void ClearSection(void * address, uint pageCount);
  31. private:
  32. #if TARGET_64
  33. static const size_t TotalSize = 0x100000000; // 4GB
  34. #endif
  35. static const uint L1Count = 4096;
  36. static const uint L2Count = 256;
  37. static uint GetLevel1Id(void * address)
  38. {
  39. return ::Math::PointerCastToIntegralTruncate<uint>(address) / L2Count / AutoSystemInfo::PageSize;
  40. }
  41. static uint GetLevel2Id(void * address)
  42. {
  43. return ::Math::PointerCastToIntegralTruncate<uint>(address) % (L2Count * AutoSystemInfo::PageSize) / AutoSystemInfo::PageSize;
  44. }
  45. bool EnsureSection(void * address, uint pageCount);
  46. void SetSectionNoCheck(void * address, uint pageCount, SectionInfo * section);
  47. void Cleanup();
  48. class L2MapChunk
  49. {
  50. public:
  51. SectionInfo * Get(void * address);
  52. void Set(uint id2, uint pageCount, SectionInfo * section);
  53. void Clear(uint id2, uint pageCount);
  54. bool IsEmpty() const;
  55. ~L2MapChunk();
  56. private:
  57. SectionInfo * map[L2Count];
  58. };
  59. uint count;
  60. L2MapChunk * map[L1Count];
  61. #if TARGET_64
  62. // On 64 bit, this structure only maps one particular 32 bit space, always 4GB aligned
  63. char * startAddress;
  64. #endif
  65. };
  66. #if TARGET_64
  67. class SectionMap64
  68. {
  69. public:
  70. SectionMap64();
  71. ~SectionMap64();
  72. bool SetSection(void * address, uint pageCount, SectionInfo * section);
  73. SectionInfo * GetSection(void * address);
  74. void ClearSection(void * address, uint pageCount);
  75. private:
  76. bool EnsureSection(void * address, size_t pageCount);
  77. void SetSectionNoCheck(void * address, size_t pageCount, SectionInfo * section);
  78. static const uint PagesPer4GB = 1 << 20; // = 1M, assume page size = 4K
  79. struct Node
  80. {
  81. Node(__in char * startAddress) : map(startAddress) { }
  82. uint nodeIndex;
  83. Node * next;
  84. SectionMap32 map;
  85. };
  86. Node * FindOrInsertNode(void * address);
  87. Node * FindNode(void * address) const;
  88. template <class Fn>
  89. void ForEachNodeInAddressRange(void * address, size_t pageCount, Fn fn);
  90. Node * list;
  91. static uint GetNodeIndex(void * address)
  92. {
  93. return GetNodeIndex((ULONG64)address);
  94. }
  95. static uint GetNodeIndex(ULONG64 address)
  96. {
  97. return (uint)((ULONG64)address >> 32);
  98. }
  99. static char * GetNodeStartAddress(void * address)
  100. {
  101. return (char *)(((size_t)address) & ~(SectionMap32::TotalSize - 1));
  102. }
  103. };
  104. typedef SectionMap64 SectionMap;
  105. #else
  106. typedef SectionMap32 SectionMap;
  107. #endif // TARGET_64
  108. class SectionAllocWrapper
  109. {
  110. public:
  111. SectionAllocWrapper(HANDLE process);
  112. LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
  113. BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
  114. LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
  115. BOOL FreeLocal(LPVOID lpAddress);
  116. bool GetFileInfo(LPVOID address, HANDLE* fileHandle, PVOID* baseAddress);
  117. private:
  118. HANDLE process;
  119. SectionMap sections;
  120. };
  121. class PreReservedSectionAllocWrapper
  122. {
  123. public:
  124. #if TARGET_32
  125. static const uint PreReservedAllocationSegmentCount = 256; // (256 * 64K) == 16 MB, if 64k is the AllocationGranularity
  126. #else // TARGET_64
  127. static const uint PreReservedAllocationSegmentCount = 4096; //(4096 * 64K) == 256MB, if 64k is the AllocationGranularity
  128. #endif
  129. #if !TARGET_64 && _CONTROL_FLOW_GUARD
  130. static const unsigned MaxPreReserveSegment = 6;
  131. #endif
  132. PreReservedSectionAllocWrapper(HANDLE process);
  133. ~PreReservedSectionAllocWrapper();
  134. LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
  135. BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
  136. LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
  137. BOOL FreeLocal(LPVOID lpAddress);
  138. bool GetFileInfo(LPVOID address, HANDLE* fileHandle, PVOID* baseAddress);
  139. bool IsInRange(void * address);
  140. static bool IsInRange(void * regionStart, void * address);
  141. LPVOID EnsurePreReservedRegion();
  142. LPVOID GetPreReservedEndAddress();
  143. static LPVOID GetPreReservedEndAddress(void * regionStart);
  144. #if !TARGET_64 && _CONTROL_FLOW_GUARD
  145. static int NumPreReservedSegment() { return numPreReservedSegment; }
  146. #endif
  147. #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
  148. bool IsPreReservedEndAddress(LPVOID address)
  149. {
  150. return IsPreReservedRegionPresent() && address == GetPreReservedEndAddress();
  151. }
  152. #endif
  153. private:
  154. LPVOID EnsurePreReservedRegionInternal();
  155. bool IsPreReservedRegionPresent();
  156. LPVOID GetPreReservedStartAddress();
  157. BVStatic<PreReservedAllocationSegmentCount> freeSegments;
  158. LPVOID preReservedStartAddress;
  159. CriticalSection cs;
  160. #if !TARGET_64 && _CONTROL_FLOW_GUARD
  161. static uint numPreReservedSegment;
  162. #endif
  163. HANDLE process;
  164. HANDLE section;
  165. };
  166. } // namespace Memory
  167. #endif
  168. #endif