1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is [Open Source Virtual Machine.].
17 * The Initial Developer of the Original Code is
18 * Adobe System Incorporated.
19 * Portions created by the Initial Developer are Copyright (C) 2004-2006
20 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
47 virtual ~GCAllocBase();
48 virtual void Free(const void* item
) = 0;
51 // Some common functionality for GCAlloc and GCLargeAlloc follows. (Could be
52 // in a separate header file.)
55 * Common block header for GCAlloc and GCLargeAlloc.
59 GC
* gc
; // The GC that owns this block
60 GCAllocBase
* alloc
; // the allocator that owns this block
61 GCBlockHeader
* next
; // The next block in the list of blocks for the allocator
62 uint32_t size
; // Size of objects stored in this block
65 GCBlockHeader
* GetBlockHeader(const void* item
);
69 * This is a fast, fixed-size memory allocator for garbage-collected
72 * Memory is allocated from the system on 4096-byte aligned boundaries,
73 * which corresponds to the size of an OS page in Windows XP. Allocation
74 * of pages is performed via the GCPageAlloc class.
76 * In each 4096-byte block, there is a block header with marked bits,
77 * finalize bits, the pointer to the next free item and "recycling"
78 * free item linked list.
80 * The bits of the "marked" bitmap are controlled by the SetMark method.
82 * The bits of the "finalize" bitmap are set when an item is
83 * allocated. The value for the finalize bit is passed in as a
84 * parameter to the allocation call.
86 * When the Sweep method is invoked, all objects that are not marked
87 * with the specified mark flag are disposed of. If the corresponding
88 * finalize bit is set, the GCObject destructor is invoked on that
91 * When an allocation is requested and there are no more free
92 * entries, GCAlloc will request that a garbage collection take
93 * place. It will allocate new blocks if more than 20% of its
94 * blocks are used after the collection, targeting a 5:1
95 * heap size / minimim heap size ratio.
98 class GCAlloc
: public GCAllocBase
101 friend class GCAllocIterator
;
105 enum ItemBit
{ kMark
=1, kQueued
=2, kFinalize
=4, kHasWeakRef
=8, kFreelist
=kMark
|kQueued
};
107 GCAlloc(GC
* gc
, int itemSize
, bool containsPointers
, bool isRC
, int sizeClassIndex
);
110 #if defined DEBUG || defined MMGC_MEMORY_PROFILER
111 void* Alloc(size_t size
, int flags
);
113 void* Alloc(int flags
);
115 virtual void Free(const void* item
);
121 void CheckFreelist();
124 static int SetMark(const void *item
);
127 static int SetFinalize(const void *item
);
130 static bool IsWhite(const void *item
);
133 static int GetMark(const void *item
);
135 static void *FindBeginning(const void *item
);
137 static bool IsMarkedThenMakeQueued(const void *item
);
139 static bool IsQueued(const void *item
);
141 static bool IsQueued(GCBlock
*block
, int index
);
144 static void ClearFinalized(const void *item
);
147 static int IsFinalized(const void *item
);
150 static int HasWeakRef(const void *item
);
152 // Very hot: called in the inner loop of GC::MarkItem
153 static bool ContainsPointers(const void *item
);
155 // Can be hot - used by PinStackObjects
156 static bool IsRCObject(const void *item
);
158 static bool IsUnmarkedPointer(const void *val
);
160 REALLY_INLINE
uint32_t GetItemSize() { return m_itemSize
; }
161 REALLY_INLINE
int GetNumAlloc() const { return m_numAlloc
; }
162 REALLY_INLINE
int GetMaxAlloc() const { return m_maxAlloc
; }
163 REALLY_INLINE
int GetNumBlocks() const { return m_numBlocks
; }
165 REALLY_INLINE
bool ContainsPointers() const { return containsPointers
; }
166 REALLY_INLINE
bool ContainsRCObjects() const { return containsRCObjects
; }
168 void GetBitsPages(void **pages
);
171 static void SetHasWeakRef(const void *item
, bool to
);
173 //This method returns the number bytes allocated for GC objects
174 size_t GetBytesInUse();
176 //This method is for more fine grained allocation details
177 //It reports the total number of bytes requested (i.e. ask size) and
178 //the number of bytes actually allocated. The latter is the same
179 //number as reported by GetBytesInUse()
180 void GetUsageInfo(size_t& totalAskSize
, size_t& totalAllocated
);
182 #ifdef MMGC_MEMORY_PROFILER
183 size_t GetTotalAskSize() { return m_totalAskSize
; }
187 const static int kBlockSize
= 4096;
189 const static short kFlagNeedsSweeping
= 1; // set if the block had finalized objects and needs to be swept
190 const static short kFlagWeakRefs
= 2; // set if the block may have weak refs and we should check during free
192 // Objects on the free list all have a next pointer in the first word and
193 // the object index within its block as the second word. Only the low 16 bits
194 // of the second word are significant: the reference counter messes around
195 // with the high 16 bits during pinning; it may pin dead objects. Those that
196 // use the index must be careful to mask off the high bits.
198 struct GCBlock
: GCBlockHeader
200 GCBlock
* prev
; // the previous block on the list of all blocks ('next' is in the block header)
201 void* firstFree
; // first item on free list
202 GCBlock
*prevFree
; // the previous block on the lists of blocks with free or sweepable objects
203 GCBlock
*nextFree
; // the next block on the lists of blocks with free or sweepable objects
204 uint32_t* bits
; // the header bits for this block
205 short numFree
; // the number of free objects in this block
206 uint8_t slowFlags
; // flags for special circumstances: kFlagNeedsSweeping, etc
207 bool finalizeState
:1; // whether we've been visited during the Finalize stage
208 char *items
; // pointer to the array of objects in the block
210 int GetCount() const;
211 uint32_t *GetBits() const;
212 void FreeSweptItem(const void *item
, int index
);
214 void setNeedsSweeping(int v
);
217 static GCBlock
*GetBlock(const void *item
);
219 #ifdef MMGC_MEMORY_INFO
220 static void VerifyFreeBlockIntegrity(const void* item
, uint32_t size
, uint32_t limit
=~0U);
223 // The list of chunk blocks
224 GCBlock
* m_firstBlock
;
225 GCBlock
* m_lastBlock
;
227 // The lowest priority block that has free items
228 GCBlock
* m_firstFree
;
230 // List of blocks that need sweeping
231 GCBlock
* m_needsSweeping
;
233 // Quick list of free objects. See comment in GCAlloc.cpp for general information.
235 void *m_qList
; // Linked list of some free objects for this allocator
236 int m_qBudget
; // Number of items we can yet free before obtaining a larger budget
237 int m_qBudgetObtained
; // Quick list budget actually obtained from the GC for this allocator
241 int m_numBitmapBytes
;
242 int m_sizeClassIndex
;
244 #ifdef MMGC_MEMORY_PROFILER
245 size_t m_totalAskSize
;
254 // fast divide numbers
258 bool containsPointers
;
259 bool containsRCObjects
;
263 bool IsOnEitherList(GCBlock
*b
);
264 void VerifyNotFree(GCBlock
* b
, const void *item
);
267 GCBlock
* CreateChunk(int flags
);
268 void UnlinkChunk(GCBlock
*b
);
269 void FreeChunk(GCBlock
* b
);
272 void AddToFreeList(GCBlock
*b
);
275 void RemoveFromFreeList(GCBlock
*b
);
278 void AddToSweepList(GCBlock
*b
);
281 void RemoveFromSweepList(GCBlock
*b
);
283 #if defined DEBUG || defined MMGC_MEMORY_PROFILER
284 void* AllocSlow(size_t askSize
, int flags
);
285 void* AllocFromQuickList(size_t askSize
, int flags
);
287 void* AllocSlow(int flags
);
288 void* AllocFromQuickList(int flags
);
290 void FillQuickList(GCBlock
* b
);
291 void CoalesceQuickList();
292 void QuickListBudgetExhausted();
293 void FreeSlow(GCBlock
* b
, int index
, const void* item
);
294 void ClearNonRCObject(void* item
, size_t size
);
296 bool Sweep(GCBlock
*b
);
297 void SweepGuts(GCBlock
*b
);
299 void ClearMarks(GCAlloc::GCBlock
* block
);
300 void SweepNeedsSweeping();
303 static int ConservativeGetMark(const void *item
, bool bogusPointerReturnValue
);
307 static int GetIndex(const GCBlock
*block
, const void *item
);
309 static int SetBit(GCBlock
*block
, int index
, int bit
);
311 static int GetBit(GCBlock
*block
, int index
, int bit
);
313 static void ClearBits(GCBlock
*block
, int index
, int bits
);
315 static void Clear4BitsAndSet(GCBlock
*block
, int index
, int bit
);
318 static void ClearQueued(const void *item
);
321 static bool IsPointerIntoGCObject(const void *item
);
323 static bool IsWhite(GCBlock
*block
, int index
);
326 void ComputeMultiplyShift(uint16_t d
, uint16_t &muli
, uint16_t &shft
);
332 static GCBlock
* Next(GCBlock
* b
);
336 * A utility class used by the marker to handle mark stack overflow: it abstracts
337 * iterating across marked, non-free objects in one allocator instance.
339 * No blocks must be added or removed during the iteration. If an object's
340 * bits are changed, those changes will visible to the iterator if the object has
341 * not yet been reached by the iteration.
343 class GCAllocIterator
346 GCAllocIterator(MMgc::GCAlloc
* alloc
);
348 bool GetNextMarkedObject(void*& out_ptr
, uint32_t& out_size
);
351 GCAlloc
* const alloc
;
352 GCAlloc::GCBlock
* block
;
359 #endif /* __GCAlloc__ */