1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
10 #endif // defined(_HOST_H_)
15 ArenaAllocator(const ArenaAllocator& other) = delete;
16 ArenaAllocator& operator=(const ArenaAllocator& other) = delete;
21 PageDescriptor* m_next;
22 PageDescriptor* m_previous;
24 size_t m_pageBytes; // # of bytes allocated
25 size_t m_usedBytes; // # of bytes actually used. (This is only valid when we've allocated a new page.)
26 // See ArenaAllocator::allocateNewPage.
31 // Anything less than 64K leaves VM holes since the OS allocates address space in this size.
32 // Thus if we want to make this smaller, we need to do a reserve / commit scheme
35 DEFAULT_PAGE_SIZE = 16 * OS_page_size,
36 MIN_PAGE_SIZE = sizeof(PageDescriptor)
39 static size_t s_defaultPageSize;
41 IEEMemoryManager* m_memoryManager;
43 PageDescriptor* m_firstPage;
44 PageDescriptor* m_lastPage;
46 // These two pointers (when non-null) will always point into 'm_lastPage'.
52 void* allocateNewPage(size_t size, bool canThrow);
54 void* allocateHostMemory(size_t size);
55 void freeHostMemory(void* block);
59 ArenaAllocator(IEEMemoryManager* memoryManager);
60 ArenaAllocator& operator=(ArenaAllocator&& other);
62 // NOTE: it would be nice to have a destructor on this type to ensure that any value that
63 // goes out of scope is either uninitialized or has been torn down via a call to
64 // destroy(), but this interacts badly in methods that use SEH. #3058 tracks
65 // revisiting EH in the JIT; such a destructor could be added if SEH is removed
66 // as part of that work.
68 virtual void destroy();
70 inline void* allocateMemory(size_t sz);
72 size_t getTotalBytesAllocated();
73 size_t getTotalBytesUsed();
75 static bool bypassHostAllocator();
76 static size_t getDefaultPageSize();
78 static void startup();
79 static void shutdown();
81 static ArenaAllocator* getPooledAllocator(IEEMemoryManager* memoryManager);
84 //------------------------------------------------------------------------
85 // ArenaAllocator::allocateMemory:
86 // Allocates memory using an `ArenaAllocator`.
89 // size - The number of bytes to allocate.
92 // A pointer to the allocated memory.
95 // The DEBUG version of the method has some abilities that the release
96 // version does not: it may inject faults into the allocator and
97 // seeds all allocations with a specified pattern to help catch
98 // use-before-init problems.
100 inline void* ArenaAllocator::allocateMemory(size_t size)
102 assert(isInitialized());
105 // Ensure that we always allocate in pointer sized increments.
106 size = (size_t)roundUp(size, sizeof(size_t));
109 if (JitConfig.ShouldInjectFault() != 0)
111 // Force the underlying memory allocator (either the OS or the CLR hoster)
112 // to allocate the memory. Any fault injection will kick in.
113 void* p = ClrAllocInProcessHeap(0, S_SIZE_T(1));
116 ClrFreeInProcessHeap(0, p);
125 void* block = m_nextFreeByte;
126 m_nextFreeByte += size;
128 if (m_nextFreeByte > m_lastFreeByte)
130 block = allocateNewPage(size, true);
134 memset(block, UninitializedWord<char>(nullptr), size);