summaryrefslogtreecommitdiff
path: root/src/jit/alloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/alloc.h')
-rw-r--r--src/jit/alloc.h99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/jit/alloc.h b/src/jit/alloc.h
new file mode 100644
index 0000000000..a769341378
--- /dev/null
+++ b/src/jit/alloc.h
@@ -0,0 +1,99 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#ifndef _ALLOC_H_
+#define _ALLOC_H_
+
+#if !defined(_HOST_H_)
+#include "host.h"
+#endif // defined(_HOST_H_)
+
+class ArenaAllocator
+{
+private:
+ ArenaAllocator(const ArenaAllocator& other) = delete;
+ ArenaAllocator& operator=(const ArenaAllocator& other) = delete;
+
+protected:
+ struct PageDescriptor
+ {
+ PageDescriptor* m_next;
+ PageDescriptor* m_previous;
+
+ size_t m_pageBytes; // # of bytes allocated
+ size_t m_usedBytes; // # of bytes actually used. (This is only valid when we've allocated a new page.)
+ // See ArenaAllocator::allocateNewPage.
+
+ BYTE m_contents[];
+ };
+
+ // Anything less than 64K leaves VM holes since the OS allocates address space in this size.
+ // Thus if we want to make this smaller, we need to do a reserve / commit scheme
+ enum
+ {
+ DEFAULT_PAGE_SIZE = 16 * OS_page_size,
+ MIN_PAGE_SIZE = sizeof(PageDescriptor)
+ };
+
+ static size_t s_defaultPageSize;
+
+ IEEMemoryManager* m_memoryManager;
+
+ PageDescriptor* m_firstPage;
+ PageDescriptor* m_lastPage;
+
+ // These two pointers (when non-null) will always point into 'm_lastPage'.
+ BYTE* m_nextFreeByte;
+ BYTE* m_lastFreeByte;
+
+ bool isInitialized();
+
+ void* allocateNewPage(size_t size, bool canThrow);
+
+ void* allocateHostMemory(size_t size);
+ void freeHostMemory(void* block);
+
+public:
+ ArenaAllocator();
+ ArenaAllocator(IEEMemoryManager* memoryManager);
+ ArenaAllocator& operator=(ArenaAllocator&& other);
+
+ // NOTE: it would be nice to have a destructor on this type to ensure that any value that
+ // goes out of scope is either uninitialized or has been torn down via a call to
+ // destroy(), but this interacts badly in methods that use SEH. #3058 tracks
+ // revisiting EH in the JIT; such a destructor could be added if SEH is removed
+ // as part of that work.
+
+ virtual void destroy();
+
+#if defined(DEBUG)
+ void* allocateMemory(size_t sz);
+#else // defined(DEBUG)
+ inline void* allocateMemory(size_t size)
+ {
+ void* block = m_nextFreeByte;
+ m_nextFreeByte += size;
+
+ if (m_nextFreeByte > m_lastFreeByte)
+ {
+ block = allocateNewPage(size, true);
+ }
+
+ return block;
+ }
+#endif // !defined(DEBUG)
+
+ size_t getTotalBytesAllocated();
+ size_t getTotalBytesUsed();
+
+ static bool bypassHostAllocator();
+ static size_t getDefaultPageSize();
+
+ static void startup();
+ static void shutdown();
+
+ static ArenaAllocator* getPooledAllocator(IEEMemoryManager* memoryManager);
+};
+
+#endif // _ALLOC_H_