1/*
2 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 *  Copyright (C) 2003-2009, 2013-2014 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 "ArrayBuffer.h"
26#include "BlockAllocator.h"
27#include "CodeBlockSet.h"
28#include "CopyVisitor.h"
29#include "GCIncomingRefCountedSet.h"
30#include "GCThreadSharedData.h"
31#include "HandleSet.h"
32#include "HandleStack.h"
33#include "HeapOperation.h"
34#include "JITStubRoutineSet.h"
35#include "MarkedAllocator.h"
36#include "MarkedBlock.h"
37#include "MarkedBlockSet.h"
38#include "MarkedSpace.h"
39#include "Options.h"
40#include "SlotVisitor.h"
41#include "StructureIDTable.h"
42#include "WeakHandleOwner.h"
43#include "WriteBarrierBuffer.h"
44#include "WriteBarrierSupport.h"
45#include <wtf/HashCountedSet.h>
46#include <wtf/HashSet.h>
47
48namespace JSC {
49
50class CopiedSpace;
51class CodeBlock;
52class ExecutableBase;
53class EdenGCActivityCallback;
54class FullGCActivityCallback;
55class GCActivityCallback;
56class GCAwareJITStubRoutine;
57class GlobalCodeBlock;
58class Heap;
59class HeapRootVisitor;
60class IncrementalSweeper;
61class JITStubRoutine;
62class JSCell;
63class VM;
64class JSStack;
65class JSValue;
66class LiveObjectIterator;
67class LLIntOffsetsExtractor;
68class MarkedArgumentBuffer;
69class WeakGCHandlePool;
70class SlotVisitor;
71
72namespace DFG {
73class Worklist;
74}
75
76static void* const zombifiedBits = reinterpret_cast<void*>(0xdeadbeef);
77
78typedef std::pair<JSValue, WTF::String> ValueStringPair;
79typedef HashCountedSet<JSCell*> ProtectCountSet;
80typedef HashCountedSet<const char*> TypeCountSet;
81
82enum HeapType { SmallHeap, LargeHeap };
83
84class Heap {
85    WTF_MAKE_NONCOPYABLE(Heap);
86public:
87    friend class JIT;
88    friend class DFG::SpeculativeJIT;
89    friend class GCThreadSharedData;
90    static Heap* heap(const JSValue); // 0 for immediate values
91    static Heap* heap(const JSCell*);
92
93    // This constant determines how many blocks we iterate between checks of our
94    // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect
95    // overstepping our deadline more quickly, while increasing it will cause
96    // our scan to run faster.
97    static const unsigned s_timeCheckResolution = 16;
98
99    static bool isLive(const void*);
100    static bool isMarked(const void*);
101    static bool testAndSetMarked(const void*);
102    static void setMarked(const void*);
103    static bool isRemembered(const void*);
104
105    JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
106    static bool isWriteBarrierEnabled();
107    void writeBarrier(const JSCell*);
108    void writeBarrier(const JSCell*, JSValue);
109    void writeBarrier(const JSCell*, JSCell*);
110
111    WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; }
112    void flushWriteBarrierBuffer(JSCell*);
113
114    Heap(VM*, HeapType);
115    ~Heap();
116    JS_EXPORT_PRIVATE void lastChanceToFinalize();
117
118    VM* vm() const { return m_vm; }
119    MarkedSpace& objectSpace() { return m_objectSpace; }
120    MachineThreads& machineThreads() { return m_machineThreads; }
121
122    const SlotVisitor& slotVisitor() const { return m_slotVisitor; }
123
124    JS_EXPORT_PRIVATE GCActivityCallback* fullActivityCallback();
125    JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
126    JS_EXPORT_PRIVATE void setFullActivityCallback(PassRefPtr<FullGCActivityCallback>);
127    JS_EXPORT_PRIVATE void setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback>);
128    JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
129
130    JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
131    JS_EXPORT_PRIVATE void setIncrementalSweeper(PassOwnPtr<IncrementalSweeper>);
132
133    // true if collection is in progress
134    bool isCollecting();
135    HeapOperation operationInProgress() { return m_operationInProgress; }
136    // true if an allocation or collection is in progress
137    bool isBusy();
138
139    MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
140    MarkedAllocator& allocatorForObjectWithNormalDestructor(size_t bytes) { return m_objectSpace.normalDestructorAllocatorFor(bytes); }
141    MarkedAllocator& allocatorForObjectWithImmortalStructureDestructor(size_t bytes) { return m_objectSpace.immortalStructureDestructorAllocatorFor(bytes); }
142    CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
143    CheckedBoolean tryAllocateStorage(JSCell* intendedOwner, size_t, void**);
144    CheckedBoolean tryReallocateStorage(JSCell* intendedOwner, void**, size_t, size_t);
145    void ascribeOwner(JSCell* intendedOwner, void*);
146
147    typedef void (*Finalizer)(JSCell*);
148    JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
149    void addCompiledCode(ExecutableBase*);
150
151    void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
152    bool isSafeToCollect() const { return m_isSafeToCollect; }
153
154    JS_EXPORT_PRIVATE void collectAllGarbage();
155    bool shouldCollect();
156    JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
157    bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
158
159    void reportExtraMemoryCost(size_t cost);
160    JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
161
162    JS_EXPORT_PRIVATE void protect(JSValue);
163    JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
164
165    size_t extraSize(); // extra memory usage outside of pages allocated by the heap
166    JS_EXPORT_PRIVATE size_t size();
167    JS_EXPORT_PRIVATE size_t capacity();
168    JS_EXPORT_PRIVATE size_t objectCount();
169    JS_EXPORT_PRIVATE size_t globalObjectCount();
170    JS_EXPORT_PRIVATE size_t protectedObjectCount();
171    JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
172    JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
173    JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> objectTypeCounts();
174    void showStatistics();
175
176    void pushTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>*);
177    void popTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>*);
178
179    HashSet<MarkedArgumentBuffer*>& markListSet();
180
181    template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
182    template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
183    template<typename Functor> void forEachCodeBlock(Functor&);
184
185    HandleSet* handleSet() { return &m_handleSet; }
186    HandleStack* handleStack() { return &m_handleStack; }
187
188    void willStartIterating();
189    void didFinishIterating();
190    void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
191
192    double lastFullGCLength() const { return m_lastFullGCLength; }
193    double lastEdenGCLength() const { return m_lastEdenGCLength; }
194    void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
195
196    size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
197    size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
198    size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
199    size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
200
201    JS_EXPORT_PRIVATE void deleteAllCompiledCode();
202    void deleteAllUnlinkedFunctionCode();
203
204    void didAllocate(size_t);
205    void didAbandon(size_t);
206
207    bool isPagedOut(double deadline);
208
209    const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; }
210
211    void addReference(JSCell*, ArrayBuffer*);
212
213    bool isDeferred() const { return !!m_deferralDepth || Options::disableGC(); }
214
215    BlockAllocator& blockAllocator();
216    StructureIDTable& structureIDTable() { return m_structureIDTable; }
217
218#if USE(CF)
219        template<typename T> void releaseSoon(RetainPtr<T>&&);
220#endif
221
222    void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); }
223
224    static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
225
226private:
227    friend class CodeBlock;
228    friend class CopiedBlock;
229    friend class DeferGC;
230    friend class DeferGCForAWhile;
231    friend class DelayedReleaseScope;
232    friend class GCAwareJITStubRoutine;
233    friend class GCLogging;
234    friend class HandleSet;
235    friend class JITStubRoutine;
236    friend class LLIntOffsetsExtractor;
237    friend class MarkedSpace;
238    friend class MarkedAllocator;
239    friend class MarkedBlock;
240    friend class CopiedSpace;
241    friend class CopyVisitor;
242    friend class RecursiveAllocationScope;
243    friend class SlotVisitor;
244    friend class SuperRegion;
245    friend class IncrementalSweeper;
246    friend class HeapStatistics;
247    friend class VM;
248    friend class WeakSet;
249    template<typename T> friend void* allocateCell(Heap&);
250    template<typename T> friend void* allocateCell(Heap&, size_t);
251
252    void* allocateWithImmortalStructureDestructor(size_t); // For use with special objects whose Structures never die.
253    void* allocateWithNormalDestructor(size_t); // For use with objects that inherit directly or indirectly from JSDestructibleObject.
254    void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
255
256    static const size_t minExtraCost = 256;
257    static const size_t maxExtraCost = 1024 * 1024;
258
259    class FinalizerOwner : public WeakHandleOwner {
260        virtual void finalize(Handle<Unknown>, void* context) override;
261    };
262
263    JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
264    JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
265
266    void suspendCompilerThreads();
267    void willStartCollection(HeapOperation collectionType);
268    void deleteOldCode(double gcStartTime);
269    void flushOldStructureIDTables();
270    void flushWriteBarrierBuffer();
271    void stopAllocation();
272
273    void markRoots(double gcStartTime);
274    void gatherStackRoots(ConservativeRoots&, void** dummy);
275    void gatherJSStackRoots(ConservativeRoots&);
276    void gatherScratchBufferRoots(ConservativeRoots&);
277    void clearLivenessData();
278    void visitExternalRememberedSet();
279    void visitSmallStrings();
280    void visitConservativeRoots(ConservativeRoots&);
281    void visitCompilerWorklistWeakReferences();
282    void removeDeadCompilerWorklistEntries();
283    void visitProtectedObjects(HeapRootVisitor&);
284    void visitTempSortVectors(HeapRootVisitor&);
285    void visitArgumentBuffers(HeapRootVisitor&);
286    void visitException(HeapRootVisitor&);
287    void visitStrongHandles(HeapRootVisitor&);
288    void visitHandleStack(HeapRootVisitor&);
289    void traceCodeBlocksAndJITStubRoutines();
290    void converge();
291    void visitWeakHandles(HeapRootVisitor&);
292    void clearRememberedSet(Vector<const JSCell*>&);
293    void updateObjectCounts(double gcStartTime);
294    void resetVisitors();
295
296    void reapWeakHandles();
297    void sweepArrayBuffers();
298    void snapshotMarkedSpace();
299    void deleteSourceProviderCaches();
300    void notifyIncrementalSweeper();
301    void rememberCurrentlyExecutingCodeBlocks();
302    void resetAllocators();
303    void copyBackingStores();
304    void harvestWeakReferences();
305    void finalizeUnconditionalFinalizers();
306    void clearUnmarkedExecutables();
307    void deleteUnmarkedCompiledCode();
308    void updateAllocationLimits();
309    void didFinishCollection(double gcStartTime);
310    void resumeCompilerThreads();
311    void zombifyDeadObjects();
312    void markDeadObjects();
313
314    bool shouldDoFullCollection(HeapOperation requestedCollectionType) const;
315    size_t sizeAfterCollect();
316
317    JSStack& stack();
318
319    void incrementDeferralDepth();
320    void decrementDeferralDepth();
321    void decrementDeferralDepthAndGCIfNeeded();
322
323    const HeapType m_heapType;
324    const size_t m_ramSize;
325    const size_t m_minBytesPerCycle;
326    size_t m_sizeAfterLastCollect;
327    size_t m_sizeAfterLastFullCollect;
328    size_t m_sizeBeforeLastFullCollect;
329    size_t m_sizeAfterLastEdenCollect;
330    size_t m_sizeBeforeLastEdenCollect;
331
332    size_t m_bytesAllocatedThisCycle;
333    size_t m_bytesAbandonedSinceLastFullCollect;
334    size_t m_maxEdenSize;
335    size_t m_maxHeapSize;
336    bool m_shouldDoFullCollection;
337    size_t m_totalBytesVisited;
338    size_t m_totalBytesCopied;
339
340    HeapOperation m_operationInProgress;
341    BlockAllocator m_blockAllocator;
342    StructureIDTable m_structureIDTable;
343    MarkedSpace m_objectSpace;
344    CopiedSpace m_storageSpace;
345    GCIncomingRefCountedSet<ArrayBuffer> m_arrayBuffers;
346    size_t m_extraMemoryUsage;
347
348    HashSet<const JSCell*> m_copyingRememberedSet;
349
350    ProtectCountSet m_protectedValues;
351    Vector<Vector<ValueStringPair, 0, UnsafeVectorOverflow>*> m_tempSortingVectors;
352    OwnPtr<HashSet<MarkedArgumentBuffer*>> m_markListSet;
353
354    MachineThreads m_machineThreads;
355
356    GCThreadSharedData m_sharedData;
357    SlotVisitor m_slotVisitor;
358    CopyVisitor m_copyVisitor;
359
360    HandleSet m_handleSet;
361    HandleStack m_handleStack;
362    CodeBlockSet m_codeBlocks;
363    JITStubRoutineSet m_jitStubRoutines;
364    FinalizerOwner m_finalizerOwner;
365
366    bool m_isSafeToCollect;
367
368    WriteBarrierBuffer m_writeBarrierBuffer;
369
370    VM* m_vm;
371    double m_lastFullGCLength;
372    double m_lastEdenGCLength;
373    double m_lastCodeDiscardTime;
374
375    DoublyLinkedList<ExecutableBase> m_compiledCode;
376
377    RefPtr<GCActivityCallback> m_fullActivityCallback;
378    RefPtr<GCActivityCallback> m_edenActivityCallback;
379    OwnPtr<IncrementalSweeper> m_sweeper;
380    Vector<MarkedBlock*> m_blockSnapshot;
381
382    unsigned m_deferralDepth;
383    Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
384};
385
386} // namespace JSC
387
388#endif // Heap_h
389