merge from argo
[tamarin-stm.git] / MMgc / GCAlloc-inlines.h
bloba4bef718b49c265c3967d42fe9eed157095a3415
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
13 * License.
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.
22 * Contributor(s):
23 * Adobe AS3 Team
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 ***** */
39 #ifndef __GCAlloc_inlines__
40 #define __GCAlloc_inlines__
42 // Inline functions for GCAlloc, GCAlloc::GCBlock, and GCAllocIterator
44 namespace MMgc
46 REALLY_INLINE GCBlockHeader* GetBlockHeader(const void* item)
48 return (GCBlockHeader*)(uintptr_t(item) & ~0xFFF);
51 /*static*/
52 REALLY_INLINE GCAlloc::GCBlock *GCAlloc::GetBlock(const void *item)
54 return (GCBlock*)GetBlockHeader(item);
57 /*static*/
58 REALLY_INLINE GCAlloc::GCBlock* GCAlloc::Next(GCAlloc::GCBlock* b)
60 return (GCBlock*)b->next;
63 REALLY_INLINE int GCAlloc::SetMark(const void *item)
65 GCBlock *block = GetBlock(item);
66 int index = GetIndex(block, item);
67 int mask = kMark << ((index&7)<<2);
68 uint32_t *bits = &block->GetBits()[index>>3];
69 int set = *bits & mask;
70 *bits |= mask;
71 *bits &= ~(kQueued << ((index&7)<<2));
72 return set;
75 /*static*/
76 REALLY_INLINE int GCAlloc::SetFinalize(const void *item)
78 GCBlock *block = GetBlock(item);
79 return SetBit(block, GetIndex(block, item), kFinalize);
82 /*static*/
83 REALLY_INLINE int GCAlloc::GetMark(const void *item)
85 GCBlock *block = GetBlock(item);
86 return GetBit(block, GetIndex(block, item), kMark);
89 /*static*/
90 REALLY_INLINE void *GCAlloc::FindBeginning(const void *item)
92 GCBlock *block = GetBlock(item);
93 return block->items + block->size * GetIndex(block, item);
96 /*static*/
97 REALLY_INLINE bool GCAlloc::IsMarkedThenMakeQueued(const void *item)
99 GCBlock *block = GetBlock(item);
100 int index = GetIndex(block, item);
101 uint32_t* bits = block->GetBits() + (index >> 3);
102 if (*bits & (kMark << ((index&7)<<2))) {
103 *bits ^= (kMark|kQueued) << ((index&7)<<2);
104 return true;
106 return false;
109 /*static*/
110 REALLY_INLINE bool GCAlloc::IsQueued(const void *item)
112 GCBlock *block = GetBlock(item);
113 int index = GetIndex(block, item);
114 uint32_t* bits = block->GetBits() + (index >> 3);
115 return (*bits & (kQueued << ((index&7)<<2))) != 0;
118 /*static*/
119 REALLY_INLINE bool GCAlloc::IsQueued(GCAlloc::GCBlock *block, int index)
121 uint32_t* bits = block->GetBits() + (index >> 3);
122 return (*bits & (kQueued << ((index&7)<<2))) != 0;
125 /*static*/
126 REALLY_INLINE void GCAlloc::ClearFinalized(const void *item)
128 GCBlock *block = GetBlock(item);
129 ClearBits(block, GetIndex(block, item), kFinalize);
132 /*static*/
133 REALLY_INLINE int GCAlloc::IsFinalized(const void *item)
135 GCBlock *block = GetBlock(item);
136 return GetBit(block, GetIndex(block, item), kFinalize);
139 /*static*/
140 REALLY_INLINE int GCAlloc::HasWeakRef(const void *item)
142 GCBlock *block = GetBlock(item);
143 return GetBit(block, GetIndex(block, item), kHasWeakRef);
146 /*static*/
147 REALLY_INLINE bool GCAlloc::ContainsPointers(const void *item)
149 GCBlock *block = GetBlock(item);
150 return ((GCAlloc*)block->alloc)->ContainsPointers();
153 /*static*/
154 REALLY_INLINE bool GCAlloc::IsRCObject(const void *item)
156 GCBlock *block = GetBlock(item);
157 return item >= block->items && ((GCAlloc*)block->alloc)->ContainsRCObjects();
160 /*static*/
161 REALLY_INLINE void GCAlloc::SetHasWeakRef(const void *item, bool to)
163 GCBlock *block = GetBlock(item);
164 if(to) {
165 SetBit(block, GetIndex(block, item), kHasWeakRef);
166 block->slowFlags |= kFlagWeakRefs;
167 } else {
168 ClearBits(block, GetIndex(block, item), kHasWeakRef);
172 REALLY_INLINE void GCAlloc::AddToFreeList(GCBlock *b)
174 GCAssert(!IsOnEitherList(b) && !b->needsSweeping());
175 b->prevFree = NULL;
176 b->nextFree = m_firstFree;
177 if (m_firstFree) {
178 GCAssert(m_firstFree->prevFree == 0 && m_firstFree != b);
179 m_firstFree->prevFree = b;
181 m_firstFree = b;
184 REALLY_INLINE void GCAlloc::RemoveFromFreeList(GCBlock *b)
186 GCAssert(m_firstFree == b || b->prevFree != NULL);
187 if ( m_firstFree == b )
188 m_firstFree = b->nextFree;
189 else
190 b->prevFree->nextFree = b->nextFree;
192 if (b->nextFree)
193 b->nextFree->prevFree = b->prevFree;
194 b->nextFree = b->prevFree = NULL;
197 REALLY_INLINE void GCAlloc::AddToSweepList(GCBlock *b)
199 GCAssert(!IsOnEitherList(b) && !b->needsSweeping());
200 b->prevFree = NULL;
201 b->nextFree = m_needsSweeping;
202 if (m_needsSweeping) {
203 GCAssert(m_needsSweeping->prevFree == 0);
204 m_needsSweeping->prevFree = b;
206 m_needsSweeping = b;
207 b->setNeedsSweeping(kFlagNeedsSweeping);
210 REALLY_INLINE void GCAlloc::RemoveFromSweepList(GCBlock *b)
212 GCAssert(m_needsSweeping == b || b->prevFree != NULL);
213 if ( m_needsSweeping == b )
214 m_needsSweeping = b->nextFree;
215 else
216 b->prevFree->nextFree = b->nextFree;
218 if (b->nextFree)
219 b->nextFree->prevFree = b->prevFree;
220 b->setNeedsSweeping(0);
221 b->nextFree = b->prevFree = NULL;
224 /*static*/
225 REALLY_INLINE int GCAlloc::GetIndex(const GCBlock *block, const void *item)
227 int index = (int)((((char*) item - block->items) * ((GCAlloc*)block->alloc)->multiple) >> ((GCAlloc*)block->alloc)->shift);
228 #ifdef _DEBUG
229 GCAssert(((char*) item - block->items) / block->size == (uint32_t) index);
230 #endif
231 return index;
234 /*static*/
235 REALLY_INLINE int GCAlloc::SetBit(GCBlock *block, int index, int bit)
237 int mask = bit << ((index&7)<<2);
238 int set = (block->GetBits()[index>>3] & mask);
239 block->GetBits()[index>>3] |= mask;
240 return set;
243 /*static*/
244 REALLY_INLINE int GCAlloc::GetBit(GCBlock *block, int index, int bit)
246 int mask = bit << ((index&7)<<2);
247 return block->GetBits()[index>>3] & mask;
250 /*static*/
251 REALLY_INLINE void GCAlloc::ClearBits(GCBlock *block, int index, int bits)
253 int mask = bits << ((index&7)<<2);
254 block->GetBits()[index>>3] &= ~mask;
257 /*static*/
258 REALLY_INLINE void GCAlloc::Clear4BitsAndSet(GCBlock *block, int index, int bit)
260 uint32_t *bitp = &(block->GetBits()[index>>3]);
261 *bitp = (*bitp & ~(15 << ((index & 7) << 2))) | (bit << ((index & 7) << 2));
264 /*static*/
265 REALLY_INLINE void GCAlloc::ClearQueued(const void *item)
267 GCBlock *block = GetBlock(item);
268 ClearBits(block, GetIndex(block, item), kQueued);
271 #ifdef _DEBUG
272 /*static*/
273 REALLY_INLINE bool GCAlloc::IsPointerIntoGCObject(const void *item)
275 GCBlock *block = GetBlock(item);
276 if(item < block->items)
277 return false;
278 return GetBit(block, GetIndex(block, item), kFreelist) != kFreelist;
281 /*static*/
282 REALLY_INLINE bool GCAlloc::IsWhite(GCBlock *block, int index)
284 return (block->GetBits()[index>>3] & ((kMark|kQueued)<<((index&7)<<2))) == 0;
287 /*static*/
288 REALLY_INLINE bool GCAlloc::IsWhite(const void *item)
290 GCBlock *block = GetBlock(item);
291 // not a real item
292 if(item < block->items)
293 return false;
295 if(FindBeginning(item) != item)
296 return false;
298 return IsWhite(block, GetIndex(block, item));
301 REALLY_INLINE bool GCAlloc::IsOnEitherList(GCBlock *b)
303 return b->nextFree != NULL || b->prevFree != NULL || b == m_firstFree || b == m_needsSweeping;
305 #endif // _DEBUG
308 REALLY_INLINE int GCAlloc::GCBlock::GetCount() const
310 return ((GCAlloc*)alloc)->m_itemsPerBlock;
313 REALLY_INLINE uint32_t *GCAlloc::GCBlock::GetBits() const
315 return bits;
318 REALLY_INLINE int GCAlloc::GCBlock::needsSweeping()
320 return slowFlags & kFlagNeedsSweeping;
323 REALLY_INLINE void GCAlloc::GCBlock::setNeedsSweeping(int v)
325 GCAssert(v == 0 || v == kFlagNeedsSweeping);
326 slowFlags = (uint8_t)((slowFlags & ~kFlagNeedsSweeping) | v);
329 REALLY_INLINE GCAllocIterator::GCAllocIterator(MMgc::GCAlloc* alloc)
330 : alloc(alloc)
331 , block(alloc->m_firstBlock)
332 , idx(0)
333 , limit(alloc->m_itemsPerBlock)
334 , size(alloc->m_itemSize)
338 REALLY_INLINE bool GCAllocIterator::GetNextMarkedObject(void*& out_ptr, uint32_t& out_size)
340 for (;;) {
341 if (idx == limit) {
342 idx = 0;
343 block = GCAlloc::Next(block);
345 if (block == NULL)
346 return false;
347 uint32_t i = idx++;
348 if (GCAlloc::GetBit(block, i, MMgc::GCAlloc::kMark) && !GCAlloc::GetBit(block, i, MMgc::GCAlloc::kQueued)) {
349 out_ptr = GetUserPointer(block->items + i*size);
350 out_size = size - (uint32_t)DebugSize();
351 return true;
357 #endif /* __GCAlloc_inlines__ */