blob: a7693413789666d4524448cc523c8abcc520d019 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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_
|