OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "xfa/fgas/crt/fgas_memory.h" | 7 #include "xfa/fgas/crt/fgas_memory.h" |
8 | 8 |
| 9 #define MEMORY_TOOL_REPLACES_ALLOCATOR // Temporary, for CF testing. |
| 10 |
9 #include <algorithm> | 11 #include <algorithm> |
10 | 12 |
| 13 #ifdef MEMORY_TOOL_REPLACES_ALLOCATOR |
| 14 |
11 namespace { | 15 namespace { |
12 | 16 |
13 class CFX_DefStore : public IFX_MEMAllocator, public CFX_Target { | 17 class CFX_DefStore : public IFX_MemoryAllocator, public CFX_Target { |
14 public: | 18 public: |
15 CFX_DefStore() {} | 19 CFX_DefStore() {} |
16 ~CFX_DefStore() {} | 20 ~CFX_DefStore() {} |
17 virtual void Release() { delete this; } | 21 virtual void Release() { delete this; } |
18 virtual void* Alloc(size_t size) { return FX_Alloc(uint8_t, size); } | 22 virtual void* Alloc(size_t size) { return FX_Alloc(uint8_t, size); } |
19 virtual void Free(void* pBlock) { FX_Free(pBlock); } | 23 virtual void Free(void* pBlock) { FX_Free(pBlock); } |
20 virtual size_t GetBlockSize() const { return 0; } | |
21 virtual size_t GetDefChunkSize() const { return 0; } | |
22 virtual size_t SetDefChunkSize(size_t size) { return 0; } | |
23 virtual size_t GetCurrentDataSize() const { return 0; } | |
24 }; | 24 }; |
25 | 25 |
26 #if _FX_OS_ != _FX_ANDROID_ | 26 } // namespace |
27 #pragma pack(push, 1) | 27 |
28 #endif | 28 IFX_MemoryAllocator* IFX_MemoryAllocator::Create(FX_ALLOCTYPE eType, |
| 29 size_t chunkSize, |
| 30 size_t blockSize) { |
| 31 return new CFX_DefStore(); |
| 32 } |
| 33 |
| 34 #else // MEMORY_TOOL_REPLACES_ALLOCATOR |
| 35 |
| 36 namespace { |
| 37 |
29 struct FX_STATICSTORECHUNK { | 38 struct FX_STATICSTORECHUNK { |
30 FX_STATICSTORECHUNK* pNextChunk; | 39 FX_STATICSTORECHUNK* pNextChunk; |
31 size_t iChunkSize; | 40 size_t iChunkSize; |
32 size_t iFreeSize; | 41 size_t iFreeSize; |
33 }; | 42 }; |
34 #if _FX_OS_ != _FX_ANDROID_ | |
35 #pragma pack(pop) | |
36 #endif | |
37 | 43 |
38 class CFX_StaticStore : public IFX_MEMAllocator, public CFX_Target { | 44 class CFX_StaticStore : public IFX_MemoryAllocator, public CFX_Target { |
39 public: | 45 public: |
40 CFX_StaticStore(size_t iDefChunkSize = 4096); | 46 CFX_StaticStore(size_t iDefChunkSize = 4096); |
41 ~CFX_StaticStore(); | 47 ~CFX_StaticStore(); |
42 virtual void Release() { delete this; } | 48 virtual void Release() { delete this; } |
43 virtual void* Alloc(size_t size); | 49 virtual void* Alloc(size_t size); |
44 virtual void Free(void* pBlock) {} | 50 virtual void Free(void* pBlock) {} |
45 virtual size_t GetBlockSize() const { return 0; } | |
46 virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; } | |
47 virtual size_t SetDefChunkSize(size_t size); | |
48 virtual size_t GetCurrentDataSize() const { return m_iAllocatedSize; } | |
49 | 51 |
50 protected: | 52 protected: |
51 size_t m_iAllocatedSize; | 53 size_t m_iAllocatedSize; |
52 size_t m_iDefChunkSize; | 54 size_t m_iDefChunkSize; |
53 FX_STATICSTORECHUNK* m_pChunk; | 55 FX_STATICSTORECHUNK* m_pChunk; |
54 FX_STATICSTORECHUNK* m_pLastChunk; | 56 FX_STATICSTORECHUNK* m_pLastChunk; |
55 FX_STATICSTORECHUNK* AllocChunk(size_t size); | 57 FX_STATICSTORECHUNK* AllocChunk(size_t size); |
56 FX_STATICSTORECHUNK* FindChunk(size_t size); | 58 FX_STATICSTORECHUNK* FindChunk(size_t size); |
57 }; | 59 }; |
58 | 60 |
59 #if _FX_OS_ != _FX_ANDROID_ | |
60 #pragma pack(push, 1) | |
61 #endif | |
62 struct FX_FIXEDSTORECHUNK { | 61 struct FX_FIXEDSTORECHUNK { |
63 uint8_t* FirstFlag() { return reinterpret_cast<uint8_t*>(this + 1); } | 62 uint8_t* FirstFlag() { return reinterpret_cast<uint8_t*>(this + 1); } |
64 uint8_t* FirstBlock() { return FirstFlag() + iChunkSize; } | 63 uint8_t* FirstBlock() { return FirstFlag() + iChunkSize; } |
65 | 64 |
66 FX_FIXEDSTORECHUNK* pNextChunk; | 65 FX_FIXEDSTORECHUNK* pNextChunk; |
67 size_t iChunkSize; | 66 size_t iChunkSize; |
68 size_t iFreeNum; | 67 size_t iFreeNum; |
69 }; | 68 }; |
70 #if _FX_OS_ != _FX_ANDROID_ | |
71 #pragma pack(pop) | |
72 #endif | |
73 | 69 |
74 class CFX_FixedStore : public IFX_MEMAllocator, public CFX_Target { | 70 class CFX_FixedStore : public IFX_MemoryAllocator, public CFX_Target { |
75 public: | 71 public: |
76 CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk); | 72 CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk); |
77 virtual ~CFX_FixedStore(); | 73 virtual ~CFX_FixedStore(); |
78 virtual void Release() { delete this; } | 74 virtual void Release() { delete this; } |
79 virtual void* Alloc(size_t size); | 75 virtual void* Alloc(size_t size); |
80 virtual void Free(void* pBlock); | 76 virtual void Free(void* pBlock); |
81 virtual size_t GetBlockSize() const { return m_iBlockSize; } | |
82 virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; } | |
83 virtual size_t SetDefChunkSize(size_t iChunkSize); | |
84 virtual size_t GetCurrentDataSize() const { return 0; } | |
85 | 77 |
86 protected: | 78 protected: |
87 FX_FIXEDSTORECHUNK* AllocChunk(); | 79 FX_FIXEDSTORECHUNK* AllocChunk(); |
88 | 80 |
89 size_t m_iBlockSize; | 81 size_t m_iBlockSize; |
90 size_t m_iDefChunkSize; | 82 size_t m_iDefChunkSize; |
91 FX_FIXEDSTORECHUNK* m_pChunk; | 83 FX_FIXEDSTORECHUNK* m_pChunk; |
92 }; | 84 }; |
93 | 85 |
94 #if _FX_OS_ != _FX_ANDROID_ | |
95 #pragma pack(push, 1) | |
96 #endif | |
97 struct FX_DYNAMICSTOREBLOCK { | |
98 uint8_t* Data() { return reinterpret_cast<uint8_t*>(this + 1); } | |
99 FX_DYNAMICSTOREBLOCK* NextBlock() { | |
100 return reinterpret_cast<FX_DYNAMICSTOREBLOCK*>(Data() + iBlockSize); | |
101 } | |
102 size_t iBlockSize; | |
103 FX_BOOL bUsed; | |
104 }; | |
105 | |
106 struct FX_DYNAMICSTORECHUNK { | |
107 FX_DYNAMICSTOREBLOCK* FirstBlock() { | |
108 return reinterpret_cast<FX_DYNAMICSTOREBLOCK*>(this + 1); | |
109 } | |
110 FX_DYNAMICSTORECHUNK* pNextChunk; | |
111 size_t iChunkSize; | |
112 size_t iFreeSize; | |
113 }; | |
114 #if _FX_OS_ != _FX_ANDROID_ | |
115 #pragma pack(pop) | |
116 #endif | |
117 | |
118 class CFX_DynamicStore : public IFX_MEMAllocator, public CFX_Target { | |
119 public: | |
120 CFX_DynamicStore(size_t iDefChunkSize = 4096); | |
121 virtual ~CFX_DynamicStore(); | |
122 virtual void Release() { delete this; } | |
123 virtual void* Alloc(size_t size); | |
124 virtual void Free(void* pBlock); | |
125 virtual size_t GetBlockSize() const { return 0; } | |
126 virtual size_t GetDefChunkSize() const { return m_iDefChunkSize; } | |
127 virtual size_t SetDefChunkSize(size_t size); | |
128 virtual size_t GetCurrentDataSize() const { return 0; } | |
129 | |
130 protected: | |
131 FX_DYNAMICSTORECHUNK* AllocChunk(size_t size); | |
132 | |
133 size_t m_iDefChunkSize; | |
134 FX_DYNAMICSTORECHUNK* m_pChunk; | |
135 }; | |
136 | |
137 } // namespace | 86 } // namespace |
138 | 87 |
139 #define FX_4BYTEALIGN(size) (((size) + 3) / 4 * 4) | 88 #define FX_4BYTEALIGN(size) (((size) + 3) & ~3) |
140 | 89 |
141 IFX_MEMAllocator* FX_CreateAllocator(FX_ALLOCTYPE eType, | 90 IFX_MemoryAllocator* IFX_MemoryAllocator::Create(FX_ALLOCTYPE eType, |
142 size_t chunkSize, | 91 size_t chunkSize, |
143 size_t blockSize) { | 92 size_t blockSize) { |
144 switch (eType) { | 93 switch (eType) { |
145 case FX_ALLOCTYPE_Dynamic: | |
146 return new CFX_DynamicStore(chunkSize); | |
147 case FX_ALLOCTYPE_Default: | |
148 return new CFX_DefStore(); | |
149 case FX_ALLOCTYPE_Static: | 94 case FX_ALLOCTYPE_Static: |
150 return new CFX_StaticStore(chunkSize); | 95 return new CFX_StaticStore(chunkSize); |
151 case FX_ALLOCTYPE_Fixed: | 96 case FX_ALLOCTYPE_Fixed: |
152 return new CFX_FixedStore(blockSize, chunkSize); | 97 return new CFX_FixedStore(blockSize, chunkSize); |
153 default: | 98 default: |
154 return NULL; | 99 ASSERT(0); |
| 100 return nullptr; |
155 } | 101 } |
156 } | 102 } |
| 103 |
157 CFX_StaticStore::CFX_StaticStore(size_t iDefChunkSize) | 104 CFX_StaticStore::CFX_StaticStore(size_t iDefChunkSize) |
158 : m_iAllocatedSize(0), | 105 : m_iAllocatedSize(0), |
159 m_iDefChunkSize(iDefChunkSize), | 106 m_iDefChunkSize(iDefChunkSize), |
160 m_pChunk(NULL), | 107 m_pChunk(nullptr), |
161 m_pLastChunk(NULL) { | 108 m_pLastChunk(nullptr) { |
162 ASSERT(m_iDefChunkSize != 0); | 109 ASSERT(m_iDefChunkSize != 0); |
163 } | 110 } |
164 CFX_StaticStore::~CFX_StaticStore() { | 111 CFX_StaticStore::~CFX_StaticStore() { |
165 FX_STATICSTORECHUNK* pChunk = m_pChunk; | 112 FX_STATICSTORECHUNK* pChunk = m_pChunk; |
166 while (pChunk) { | 113 while (pChunk) { |
167 FX_STATICSTORECHUNK* pNext = pChunk->pNextChunk; | 114 FX_STATICSTORECHUNK* pNext = pChunk->pNextChunk; |
168 FX_Free(pChunk); | 115 FX_Free(pChunk); |
169 pChunk = pNext; | 116 pChunk = pNext; |
170 } | 117 } |
171 } | 118 } |
172 FX_STATICSTORECHUNK* CFX_StaticStore::AllocChunk(size_t size) { | 119 FX_STATICSTORECHUNK* CFX_StaticStore::AllocChunk(size_t size) { |
173 ASSERT(size != 0); | 120 ASSERT(size != 0); |
174 FX_STATICSTORECHUNK* pChunk = (FX_STATICSTORECHUNK*)FX_Alloc( | 121 FX_STATICSTORECHUNK* pChunk = (FX_STATICSTORECHUNK*)FX_Alloc( |
175 uint8_t, sizeof(FX_STATICSTORECHUNK) + size); | 122 uint8_t, sizeof(FX_STATICSTORECHUNK) + size); |
176 pChunk->iChunkSize = size; | 123 pChunk->iChunkSize = size; |
177 pChunk->iFreeSize = size; | 124 pChunk->iFreeSize = size; |
178 pChunk->pNextChunk = NULL; | 125 pChunk->pNextChunk = nullptr; |
179 if (m_pLastChunk == NULL) { | 126 if (!m_pLastChunk) { |
180 m_pChunk = pChunk; | 127 m_pChunk = pChunk; |
181 } else { | 128 } else { |
182 m_pLastChunk->pNextChunk = pChunk; | 129 m_pLastChunk->pNextChunk = pChunk; |
183 } | 130 } |
184 m_pLastChunk = pChunk; | 131 m_pLastChunk = pChunk; |
185 return pChunk; | 132 return pChunk; |
186 } | 133 } |
187 FX_STATICSTORECHUNK* CFX_StaticStore::FindChunk(size_t size) { | 134 FX_STATICSTORECHUNK* CFX_StaticStore::FindChunk(size_t size) { |
188 ASSERT(size != 0); | 135 ASSERT(size != 0); |
189 if (m_pLastChunk == NULL || m_pLastChunk->iFreeSize < size) { | 136 if (!m_pLastChunk || m_pLastChunk->iFreeSize < size) { |
190 return AllocChunk(std::max(m_iDefChunkSize, size)); | 137 return AllocChunk(std::max(m_iDefChunkSize, size)); |
191 } | 138 } |
192 return m_pLastChunk; | 139 return m_pLastChunk; |
193 } | 140 } |
194 void* CFX_StaticStore::Alloc(size_t size) { | 141 void* CFX_StaticStore::Alloc(size_t size) { |
195 size = FX_4BYTEALIGN(size); | 142 size = FX_4BYTEALIGN(size); |
196 ASSERT(size != 0); | 143 ASSERT(size != 0); |
197 FX_STATICSTORECHUNK* pChunk = FindChunk(size); | 144 FX_STATICSTORECHUNK* pChunk = FindChunk(size); |
198 ASSERT(pChunk->iFreeSize >= size); | 145 ASSERT(pChunk->iFreeSize >= size); |
199 uint8_t* p = (uint8_t*)pChunk; | 146 uint8_t* p = (uint8_t*)pChunk; |
200 p += sizeof(FX_STATICSTORECHUNK) + pChunk->iChunkSize - pChunk->iFreeSize; | 147 p += sizeof(FX_STATICSTORECHUNK) + pChunk->iChunkSize - pChunk->iFreeSize; |
201 pChunk->iFreeSize -= size; | 148 pChunk->iFreeSize -= size; |
202 m_iAllocatedSize += size; | 149 m_iAllocatedSize += size; |
203 return p; | 150 return p; |
204 } | 151 } |
205 size_t CFX_StaticStore::SetDefChunkSize(size_t size) { | 152 size_t CFX_StaticStore::SetDefChunkSize(size_t size) { |
206 ASSERT(size != 0); | 153 ASSERT(size != 0); |
207 size_t v = m_iDefChunkSize; | 154 size_t v = m_iDefChunkSize; |
208 m_iDefChunkSize = size; | 155 m_iDefChunkSize = size; |
209 return v; | 156 return v; |
210 } | 157 } |
211 CFX_FixedStore::CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk) | 158 CFX_FixedStore::CFX_FixedStore(size_t iBlockSize, size_t iBlockNumsInChunk) |
212 : m_iBlockSize(FX_4BYTEALIGN(iBlockSize)), | 159 : m_iBlockSize(FX_4BYTEALIGN(iBlockSize)), |
213 m_iDefChunkSize(FX_4BYTEALIGN(iBlockNumsInChunk)), | 160 m_iDefChunkSize(FX_4BYTEALIGN(iBlockNumsInChunk)), |
214 m_pChunk(NULL) { | 161 m_pChunk(nullptr) { |
215 ASSERT(m_iBlockSize != 0 && m_iDefChunkSize != 0); | 162 ASSERT(m_iBlockSize != 0 && m_iDefChunkSize != 0); |
216 } | 163 } |
217 CFX_FixedStore::~CFX_FixedStore() { | 164 CFX_FixedStore::~CFX_FixedStore() { |
218 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; | 165 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; |
219 while (pChunk) { | 166 while (pChunk) { |
220 FX_FIXEDSTORECHUNK* pNext = pChunk->pNextChunk; | 167 FX_FIXEDSTORECHUNK* pNext = pChunk->pNextChunk; |
221 FX_Free(pChunk); | 168 FX_Free(pChunk); |
222 pChunk = pNext; | 169 pChunk = pNext; |
223 } | 170 } |
224 } | 171 } |
225 FX_FIXEDSTORECHUNK* CFX_FixedStore::AllocChunk() { | 172 FX_FIXEDSTORECHUNK* CFX_FixedStore::AllocChunk() { |
226 int32_t iTotalSize = sizeof(FX_FIXEDSTORECHUNK) + m_iDefChunkSize + | 173 int32_t iTotalSize = sizeof(FX_FIXEDSTORECHUNK) + m_iDefChunkSize + |
227 m_iBlockSize * m_iDefChunkSize; | 174 m_iBlockSize * m_iDefChunkSize; |
228 FX_FIXEDSTORECHUNK* pChunk = | 175 FX_FIXEDSTORECHUNK* pChunk = |
229 (FX_FIXEDSTORECHUNK*)FX_Alloc(uint8_t, iTotalSize); | 176 (FX_FIXEDSTORECHUNK*)FX_Alloc(uint8_t, iTotalSize); |
230 if (pChunk == NULL) { | 177 if (!pChunk) |
231 return NULL; | 178 return nullptr; |
232 } | 179 |
233 FXSYS_memset(pChunk->FirstFlag(), 0, m_iDefChunkSize); | 180 FXSYS_memset(pChunk->FirstFlag(), 0, m_iDefChunkSize); |
234 pChunk->pNextChunk = m_pChunk; | 181 pChunk->pNextChunk = m_pChunk; |
235 pChunk->iChunkSize = m_iDefChunkSize; | 182 pChunk->iChunkSize = m_iDefChunkSize; |
236 pChunk->iFreeNum = m_iDefChunkSize; | 183 pChunk->iFreeNum = m_iDefChunkSize; |
237 m_pChunk = pChunk; | 184 m_pChunk = pChunk; |
238 return pChunk; | 185 return pChunk; |
239 } | 186 } |
240 void* CFX_FixedStore::Alloc(size_t size) { | 187 void* CFX_FixedStore::Alloc(size_t size) { |
241 if (size > m_iBlockSize) { | 188 if (size > m_iBlockSize) { |
242 return NULL; | 189 return nullptr; |
243 } | 190 } |
244 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; | 191 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; |
245 while (pChunk != NULL) { | 192 while (pChunk) { |
246 if (pChunk->iFreeNum > 0) { | 193 if (pChunk->iFreeNum > 0) { |
247 break; | 194 break; |
248 } | 195 } |
249 pChunk = pChunk->pNextChunk; | 196 pChunk = pChunk->pNextChunk; |
250 } | 197 } |
251 if (pChunk == NULL) { | 198 if (!pChunk) { |
252 pChunk = AllocChunk(); | 199 pChunk = AllocChunk(); |
253 } | 200 } |
254 ASSERT(pChunk != NULL); | |
255 uint8_t* pFlags = pChunk->FirstFlag(); | 201 uint8_t* pFlags = pChunk->FirstFlag(); |
256 size_t i = 0; | 202 size_t i = 0; |
257 for (; i < pChunk->iChunkSize; i++) | 203 for (; i < pChunk->iChunkSize; i++) |
258 if (pFlags[i] == 0) { | 204 if (pFlags[i] == 0) { |
259 break; | 205 break; |
260 } | 206 } |
261 ASSERT(i < pChunk->iChunkSize); | 207 ASSERT(i < pChunk->iChunkSize); |
262 pFlags[i] = 1; | 208 pFlags[i] = 1; |
263 pChunk->iFreeNum--; | 209 pChunk->iFreeNum--; |
264 return pChunk->FirstBlock() + i * m_iBlockSize; | 210 return pChunk->FirstBlock() + i * m_iBlockSize; |
265 } | 211 } |
266 void CFX_FixedStore::Free(void* pBlock) { | 212 void CFX_FixedStore::Free(void* pBlock) { |
267 ASSERT(pBlock != NULL); | 213 FX_FIXEDSTORECHUNK* pPrior = nullptr; |
268 FX_FIXEDSTORECHUNK* pPrior = NULL; | |
269 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; | 214 FX_FIXEDSTORECHUNK* pChunk = m_pChunk; |
270 uint8_t* pStart = NULL; | 215 uint8_t* pStart = nullptr; |
271 uint8_t* pEnd; | 216 uint8_t* pEnd; |
272 while (pChunk != NULL) { | 217 while (pChunk) { |
273 pStart = pChunk->FirstBlock(); | 218 pStart = pChunk->FirstBlock(); |
274 if (pBlock >= pStart) { | 219 if (pBlock >= pStart) { |
275 pEnd = pStart + m_iBlockSize * pChunk->iChunkSize; | 220 pEnd = pStart + m_iBlockSize * pChunk->iChunkSize; |
276 if (pBlock < pEnd) { | 221 if (pBlock < pEnd) { |
277 break; | 222 break; |
278 } | 223 } |
279 } | 224 } |
280 pPrior = pChunk, pChunk = pChunk->pNextChunk; | 225 pPrior = pChunk, pChunk = pChunk->pNextChunk; |
281 } | 226 } |
282 ASSERT(pChunk != NULL); | 227 ASSERT(pChunk); |
283 size_t iPos = ((uint8_t*)pBlock - pStart) / m_iBlockSize; | 228 size_t iPos = ((uint8_t*)pBlock - pStart) / m_iBlockSize; |
284 ASSERT(iPos < pChunk->iChunkSize); | 229 ASSERT(iPos < pChunk->iChunkSize); |
285 uint8_t* pFlags = pChunk->FirstFlag(); | 230 uint8_t* pFlags = pChunk->FirstFlag(); |
286 if (pFlags[iPos] == 0) { | 231 if (pFlags[iPos] == 0) { |
287 return; | 232 return; |
288 } | 233 } |
289 pFlags[iPos] = 0; | 234 pFlags[iPos] = 0; |
290 pChunk->iFreeNum++; | 235 pChunk->iFreeNum++; |
291 if (pChunk->iFreeNum == pChunk->iChunkSize) { | 236 if (pChunk->iFreeNum == pChunk->iChunkSize) { |
292 if (pPrior == NULL) { | 237 if (!pPrior) { |
293 m_pChunk = pChunk->pNextChunk; | 238 m_pChunk = pChunk->pNextChunk; |
294 } else { | 239 } else { |
295 pPrior->pNextChunk = pChunk->pNextChunk; | 240 pPrior->pNextChunk = pChunk->pNextChunk; |
296 } | 241 } |
297 FX_Free(pChunk); | 242 FX_Free(pChunk); |
298 } | 243 } |
299 } | 244 } |
300 size_t CFX_FixedStore::SetDefChunkSize(size_t iChunkSize) { | 245 size_t CFX_FixedStore::SetDefChunkSize(size_t iChunkSize) { |
301 ASSERT(iChunkSize != 0); | 246 ASSERT(iChunkSize != 0); |
302 size_t v = m_iDefChunkSize; | 247 size_t v = m_iDefChunkSize; |
303 m_iDefChunkSize = FX_4BYTEALIGN(iChunkSize); | 248 m_iDefChunkSize = FX_4BYTEALIGN(iChunkSize); |
304 return v; | 249 return v; |
305 } | 250 } |
306 CFX_DynamicStore::CFX_DynamicStore(size_t iDefChunkSize) | 251 |
307 : m_iDefChunkSize(iDefChunkSize), m_pChunk(NULL) { | 252 #endif // MEMORY_TOOL_REPLACES_ALLOCATOR |
308 ASSERT(m_iDefChunkSize != 0); | |
309 } | |
310 CFX_DynamicStore::~CFX_DynamicStore() { | |
311 FX_DYNAMICSTORECHUNK* pChunk = m_pChunk; | |
312 while (pChunk) { | |
313 FX_DYNAMICSTORECHUNK* pNext = pChunk->pNextChunk; | |
314 FX_Free(pChunk); | |
315 pChunk = pNext; | |
316 } | |
317 } | |
318 FX_DYNAMICSTORECHUNK* CFX_DynamicStore::AllocChunk(size_t size) { | |
319 ASSERT(size != 0); | |
320 FX_DYNAMICSTORECHUNK* pChunk = (FX_DYNAMICSTORECHUNK*)FX_Alloc( | |
321 uint8_t, | |
322 sizeof(FX_DYNAMICSTORECHUNK) + sizeof(FX_DYNAMICSTOREBLOCK) * 2 + size); | |
323 if (pChunk == NULL) { | |
324 return NULL; | |
325 } | |
326 pChunk->iChunkSize = size; | |
327 pChunk->iFreeSize = size; | |
328 FX_DYNAMICSTOREBLOCK* pBlock = pChunk->FirstBlock(); | |
329 pBlock->iBlockSize = size; | |
330 pBlock->bUsed = FALSE; | |
331 pBlock = pBlock->NextBlock(); | |
332 pBlock->iBlockSize = 0; | |
333 pBlock->bUsed = TRUE; | |
334 if (m_pChunk != NULL && size >= m_iDefChunkSize) { | |
335 FX_DYNAMICSTORECHUNK* pLast = m_pChunk; | |
336 while (pLast->pNextChunk != NULL) { | |
337 pLast = pLast->pNextChunk; | |
338 } | |
339 pLast->pNextChunk = pChunk; | |
340 pChunk->pNextChunk = NULL; | |
341 } else { | |
342 pChunk->pNextChunk = m_pChunk; | |
343 m_pChunk = pChunk; | |
344 } | |
345 return pChunk; | |
346 } | |
347 void* CFX_DynamicStore::Alloc(size_t size) { | |
348 size = FX_4BYTEALIGN(size); | |
349 ASSERT(size != 0); | |
350 FX_DYNAMICSTORECHUNK* pChunk = m_pChunk; | |
351 FX_DYNAMICSTOREBLOCK* pBlock = NULL; | |
352 while (pChunk != NULL) { | |
353 if (pChunk->iFreeSize >= size) { | |
354 pBlock = pChunk->FirstBlock(); | |
355 FX_BOOL bFind = FALSE; | |
356 while (pBlock->iBlockSize != 0) { | |
357 if (!pBlock->bUsed && pBlock->iBlockSize >= size) { | |
358 bFind = TRUE; | |
359 break; | |
360 } | |
361 pBlock = pBlock->NextBlock(); | |
362 } | |
363 if (bFind) { | |
364 break; | |
365 } | |
366 } | |
367 pChunk = pChunk->pNextChunk; | |
368 } | |
369 if (pChunk == NULL) { | |
370 pChunk = AllocChunk(std::max(m_iDefChunkSize, size)); | |
371 pBlock = pChunk->FirstBlock(); | |
372 } | |
373 ASSERT(pChunk != NULL && pBlock != NULL); | |
374 size_t m = size + sizeof(FX_DYNAMICSTOREBLOCK); | |
375 pBlock->bUsed = TRUE; | |
376 if (pBlock->iBlockSize > m) { | |
377 size_t n = pBlock->iBlockSize; | |
378 pBlock->iBlockSize = size; | |
379 FX_DYNAMICSTOREBLOCK* pNextBlock = pBlock->NextBlock(); | |
380 pNextBlock->bUsed = FALSE; | |
381 pNextBlock->iBlockSize = n - size - sizeof(FX_DYNAMICSTOREBLOCK); | |
382 pChunk->iFreeSize -= size + sizeof(FX_DYNAMICSTOREBLOCK); | |
383 } else { | |
384 pChunk->iFreeSize -= pBlock->iBlockSize; | |
385 } | |
386 return pBlock->Data(); | |
387 } | |
388 void CFX_DynamicStore::Free(void* pBlock) { | |
389 ASSERT(pBlock != NULL); | |
390 FX_DYNAMICSTORECHUNK* pPriorChunk = NULL; | |
391 FX_DYNAMICSTORECHUNK* pChunk = m_pChunk; | |
392 while (pChunk != NULL) { | |
393 if (pBlock > pChunk && | |
394 pBlock <= ((uint8_t*)pChunk + sizeof(FX_DYNAMICSTORECHUNK) + | |
395 pChunk->iChunkSize)) { | |
396 break; | |
397 } | |
398 pPriorChunk = pChunk, pChunk = pChunk->pNextChunk; | |
399 } | |
400 ASSERT(pChunk != NULL); | |
401 FX_DYNAMICSTOREBLOCK* pPriorBlock = NULL; | |
402 FX_DYNAMICSTOREBLOCK* pFindBlock = pChunk->FirstBlock(); | |
403 while (pFindBlock->iBlockSize != 0) { | |
404 if (pBlock == (void*)pFindBlock->Data()) { | |
405 break; | |
406 } | |
407 pPriorBlock = pFindBlock; | |
408 pFindBlock = pFindBlock->NextBlock(); | |
409 } | |
410 ASSERT(pFindBlock->iBlockSize != 0 && pFindBlock->bUsed && | |
411 pBlock == (void*)pFindBlock->Data()); | |
412 pFindBlock->bUsed = FALSE; | |
413 pChunk->iFreeSize += pFindBlock->iBlockSize; | |
414 if (pPriorBlock == NULL) { | |
415 pPriorBlock = pChunk->FirstBlock(); | |
416 } else if (pPriorBlock->bUsed) { | |
417 pPriorBlock = pFindBlock; | |
418 } | |
419 pFindBlock = pPriorBlock; | |
420 size_t sizeFree = 0; | |
421 size_t sizeBlock = 0; | |
422 while (pFindBlock->iBlockSize != 0 && !pFindBlock->bUsed) { | |
423 if (pFindBlock != pPriorBlock) { | |
424 sizeFree += sizeof(FX_DYNAMICSTOREBLOCK); | |
425 sizeBlock += sizeof(FX_DYNAMICSTOREBLOCK); | |
426 } | |
427 sizeBlock += pFindBlock->iBlockSize; | |
428 pFindBlock = pFindBlock->NextBlock(); | |
429 } | |
430 pPriorBlock->iBlockSize = sizeBlock; | |
431 pChunk->iFreeSize += sizeFree; | |
432 if (pChunk->iFreeSize == pChunk->iChunkSize) { | |
433 if (pPriorChunk == NULL) { | |
434 m_pChunk = pChunk->pNextChunk; | |
435 } else { | |
436 pPriorChunk->pNextChunk = pChunk->pNextChunk; | |
437 } | |
438 FX_Free(pChunk); | |
439 } | |
440 } | |
441 size_t CFX_DynamicStore::SetDefChunkSize(size_t size) { | |
442 ASSERT(size != 0); | |
443 size_t v = m_iDefChunkSize; | |
444 m_iDefChunkSize = size; | |
445 return v; | |
446 } | |
OLD | NEW |