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