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 ***** */
39 #ifndef __GCAlloc_inlines__
40 #define __GCAlloc_inlines__
42 // Inline functions for GCAlloc, GCAlloc::GCBlock, and GCAllocIterator
46 REALLY_INLINE GCBlockHeader
* GetBlockHeader(const void* item
)
48 return (GCBlockHeader
*)(uintptr_t(item
) & ~0xFFF);
52 REALLY_INLINE
GCAlloc::GCBlock
*GCAlloc::GetBlock(const void *item
)
54 return (GCBlock
*)GetBlockHeader(item
);
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
;
71 *bits
&= ~(kQueued
<< ((index
&7)<<2));
76 REALLY_INLINE
int GCAlloc::SetFinalize(const void *item
)
78 GCBlock
*block
= GetBlock(item
);
79 return SetBit(block
, GetIndex(block
, item
), kFinalize
);
83 REALLY_INLINE
int GCAlloc::GetMark(const void *item
)
85 GCBlock
*block
= GetBlock(item
);
86 return GetBit(block
, GetIndex(block
, item
), kMark
);
90 REALLY_INLINE
void *GCAlloc::FindBeginning(const void *item
)
92 GCBlock
*block
= GetBlock(item
);
93 return block
->items
+ block
->size
* GetIndex(block
, item
);
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);
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;
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;
126 REALLY_INLINE
void GCAlloc::ClearFinalized(const void *item
)
128 GCBlock
*block
= GetBlock(item
);
129 ClearBits(block
, GetIndex(block
, item
), kFinalize
);
133 REALLY_INLINE
int GCAlloc::IsFinalized(const void *item
)
135 GCBlock
*block
= GetBlock(item
);
136 return GetBit(block
, GetIndex(block
, item
), kFinalize
);
140 REALLY_INLINE
int GCAlloc::HasWeakRef(const void *item
)
142 GCBlock
*block
= GetBlock(item
);
143 return GetBit(block
, GetIndex(block
, item
), kHasWeakRef
);
147 REALLY_INLINE
bool GCAlloc::ContainsPointers(const void *item
)
149 GCBlock
*block
= GetBlock(item
);
150 return ((GCAlloc
*)block
->alloc
)->ContainsPointers();
154 REALLY_INLINE
bool GCAlloc::IsRCObject(const void *item
)
156 GCBlock
*block
= GetBlock(item
);
157 return item
>= block
->items
&& ((GCAlloc
*)block
->alloc
)->ContainsRCObjects();
161 REALLY_INLINE
void GCAlloc::SetHasWeakRef(const void *item
, bool to
)
163 GCBlock
*block
= GetBlock(item
);
165 SetBit(block
, GetIndex(block
, item
), kHasWeakRef
);
166 block
->slowFlags
|= kFlagWeakRefs
;
168 ClearBits(block
, GetIndex(block
, item
), kHasWeakRef
);
172 REALLY_INLINE
void GCAlloc::AddToFreeList(GCBlock
*b
)
174 GCAssert(!IsOnEitherList(b
) && !b
->needsSweeping());
176 b
->nextFree
= m_firstFree
;
178 GCAssert(m_firstFree
->prevFree
== 0 && m_firstFree
!= b
);
179 m_firstFree
->prevFree
= 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
;
190 b
->prevFree
->nextFree
= 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());
201 b
->nextFree
= m_needsSweeping
;
202 if (m_needsSweeping
) {
203 GCAssert(m_needsSweeping
->prevFree
== 0);
204 m_needsSweeping
->prevFree
= 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
;
216 b
->prevFree
->nextFree
= b
->nextFree
;
219 b
->nextFree
->prevFree
= b
->prevFree
;
220 b
->setNeedsSweeping(0);
221 b
->nextFree
= b
->prevFree
= NULL
;
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
);
229 GCAssert(((char*) item
- block
->items
) / block
->size
== (uint32_t) index
);
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
;
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
;
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
;
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));
265 REALLY_INLINE
void GCAlloc::ClearQueued(const void *item
)
267 GCBlock
*block
= GetBlock(item
);
268 ClearBits(block
, GetIndex(block
, item
), kQueued
);
273 REALLY_INLINE
bool GCAlloc::IsPointerIntoGCObject(const void *item
)
275 GCBlock
*block
= GetBlock(item
);
276 if(item
< block
->items
)
278 return GetBit(block
, GetIndex(block
, item
), kFreelist
) != kFreelist
;
282 REALLY_INLINE
bool GCAlloc::IsWhite(GCBlock
*block
, int index
)
284 return (block
->GetBits()[index
>>3] & ((kMark
|kQueued
)<<((index
&7)<<2))) == 0;
288 REALLY_INLINE
bool GCAlloc::IsWhite(const void *item
)
290 GCBlock
*block
= GetBlock(item
);
292 if(item
< block
->items
)
295 if(FindBeginning(item
) != item
)
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
;
308 REALLY_INLINE
int GCAlloc::GCBlock::GetCount() const
310 return ((GCAlloc
*)alloc
)->m_itemsPerBlock
;
313 REALLY_INLINE
uint32_t *GCAlloc::GCBlock::GetBits() const
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
)
331 , block(alloc
->m_firstBlock
)
333 , limit(alloc
->m_itemsPerBlock
)
334 , size(alloc
->m_itemSize
)
338 REALLY_INLINE
bool GCAllocIterator::GetNextMarkedObject(void*& out_ptr
, uint32_t& out_size
)
343 block
= GCAlloc::Next(block
);
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();
357 #endif /* __GCAlloc_inlines__ */