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#ifndef _FXM_MEM_INT_H_
8#define _FXM_MEM_INT_H_
9struct FX_DefAllocator {
10    IFX_Allocator			m_Allocator;
11    struct CFX_MemoryMgr*	m_pFoxitMgr;
12};
13struct CFX_MemoryMgr {
14public:
15    FXMEM_SystemMgr*	m_pSystemMgr;
16    FX_DefAllocator		m_DefAllocator;
17    FX_LPVOID			m_pExternalMemory;
18    FX_BOOL				m_bReleaseMgr;
19    void			Init(FXMEM_SystemMgr* pSystemMgr);
20    void*			Alloc(size_t size, int flags);
21    void*			AllocDebug(size_t size, int flags, FX_LPCSTR file, int line);
22    void*			Realloc(void* p, size_t size, int flags);
23    void*			ReallocDebug(void* p, size_t size, int flags, FX_LPCSTR file, int line);
24    void			Free(void* p, int flags);
25    void			PurgeMgr();
26};
27extern CFX_MemoryMgr* g_pDefFoxitMgr;
28#define FIXEDMEM_PAGE_EXTRASPACE		sizeof(size_t)
29#define FIXEDMEM_BLOCKNUM(bs)			(8 * (FX_FIXEDMEM_PAGESIZE - FIXEDMEM_PAGE_EXTRASPACE) / (8 * bs + 1))
30#define FIXEDMEM_8BYTES_BLOCKNUM		FIXEDMEM_BLOCKNUM(8)
31#define FIXEDMEM_16BYTES_BLOCKNUM		FIXEDMEM_BLOCKNUM(16)
32#define FIXEDMEM_32BYTES_BLOCKNUM		FIXEDMEM_BLOCKNUM(32)
33extern const FX_BYTE ZeroLeadPos[256];
34extern const FX_BYTE OneLeadPos[256];
35template <size_t blockNum, size_t blockSize>
36class CFXMEM_FixedPage
37{
38public:
39    void		Initialize()
40    {
41        m_nAvailCount = blockNum;
42        FXSYS_memset32(m_BusyMap, 0, (blockNum + 7) / 8);
43    }
44    FX_BOOL		HasFreeBlock() const
45    {
46        return (FX_BOOL)m_nAvailCount;
47    }
48    FX_LPVOID	Alloc(size_t size)
49    {
50        FXSYS_assert(m_nAvailCount);
51        FX_LPDWORD pFind = (FX_LPDWORD)m_BusyMap;
52        size_t i = 0;
53        while (i < (blockNum + 7) / 8 / 4 && pFind[i] == 0xFFFFFFFF) {
54            i ++;
55        }
56        i *= 4;
57        while (m_BusyMap[i] == 0xFF) {
58            i ++;
59        }
60        size_t pos = ZeroLeadPos[m_BusyMap[i]];
61        m_BusyMap[i] |= 1 << (7 - pos);
62        m_nAvailCount --;
63        return (FX_LPBYTE)(this + 1) + (i * 8 + pos) * blockSize;
64    }
65    void		Free(FX_LPVOID p)
66    {
67        FXSYS_assert(p > (FX_LPVOID)this && p < (FX_LPVOID)((FX_LPBYTE)this + FX_FIXEDMEM_PAGESIZE));
68        size_t pos = ((FX_LPBYTE)p - (FX_LPBYTE)(this + 1)) / blockSize;
69        m_BusyMap[pos / 8] &= ~(1 << (7 - (pos % 8)));
70        m_nAvailCount ++;
71    }
72    volatile size_t	m_nAvailCount;
73    FX_BYTE			m_BusyMap[(blockNum + 7) / 8];
74};
75typedef CFXMEM_FixedPage<FIXEDMEM_8BYTES_BLOCKNUM, 8>	CFXMEM_8BytesPage;
76typedef CFXMEM_FixedPage<FIXEDMEM_16BYTES_BLOCKNUM, 16>	CFXMEM_16BytesPage;
77typedef CFXMEM_FixedPage<FIXEDMEM_32BYTES_BLOCKNUM, 32>	CFXMEM_32BytesPage;
78template <size_t blockNum, size_t blockSize>
79class CFXMEM_FixedPages
80{
81public:
82    typedef CFXMEM_FixedPage<blockNum, blockSize> T;
83    FX_LPBYTE		m_pStartPage;
84    FX_LPBYTE		m_pLimitPos;
85    FX_LPBYTE		m_pCurPage;
86    volatile size_t	m_nAvailBlocks;
87    void		Initialize(FX_LPBYTE pStart, size_t pages)
88    {
89        m_pStartPage = m_pCurPage = pStart;
90        m_nAvailBlocks = pages * blockNum;
91        for (size_t n = 0; n < pages; n ++) {
92            ((T*)pStart)->Initialize();
93            pStart += FX_FIXEDMEM_PAGESIZE;
94        }
95        m_pLimitPos = pStart;
96    }
97    FX_BOOL		IsEmpty() const
98    {
99        return m_nAvailBlocks == (m_pLimitPos - m_pStartPage) / FX_FIXEDMEM_PAGESIZE * blockNum;
100    }
101    FX_BOOL		HasFreeBlock() const
102    {
103        return (FX_BOOL)m_nAvailBlocks;
104    }
105    FX_LPVOID	Alloc(size_t size)
106    {
107        FXSYS_assert(m_nAvailBlocks);
108        do {
109            if (((T*)m_pCurPage)->HasFreeBlock()) {
110                m_nAvailBlocks --;
111                return ((T*)m_pCurPage)->Alloc(size);
112            }
113            m_pCurPage += FX_FIXEDMEM_PAGESIZE;
114            if (m_pCurPage == m_pLimitPos) {
115                m_pCurPage = m_pStartPage;
116            }
117        } while (TRUE);
118        return NULL;
119    }
120    void		Free(FX_LPVOID p)
121    {
122        FXSYS_assert(p > (FX_LPVOID)m_pStartPage && p < (FX_LPVOID)m_pLimitPos);
123        ((T*)(m_pStartPage + ((FX_LPBYTE)p - m_pStartPage) / FX_FIXEDMEM_PAGESIZE * FX_FIXEDMEM_PAGESIZE))->Free(p);
124        m_nAvailBlocks ++;
125    }
126};
127typedef CFXMEM_FixedPages<FIXEDMEM_8BYTES_BLOCKNUM, 8>		CFXMEM_8BytesPages;
128typedef CFXMEM_FixedPages<FIXEDMEM_16BYTES_BLOCKNUM, 16>	CFXMEM_16BytesPages;
129typedef CFXMEM_FixedPages<FIXEDMEM_32BYTES_BLOCKNUM, 32>	CFXMEM_32BytesPages;
130class CFXMEM_Block
131{
132public:
133    size_t			m_nBlockSize;
134    CFXMEM_Block*	m_pNextBlock;
135};
136class CFXMEM_Page
137{
138public:
139    size_t			m_nAvailSize;
140    CFXMEM_Block*	m_pLimitPos;
141    CFXMEM_Block	m_AvailHead;
142    void		Initialize(size_t size);
143    FX_BOOL		IsEmpty() const
144    {
145        return m_AvailHead.m_pNextBlock && m_AvailHead.m_nBlockSize == m_AvailHead.m_pNextBlock->m_nBlockSize;
146    }
147    FX_LPVOID	Alloc(size_t size);
148    FX_LPVOID	Realloc(FX_LPVOID p, size_t oldSize, size_t newSize);
149    void		Free(FX_LPVOID p);
150protected:
151    FX_LPVOID	Alloc(CFXMEM_Block* pPrevBlock, CFXMEM_Block* pNextBlock, size_t size, size_t oldsize);
152};
153class CFXMEM_Pages
154{
155public:
156    CFXMEM_Page*	m_pStartPage;
157    CFXMEM_Page*	m_pLimitPos;
158    CFXMEM_Page*	m_pCurPage;
159    size_t			m_nPageSize;
160    void		Initialize(FX_LPBYTE pStart, size_t pageSize, size_t pages);
161    FX_BOOL		IsEmpty() const;
162    FX_LPVOID	Alloc(size_t size);
163    FX_LPVOID	Realloc(FX_LPVOID p, size_t oldSize, size_t newSize);
164    void		Free(FX_LPVOID p);
165};
166class CFXMEM_Pool
167{
168public:
169    CFXMEM_Pool*			m_pPrevPool;
170    CFXMEM_Pool*			m_pNextPool;
171    CFXMEM_8BytesPages		m_8BytesPages;
172    CFXMEM_16BytesPages		m_16BytesPages;
173    CFXMEM_32BytesPages		m_32BytesPages;
174    CFXMEM_Pages			m_MidPages;
175    FX_BOOL					m_bAlone;
176    FX_DWORD				m_dwReserved[3];
177    FX_LPVOID				m_pLimitPos;
178    CFXMEM_Page*			m_pLargePage;
179    void		Initialize(const FX_MEMCONFIG* pMemConfig, size_t size, size_t pageNum8Bytes, size_t pageNum16Bytes, size_t pageNum32Bytes, size_t pageNumMid);
180    FX_BOOL		IsEmpty() const;
181    size_t		GetSize(FX_LPVOID p) const;
182    FX_LPVOID	Realloc(FX_LPVOID p, size_t oldSize, size_t newSize);
183    void		Free(FX_LPVOID p);
184};
185class CFXMEM_FixedMgr
186{
187public:
188    void			Initialize(size_t size);
189    FX_LPVOID		Alloc(size_t size);
190    FX_LPVOID		Realloc(FX_LPVOID p, size_t newSize);
191    void			Free(FX_LPVOID p);
192    void			FreeAll();
193    void			Purge();
194    CFXMEM_Pool*	GetFirstPool()
195    {
196        return &m_FirstPool;
197    }
198    size_t			GetSize(FX_LPVOID p) const;
199    FXMEM_SystemMgr		m_SystemMgr;
200    FXMEM_SystemMgr2*	m_pExtender;
201    FX_LPVOID			m_pReserved;
202    FX_MEMCONFIG		m_MemConfig;
203protected:
204    FX_LPVOID		Alloc16(CFXMEM_Pool **pp32Pool = NULL, size_t size = 0);
205    FX_LPVOID		Alloc32(size_t size);
206    FX_LPVOID		AllocSmall(size_t size);
207    FX_LPVOID		AllocMid(size_t size);
208    FX_LPVOID		AllocLarge(size_t size);
209    FX_LPVOID		ReallocSmall(CFXMEM_Pool* pPool, FX_LPVOID p, size_t oldSize, size_t newSize);
210    void			FreePool(CFXMEM_Pool* pPool);
211    CFXMEM_Pool		m_FirstPool;
212};
213#define FIXEDMEM_PROXYSIZE_0	(1024 * 1024 * 8)
214#define FIXEDMEM_PROXYSIZE_1	(1024 * 1024 * 16)
215#define FIXEDMEM_PROXYSIZE_2	(1024 * 1024 * 32)
216#define FIXEDMEM_PROXYSIZE_3	(1024 * 1024 * 64)
217#define FIXEDMEM_PROXYSIZE_4	(1024 * 1024 * 128)
218#define FIXEDMEM_PROXYSIZE_5	(1024 * 1024 * 256)
219const FX_MEMCONFIG*	FixedMgr_GetConfig(size_t nSize);
220class CFixedMgr_Proxy
221{
222public:
223    FXMEM_FoxitMgr*	Initialize(FX_LPVOID pBuffer, size_t nSize, FX_BOOL bExtensible);
224    static FX_BOOL	Common_More(FXMEM_SystemMgr2* pMgr, size_t alloc_size, void** new_memory, size_t* new_size);
225    static void		Common_Free(FXMEM_SystemMgr2* pMgr, void* memory);
226    FXMEM_SystemMgr2	m_SystemMgr;
227    CFXMEM_Page*		m_pFixedPage;
228    FX_LPVOID			m_pBuffer;
229    size_t				m_nSize;
230    FX_BOOL				m_bExtensible;
231};
232#endif
233