1021ab7adfc6613f8344ef2ac5d20ac67534701e
[pdfium.git] / core / src / fxcrt / fx_basic_memmgr.cpp
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_basic.h"
8 #include "mem_int.h"
9
10 void FXMEM_DestroyFoxitMgr(FXMEM_FoxitMgr* pFoxitMgr)
11 {
12     if (pFoxitMgr == NULL) {
13         return;
14     }
15     CFX_MemoryMgr* p = (CFX_MemoryMgr*)pFoxitMgr;
16     if (p->m_pSystemMgr->CollectAll) {
17         p->m_pSystemMgr->CollectAll(p->m_pSystemMgr);
18     }
19     if (p->m_bReleaseMgr) {
20         p->m_pSystemMgr->Free(p->m_pSystemMgr, p, 0);
21     }
22     if (p->m_pExternalMemory) {
23         free(p->m_pExternalMemory);
24     }
25 }
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 static void* _DefAllocDebug(IFX_Allocator* pAllocator, size_t num, size_t size, FX_LPCSTR filename, int line)
30 {
31     if (size == 0 || num > SIZE_MAX/size)
32         return NULL;
33
34     size = size * num; 
35     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->AllocDebug(size, 0, filename, line);
36 }
37 static void* _DefAlloc(IFX_Allocator* pAllocator, size_t num, size_t size)
38 {
39     if (size == 0 || num > SIZE_MAX/size)
40         return NULL;
41
42     size = size * num;
43     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Alloc(size, 0);
44 }
45 static void* _DefReallocDebug(IFX_Allocator* pAllocator, void* p, size_t new_num, size_t size, FX_LPCSTR filename, int line)
46 {
47     if (size == 0 || new_num > SIZE_MAX/size)
48         return NULL;
49
50     size = size * new_num;
51     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->ReallocDebug(p, size, 0, filename, line);
52 }
53 static void* _DefRealloc(IFX_Allocator* pAllocator, void* p, size_t new_num, size_t size)
54 {
55     if (size == 0 || new_num > SIZE_MAX/size)
56         return NULL;
57
58     size = size * new_num;
59     return ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Realloc(p, size, 0);
60 }
61 static void _DefFree(IFX_Allocator* pAllocator, void* p)
62 {
63     ((FX_DefAllocator*)pAllocator)->m_pFoxitMgr->Free(p, 0);
64 }
65 #ifdef __cplusplus
66 }
67 #endif
68 void CFX_MemoryMgr::Init(FXMEM_SystemMgr* pSystemMgr)
69 {
70     m_pSystemMgr = pSystemMgr;
71     IFX_Allocator &ac = m_DefAllocator.m_Allocator;
72     ac.m_Alloc = _DefAlloc;
73     ac.m_AllocDebug = _DefAllocDebug;
74     ac.m_Realloc = _DefRealloc;
75     ac.m_ReallocDebug = _DefReallocDebug;
76     ac.m_Free = _DefFree;
77     m_DefAllocator.m_pFoxitMgr = this;
78     m_pExternalMemory = NULL;
79     m_bReleaseMgr = TRUE;
80 }
81 void CFX_MemoryMgr::PurgeMgr()
82 {
83     if (m_pSystemMgr->Purge) {
84         m_pSystemMgr->Purge(m_pSystemMgr);
85     }
86 }
87 void* CFX_MemoryMgr::Alloc(size_t size, int flags)
88 {
89     void* p = m_pSystemMgr->Alloc(m_pSystemMgr, size, flags);
90     if (p == NULL) {
91         return NULL;
92     }
93     return p;
94 }
95 void* CFX_MemoryMgr::AllocDebug(size_t size, int flags, FX_LPCSTR file, int line)
96 {
97     void* p = m_pSystemMgr->AllocDebug(m_pSystemMgr, size, flags, file, line);
98     if (p == NULL) {
99         return NULL;
100     }
101     return p;
102 }
103 void* CFX_MemoryMgr::Realloc(void* p, size_t size, int flags)
104 {
105     void* p1 = m_pSystemMgr->Realloc(m_pSystemMgr, p, size, flags);
106     if (p1 == NULL) {
107         return NULL;
108     }
109     return p1;
110 }
111 void* CFX_MemoryMgr::ReallocDebug(void* p, size_t size, int flags, FX_LPCSTR file, int line)
112 {
113     void* p1 = m_pSystemMgr->ReallocDebug(m_pSystemMgr, p, size, flags, file, line);
114     if (p1 == NULL) {
115         return NULL;
116     }
117     return p1;
118 }
119 void CFX_MemoryMgr::Free(void* p, int flags)
120 {
121     if (p == NULL) {
122         return;
123     }
124     m_pSystemMgr->Free(m_pSystemMgr, p, flags);
125 }
126 CFX_MemoryMgr* g_pDefFoxitMgr = NULL;
127 void* FXMEM_DefaultAlloc(size_t size, int flags)
128 {
129     return g_pDefFoxitMgr->Alloc(size, flags);
130 }
131 void* FXMEM_DefaultAlloc2(size_t size, size_t unit, int flags)
132 {
133     return g_pDefFoxitMgr->Alloc(size * unit, flags);
134 }
135 void* FXMEM_DefaultRealloc(void* p, size_t size, int flags)
136 {
137     if (p == NULL) {
138         return FXMEM_DefaultAlloc(size, flags);
139     }
140     return g_pDefFoxitMgr->Realloc(p, size, flags);
141 }
142 void* FXMEM_DefaultRealloc2(void* p, size_t size, size_t unit, int flags)
143 {
144     if (p == NULL) {
145         return FXMEM_DefaultAlloc2(size, unit, flags);
146     }
147     return g_pDefFoxitMgr->Realloc(p, size * unit, flags);
148 }
149 void* FXMEM_DefaultAllocDebug(size_t size, int flags, FX_LPCSTR file, int line)
150 {
151     return g_pDefFoxitMgr->AllocDebug(size, flags, file, line);
152 }
153 void* FXMEM_DefaultAllocDebug2(size_t size, size_t unit, int flags, FX_LPCSTR file, int line)
154 {
155     return g_pDefFoxitMgr->AllocDebug(size * unit, flags, file, line);
156 }
157 void* FXMEM_DefaultReallocDebug(void* p, size_t size, int flags, FX_LPCSTR file, int line)
158 {
159     if (p == NULL) {
160         return FXMEM_DefaultAllocDebug(size, flags, file, line);
161     }
162     return g_pDefFoxitMgr->ReallocDebug(p, size, flags, file, line);
163 }
164 void* FXMEM_DefaultReallocDebug2(void* p, size_t size, size_t unit, int flags, FX_LPCSTR file, int line)
165 {
166     if (p == NULL) {
167         return FXMEM_DefaultAllocDebug2(size, unit, flags, file, line);
168     }
169     return g_pDefFoxitMgr->ReallocDebug(p, size * unit, flags, file, line);
170 }
171 void FXMEM_DefaultFree(void* p, int flags)
172 {
173     g_pDefFoxitMgr->Free(p, flags);
174 }
175 IFX_Allocator* FXMEM_GetDefAllocator()
176 {
177     return &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
178 }
179 void* CFX_Object::operator new(size_t size)
180 {
181     return g_pDefFoxitMgr->Alloc(size, 0);
182 }
183 void* CFX_Object::operator new[](size_t size)
184 {
185     return g_pDefFoxitMgr->Alloc(size, 0);
186 }
187 void* CFX_Object::operator new[](size_t size, FX_LPCSTR file, int line)
188 {
189     return g_pDefFoxitMgr->AllocDebug(size, 0, file, line);
190 }
191 void* CFX_Object::operator new(size_t size, FX_LPCSTR file, int line)
192 {
193     return g_pDefFoxitMgr->AllocDebug(size, 0, file, line);
194 }
195 void CFX_Object::operator delete(void* p)
196 {
197     g_pDefFoxitMgr->Free(p, 0);
198 }
199 void CFX_Object::operator delete[](void* p)
200 {
201     g_pDefFoxitMgr->Free(p, 0);
202 }
203 void CFX_Object::operator delete(void* p, FX_LPCSTR file, int line)
204 {
205     g_pDefFoxitMgr->Free(p, 0);
206 }
207 void CFX_Object::operator delete[](void* p, FX_LPCSTR file, int line)
208 {
209     g_pDefFoxitMgr->Free(p, 0);
210 }
211 void* CFX_AllocObject::operator new(size_t size, IFX_Allocator* pAllocator, FX_LPCSTR filename, int line)
212 {
213     void* p = pAllocator ? pAllocator->m_AllocDebug(pAllocator, size, 1, filename, line) :
214               g_pDefFoxitMgr->AllocDebug(size, 0, filename, line);
215     ((CFX_AllocObject*)p)->m_pAllocator = pAllocator;
216     return p;
217 }
218 void CFX_AllocObject::operator delete (void* p, IFX_Allocator* pAllocator, FX_LPCSTR filename, int line)
219 {
220     if (pAllocator) {
221         pAllocator->m_Free(pAllocator, p);
222     } else {
223         g_pDefFoxitMgr->Free(p, 0);
224     }
225 }
226 void* CFX_AllocObject::operator new(size_t size, IFX_Allocator* pAllocator)
227 {
228     void* p = pAllocator ? pAllocator->m_Alloc(pAllocator, size, 1) : g_pDefFoxitMgr->Alloc(size, 0);
229     ((CFX_AllocObject*)p)->m_pAllocator = pAllocator;
230     return p;
231 }
232 void CFX_AllocObject::operator delete(void* p)
233 {
234     if (((CFX_AllocObject*)p)->m_pAllocator) {
235         (((CFX_AllocObject*)p)->m_pAllocator)->m_Free(((CFX_AllocObject*)p)->m_pAllocator, p);
236     } else {
237         g_pDefFoxitMgr->Free(p, 0);
238     }
239 }
240 void CFX_AllocObject::operator delete(void* p, IFX_Allocator* pAllocator)
241 {
242     if (pAllocator) {
243         pAllocator->m_Free(pAllocator, p);
244     } else {
245         g_pDefFoxitMgr->Free(p, 0);
246     }
247 }
248 extern "C" {
249     static void* _GOPAllocDebug(IFX_Allocator* pAllocator, size_t num, size_t size, FX_LPCSTR file, int line)
250     {
251         if (size == 0 || num > SIZE_MAX/size)
252             return NULL;
253
254         size = size * num;
255         return ((CFX_GrowOnlyPool*)pAllocator)->Alloc(size);
256     }
257     static void* _GOPAlloc(IFX_Allocator* pAllocator, size_t num, size_t size)
258     {
259         if (size == 0 || num > SIZE_MAX/size)
260             return NULL;
261
262         size = size * num;
263         return ((CFX_GrowOnlyPool*)pAllocator)->Alloc(size);
264     }
265     static void* _GOPReallocDebug(IFX_Allocator* pAllocator, void* p, size_t new_num, size_t size, FX_LPCSTR file, int line)
266     {
267         if (size == 0 || new_num > SIZE_MAX/size)
268             return NULL;
269
270         size = size * new_num;
271         return ((CFX_GrowOnlyPool*)pAllocator)->Realloc(p, size);
272     }
273     static void* _GOPRealloc(IFX_Allocator* pAllocator, void* p, size_t new_num, size_t size)
274     {
275         if (size == 0 || new_num > SIZE_MAX/size)
276             return NULL;
277
278         size = size * new_num;
279         return ((CFX_GrowOnlyPool*)pAllocator)->Realloc(p, size);
280     }
281     static void _GOPFree(IFX_Allocator* pAllocator, void* p)
282     {
283     }
284 };
285 CFX_GrowOnlyPool::CFX_GrowOnlyPool(IFX_Allocator* pAllocator, size_t trunk_size)
286 {
287     m_TrunkSize = trunk_size;
288     m_pFirstTrunk = NULL;
289     m_pAllocator = pAllocator ? pAllocator : &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
290     m_AllocDebug = _GOPAllocDebug;
291     m_Alloc = _GOPAlloc;
292     m_ReallocDebug = _GOPReallocDebug;
293     m_Realloc = _GOPRealloc;
294     m_Free = _GOPFree;
295 }
296 CFX_GrowOnlyPool::~CFX_GrowOnlyPool()
297 {
298     FreeAll();
299 }
300 void CFX_GrowOnlyPool::SetAllocator(IFX_Allocator* pAllocator)
301 {
302     ASSERT(m_pFirstTrunk == NULL);
303     m_pAllocator = pAllocator ? pAllocator : &g_pDefFoxitMgr->m_DefAllocator.m_Allocator;
304 }
305 struct _FX_GrowOnlyTrunk {
306     size_t      m_Size;
307     size_t      m_Allocated;
308     _FX_GrowOnlyTrunk*  m_pNext;
309 };
310 void CFX_GrowOnlyPool::FreeAll()
311 {
312     _FX_GrowOnlyTrunk* pTrunk = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
313     while (pTrunk) {
314         _FX_GrowOnlyTrunk* pNext = pTrunk->m_pNext;
315         m_pAllocator->m_Free(m_pAllocator, pTrunk);
316         pTrunk = pNext;
317     }
318     m_pFirstTrunk = NULL;
319 }
320 void* CFX_GrowOnlyPool::Alloc(size_t size)
321 {
322     size = (size + 3) / 4 * 4;
323     _FX_GrowOnlyTrunk* pTrunk = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
324     while (pTrunk) {
325         if (pTrunk->m_Size - pTrunk->m_Allocated >= size) {
326             void* p = (FX_LPBYTE)(pTrunk + 1) + pTrunk->m_Allocated;
327             pTrunk->m_Allocated += size;
328             return p;
329         }
330         pTrunk = pTrunk->m_pNext;
331     }
332     size_t alloc_size = size > m_TrunkSize ? size : m_TrunkSize;
333     
334     if (alloc_size > SIZE_MAX - sizeof(_FX_GrowOnlyTrunk) )
335         return NULL;
336
337     pTrunk = (_FX_GrowOnlyTrunk*)m_pAllocator->m_Alloc(m_pAllocator, sizeof(_FX_GrowOnlyTrunk) + alloc_size, 1);
338     pTrunk->m_Size = alloc_size;
339     pTrunk->m_Allocated = size;
340     pTrunk->m_pNext = (_FX_GrowOnlyTrunk*)m_pFirstTrunk;
341     m_pFirstTrunk = pTrunk;
342     return pTrunk + 1;
343 }