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