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 "MachineStackMarker.h"
26 #include "MarkedAllocator.h"
27 #include "MarkedBlock.h"
28 #include "MarkedBlockSet.h"
30 #include <wtf/PageAllocationAligned.h>
31 #include <wtf/Bitmap.h>
32 #include <wtf/DoublyLinkedList.h>
33 #include <wtf/HashSet.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Vector.h>
39 class DelayedReleaseScope
;
41 class HeapIterationScope
;
43 class LiveObjectIterator
;
44 class LLIntOffsetsExtractor
;
48 struct ClearMarks
: MarkedBlock::VoidFunctor
{
49 void operator()(MarkedBlock
* block
)
55 struct ClearRememberedSet
: MarkedBlock::VoidFunctor
{
56 void operator()(MarkedBlock
* block
)
58 block
->clearRememberedSet();
62 struct Sweep
: MarkedBlock::VoidFunctor
{
63 void operator()(MarkedBlock
* block
) { block
->sweep(); }
66 struct ZombifySweep
: MarkedBlock::VoidFunctor
{
67 void operator()(MarkedBlock
* block
)
69 if (block
->needsSweeping())
74 struct MarkCount
: MarkedBlock::CountFunctor
{
75 void operator()(MarkedBlock
* block
) { count(block
->markCount()); }
78 struct Size
: MarkedBlock::CountFunctor
{
79 void operator()(MarkedBlock
* block
) { count(block
->markCount() * block
->cellSize()); }
83 WTF_MAKE_NONCOPYABLE(MarkedSpace
);
87 void lastChanceToFinalize();
89 MarkedAllocator
& firstAllocator();
90 MarkedAllocator
& allocatorFor(size_t);
91 MarkedAllocator
& immortalStructureDestructorAllocatorFor(size_t);
92 MarkedAllocator
& normalDestructorAllocatorFor(size_t);
93 void* allocateWithNormalDestructor(size_t);
94 void* allocateWithImmortalStructureDestructor(size_t);
95 void* allocateWithoutDestructor(size_t);
97 void resetAllocators();
99 void visitWeakSets(HeapRootVisitor
&);
102 MarkedBlockSet
& blocks() { return m_blocks
; }
104 void willStartIterating();
105 bool isIterating() { return m_isIterating
; }
106 void didFinishIterating();
108 void stopAllocating();
109 void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation.
111 typedef HashSet
<MarkedBlock
*>::iterator BlockIterator
;
113 template<typename Functor
> typename
Functor::ReturnType
forEachLiveCell(HeapIterationScope
&, Functor
&);
114 template<typename Functor
> typename
Functor::ReturnType
forEachLiveCell(HeapIterationScope
&);
115 template<typename Functor
> typename
Functor::ReturnType
forEachDeadCell(HeapIterationScope
&, Functor
&);
116 template<typename Functor
> typename
Functor::ReturnType
forEachDeadCell(HeapIterationScope
&);
117 template<typename Functor
> typename
Functor::ReturnType
forEachBlock(Functor
&);
118 template<typename Functor
> typename
Functor::ReturnType
forEachBlock();
121 void freeBlock(MarkedBlock
*);
122 void freeOrShrinkBlock(MarkedBlock
*);
124 void didAddBlock(MarkedBlock
*);
125 void didConsumeFreeList(MarkedBlock
*);
126 void didAllocateInBlock(MarkedBlock
*);
129 void clearRememberedSet();
130 void clearNewlyAllocated();
133 size_t objectCount();
137 bool isPagedOut(double deadline
);
140 template<typename T
> void releaseSoon(RetainPtr
<T
>&&);
144 friend class DelayedReleaseScope
;
145 friend class LLIntOffsetsExtractor
;
147 template<typename Functor
> void forEachAllocator(Functor
&);
148 template<typename Functor
> void forEachAllocator();
151 static const size_t preciseStep
= MarkedBlock::atomSize
;
152 static const size_t preciseCutoff
= 128;
153 static const size_t preciseCount
= preciseCutoff
/ preciseStep
;
155 // [ 1024... blockSize ]
156 static const size_t impreciseStep
= 2 * preciseCutoff
;
157 static const size_t impreciseCutoff
= MarkedBlock::blockSize
/ 2;
158 static const size_t impreciseCount
= impreciseCutoff
/ impreciseStep
;
161 std::array
<MarkedAllocator
, preciseCount
> preciseAllocators
;
162 std::array
<MarkedAllocator
, impreciseCount
> impreciseAllocators
;
163 MarkedAllocator largeAllocator
;
166 Subspace m_normalDestructorSpace
;
167 Subspace m_immortalStructureDestructorSpace
;
168 Subspace m_normalSpace
;
173 MarkedBlockSet m_blocks
;
174 Vector
<MarkedBlock
*> m_blocksWithNewObjects
;
176 DelayedReleaseScope
* m_currentDelayedReleaseScope
;
179 template<typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachLiveCell(HeapIterationScope
&, Functor
& functor
)
181 ASSERT(isIterating());
182 BlockIterator end
= m_blocks
.set().end();
183 for (BlockIterator it
= m_blocks
.set().begin(); it
!= end
; ++it
)
184 (*it
)->forEachLiveCell(functor
);
185 return functor
.returnValue();
188 template<typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachLiveCell(HeapIterationScope
& scope
)
191 return forEachLiveCell(scope
, functor
);
194 template<typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachDeadCell(HeapIterationScope
&, Functor
& functor
)
196 ASSERT(isIterating());
197 BlockIterator end
= m_blocks
.set().end();
198 for (BlockIterator it
= m_blocks
.set().begin(); it
!= end
; ++it
)
199 (*it
)->forEachDeadCell(functor
);
200 return functor
.returnValue();
203 template<typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachDeadCell(HeapIterationScope
& scope
)
206 return forEachDeadCell(scope
, functor
);
209 inline MarkedAllocator
& MarkedSpace::allocatorFor(size_t bytes
)
212 if (bytes
<= preciseCutoff
)
213 return m_normalSpace
.preciseAllocators
[(bytes
- 1) / preciseStep
];
214 if (bytes
<= impreciseCutoff
)
215 return m_normalSpace
.impreciseAllocators
[(bytes
- 1) / impreciseStep
];
216 return m_normalSpace
.largeAllocator
;
219 inline MarkedAllocator
& MarkedSpace::immortalStructureDestructorAllocatorFor(size_t bytes
)
222 if (bytes
<= preciseCutoff
)
223 return m_immortalStructureDestructorSpace
.preciseAllocators
[(bytes
- 1) / preciseStep
];
224 if (bytes
<= impreciseCutoff
)
225 return m_immortalStructureDestructorSpace
.impreciseAllocators
[(bytes
- 1) / impreciseStep
];
226 return m_immortalStructureDestructorSpace
.largeAllocator
;
229 inline MarkedAllocator
& MarkedSpace::normalDestructorAllocatorFor(size_t bytes
)
232 if (bytes
<= preciseCutoff
)
233 return m_normalDestructorSpace
.preciseAllocators
[(bytes
- 1) / preciseStep
];
234 if (bytes
<= impreciseCutoff
)
235 return m_normalDestructorSpace
.impreciseAllocators
[(bytes
- 1) / impreciseStep
];
236 return m_normalDestructorSpace
.largeAllocator
;
239 inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes
)
241 return allocatorFor(bytes
).allocate(bytes
);
244 inline void* MarkedSpace::allocateWithImmortalStructureDestructor(size_t bytes
)
246 return immortalStructureDestructorAllocatorFor(bytes
).allocate(bytes
);
249 inline void* MarkedSpace::allocateWithNormalDestructor(size_t bytes
)
251 return normalDestructorAllocatorFor(bytes
).allocate(bytes
);
254 template <typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachBlock(Functor
& functor
)
256 for (size_t i
= 0; i
< preciseCount
; ++i
)
257 m_normalSpace
.preciseAllocators
[i
].forEachBlock(functor
);
258 for (size_t i
= 0; i
< impreciseCount
; ++i
)
259 m_normalSpace
.impreciseAllocators
[i
].forEachBlock(functor
);
260 m_normalSpace
.largeAllocator
.forEachBlock(functor
);
262 for (size_t i
= 0; i
< preciseCount
; ++i
)
263 m_normalDestructorSpace
.preciseAllocators
[i
].forEachBlock(functor
);
264 for (size_t i
= 0; i
< impreciseCount
; ++i
)
265 m_normalDestructorSpace
.impreciseAllocators
[i
].forEachBlock(functor
);
266 m_normalDestructorSpace
.largeAllocator
.forEachBlock(functor
);
268 for (size_t i
= 0; i
< preciseCount
; ++i
)
269 m_immortalStructureDestructorSpace
.preciseAllocators
[i
].forEachBlock(functor
);
270 for (size_t i
= 0; i
< impreciseCount
; ++i
)
271 m_immortalStructureDestructorSpace
.impreciseAllocators
[i
].forEachBlock(functor
);
272 m_immortalStructureDestructorSpace
.largeAllocator
.forEachBlock(functor
);
274 return functor
.returnValue();
277 template <typename Functor
> inline typename
Functor::ReturnType
MarkedSpace::forEachBlock()
280 return forEachBlock(functor
);
283 inline void MarkedSpace::didAddBlock(MarkedBlock
* block
)
285 m_capacity
+= block
->capacity();
289 inline void MarkedSpace::didAllocateInBlock(MarkedBlock
* block
)
292 m_blocksWithNewObjects
.append(block
);
298 inline void MarkedSpace::clearRememberedSet()
300 forEachBlock
<ClearRememberedSet
>();
303 inline size_t MarkedSpace::objectCount()
305 return forEachBlock
<MarkCount
>();
308 inline size_t MarkedSpace::size()
310 return forEachBlock
<Size
>();
313 inline size_t MarkedSpace::capacity()
320 #endif // MarkedSpace_h