2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <wtf/Bitmap.h>
26 #include <wtf/PageAllocationAligned.h>
27 #include <wtf/StdLibExtras.h>
35 typedef uintptr_t Bits
;
37 static const size_t KB
= 1024;
41 static const size_t atomSize
= sizeof(double); // Ensures natural alignment for all built-in types.
43 static MarkedBlock
* create(JSGlobalData
*, size_t cellSize
);
44 static void destroy(MarkedBlock
*);
46 static bool isAtomAligned(const void*);
47 static MarkedBlock
* blockFor(const void*);
48 static size_t firstAtom();
52 void setPrev(MarkedBlock
*);
53 void setNext(MarkedBlock
*);
54 MarkedBlock
* prev() const;
55 MarkedBlock
* next() const;
71 bool contains(const void*);
72 size_t atomNumber(const void*);
73 bool isMarked(const void*);
74 bool testAndSetMarked(const void*);
75 void setMarked(const void*);
77 template <typename Functor
> void forEach(Functor
&);
80 static const size_t blockSize
= 16 * KB
;
81 static const size_t blockMask
= ~(blockSize
- 1); // blockSize must be a power of two.
83 static const size_t atomMask
= ~(atomSize
- 1); // atomSize must be a power of two.
85 static const size_t atomsPerBlock
= blockSize
/ atomSize
;
87 typedef char Atom
[atomSize
];
89 MarkedBlock(const PageAllocationAligned
&, JSGlobalData
*, size_t cellSize
);
93 size_t m_endAtom
; // This is a fuzzy end. Always test for < m_endAtom.
94 size_t m_atomsPerCell
;
95 WTF::Bitmap
<blockSize
/ atomSize
> m_marks
;
96 PageAllocationAligned m_allocation
;
102 inline size_t MarkedBlock::firstAtom()
104 return WTF::roundUpToMultipleOf
<atomSize
>(sizeof(MarkedBlock
)) / atomSize
;
107 inline MarkedBlock::Atom
* MarkedBlock::atoms()
109 return reinterpret_cast<Atom
*>(this);
112 inline bool MarkedBlock::isAtomAligned(const void* p
)
114 return !((intptr_t)(p
) & ~atomMask
);
117 inline MarkedBlock
* MarkedBlock::blockFor(const void* p
)
119 return reinterpret_cast<MarkedBlock
*>(reinterpret_cast<uintptr_t>(p
) & blockMask
);
122 inline Heap
* MarkedBlock::heap() const
127 inline void MarkedBlock::setPrev(MarkedBlock
* prev
)
132 inline void MarkedBlock::setNext(MarkedBlock
* next
)
137 inline MarkedBlock
* MarkedBlock::prev() const
142 inline MarkedBlock
* MarkedBlock::next() const
147 inline void MarkedBlock::reset()
149 m_nextAtom
= firstAtom();
152 inline bool MarkedBlock::isEmpty()
154 return m_marks
.isEmpty();
157 inline void MarkedBlock::clearMarks()
162 inline size_t MarkedBlock::markCount()
164 return m_marks
.count();
167 inline size_t MarkedBlock::cellSize()
169 return m_atomsPerCell
* atomSize
;
172 inline size_t MarkedBlock::size()
174 return markCount() * cellSize();
177 inline size_t MarkedBlock::capacity()
179 return m_allocation
.size();
182 inline bool MarkedBlock::contains(const void* p
)
184 ASSERT(p
&& isAtomAligned(p
) && atomNumber(p
) < atomsPerBlock
);
186 // Even though we physically contain p, we only logically contain p if p
187 // points to a live cell. (Claiming to contain a dead cell would trick the
188 // conservative garbage collector into resurrecting the cell in a zombie state.)
192 inline size_t MarkedBlock::atomNumber(const void* p
)
194 return (reinterpret_cast<uintptr_t>(p
) - reinterpret_cast<uintptr_t>(this)) / atomSize
;
197 inline bool MarkedBlock::isMarked(const void* p
)
199 return m_marks
.get(atomNumber(p
));
202 inline bool MarkedBlock::testAndSetMarked(const void* p
)
204 return m_marks
.testAndSet(atomNumber(p
));
207 inline void MarkedBlock::setMarked(const void* p
)
209 m_marks
.set(atomNumber(p
));
212 template <typename Functor
> inline void MarkedBlock::forEach(Functor
& functor
)
214 for (size_t i
= firstAtom(); i
< m_endAtom
; i
+= m_atomsPerCell
) {
217 functor(reinterpret_cast<JSCell
*>(&atoms()[i
]));
223 #endif // MarkedSpace_h