-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathAlloc.cpp
172 lines (157 loc) · 4.86 KB
/
Alloc.cpp
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
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "ParserPch.h"
#if DEBUG
#define DEBUG_TRASHMEM(pv, cb) memset(pv, 0xbc, cb)
#else
#define DEBUG_TRASHMEM
#endif //DEBUG
#if TARGET_64
struct __ALIGN_FOO__ {
int w1;
double dbl;
};
#define ALIGN_FULL (offsetof(__ALIGN_FOO__, dbl))
#else
// Force check for 4 byte alignment to support Win98/ME
#define ALIGN_FULL 4
#endif // TARGET_64
#define AlignFull(VALUE) (~(~((VALUE) + (ALIGN_FULL-1)) | (ALIGN_FULL-1)))
NoReleaseAllocator::NoReleaseAllocator(int32 cbFirst, int32 cbMax)
: m_pblkList(NULL)
, m_ibCur(0)
, m_ibMax(0)
, m_cbMinBlock(cbFirst)
, m_cbMaxBlock(cbMax)
#if DEBUG
, m_cbTotRequested(0)
, m_cbTotAlloced(0)
, m_cblk(0)
, m_cpvBig(0)
, m_cpvSmall(0)
#endif
{
// require reasonable ranges
Assert((0 < cbFirst) && (cbFirst < SHRT_MAX/2));
Assert((0 < cbMax ) && (cbMax < SHRT_MAX));
}
void * NoReleaseAllocator::Alloc(int32 cb)
{
Assert(cb > 0);
if (cb <= 0)
return NULL;
const int32 kcbHead = AlignFull(sizeof(NoReleaseAllocator::NraBlock));
void * pv;
if (cb > m_ibMax - m_ibCur)
{
int32 cbBlock;
int32 cbAlloc;
NraBlock * pblk;
if (cb >= m_cbMaxBlock)
{
// check for integer overflow before allocating (See WindowsSE #88972)
cbAlloc = cb + kcbHead;
if (cbAlloc < cb)
{
Assert(FALSE); // too big!
return NULL;
}
// create a chunk just for this allocation
pblk = (NraBlock *)malloc(cbAlloc);
if (NULL == pblk)
return NULL;
#if DEBUG
m_cbTotAlloced += cbAlloc;
m_cbTotRequested += cb;
m_cpvBig++;
m_cblk++;
#endif //DEBUG
if (m_ibCur < m_ibMax)
{
// There is still room in current block, so put the new block
// after the current block.
pblk->pblkNext = m_pblkList->pblkNext;
m_pblkList->pblkNext = pblk;
}
else
{
// Link into front of the list.
// Don't need to adjust m_ibCur and m_ibMax, because they
// already have the correct relationship for this full block
// (m_ibCur >= m_ibMax) and the actual values will not be
// used.
pblk->pblkNext = m_pblkList;
m_pblkList = pblk;
}
DEBUG_TRASHMEM((byte *)pblk + kcbHead, cb);
return (byte *)pblk + kcbHead;
}
cbBlock = cb; // requested size
if (m_ibMax > cbBlock) // at least current block size
cbBlock = m_ibMax;
cbBlock += cbBlock; // *2 (can overflow, but checked below)
if (m_cbMinBlock > cbBlock) // at least minimum size
cbBlock = m_cbMinBlock;
if (cbBlock > m_cbMaxBlock) // no larger than the max
cbBlock = m_cbMaxBlock;
if (cb > cbBlock) // guarantee it's big enough
{
Assert(("Request too large", FALSE));
return NULL;
}
// check for integer overflow before allocating (See WindowsSE #88972)
cbAlloc = cbBlock + kcbHead;
if ((cbAlloc < cbBlock) || (cbAlloc < cb))
{
Assert(FALSE); // too big!
return NULL ;
}
// allocate a new block
pblk = (NraBlock *)malloc(cbAlloc);
#ifdef MEM_TRACK
RegisterAlloc((char*)pblk,cbAlloc);
#endif
if (NULL == pblk)
return NULL;
#if DEBUG
m_cbTotAlloced += cbAlloc;
m_cblk++;
#endif //DEBUG
pblk->pblkNext = m_pblkList;
m_pblkList = pblk;
m_ibMax = cbBlock;
m_ibCur = 0;
}
Assert(m_ibCur + cb <= m_ibMax);
#if DEBUG
m_cbTotRequested += cb;
m_cpvSmall++;
#endif //DEBUG
pv = (byte *)m_pblkList + kcbHead + m_ibCur;
DEBUG_TRASHMEM(pv, cb);
m_ibCur += (int32)AlignFull(cb);
Assert(m_ibCur >= 0);
return pv;
}
void NoReleaseAllocator::FreeAll(void)
{
// Free all of the allocated blocks
while (NULL != m_pblkList)
{
NraBlock * pblk = m_pblkList;
#pragma prefast(suppress:6001, "Not sure why it is complaining *m_plkList is uninitialized")
m_pblkList = pblk->pblkNext;
free(pblk);
}
// prepare for next round of allocations
m_ibCur = m_ibMax = 0;
#if DEBUG
m_cbTotRequested = 0;
m_cbTotAlloced = 0;
m_cblk = 0;
m_cpvBig = 0;
m_cpvSmall = 0;
#endif
}