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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
// 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_
/*****************************************************************************/
#ifndef _HOST_H_
#include "host.h"
#endif
/*****************************************************************************/
#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif
/*****************************************************************************/
#if defined(DEBUG)
#include "malloc.h"
inline void * DbgNew(size_t size)
{
return ClrAllocInProcessHeap(0, S_SIZE_T(size));
}
inline void DbgDelete(void * ptr)
{
(void)ClrFreeInProcessHeap(0, ptr);
}
#endif // DEBUG
/*****************************************************************************/
struct nraMarkDsc
{
void * nmPage;
BYTE * nmNext;
BYTE * nmLast;
};
struct norls_allocator
{
private:
struct norls_pagdesc
{
norls_pagdesc * nrpNextPage;
norls_pagdesc * nrpPrevPage;
#ifdef DEBUG
void * nrpSelfPtr;
#endif
size_t nrpPageSize; // # of bytes allocated
size_t nrpUsedSize; // # of bytes actually used. (This is only valid when we've allocated a new page.)
// See norls_allocator::nraAllocNewPage.
BYTE nrpContents[];
};
norls_pagdesc * nraPageList;
norls_pagdesc * nraPageLast;
BYTE * nraFreeNext; // these two (when non-zero) will
BYTE * nraFreeLast; // always point into 'nraPageLast'
size_t nraPageSize;
#ifdef DEBUG
bool nraShouldInjectFault; // Should we inject fault?
#endif
IEEMemoryManager* nraMemoryManager;
void * nraAllocNewPage(size_t sz);
public:
// 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) };
enum { MIN_PAGE_SIZE = sizeof(norls_pagdesc) };
bool nraInit (IEEMemoryManager* pMemoryManager, size_t pageSize = 0, int preAlloc = 0);
void nraFree (void);
void * nraAlloc(size_t sz);
/* The following used for mark/release operation */
void nraMark(nraMarkDsc &mark)
{
mark.nmPage = nraPageLast;
mark.nmNext = nraFreeNext;
mark.nmLast = nraFreeLast;
}
private:
void nraToss(nraMarkDsc &mark);
LPVOID nraVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
{
#if defined(DEBUG)
assert(lpAddress == 0 && flAllocationType == MEM_COMMIT && flProtect == PAGE_READWRITE);
if (nraDirectAlloc())
{
#undef GetProcessHeap
#undef HeapAlloc
return ::HeapAlloc(GetProcessHeap(), 0, dwSize);
}
else
return DbgNew(dwSize);
#else
return nraMemoryManager->ClrVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
#endif
}
void nraVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
{
#if defined(DEBUG)
assert(dwSize == 0 && dwFreeType == MEM_RELEASE);
if (nraDirectAlloc())
{
#undef GetProcessHeap
#undef HeapFree
::HeapFree(GetProcessHeap(), 0, lpAddress);
}
else
DbgDelete(lpAddress);
#else
nraMemoryManager->ClrVirtualFree(lpAddress, dwSize, dwFreeType);
#endif
}
public:
void nraRlsm(nraMarkDsc &mark)
{
if (nraPageLast != mark.nmPage)
{
nraToss(mark);
}
else
{
nraFreeNext = mark.nmNext;
nraFreeLast = mark.nmLast;
}
}
size_t nraTotalSizeAlloc();
size_t nraTotalSizeUsed ();
IEEMemoryManager * nraGetMemoryManager()
{
return nraMemoryManager;
}
static bool nraDirectAlloc();
#ifdef _TARGET_AMD64_
/*
* IGcInfoEncoderAllocator implementation (protected)
* - required to use GcInfoEncoder
*/
protected:
void* Alloc(size_t size)
{
//GcInfoEncoder likes to allocate things of 0-size when m_NumSlots == 0
//but nraAlloc doesn't like to allocate 0-size things.. so lets not let it
return size ? nraAlloc(size) : NULL;
}
void Free( void* ) {}
#endif // _TARGET_AMD64_
};
#if !defined(DEBUG)
inline
void * norls_allocator::nraAlloc(size_t sz)
{
void * block;
block = nraFreeNext;
nraFreeNext += sz;
if (nraFreeNext > nraFreeLast)
block = nraAllocNewPage(sz);
return block;
}
#endif
/*****************************************************************************/
/*****************************************************************************
* If most uses of the norls_alloctor are going to be non-simultaneous,
* we keep a single instance handy and preallocate 1 chunk of 64K
* Then most uses won't need to call VirtualAlloc() for the first page.
*/
#if defined(DEBUG)
inline bool norls_allocator::nraDirectAlloc()
{
// When JitDirectAlloc is set, all JIT allocations requests are forwarded
// directly to the OS. This allows taking advantage of pageheap and other gflag
// knobs for ensuring that we do not have buffer overruns in the JIT.
return JitConfig.JitDirectAlloc() != 0;
}
#else // RELEASE
inline bool norls_allocator::nraDirectAlloc()
{
return false;
}
#endif
extern size_t THE_ALLOCATOR_BASE_SIZE;
void nraInitTheAllocator(); // One-time initialization
void nraTheAllocatorDone(); // One-time completion code
// returns NULL if the single instance is already in use.
// User will need to allocate a new instance of the norls_allocator
norls_allocator * nraGetTheAllocator(IEEMemoryManager* pMemoryManager);
// Should be called after we are done with the current use, so that the
// next user can reuse it, instead of allocating a new instance
void nraFreeTheAllocator();
/*****************************************************************************/
#endif // _ALLOC_H_
/*****************************************************************************/
|