2011-06-16 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / heap / Heap.h
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 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 Heap_h
23 #define Heap_h
24
25 #include "HandleHeap.h"
26 #include "HandleStack.h"
27 #include "SlotVisitor.h"
28 #include "MarkedBlockSet.h"
29 #include "NewSpace.h"
30 #include <wtf/Forward.h>
31 #include <wtf/HashCountedSet.h>
32 #include <wtf/HashSet.h>
33
34 namespace JSC {
35
36     class GCActivityCallback;
37     class GlobalCodeBlock;
38     class HeapRootVisitor;
39     class JSCell;
40     class JSGlobalData;
41     class JSValue;
42     class LiveObjectIterator;
43     class MarkedArgumentBuffer;
44     class RegisterFile;
45     class UString;
46     class WeakGCHandlePool;
47     class SlotVisitor;
48
49     typedef std::pair<JSValue, UString> ValueStringPair;
50     typedef HashCountedSet<JSCell*> ProtectCountSet;
51     typedef HashCountedSet<const char*> TypeCountSet;
52
53     enum OperationInProgress { NoOperation, Allocation, Collection };
54
55     class Heap {
56         WTF_MAKE_NONCOPYABLE(Heap);
57     public:
58         static Heap* heap(JSValue); // 0 for immediate values
59         static Heap* heap(JSCell*);
60
61         static bool isMarked(const void*);
62         static bool testAndSetMarked(const void*);
63         static bool testAndClearMarked(const void*);
64         static void setMarked(const void*);
65
66         static void writeBarrier(const JSCell*, JSValue);
67         static void writeBarrier(const JSCell*, JSCell*);
68
69         Heap(JSGlobalData*);
70         ~Heap();
71         void destroy(); // JSGlobalData must call destroy() before ~Heap().
72
73         JSGlobalData* globalData() const { return m_globalData; }
74         NewSpace& markedSpace() { return m_newSpace; }
75         MachineThreads& machineThreads() { return m_machineThreads; }
76
77         GCActivityCallback* activityCallback();
78         void setActivityCallback(PassOwnPtr<GCActivityCallback>);
79
80         // true if an allocation or collection is in progress
81         inline bool isBusy();
82
83         void* allocate(size_t);
84         void* allocate(NewSpace::SizeClass&);
85         void collectAllGarbage();
86
87         void reportExtraMemoryCost(size_t cost);
88
89         void protect(JSValue);
90         bool unprotect(JSValue); // True when the protect count drops to 0.
91
92         size_t size();
93         size_t capacity();
94         size_t objectCount();
95         size_t globalObjectCount();
96         size_t protectedObjectCount();
97         size_t protectedGlobalObjectCount();
98         PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
99         PassOwnPtr<TypeCountSet> objectTypeCounts();
100
101         void pushTempSortVector(Vector<ValueStringPair>*);
102         void popTempSortVector(Vector<ValueStringPair>*);
103     
104         HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
105         
106         template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
107         template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
108         template<typename Functor> typename Functor::ReturnType forEachCell(Functor&);
109         template<typename Functor> typename Functor::ReturnType forEachCell();
110         template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&);
111         template<typename Functor> typename Functor::ReturnType forEachBlock();
112         
113         HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); }
114         HandleSlot allocateLocalHandle() { return m_handleStack.push(); }
115
116         HandleStack* handleStack() { return &m_handleStack; }
117
118     private:
119         typedef HashSet<MarkedBlock*>::iterator BlockIterator;
120
121         static const size_t minExtraCost = 256;
122         static const size_t maxExtraCost = 1024 * 1024;
123
124         bool isValidAllocation(size_t);
125         void* allocateSlowCase(size_t);
126         void reportExtraMemoryCostSlowCase(size_t);
127         void resetAllocator();
128
129         MarkedBlock* allocateBlock(size_t cellSize);
130         void freeBlocks(MarkedBlock*);
131
132         void clearMarks();
133         void markRoots();
134         void markProtectedObjects(HeapRootVisitor&);
135         void markTempSortVectors(HeapRootVisitor&);
136
137         enum SweepToggle { DoNotSweep, DoSweep };
138         void collect(SweepToggle);
139         void shrink();
140         void sweep();
141
142         RegisterFile& registerFile();
143
144         static void writeBarrierSlowCase(const JSCell*, JSCell*);
145
146         OperationInProgress m_operationInProgress;
147         NewSpace m_newSpace;
148         MarkedBlockSet m_blocks;
149
150         size_t m_extraCost;
151
152         ProtectCountSet m_protectedValues;
153         Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
154         HashSet<MarkedArgumentBuffer*>* m_markListSet;
155
156         OwnPtr<GCActivityCallback> m_activityCallback;
157         
158         MachineThreads m_machineThreads;
159         SlotVisitor m_slotVisitor;
160         HandleHeap m_handleHeap;
161         HandleStack m_handleStack;
162
163         JSGlobalData* m_globalData;
164     };
165
166     bool Heap::isBusy()
167     {
168         return m_operationInProgress != NoOperation;
169     }
170
171     inline Heap* Heap::heap(JSCell* cell)
172     {
173         return MarkedBlock::blockFor(cell)->heap();
174     }
175
176     inline Heap* Heap::heap(JSValue v)
177     {
178         if (!v.isCell())
179             return 0;
180         return heap(v.asCell());
181     }
182
183     inline bool Heap::isMarked(const void* cell)
184     {
185         return MarkedBlock::blockFor(cell)->isMarked(cell);
186     }
187
188     inline bool Heap::testAndSetMarked(const void* cell)
189     {
190         return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
191     }
192
193     inline bool Heap::testAndClearMarked(const void* cell)
194     {
195         return MarkedBlock::blockFor(cell)->testAndClearMarked(cell);
196     }
197
198     inline void Heap::setMarked(const void* cell)
199     {
200         MarkedBlock::blockFor(cell)->setMarked(cell);
201     }
202
203 #if ENABLE(GGC)
204     inline void Heap::writeBarrier(const JSCell* owner, JSCell* cell)
205     {
206         if (MarkedBlock::blockFor(owner)->inNewSpace())
207             return;
208         writeBarrierSlowCase(owner, cell);
209     }
210
211     inline void Heap::writeBarrier(const JSCell* owner, JSValue value)
212     {
213         if (!value)
214             return;
215         if (!value.isCell())
216             return;
217         writeBarrier(owner, value.asCell());
218     }
219
220 #else
221
222     inline void Heap::writeBarrier(const JSCell*, JSCell*)
223     {
224     }
225
226     inline void Heap::writeBarrier(const JSCell*, JSValue)
227     {
228     }
229 #endif
230
231     inline void Heap::reportExtraMemoryCost(size_t cost)
232     {
233         if (cost > minExtraCost) 
234             reportExtraMemoryCostSlowCase(cost);
235     }
236
237     template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
238     {
239         ProtectCountSet::iterator end = m_protectedValues.end();
240         for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
241             functor(it->first);
242         m_handleHeap.forEachStrongHandle(functor, m_protectedValues);
243
244         return functor.returnValue();
245     }
246
247     template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
248     {
249         Functor functor;
250         return forEachProtectedCell(functor);
251     }
252
253     template<typename Functor> inline typename Functor::ReturnType Heap::forEachCell(Functor& functor)
254     {
255         BlockIterator end = m_blocks.set().end();
256         for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
257             (*it)->forEachCell(functor);
258         return functor.returnValue();
259     }
260
261     template<typename Functor> inline typename Functor::ReturnType Heap::forEachCell()
262     {
263         Functor functor;
264         return forEachCell(functor);
265     }
266
267     template<typename Functor> inline typename Functor::ReturnType Heap::forEachBlock(Functor& functor)
268     {
269         BlockIterator end = m_blocks.set().end();
270         for (BlockIterator it = m_blocks.set().begin(); it != end; ++it)
271             functor(*it);
272         return functor.returnValue();
273     }
274
275     template<typename Functor> inline typename Functor::ReturnType Heap::forEachBlock()
276     {
277         Functor functor;
278         return forEachBlock(functor);
279     }
280
281     inline void* Heap::allocate(size_t bytes)
282     {
283         ASSERT(isValidAllocation(bytes));
284         NewSpace::SizeClass& sizeClass = m_newSpace.sizeClassFor(bytes);
285         return allocate(sizeClass);
286     }
287
288 } // namespace JSC
289
290 #endif // Heap_h