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
FXMEM_SetConfig(const FX_MEMCONFIG * memConfig)36 void FXMEM_SetConfig(const FX_MEMCONFIG* memConfig)
37 {
38 g_MemConfig = *memConfig;
39 }
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
FixedAlloc(FXMEM_SystemMgr * pMgr,size_t size,int flags)43 static void* FixedAlloc(FXMEM_SystemMgr* pMgr, size_t size, int flags)
44 {
45 return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size);
46 }
FixedAllocDebug(FXMEM_SystemMgr * pMgr,size_t size,int flags,FX_LPCSTR file,int line)47 static void* FixedAllocDebug(FXMEM_SystemMgr* pMgr, size_t size, int flags, FX_LPCSTR file, int line)
48 {
49 return ((CFXMEM_FixedMgr*)pMgr->user)->Alloc(size);
50 }
FixedRealloc(FXMEM_SystemMgr * pMgr,void * pointer,size_t size,int flags)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 }
FixedReallocDebug(FXMEM_SystemMgr * pMgr,void * pointer,size_t size,int flags,FX_LPCSTR file,int line)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 }
FixedFree(FXMEM_SystemMgr * pMgr,void * pointer,int flags)59 static void FixedFree(FXMEM_SystemMgr* pMgr, void* pointer, int flags)
60 {
61 ((CFXMEM_FixedMgr*)pMgr->user)->Free(pointer);
62 }
FixedPurge(FXMEM_SystemMgr * pMgr)63 static void FixedPurge(FXMEM_SystemMgr* pMgr)
64 {
65 ((CFXMEM_FixedMgr*)pMgr->user)->Purge();
66 }
FixedCollectAll(FXMEM_SystemMgr * pMgr)67 static void FixedCollectAll(FXMEM_SystemMgr* pMgr)
68 {
69 ((CFXMEM_FixedMgr*)pMgr->user)->FreeAll();
70 }
71 #define FIXEDMEM_MINIMUMSIZE (1024 * 1024 * 8)
FXMEM_CreateMemoryMgr(size_t size,FX_BOOL extensible)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 + offsetSize, 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 }
FXMEM_CreateFixedMgr(void * pMemory,size_t size,FXMEM_SystemMgr2 * pSystemMgr)92 FXMEM_FoxitMgr* FXMEM_CreateFixedMgr(void* pMemory, size_t size, FXMEM_SystemMgr2* 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 - offsetSize, 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 }
FXMEM_GetBlockSizeInFixedMgr(FXMEM_FoxitMgr * pFoxitMgr,void * ptr)112 size_t FXMEM_GetBlockSizeInFixedMgr(FXMEM_FoxitMgr* pFoxitMgr, void* ptr)
113 {
114 return pFoxitMgr ? ((CFXMEM_FixedMgr*)((CFX_MemoryMgr*)pFoxitMgr)->m_pSystemMgr->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 };
FixedMgr_GetConfig(size_t nSize)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 }
Initialize(FX_LPVOID pBuffer,size_t nSize,FX_BOOL bExtensible)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(CFixedMgr_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 }
Common_More(FXMEM_SystemMgr2 * pMgr,size_t alloc_size,void ** new_memory,size_t * new_size)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 }
Common_Free(FXMEM_SystemMgr2 * pMgr,void * memory)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_pBuffer + pProxyMgr->m_nSize) {
172 pProxyMgr->m_pFixedPage->Free(memory);
173 } else if (pProxyMgr->m_bExtensible) {
174 free(memory);
175 }
176 }
Initialize(size_t size)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 }
Alloc(CFXMEM_Block * pPrevBlock,CFXMEM_Block * pNextBlock,size_t size,size_t oldsize)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 }
Alloc(size_t size)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 }
Realloc(FX_LPVOID p,size_t oldSize,size_t newSize)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)(pPrevBlock + 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)(pPrevBlock + 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_Block);
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 }
Free(FX_LPVOID p)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)(pPrevBlock + 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_nBlockSize) {
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)(pPrevBlock + 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 }
Initialize(FX_LPBYTE pStart,size_t pageSize,size_t pages)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 }
IsEmpty() const340 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 }
Alloc(size_t size)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 }
Realloc(FX_LPVOID p,size_t oldSize,size_t newSize)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 }
Free(FX_LPVOID p)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 }
Initialize(const FX_MEMCONFIG * pMemConfig,size_t size,size_t pageNum8Bytes,size_t pageNum16Bytes,size_t pageNum32Bytes,size_t pageNumMid)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_PAGESIZE, 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 }
IsEmpty() const408 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 }
GetSize(FX_LPVOID p) const424 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 }
Realloc(FX_LPVOID p,size_t oldSize,size_t newSize)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 }
Free(FX_LPVOID p)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 }
Initialize(size_t size)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_Init16 + m_MemConfig.nPageNum_Init32) * FX_FIXEDMEM_PAGESIZE) / (m_MemConfig.nPageSize_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_MemConfig.nPageNum_Init16, m_MemConfig.nPageNum_Init32, nMidPages);
489 }
Alloc16(CFXMEM_Pool ** pp32Pool,size_t size)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 }
Alloc32(size_t size)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 }
AllocSmall(size_t size)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_More32) * 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_FIXEDMEM_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 }
AllocMid(size_t size)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_MemConfig.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 }
AllocLarge(size_t size)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(CFXMEM_Page) + sizeof(CFXMEM_Block) + 4095) / 4096 * 4096;
625 #else
626 size_t newSize = (size + 7) / 8 * 8 + sizeof(CFXMEM_Pool) + sizeof(CFXMEM_Page) + 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_PAGESIZE;
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 }
GetSize(FX_LPVOID p) const645 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 }
Alloc(size_t size)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 }
ReallocSmall(CFXMEM_Pool * pPool,FX_LPVOID p,size_t oldSize,size_t newSize)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 }
Realloc(FX_LPVOID p,size_t newSize)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 }
Free(FX_LPVOID p)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 }
FreePool(CFXMEM_Pool * pPool)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 }
FreeAll()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 }
Purge()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 };
823