| 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 |