]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/MarkedSpace.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / heap / MarkedSpace.h
CommitLineData
14957cd0
A
1/*
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.
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21
22#ifndef MarkedSpace_h
23#define MarkedSpace_h
24
25#include "MachineStackMarker.h"
6fe7ccc8 26#include "MarkedAllocator.h"
14957cd0 27#include "MarkedBlock.h"
6fe7ccc8 28#include "MarkedBlockSet.h"
81345200 29#include <array>
6fe7ccc8 30#include <wtf/PageAllocationAligned.h>
14957cd0
A
31#include <wtf/Bitmap.h>
32#include <wtf/DoublyLinkedList.h>
14957cd0
A
33#include <wtf/HashSet.h>
34#include <wtf/Noncopyable.h>
35#include <wtf/Vector.h>
36
14957cd0
A
37namespace JSC {
38
81345200 39class DelayedReleaseScope;
6fe7ccc8 40class Heap;
81345200 41class HeapIterationScope;
6fe7ccc8
A
42class JSCell;
43class LiveObjectIterator;
44class LLIntOffsetsExtractor;
45class WeakGCHandle;
46class SlotVisitor;
47
93a37866 48struct ClearMarks : MarkedBlock::VoidFunctor {
81345200
A
49 void operator()(MarkedBlock* block)
50 {
51 block->clearMarks();
52 }
53};
54
55struct ClearRememberedSet : MarkedBlock::VoidFunctor {
56 void operator()(MarkedBlock* block)
57 {
58 block->clearRememberedSet();
59 }
93a37866
A
60};
61
62struct Sweep : MarkedBlock::VoidFunctor {
63 void operator()(MarkedBlock* block) { block->sweep(); }
64};
65
81345200
A
66struct ZombifySweep : MarkedBlock::VoidFunctor {
67 void operator()(MarkedBlock* block)
68 {
69 if (block->needsSweeping())
70 block->sweep();
71 }
72};
73
93a37866
A
74struct MarkCount : MarkedBlock::CountFunctor {
75 void operator()(MarkedBlock* block) { count(block->markCount()); }
76};
77
78struct Size : MarkedBlock::CountFunctor {
79 void operator()(MarkedBlock* block) { count(block->markCount() * block->cellSize()); }
80};
81
6fe7ccc8
A
82class MarkedSpace {
83 WTF_MAKE_NONCOPYABLE(MarkedSpace);
84public:
6fe7ccc8 85 MarkedSpace(Heap*);
93a37866
A
86 ~MarkedSpace();
87 void lastChanceToFinalize();
6fe7ccc8
A
88
89 MarkedAllocator& firstAllocator();
90 MarkedAllocator& allocatorFor(size_t);
93a37866
A
91 MarkedAllocator& immortalStructureDestructorAllocatorFor(size_t);
92 MarkedAllocator& normalDestructorAllocatorFor(size_t);
93 void* allocateWithNormalDestructor(size_t);
94 void* allocateWithImmortalStructureDestructor(size_t);
6fe7ccc8 95 void* allocateWithoutDestructor(size_t);
93a37866 96
6fe7ccc8
A
97 void resetAllocators();
98
93a37866
A
99 void visitWeakSets(HeapRootVisitor&);
100 void reapWeakSets();
101
6fe7ccc8 102 MarkedBlockSet& blocks() { return m_blocks; }
81345200
A
103
104 void willStartIterating();
105 bool isIterating() { return m_isIterating; }
106 void didFinishIterating();
107
108 void stopAllocating();
109 void resumeAllocating(); // If we just stopped allocation but we didn't do a collection, we need to resume allocation.
6fe7ccc8
A
110
111 typedef HashSet<MarkedBlock*>::iterator BlockIterator;
112
81345200
A
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&);
6fe7ccc8
A
117 template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
118 template<typename Functor> typename Functor::ReturnType forEachBlock();
119
120 void shrink();
93a37866
A
121 void freeBlock(MarkedBlock*);
122 void freeOrShrinkBlock(MarkedBlock*);
6fe7ccc8
A
123
124 void didAddBlock(MarkedBlock*);
125 void didConsumeFreeList(MarkedBlock*);
81345200 126 void didAllocateInBlock(MarkedBlock*);
6fe7ccc8 127
93a37866 128 void clearMarks();
81345200
A
129 void clearRememberedSet();
130 void clearNewlyAllocated();
93a37866 131 void sweep();
81345200 132 void zombifySweep();
93a37866
A
133 size_t objectCount();
134 size_t size();
135 size_t capacity();
136
6fe7ccc8
A
137 bool isPagedOut(double deadline);
138
81345200
A
139#if USE(CF)
140 template<typename T> void releaseSoon(RetainPtr<T>&&);
141#endif
142
6fe7ccc8 143private:
81345200 144 friend class DelayedReleaseScope;
6fe7ccc8 145 friend class LLIntOffsetsExtractor;
93a37866 146
81345200
A
147 template<typename Functor> void forEachAllocator(Functor&);
148 template<typename Functor> void forEachAllocator();
149
93a37866 150 // [ 32... 128 ]
6fe7ccc8 151 static const size_t preciseStep = MarkedBlock::atomSize;
93a37866 152 static const size_t preciseCutoff = 128;
6fe7ccc8
A
153 static const size_t preciseCount = preciseCutoff / preciseStep;
154
93a37866
A
155 // [ 1024... blockSize ]
156 static const size_t impreciseStep = 2 * preciseCutoff;
157 static const size_t impreciseCutoff = MarkedBlock::blockSize / 2;
6fe7ccc8
A
158 static const size_t impreciseCount = impreciseCutoff / impreciseStep;
159
160 struct Subspace {
81345200
A
161 std::array<MarkedAllocator, preciseCount> preciseAllocators;
162 std::array<MarkedAllocator, impreciseCount> impreciseAllocators;
93a37866 163 MarkedAllocator largeAllocator;
14957cd0
A
164 };
165
93a37866
A
166 Subspace m_normalDestructorSpace;
167 Subspace m_immortalStructureDestructorSpace;
6fe7ccc8
A
168 Subspace m_normalSpace;
169
170 Heap* m_heap;
81345200
A
171 size_t m_capacity;
172 bool m_isIterating;
6fe7ccc8 173 MarkedBlockSet m_blocks;
81345200
A
174 Vector<MarkedBlock*> m_blocksWithNewObjects;
175
176 DelayedReleaseScope* m_currentDelayedReleaseScope;
6fe7ccc8
A
177};
178
81345200 179template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope&, Functor& functor)
6fe7ccc8 180{
81345200 181 ASSERT(isIterating());
6fe7ccc8
A
182 BlockIterator end = m_blocks.set().end();
183 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
93a37866 184 (*it)->forEachLiveCell(functor);
6fe7ccc8
A
185 return functor.returnValue();
186}
187
81345200 188template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope& scope)
6fe7ccc8
A
189{
190 Functor functor;
81345200 191 return forEachLiveCell(scope, functor);
6fe7ccc8
A
192}
193
81345200 194template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope&, Functor& functor)
6fe7ccc8 195{
81345200 196 ASSERT(isIterating());
93a37866
A
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();
201}
202
81345200 203template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachDeadCell(HeapIterationScope& scope)
93a37866
A
204{
205 Functor functor;
81345200 206 return forEachDeadCell(scope, functor);
6fe7ccc8
A
207}
208
209inline MarkedAllocator& MarkedSpace::allocatorFor(size_t bytes)
210{
93a37866 211 ASSERT(bytes);
6fe7ccc8
A
212 if (bytes <= preciseCutoff)
213 return m_normalSpace.preciseAllocators[(bytes - 1) / preciseStep];
93a37866
A
214 if (bytes <= impreciseCutoff)
215 return m_normalSpace.impreciseAllocators[(bytes - 1) / impreciseStep];
216 return m_normalSpace.largeAllocator;
6fe7ccc8
A
217}
218
93a37866 219inline MarkedAllocator& MarkedSpace::immortalStructureDestructorAllocatorFor(size_t bytes)
6fe7ccc8 220{
93a37866
A
221 ASSERT(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;
6fe7ccc8
A
227}
228
93a37866 229inline MarkedAllocator& MarkedSpace::normalDestructorAllocatorFor(size_t bytes)
6fe7ccc8 230{
93a37866 231 ASSERT(bytes);
6fe7ccc8 232 if (bytes <= preciseCutoff)
93a37866
A
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;
6fe7ccc8
A
237}
238
239inline void* MarkedSpace::allocateWithoutDestructor(size_t bytes)
240{
93a37866 241 return allocatorFor(bytes).allocate(bytes);
6fe7ccc8
A
242}
243
93a37866 244inline void* MarkedSpace::allocateWithImmortalStructureDestructor(size_t bytes)
6fe7ccc8 245{
93a37866
A
246 return immortalStructureDestructorAllocatorFor(bytes).allocate(bytes);
247}
248
249inline void* MarkedSpace::allocateWithNormalDestructor(size_t bytes)
250{
251 return normalDestructorAllocatorFor(bytes).allocate(bytes);
6fe7ccc8
A
252}
253
254template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock(Functor& functor)
255{
81345200 256 for (size_t i = 0; i < preciseCount; ++i)
6fe7ccc8 257 m_normalSpace.preciseAllocators[i].forEachBlock(functor);
81345200 258 for (size_t i = 0; i < impreciseCount; ++i)
6fe7ccc8 259 m_normalSpace.impreciseAllocators[i].forEachBlock(functor);
93a37866 260 m_normalSpace.largeAllocator.forEachBlock(functor);
81345200
A
261
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);
93a37866 266 m_normalDestructorSpace.largeAllocator.forEachBlock(functor);
81345200
A
267
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);
93a37866
A
272 m_immortalStructureDestructorSpace.largeAllocator.forEachBlock(functor);
273
6fe7ccc8
A
274 return functor.returnValue();
275}
14957cd0 276
6fe7ccc8
A
277template <typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachBlock()
278{
279 Functor functor;
280 return forEachBlock(functor);
281}
14957cd0 282
6fe7ccc8
A
283inline void MarkedSpace::didAddBlock(MarkedBlock* block)
284{
81345200 285 m_capacity += block->capacity();
6fe7ccc8
A
286 m_blocks.add(block);
287}
14957cd0 288
81345200
A
289inline void MarkedSpace::didAllocateInBlock(MarkedBlock* block)
290{
291#if ENABLE(GGC)
292 m_blocksWithNewObjects.append(block);
293#else
294 UNUSED_PARAM(block);
295#endif
296}
297
298inline void MarkedSpace::clearRememberedSet()
93a37866 299{
81345200 300 forEachBlock<ClearRememberedSet>();
93a37866
A
301}
302
303inline size_t MarkedSpace::objectCount()
304{
305 return forEachBlock<MarkCount>();
306}
307
308inline size_t MarkedSpace::size()
309{
310 return forEachBlock<Size>();
311}
312
313inline size_t MarkedSpace::capacity()
314{
81345200 315 return m_capacity;
93a37866
A
316}
317
14957cd0
A
318} // namespace JSC
319
320#endif // MarkedSpace_h