OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "../../include/fxcrt/fx_ext.h" | |
8 #include "mem_int.h" | |
9 #ifdef _FPDFAPI_MINI_ | |
10 static FX_MEMCONFIG g_MemConfig = { | |
11 1, | |
12 5, | |
13 8, | |
14 4, | |
15 12, | |
16 8, | |
17 2, | |
18 4, | |
19 32, | |
20 64, | |
21 }; | |
22 #else | |
23 static FX_MEMCONFIG g_MemConfig = { | |
24 1, | |
25 8, | |
26 24, | |
27 8, | |
28 32, | |
29 16, | |
30 4, | |
31 8, | |
32 128, | |
33 64, | |
34 }; | |
35 #endif | |
36 void FXMEM_SetConfig(const FX_MEMCONFIG* memConfig) | |
37 { | |
38 g_MemConfig = *memConfig; | |
39 } | |
40 #ifdef __cplusplus | |
41 extern "C" { | |
42 #endif | |
43 static void* FixedAlloc(FXMEM_SystemMgr* pMgr, size_t size, int flags) | |
44 { | |
45 return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size); | |
46 } | |
47 static void* FixedAllocDebug(FXMEM_SystemMgr* pMgr, size_t size, int flags, FX_L
PCSTR file, int line) | |
48 { | |
49 return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size); | |
50 } | |
51 static void* FixedRealloc(FXMEM_SystemMgr* pMgr, void* pointer, size_t size, int
flags) | |
52 { | |
53 return ((CFXMEM_FixedMgr*)pMgr->user)->Realloc(pointer, size); | |
54 } | |
55 static void* FixedReallocDebug(FXMEM_SystemMgr* pMgr, void* pointer, size_t size
, int flags, FX_LPCSTR file, int line) | |
56 { | |
57 return ((CFXMEM_FixedMgr*)pMgr->user)->Realloc(pointer, size); | |
58 } | |
59 static void FixedFree(FXMEM_SystemMgr* pMgr, void* pointer, int flags) | |
60 { | |
61 ((CFXMEM_FixedMgr*)pMgr->user)->Free(pointer); | |
62 } | |
63 static void FixedPurge(FXMEM_SystemMgr* pMgr) | |
64 { | |
65 ((CFXMEM_FixedMgr*)pMgr->user)->Purge(); | |
66 } | |
67 static void FixedCollectAll(FXMEM_SystemMgr* pMgr) | |
68 { | |
69 ((CFXMEM_FixedMgr*)pMgr->user)->FreeAll(); | |
70 } | |
71 #define FIXEDMEM_MINIMUMSIZE (1024 * 1024 * 8) | |
72 FXMEM_FoxitMgr* FXMEM_CreateMemoryMgr(size_t size, FX_BOOL extensible) | |
73 { | |
74 if (size < FIXEDMEM_MINIMUMSIZE) { | |
75 size = FIXEDMEM_MINIMUMSIZE; | |
76 } | |
77 FX_LPVOID pMemory = malloc(size); | |
78 if (!pMemory) { | |
79 return NULL; | |
80 } | |
81 CFixedMgr_Proxy* pProxy = (CFixedMgr_Proxy*)pMemory; | |
82 size_t offsetSize = (sizeof(CFixedMgr_Proxy) + 15) / 16 * 16; | |
83 FXMEM_FoxitMgr* pFoxitMgr = pProxy->Initialize((FX_LPBYTE)pProxy + offsetSiz
e, size - offsetSize, extensible); | |
84 if (!pFoxitMgr) { | |
85 free(pMemory); | |
86 return NULL; | |
87 } | |
88 g_pDefFoxitMgr = (CFX_MemoryMgr*)pFoxitMgr; | |
89 g_pDefFoxitMgr->m_pExternalMemory = pMemory; | |
90 return pFoxitMgr; | |
91 } | |
92 FXMEM_FoxitMgr* FXMEM_CreateFixedMgr(void* pMemory, size_t size, FXMEM_SystemMgr
2* pSystemMgr) | |
93 { | |
94 if (pMemory == NULL || size < FX_FIXEDMEM_PAGESIZE) { | |
95 return NULL; | |
96 } | |
97 if (!pSystemMgr && size >= FIXEDMEM_PROXYSIZE_1) { | |
98 CFixedMgr_Proxy* pProxy = (CFixedMgr_Proxy*)pMemory; | |
99 size_t offsetSize = (sizeof(CFixedMgr_Proxy) + 15) / 16 * 16; | |
100 return pProxy->Initialize((FX_LPBYTE)pProxy + offsetSize, size - offsetS
ize, FALSE); | |
101 } | |
102 CFXMEM_FixedMgr* pHeader = (CFXMEM_FixedMgr*)pMemory; | |
103 pHeader->Initialize(size); | |
104 pHeader->m_pExtender = pSystemMgr; | |
105 CFX_MemoryMgr* p = (CFX_MemoryMgr*)pHeader->Alloc(sizeof(CFX_MemoryMgr)); | |
106 if (p == NULL) { | |
107 return NULL; | |
108 } | |
109 p->Init(&pHeader->m_SystemMgr); | |
110 return (FXMEM_FoxitMgr*)p; | |
111 } | |
112 size_t FXMEM_GetBlockSizeInFixedMgr(FXMEM_FoxitMgr* pFoxitMgr, void* ptr) | |
113 { | |
114 return pFoxitMgr ? ((CFXMEM_FixedMgr*)((CFX_MemoryMgr*)pFoxitMgr)->m_pSystem
Mgr->user)->GetSize(ptr) : 0; | |
115 } | |
116 #ifdef __cplusplus | |
117 } | |
118 #endif | |
119 const FX_MEMCONFIG g_ProxyMgr_MemConfigs[6] = { | |
120 {1, 2, 4, 0, 2, 2, 2, 0, 0, 0}, | |
121 {1, 4, 8, 0, 2, 2, 2, 0, 0, 0}, | |
122 {1, 4, 16, 4, 8, 8, 2, 1, 16, 16}, | |
123 {1, 8, 24, 4, 12, 12, 4, 2, 32, 16}, | |
124 {1, 8, 24, 8, 16, 16, 4, 2, 64, 32}, | |
125 {1, 8, 24, 8, 24, 32, 4, 2, 128, 64}, | |
126 }; | |
127 const FX_MEMCONFIG* FixedMgr_GetConfig(size_t nSize) | |
128 { | |
129 int index = 5; | |
130 if (nSize <= FIXEDMEM_PROXYSIZE_0) { | |
131 index = 0; | |
132 } else if (nSize <= FIXEDMEM_PROXYSIZE_1) { | |
133 index = 1; | |
134 } else if (nSize <= FIXEDMEM_PROXYSIZE_2) { | |
135 index = 2; | |
136 } else if (nSize <= FIXEDMEM_PROXYSIZE_3) { | |
137 index = 3; | |
138 } else if (nSize <= FIXEDMEM_PROXYSIZE_4) { | |
139 index = 4; | |
140 } | |
141 return &g_ProxyMgr_MemConfigs[index]; | |
142 } | |
143 FXMEM_FoxitMgr* CFixedMgr_Proxy::Initialize(FX_LPVOID pBuffer, size_t nSize, FX_
BOOL bExtensible) | |
144 { | |
145 FXSYS_assert(pBuffer != NULL && nSize >= FIXEDMEM_PROXYSIZE_1 - sizeof(CFixe
dMgr_Proxy)); | |
146 FXMEM_SetConfig(FixedMgr_GetConfig(nSize)); | |
147 m_SystemMgr.More = &CFixedMgr_Proxy::Common_More; | |
148 m_SystemMgr.Free = &CFixedMgr_Proxy::Common_Free; | |
149 m_pFixedPage = (CFXMEM_Page*)((FX_LPBYTE)pBuffer + FIXEDMEM_PROXYSIZE_0); | |
150 m_pFixedPage->Initialize(nSize - FIXEDMEM_PROXYSIZE_0); | |
151 m_pBuffer = pBuffer; | |
152 m_nSize = nSize; | |
153 m_bExtensible = bExtensible; | |
154 return FXMEM_CreateFixedMgr(pBuffer, FIXEDMEM_PROXYSIZE_0, &m_SystemMgr); | |
155 } | |
156 FX_BOOL CFixedMgr_Proxy::Common_More(FXMEM_SystemMgr2* pMgr, size_t alloc_size,
void** new_memory, size_t* new_size) | |
157 { | |
158 CFixedMgr_Proxy* pProxyMgr = (CFixedMgr_Proxy*)pMgr; | |
159 FXSYS_assert(pProxyMgr != NULL && pProxyMgr->m_pFixedPage != NULL); | |
160 *new_size = alloc_size; | |
161 *new_memory = pProxyMgr->m_pFixedPage->Alloc(alloc_size); | |
162 if (*new_memory == NULL && pProxyMgr->m_bExtensible) { | |
163 *new_memory = malloc(alloc_size); | |
164 } | |
165 return *new_memory != NULL; | |
166 } | |
167 void CFixedMgr_Proxy::Common_Free(FXMEM_SystemMgr2* pMgr, void* memory) | |
168 { | |
169 CFixedMgr_Proxy* pProxyMgr = (CFixedMgr_Proxy*)pMgr; | |
170 FXSYS_assert(pProxyMgr != NULL && pProxyMgr->m_pFixedPage != NULL); | |
171 if (memory > pProxyMgr->m_pBuffer && memory < (FX_LPBYTE)pProxyMgr->m_pBuffe
r + pProxyMgr->m_nSize) { | |
172 pProxyMgr->m_pFixedPage->Free(memory); | |
173 } else if (pProxyMgr->m_bExtensible) { | |
174 free(memory); | |
175 } | |
176 } | |
177 void CFXMEM_Page::Initialize(size_t size) | |
178 { | |
179 CFXMEM_Block *pFirstBlock = (CFXMEM_Block*)(this + 1); | |
180 m_nAvailSize = size - sizeof(CFXMEM_Page) - sizeof(CFXMEM_Block); | |
181 pFirstBlock->m_nBlockSize = m_nAvailSize; | |
182 pFirstBlock->m_pNextBlock = NULL; | |
183 m_AvailHead.m_nBlockSize = m_nAvailSize; | |
184 m_AvailHead.m_pNextBlock = pFirstBlock; | |
185 m_pLimitPos = (CFXMEM_Block*)((FX_LPBYTE)this + size); | |
186 } | |
187 FX_LPVOID CFXMEM_Page::Alloc(CFXMEM_Block* pPrevBlock, CFXMEM_Block* pNextBlock,
size_t size, size_t oldsize) | |
188 { | |
189 size_t gap = pNextBlock->m_nBlockSize - size; | |
190 if (gap <= 64 + sizeof(CFXMEM_Block)) { | |
191 pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock; | |
192 m_nAvailSize -= pNextBlock->m_nBlockSize; | |
193 } else { | |
194 m_nAvailSize -= size + sizeof(CFXMEM_Block); | |
195 pNextBlock->m_nBlockSize = size; | |
196 CFXMEM_Block *pNewBlock = (CFXMEM_Block*)((FX_LPBYTE)(pNextBlock + 1) +
size); | |
197 pNewBlock->m_nBlockSize = gap - sizeof(CFXMEM_Block); | |
198 pNewBlock->m_pNextBlock = pNextBlock->m_pNextBlock; | |
199 pPrevBlock->m_pNextBlock = pNewBlock; | |
200 } | |
201 return (FX_LPVOID)(pNextBlock + 1); | |
202 } | |
203 FX_LPVOID CFXMEM_Page::Alloc(size_t size) | |
204 { | |
205 size_t oldsize = size; | |
206 #if _FX_WORDSIZE_ == _FX_W64_ | |
207 size = (size + 31) / 32 * 32; | |
208 #else | |
209 size = (size + 7) / 8 * 8; | |
210 #endif | |
211 if (m_nAvailSize < size) { | |
212 return NULL; | |
213 } | |
214 CFXMEM_Block *pNextBlock; | |
215 CFXMEM_Block *pPrevBlock = &m_AvailHead; | |
216 while (TRUE) { | |
217 pNextBlock = pPrevBlock->m_pNextBlock; | |
218 if (!pNextBlock) { | |
219 return NULL; | |
220 } | |
221 if (pNextBlock->m_nBlockSize >= size) { | |
222 break; | |
223 } | |
224 pPrevBlock = pNextBlock; | |
225 } | |
226 return Alloc(pPrevBlock, pNextBlock, size, oldsize); | |
227 } | |
228 FX_LPVOID CFXMEM_Page::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize) | |
229 { | |
230 FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos); | |
231 size_t oldnewSize = newSize; | |
232 #if _FX_WORDSIZE_ == _FX_W64_ | |
233 newSize = (newSize + 31) / 32 * 32; | |
234 #else | |
235 newSize = (newSize + 7) / 8 * 8; | |
236 #endif | |
237 CFXMEM_Block *pPrevBlock = &m_AvailHead; | |
238 CFXMEM_Block *pNextBlock, *pPrevPrev; | |
239 CFXMEM_Block *pBlock = (CFXMEM_Block*)p - 1; | |
240 pPrevPrev = NULL; | |
241 while (TRUE) { | |
242 pNextBlock = pPrevBlock->m_pNextBlock; | |
243 if (pNextBlock == NULL || pNextBlock > pBlock) { | |
244 break; | |
245 } | |
246 if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)(p
PrevBlock + 1) + pPrevBlock->m_nBlockSize) { | |
247 m_nAvailSize += sizeof(CFXMEM_Block); | |
248 pPrevBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM
_Block); | |
249 pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock; | |
250 } else { | |
251 pPrevPrev = pPrevBlock; | |
252 pPrevBlock = pNextBlock; | |
253 } | |
254 } | |
255 if (pNextBlock) { | |
256 CFXMEM_Block* pCurBlock = pNextBlock->m_pNextBlock; | |
257 while ((FX_LPBYTE)pCurBlock == (FX_LPBYTE)(pNextBlock + 1) + pNextBlock-
>m_nBlockSize) { | |
258 m_nAvailSize += sizeof(CFXMEM_Block); | |
259 pNextBlock->m_nBlockSize += pCurBlock->m_nBlockSize + sizeof(CFXMEM_
Block); | |
260 pCurBlock = pCurBlock->m_pNextBlock; | |
261 pNextBlock->m_pNextBlock = pCurBlock; | |
262 } | |
263 } | |
264 size_t size = 0; | |
265 FX_DWORD dwFlags = 0; | |
266 if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pBlock == (FX_LPBYTE)(pPrevBloc
k + 1) + pPrevBlock->m_nBlockSize) { | |
267 size += pPrevBlock->m_nBlockSize + oldSize + sizeof(CFXMEM_Block); | |
268 dwFlags |= 0x10; | |
269 } | |
270 if (pNextBlock && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)p + oldSize) { | |
271 size += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block); | |
272 dwFlags |= 0x01; | |
273 } | |
274 if (size >= newSize) { | |
275 m_nAvailSize += pBlock->m_nBlockSize; | |
276 CFXMEM_Block* pCurBlock = pBlock; | |
277 if (dwFlags & 0x10) { | |
278 pCurBlock = pPrevBlock; | |
279 m_nAvailSize += sizeof(CFXMEM_Block); | |
280 pCurBlock->m_nBlockSize += pBlock->m_nBlockSize + sizeof(CFXMEM_Bloc
k); | |
281 pPrevBlock = pPrevPrev; | |
282 } | |
283 if (dwFlags & 0x01) { | |
284 m_nAvailSize += sizeof(CFXMEM_Block); | |
285 pCurBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_
Block); | |
286 pCurBlock->m_pNextBlock = pNextBlock->m_pNextBlock; | |
287 } | |
288 if (pCurBlock != pBlock) { | |
289 FXSYS_memmove32((FX_LPVOID)(pCurBlock + 1), p, oldSize); | |
290 } | |
291 return Alloc(pPrevBlock, pCurBlock, newSize, oldnewSize); | |
292 } | |
293 return NULL; | |
294 } | |
295 void CFXMEM_Page::Free(FX_LPVOID p) | |
296 { | |
297 FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos); | |
298 CFXMEM_Block *pPrevBlock = &m_AvailHead; | |
299 CFXMEM_Block *pNextBlock; | |
300 CFXMEM_Block *pBlock = (CFXMEM_Block*)p - 1; | |
301 m_nAvailSize += pBlock->m_nBlockSize; | |
302 while (TRUE) { | |
303 pNextBlock = pPrevBlock->m_pNextBlock; | |
304 if (pNextBlock == NULL || pNextBlock > pBlock) { | |
305 break; | |
306 } | |
307 if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pNextBlock == (FX_LPBYTE)(p
PrevBlock + 1) + pPrevBlock->m_nBlockSize) { | |
308 m_nAvailSize += sizeof(CFXMEM_Block); | |
309 pPrevBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM
_Block); | |
310 pPrevBlock->m_pNextBlock = pNextBlock->m_pNextBlock; | |
311 } else { | |
312 pPrevBlock = pNextBlock; | |
313 } | |
314 } | |
315 while ((FX_LPBYTE)pNextBlock == (FX_LPBYTE)(pBlock + 1) + pBlock->m_nBlockSi
ze) { | |
316 m_nAvailSize += sizeof(CFXMEM_Block); | |
317 pBlock->m_nBlockSize += pNextBlock->m_nBlockSize + sizeof(CFXMEM_Block); | |
318 pNextBlock = pNextBlock->m_pNextBlock; | |
319 } | |
320 pBlock->m_pNextBlock = pNextBlock; | |
321 if (pPrevBlock != &m_AvailHead && (FX_LPBYTE)pBlock == (FX_LPBYTE)(pPrevBloc
k + 1) + pPrevBlock->m_nBlockSize) { | |
322 m_nAvailSize += sizeof(CFXMEM_Block); | |
323 pPrevBlock->m_nBlockSize += pBlock->m_nBlockSize + sizeof(CFXMEM_Block); | |
324 pPrevBlock->m_pNextBlock = pBlock->m_pNextBlock; | |
325 } else { | |
326 FXSYS_assert(pPrevBlock != pBlock); | |
327 pPrevBlock->m_pNextBlock = pBlock; | |
328 } | |
329 } | |
330 void CFXMEM_Pages::Initialize(FX_LPBYTE pStart, size_t pageSize, size_t pages) | |
331 { | |
332 m_pStartPage = m_pCurPage = (CFXMEM_Page*)pStart; | |
333 m_nPageSize = pageSize; | |
334 for (size_t n = 0; n < pages; n++) { | |
335 ((CFXMEM_Page*)pStart)->Initialize(pageSize); | |
336 pStart += pageSize; | |
337 } | |
338 m_pLimitPos = (CFXMEM_Page*)pStart; | |
339 } | |
340 FX_BOOL CFXMEM_Pages::IsEmpty() const | |
341 { | |
342 if (m_pStartPage >= m_pLimitPos) { | |
343 return TRUE; | |
344 } | |
345 FX_LPBYTE pPage = (FX_LPBYTE)m_pStartPage; | |
346 while (pPage < (FX_LPBYTE)m_pLimitPos) { | |
347 if (!((CFXMEM_Page*)pPage)->IsEmpty()) { | |
348 return FALSE; | |
349 } | |
350 pPage += m_nPageSize; | |
351 } | |
352 return TRUE; | |
353 } | |
354 FX_LPVOID CFXMEM_Pages::Alloc(size_t size) | |
355 { | |
356 CFXMEM_Page *pCurPage = m_pCurPage; | |
357 do { | |
358 FX_LPVOID p = m_pCurPage->Alloc(size); | |
359 if (p) { | |
360 return p; | |
361 } | |
362 m_pCurPage = (CFXMEM_Page*)((FX_LPBYTE)m_pCurPage + m_nPageSize); | |
363 if (m_pCurPage == m_pLimitPos) { | |
364 m_pCurPage = m_pStartPage; | |
365 } | |
366 } while (m_pCurPage != pCurPage); | |
367 return NULL; | |
368 } | |
369 FX_LPVOID CFXMEM_Pages::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize) | |
370 { | |
371 FXSYS_assert (p > (FX_LPVOID)m_pStartPage && p < (FX_LPVOID)m_pLimitPos); | |
372 CFXMEM_Page* pPage = (CFXMEM_Page*)((FX_LPBYTE)m_pStartPage + ((FX_LPBYTE)p
- (FX_LPBYTE)m_pStartPage) / m_nPageSize * m_nPageSize); | |
373 return pPage->Realloc(p, oldSize, newSize); | |
374 } | |
375 void CFXMEM_Pages::Free(FX_LPVOID p) | |
376 { | |
377 FXSYS_assert (p > (FX_LPVOID)m_pStartPage && p < (FX_LPVOID)m_pLimitPos); | |
378 CFXMEM_Page* pPage = (CFXMEM_Page*)((FX_LPBYTE)m_pStartPage + ((FX_LPBYTE)p
- (FX_LPBYTE)m_pStartPage) / m_nPageSize * m_nPageSize); | |
379 pPage->Free(p); | |
380 } | |
381 void CFXMEM_Pool::Initialize(const FX_MEMCONFIG* pMemConfig, size_t size, size_t
pageNum8Bytes, size_t pageNum16Bytes, size_t pageNum32Bytes, size_t pageNumMid) | |
382 { | |
383 m_pPrevPool = NULL; | |
384 m_pNextPool = NULL; | |
385 m_bAlone = FALSE; | |
386 FX_LPBYTE pPage = (FX_LPBYTE)this + sizeof(CFXMEM_Pool); | |
387 size -= sizeof(CFXMEM_Pool); | |
388 m_8BytesPages.Initialize(pPage, pageNum8Bytes); | |
389 pPage += pageNum8Bytes * FX_FIXEDMEM_PAGESIZE; | |
390 size -= pageNum8Bytes * FX_FIXEDMEM_PAGESIZE; | |
391 m_16BytesPages.Initialize(pPage, pageNum16Bytes); | |
392 pPage += pageNum16Bytes * FX_FIXEDMEM_PAGESIZE; | |
393 size -= pageNum16Bytes * FX_FIXEDMEM_PAGESIZE; | |
394 m_32BytesPages.Initialize(pPage, pageNum32Bytes); | |
395 pPage += pageNum32Bytes * FX_FIXEDMEM_PAGESIZE; | |
396 size -= pageNum32Bytes * FX_FIXEDMEM_PAGESIZE; | |
397 m_MidPages.Initialize(pPage, pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZ
E, pageNumMid); | |
398 pPage += pageNumMid * pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZE; | |
399 size -= pageNumMid * pMemConfig->nPageSize_Mid * FX_FIXEDMEM_PAGESIZE; | |
400 if (size < FX_FIXEDMEM_MIDBLOCKSIZE) { | |
401 m_pLargePage = NULL; | |
402 } else { | |
403 m_pLargePage = (CFXMEM_Page*)pPage; | |
404 m_pLargePage->Initialize(size); | |
405 } | |
406 m_pLimitPos = pPage + size; | |
407 } | |
408 FX_BOOL CFXMEM_Pool::IsEmpty() const | |
409 { | |
410 if (!m_8BytesPages.IsEmpty()) { | |
411 return FALSE; | |
412 } | |
413 if (!m_16BytesPages.IsEmpty()) { | |
414 return FALSE; | |
415 } | |
416 if (!m_32BytesPages.IsEmpty()) { | |
417 return FALSE; | |
418 } | |
419 if (!m_MidPages.IsEmpty()) { | |
420 return FALSE; | |
421 } | |
422 return !m_pLargePage || m_pLargePage->IsEmpty(); | |
423 } | |
424 size_t CFXMEM_Pool::GetSize(FX_LPVOID p) const | |
425 { | |
426 FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos); | |
427 if (p < (FX_LPVOID)m_8BytesPages.m_pLimitPos) { | |
428 return 8; | |
429 } | |
430 if (p < (FX_LPVOID)m_16BytesPages.m_pLimitPos) { | |
431 return 16; | |
432 } | |
433 if (p < (FX_LPVOID)m_32BytesPages.m_pLimitPos) { | |
434 return 32; | |
435 } | |
436 return ((CFXMEM_Block*)p - 1)->m_nBlockSize; | |
437 } | |
438 FX_LPVOID CFXMEM_Pool::Realloc(FX_LPVOID p, size_t oldSize, size_t newSize) | |
439 { | |
440 FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos); | |
441 if (p > (FX_LPVOID)m_32BytesPages.m_pLimitPos) { | |
442 if (p < (FX_LPVOID)m_MidPages.m_pLimitPos) { | |
443 return m_MidPages.Realloc(p, oldSize, newSize); | |
444 } else if (m_pLargePage) { | |
445 return m_pLargePage->Realloc(p, oldSize, newSize); | |
446 } | |
447 } | |
448 return NULL; | |
449 } | |
450 void CFXMEM_Pool::Free(FX_LPVOID p) | |
451 { | |
452 FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)m_pLimitPos); | |
453 if (p < (FX_LPVOID)m_32BytesPages.m_pLimitPos) { | |
454 if (p < (FX_LPVOID)m_8BytesPages.m_pLimitPos) { | |
455 m_8BytesPages.Free(p); | |
456 } else if (p < (FX_LPVOID)m_16BytesPages.m_pLimitPos) { | |
457 m_16BytesPages.Free(p); | |
458 } else { | |
459 m_32BytesPages.Free(p); | |
460 } | |
461 return; | |
462 } else if (p < (FX_LPVOID)m_MidPages.m_pLimitPos) { | |
463 m_MidPages.Free(p); | |
464 } else { | |
465 m_pLargePage->Free(p); | |
466 } | |
467 } | |
468 void CFXMEM_FixedMgr::Initialize(size_t size) | |
469 { | |
470 m_MemConfig = g_MemConfig; | |
471 FXSYS_memset32(&m_SystemMgr, 0, sizeof m_SystemMgr); | |
472 m_SystemMgr.Alloc = FixedAlloc; | |
473 m_SystemMgr.AllocDebug = FixedAllocDebug; | |
474 m_SystemMgr.Free = FixedFree; | |
475 m_SystemMgr.Realloc = FixedRealloc; | |
476 m_SystemMgr.ReallocDebug = FixedReallocDebug; | |
477 m_SystemMgr.CollectAll = FixedCollectAll; | |
478 m_SystemMgr.Purge = FixedPurge; | |
479 m_SystemMgr.user = this; | |
480 size -= sizeof(CFXMEM_FixedMgr); | |
481 size_t nMidPages = 0; | |
482 if (m_MemConfig.nPageSize_Mid) { | |
483 nMidPages = (size - (m_MemConfig.nPageNum_Init8 + m_MemConfig.nPageNum_I
nit16 + m_MemConfig.nPageNum_Init32) * FX_FIXEDMEM_PAGESIZE) / (m_MemConfig.nPag
eSize_Mid * FX_FIXEDMEM_PAGESIZE); | |
484 if (nMidPages > m_MemConfig.nPageNum_InitMid) { | |
485 nMidPages = m_MemConfig.nPageNum_InitMid; | |
486 } | |
487 } | |
488 m_FirstPool.Initialize(&m_MemConfig, size, m_MemConfig.nPageNum_Init8, m_Mem
Config.nPageNum_Init16, m_MemConfig.nPageNum_Init32, nMidPages); | |
489 } | |
490 FX_LPVOID CFXMEM_FixedMgr::Alloc16(CFXMEM_Pool **pp32Pool, size_t size) | |
491 { | |
492 CFXMEM_Pool *pPool = &m_FirstPool; | |
493 do { | |
494 CFXMEM_16BytesPages &pages = pPool->m_16BytesPages; | |
495 if (pages.HasFreeBlock()) { | |
496 return pages.Alloc(size); | |
497 } | |
498 if (pp32Pool && pPool->m_32BytesPages.HasFreeBlock()) { | |
499 *pp32Pool = pPool; | |
500 } | |
501 pPool = pPool->m_pNextPool; | |
502 } while(pPool); | |
503 return NULL; | |
504 } | |
505 FX_LPVOID CFXMEM_FixedMgr::Alloc32(size_t size) | |
506 { | |
507 if (size <= 8) { | |
508 CFXMEM_8BytesPages &pages = m_FirstPool.m_8BytesPages; | |
509 if (pages.HasFreeBlock()) { | |
510 return pages.Alloc(size); | |
511 } | |
512 } | |
513 CFXMEM_Pool *p32BytesPool; | |
514 if (size <= 16) { | |
515 p32BytesPool = NULL; | |
516 FX_LPVOID p = Alloc16(&p32BytesPool, size); | |
517 if (p) { | |
518 return p; | |
519 } | |
520 } else { | |
521 p32BytesPool = &m_FirstPool; | |
522 } | |
523 while (p32BytesPool) { | |
524 CFXMEM_32BytesPages &pages = p32BytesPool->m_32BytesPages; | |
525 if (pages.HasFreeBlock()) { | |
526 return pages.Alloc(size); | |
527 } | |
528 p32BytesPool = p32BytesPool->m_pNextPool; | |
529 } | |
530 return NULL; | |
531 } | |
532 FX_LPVOID CFXMEM_FixedMgr::AllocSmall(size_t size) | |
533 { | |
534 FX_LPVOID p = Alloc32(size); | |
535 if (p) { | |
536 return p; | |
537 } | |
538 if (!m_pExtender) { | |
539 return NULL; | |
540 } | |
541 size_t requiredSize = (m_MemConfig.nPageNum_More16 + m_MemConfig.nPageNum_Mo
re32) * FX_FIXEDMEM_PAGESIZE; | |
542 if (!requiredSize) { | |
543 return NULL; | |
544 } | |
545 CFXMEM_Pool *pNewPool = NULL; | |
546 requiredSize += sizeof(CFXMEM_Pool); | |
547 size_t newSize = requiredSize; | |
548 if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) { | |
549 return NULL; | |
550 } | |
551 size_t nMidPages = 0; | |
552 if (m_MemConfig.nPageSize_Mid) { | |
553 nMidPages = (newSize - requiredSize) / (m_MemConfig.nPageSize_Mid * FX_F
IXEDMEM_PAGESIZE); | |
554 if (nMidPages > m_MemConfig.nPageNum_MoreMid) { | |
555 nMidPages = m_MemConfig.nPageNum_MoreMid; | |
556 } | |
557 } | |
558 pNewPool->Initialize(&m_MemConfig, newSize, 0, m_MemConfig.nPageNum_More16,
m_MemConfig.nPageNum_More32, nMidPages); | |
559 pNewPool->m_pPrevPool = &m_FirstPool; | |
560 CFXMEM_Pool *pPool = m_FirstPool.m_pNextPool; | |
561 pNewPool->m_pNextPool = pPool; | |
562 if (pPool) { | |
563 pPool->m_pPrevPool = pNewPool; | |
564 } | |
565 m_FirstPool.m_pNextPool = pNewPool; | |
566 return Alloc32(size); | |
567 } | |
568 FX_LPVOID CFXMEM_FixedMgr::AllocMid(size_t size) | |
569 { | |
570 CFXMEM_Pool *pPool = &m_FirstPool; | |
571 do { | |
572 CFXMEM_Pages &pages = pPool->m_MidPages; | |
573 if (pages.m_pLimitPos > pages.m_pStartPage) { | |
574 FX_LPVOID p = pages.Alloc(size); | |
575 if (p) { | |
576 return p; | |
577 } | |
578 } | |
579 pPool = pPool->m_pNextPool; | |
580 } while(pPool); | |
581 if (!m_pExtender) { | |
582 return NULL; | |
583 } | |
584 size_t newSize = m_MemConfig.nPageSize_Mid * FX_FIXEDMEM_PAGESIZE * m_MemCon
fig.nPageNum_MoreMid; | |
585 if (!newSize) { | |
586 return NULL; | |
587 } | |
588 CFXMEM_Pool *pNewPool = NULL; | |
589 newSize += sizeof(CFXMEM_Pool); | |
590 if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) { | |
591 return NULL; | |
592 } | |
593 size_t nMidPages = (newSize - sizeof(CFXMEM_Pool)) / (m_MemConfig.nPageSize_
Mid * FX_FIXEDMEM_PAGESIZE); | |
594 if (nMidPages > m_MemConfig.nPageNum_MoreMid) { | |
595 nMidPages = m_MemConfig.nPageNum_MoreMid; | |
596 } | |
597 pNewPool->Initialize(&m_MemConfig, newSize, 0, 0, 0, nMidPages); | |
598 pNewPool->m_pPrevPool = &m_FirstPool; | |
599 pPool = m_FirstPool.m_pNextPool; | |
600 pNewPool->m_pNextPool = pPool; | |
601 if (pPool) { | |
602 pPool->m_pPrevPool = pNewPool; | |
603 } | |
604 m_FirstPool.m_pNextPool = pNewPool; | |
605 return pNewPool->m_MidPages.Alloc(size); | |
606 } | |
607 FX_LPVOID CFXMEM_FixedMgr::AllocLarge(size_t size) | |
608 { | |
609 CFXMEM_Pool *pPool = &m_FirstPool; | |
610 do { | |
611 if (!pPool->m_bAlone && pPool->m_pLargePage) { | |
612 FX_LPVOID p = pPool->m_pLargePage->Alloc(size); | |
613 if (p) { | |
614 return p; | |
615 } | |
616 } | |
617 pPool = pPool->m_pNextPool; | |
618 } while(pPool); | |
619 if (!m_pExtender || !m_MemConfig.nPageSize_Large) { | |
620 return NULL; | |
621 } | |
622 CFXMEM_Pool *pNewPool = NULL; | |
623 #if _FX_WORDSIZE_ == _FX_W64_ | |
624 size_t newSize = ((size + 31) / 32 * 32 + sizeof(CFXMEM_Pool) + sizeof(CFXME
M_Page) + sizeof(CFXMEM_Block) + 4095) / 4096 * 4096; | |
625 #else | |
626 size_t newSize = (size + 7) / 8 * 8 + sizeof(CFXMEM_Pool) + sizeof(CFXMEM_Pa
ge) + sizeof(CFXMEM_Block); | |
627 #endif | |
628 if (newSize < m_MemConfig.nPageSize_Large * FX_FIXEDMEM_PAGESIZE) { | |
629 newSize = m_MemConfig.nPageSize_Large * FX_FIXEDMEM_PAGESIZE; | |
630 } | |
631 if (!m_pExtender->More(m_pExtender, newSize, (void**)&pNewPool, &newSize)) { | |
632 return NULL; | |
633 } | |
634 pNewPool->Initialize(&m_MemConfig, newSize, 0, 0, 0, 0); | |
635 pNewPool->m_bAlone = size >= m_MemConfig.nPageSize_Alone * FX_FIXEDMEM_PAGES
IZE; | |
636 pNewPool->m_pPrevPool = &m_FirstPool; | |
637 pPool = m_FirstPool.m_pNextPool; | |
638 pNewPool->m_pNextPool = pPool; | |
639 if (pPool) { | |
640 pPool->m_pPrevPool = pNewPool; | |
641 } | |
642 m_FirstPool.m_pNextPool = pNewPool; | |
643 return pNewPool->m_pLargePage->Alloc(size); | |
644 } | |
645 size_t CFXMEM_FixedMgr::GetSize(FX_LPVOID p) const | |
646 { | |
647 const CFXMEM_Pool *pFind = &m_FirstPool; | |
648 do { | |
649 if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) { | |
650 return pFind->GetSize(p); | |
651 } | |
652 pFind = pFind->m_pNextPool; | |
653 } while (pFind); | |
654 return 0; | |
655 } | |
656 FX_LPVOID CFXMEM_FixedMgr::Alloc(size_t size) | |
657 { | |
658 FX_LPVOID p; | |
659 if (size <= 32) { | |
660 p = AllocSmall(size); | |
661 if (p) { | |
662 return p; | |
663 } | |
664 } | |
665 if (size <= FX_FIXEDMEM_MIDBLOCKSIZE) { | |
666 p = AllocMid(size); | |
667 if (p) { | |
668 return p; | |
669 } | |
670 } | |
671 p = AllocLarge(size); | |
672 return p; | |
673 } | |
674 FX_LPVOID CFXMEM_FixedMgr::ReallocSmall(CFXMEM_Pool* pPool, FX_LPVOID p, size_t
oldSize, size_t newSize) | |
675 { | |
676 FX_LPVOID np = AllocSmall(newSize); | |
677 if (!np) { | |
678 return NULL; | |
679 } | |
680 FXSYS_memcpy32(np, p, oldSize); | |
681 pPool->Free(p); | |
682 return np; | |
683 } | |
684 FX_LPVOID CFXMEM_FixedMgr::Realloc(FX_LPVOID p, size_t newSize) | |
685 { | |
686 if (!p) { | |
687 return Alloc(newSize); | |
688 } | |
689 size_t oldSize = 0; | |
690 CFXMEM_Pool *pFind = &m_FirstPool; | |
691 do { | |
692 if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) { | |
693 oldSize = pFind->GetSize(p); | |
694 if (oldSize >= newSize) { | |
695 return p; | |
696 } | |
697 break; | |
698 } | |
699 pFind = pFind->m_pNextPool; | |
700 } while (pFind); | |
701 if (!oldSize || !pFind) { | |
702 return Alloc(newSize); | |
703 } | |
704 FX_LPVOID np = NULL; | |
705 if (newSize <= 32) { | |
706 np = ReallocSmall(pFind, p, oldSize, newSize); | |
707 if (np) { | |
708 return np; | |
709 } | |
710 } | |
711 if (newSize <= FX_FIXEDMEM_MIDBLOCKSIZE) { | |
712 np = pFind->Realloc(p, oldSize, newSize); | |
713 if (np) { | |
714 return np; | |
715 } | |
716 } | |
717 np = Alloc(newSize); | |
718 if (np) { | |
719 FXSYS_memcpy32(np, p, oldSize); | |
720 pFind->Free(p); | |
721 } | |
722 if (pFind->m_bAlone && pFind->IsEmpty()) { | |
723 FreePool(pFind); | |
724 } | |
725 return np; | |
726 } | |
727 void CFXMEM_FixedMgr::Free(FX_LPVOID p) | |
728 { | |
729 CFXMEM_Pool *pFind = &m_FirstPool; | |
730 do { | |
731 if (p > (FX_LPVOID)pFind && p < pFind->m_pLimitPos) { | |
732 pFind->Free(p); | |
733 if (pFind->m_bAlone && pFind->IsEmpty()) { | |
734 FreePool(pFind); | |
735 } | |
736 return; | |
737 } | |
738 pFind = pFind->m_pNextPool; | |
739 } while (pFind); | |
740 } | |
741 void CFXMEM_FixedMgr::FreePool(CFXMEM_Pool* pPool) | |
742 { | |
743 FXSYS_assert(pPool->m_bAlone && pPool->IsEmpty()); | |
744 FXSYS_assert(m_pExtender != NULL); | |
745 CFXMEM_Pool* pPrevPool = pPool->m_pPrevPool; | |
746 CFXMEM_Pool* pNextPool = pPool->m_pNextPool; | |
747 if (pPrevPool) { | |
748 pPrevPool->m_pNextPool = pNextPool; | |
749 } | |
750 if (pNextPool) { | |
751 pNextPool->m_pPrevPool = pPrevPool; | |
752 } | |
753 m_pExtender->Free(m_pExtender, pPool); | |
754 } | |
755 void CFXMEM_FixedMgr::FreeAll() | |
756 { | |
757 if (!m_pExtender) { | |
758 return; | |
759 } | |
760 CFXMEM_Pool* pPool = m_FirstPool.m_pNextPool; | |
761 while (pPool) { | |
762 CFXMEM_Pool* pPrevPool = pPool; | |
763 pPool = pPool->m_pNextPool; | |
764 m_pExtender->Free(m_pExtender, pPrevPool); | |
765 } | |
766 m_FirstPool.m_pNextPool = NULL; | |
767 } | |
768 void CFXMEM_FixedMgr::Purge() | |
769 { | |
770 if (!m_pExtender) { | |
771 return; | |
772 } | |
773 CFXMEM_Pool* pPool = m_FirstPool.m_pNextPool; | |
774 while (pPool) { | |
775 CFXMEM_Pool* pNextPool = pPool->m_pNextPool; | |
776 if (pPool->IsEmpty()) { | |
777 CFXMEM_Pool* pPrevPool = pPool->m_pPrevPool; | |
778 pPrevPool->m_pNextPool = pNextPool; | |
779 if (pNextPool) { | |
780 pNextPool->m_pPrevPool = pPrevPool; | |
781 } | |
782 m_pExtender->Free(m_pExtender, pPool); | |
783 } | |
784 pPool = pNextPool; | |
785 } | |
786 } | |
787 extern const FX_BYTE OneLeadPos[256] = { | |
788 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, | |
789 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | |
790 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
791 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
792 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
793 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
794 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
795 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
796 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
799 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
801 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
802 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
803 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
804 }; | |
805 extern const FX_BYTE ZeroLeadPos[256] = { | |
806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
807 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
808 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
809 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
810 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
811 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
812 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
813 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
814 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
815 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
816 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
817 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
818 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
819 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
820 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, | |
821 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, | |
822 }; | |
OLD | NEW |