ac11c4fa5c51e9268ba2a9a569f0789df75945aa
[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-2009, 2013-2015 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 "CodeBlockSet.h"
27 #include "CopyVisitor.h"
28 #include "GCIncomingRefCountedSet.h"
29 #include "HandleSet.h"
30 #include "HandleStack.h"
31 #include "HeapObserver.h"
32 #include "HeapOperation.h"
33 #include "JITStubRoutineSet.h"
34 #include "ListableHandler.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 "UnconditionalFinalizer.h"
43 #include "WeakHandleOwner.h"
44 #include "WeakReferenceHarvester.h"
45 #include "WriteBarrierBuffer.h"
46 #include "WriteBarrierSupport.h"
47 #include <wtf/HashCountedSet.h>
48 #include <wtf/HashSet.h>
49 #include <wtf/ParallelHelperPool.h>
50
51 namespace JSC {
52
53 class CodeBlock;
54 class CopiedSpace;
55 class EdenGCActivityCallback;
56 class ExecutableBase;
57 class FullGCActivityCallback;
58 class GCActivityCallback;
59 class GCAwareJITStubRoutine;
60 class Heap;
61 class HeapRootVisitor;
62 class HeapVerifier;
63 class IncrementalSweeper;
64 class JITStubRoutine;
65 class JSCell;
66 class JSStack;
67 class JSValue;
68 class LLIntOffsetsExtractor;
69 class MarkedArgumentBuffer;
70 class VM;
71
72 namespace DFG {
73 class Worklist;
74 }
75
76 static void* const zombifiedBits = reinterpret_cast<void*>(static_cast<uintptr_t>(0xdeadbeef));
77
78 typedef HashCountedSet<JSCell*> ProtectCountSet;
79 typedef HashCountedSet<const char*> TypeCountSet;
80
81 enum HeapType { SmallHeap, LargeHeap };
82
83 class Heap {
84     WTF_MAKE_NONCOPYABLE(Heap);
85 public:
86     friend class JIT;
87     friend class DFG::SpeculativeJIT;
88     static Heap* heap(const JSValue); // 0 for immediate values
89     static Heap* heap(const JSCell*);
90
91     // This constant determines how many blocks we iterate between checks of our 
92     // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect 
93     // overstepping our deadline more quickly, while increasing it will cause 
94     // our scan to run faster. 
95     static const unsigned s_timeCheckResolution = 16;
96
97     static bool isLive(const void*);
98     static bool isMarked(const void*);
99     static bool testAndSetMarked(const void*);
100     static void setMarked(const void*);
101     static bool isRemembered(const void*);
102
103     JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
104     static bool isWriteBarrierEnabled();
105     void writeBarrier(const JSCell*);
106     void writeBarrier(const JSCell*, JSValue);
107     void writeBarrier(const JSCell*, JSCell*);
108
109     WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; }
110     void flushWriteBarrierBuffer(JSCell*);
111
112     Heap(VM*, HeapType);
113     ~Heap();
114     JS_EXPORT_PRIVATE void lastChanceToFinalize();
115     void releaseDelayedReleasedObjects();
116
117     VM* vm() const { return m_vm; }
118     MarkedSpace& objectSpace() { return m_objectSpace; }
119     CopiedSpace& storageSpace() { return m_storageSpace; }
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(std::unique_ptr<IncrementalSweeper>);
132
133     void addObserver(HeapObserver* observer) { m_observers.append(observer); }
134     void removeObserver(HeapObserver* observer) { m_observers.removeFirst(observer); }
135
136     // true if collection is in progress
137     bool isCollecting();
138     HeapOperation operationInProgress() { return m_operationInProgress; }
139     // true if an allocation or collection is in progress
140     bool isBusy();
141     MarkedSpace::Subspace& subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
142     MarkedSpace::Subspace& subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); }
143     template<typename ClassType> MarkedSpace::Subspace& subspaceForObjectOfType();
144     MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
145     MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
146     template<typename ClassType> MarkedAllocator& allocatorForObjectOfType(size_t bytes);
147     CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
148     CheckedBoolean tryAllocateStorage(JSCell* intendedOwner, size_t, void**);
149     CheckedBoolean tryReallocateStorage(JSCell* intendedOwner, void**, size_t, size_t);
150     void ascribeOwner(JSCell* intendedOwner, void*);
151
152     typedef void (*Finalizer)(JSCell*);
153     JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
154     void addExecutable(ExecutableBase*);
155
156     void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
157     bool isSafeToCollect() const { return m_isSafeToCollect; }
158
159     JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
160     void collectAllGarbage() { collectAndSweep(FullCollection); }
161     JS_EXPORT_PRIVATE void collectAndSweep(HeapOperation collectionType = AnyCollection);
162     bool shouldCollect();
163     JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
164     bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
165
166     // Use this API to report non-GC memory referenced by GC objects. Be sure to
167     // call both of these functions: Calling only one may trigger catastropic
168     // memory growth.
169     void reportExtraMemoryAllocated(size_t);
170     void reportExtraMemoryVisited(JSCell*, size_t);
171
172     // Use this API to report non-GC memory if you can't use the better API above.
173     void deprecatedReportExtraMemory(size_t);
174
175     JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
176
177     JS_EXPORT_PRIVATE void protect(JSValue);
178     JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
179     
180     size_t extraMemorySize(); // Non-GC memory referenced by GC objects.
181     JS_EXPORT_PRIVATE size_t size();
182     JS_EXPORT_PRIVATE size_t capacity();
183     JS_EXPORT_PRIVATE size_t objectCount();
184     JS_EXPORT_PRIVATE size_t globalObjectCount();
185     JS_EXPORT_PRIVATE size_t protectedObjectCount();
186     JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
187     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> protectedObjectTypeCounts();
188     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> objectTypeCounts();
189
190     HashSet<MarkedArgumentBuffer*>& markListSet();
191     
192     template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
193     template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
194     template<typename Functor> void forEachCodeBlock(Functor&);
195
196     HandleSet* handleSet() { return &m_handleSet; }
197     HandleStack* handleStack() { return &m_handleStack; }
198
199     void willStartIterating();
200     void didFinishIterating();
201
202     double lastFullGCLength() const { return m_lastFullGCLength; }
203     double lastEdenGCLength() const { return m_lastEdenGCLength; }
204     void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
205
206     size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
207     size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
208     size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
209     size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
210
211     JS_EXPORT_PRIVATE void deleteAllCodeBlocks();
212     void deleteAllUnlinkedCodeBlocks();
213
214     void didAllocate(size_t);
215     void didAbandon(size_t);
216
217     bool isPagedOut(double deadline);
218     
219     const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; }
220     
221     void addReference(JSCell*, ArrayBuffer*);
222     
223     bool isDeferred() const { return !!m_deferralDepth || Options::disableGC(); }
224
225     StructureIDTable& structureIDTable() { return m_structureIDTable; }
226
227 #if USE(CF)
228         template<typename T> void releaseSoon(RetainPtr<T>&&);
229 #endif
230
231     void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); }
232
233     static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
234
235     void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
236     void unregisterWeakGCMap(void* weakGCMap);
237
238     void addLogicallyEmptyWeakBlock(WeakBlock*);
239
240 private:
241     friend class CodeBlock;
242     friend class CopiedBlock;
243     friend class DeferGC;
244     friend class DeferGCForAWhile;
245     friend class GCAwareJITStubRoutine;
246     friend class GCLogging;
247     friend class GCThread;
248     friend class HandleSet;
249     friend class HeapVerifier;
250     friend class JITStubRoutine;
251     friend class LLIntOffsetsExtractor;
252     friend class MarkedSpace;
253     friend class MarkedAllocator;
254     friend class MarkedBlock;
255     friend class CopiedSpace;
256     friend class CopyVisitor;
257     friend class RecursiveAllocationScope;
258     friend class SlotVisitor;
259     friend class SuperRegion;
260     friend class IncrementalSweeper;
261     friend class HeapStatistics;
262     friend class VM;
263     friend class WeakSet;
264     template<typename T> friend void* allocateCell(Heap&);
265     template<typename T> friend void* allocateCell(Heap&, size_t);
266
267     void* allocateWithDestructor(size_t); // For use with objects with destructors.
268     void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
269     template<typename ClassType> void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type.
270
271     static const size_t minExtraMemory = 256;
272     
273     class FinalizerOwner : public WeakHandleOwner {
274         virtual void finalize(Handle<Unknown>, void* context) override;
275     };
276
277     JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
278     JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
279     JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
280
281     void collectImpl(HeapOperation, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
282
283     void suspendCompilerThreads();
284     void willStartCollection(HeapOperation collectionType);
285     void flushOldStructureIDTables();
286     void flushWriteBarrierBuffer();
287     void stopAllocation();
288     
289     void completeAllDFGPlans();
290
291     void markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
292     void gatherStackRoots(ConservativeRoots&, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
293     void gatherJSStackRoots(ConservativeRoots&);
294     void gatherScratchBufferRoots(ConservativeRoots&);
295     void clearLivenessData();
296     void visitExternalRememberedSet();
297     void visitSmallStrings();
298     void visitConservativeRoots(ConservativeRoots&);
299     void visitCompilerWorklistWeakReferences();
300     void removeDeadCompilerWorklistEntries();
301     void visitProtectedObjects(HeapRootVisitor&);
302     void visitArgumentBuffers(HeapRootVisitor&);
303     void visitException(HeapRootVisitor&);
304     void visitStrongHandles(HeapRootVisitor&);
305     void visitHandleStack(HeapRootVisitor&);
306     void traceCodeBlocksAndJITStubRoutines();
307     void converge();
308     void visitWeakHandles(HeapRootVisitor&);
309     void clearRememberedSet(Vector<const JSCell*>&);
310     void updateObjectCounts(double gcStartTime);
311     void resetVisitors();
312
313     void reapWeakHandles();
314     void pruneStaleEntriesFromWeakGCMaps();
315     void sweepArrayBuffers();
316     void snapshotMarkedSpace();
317     void deleteSourceProviderCaches();
318     void notifyIncrementalSweeper();
319     void rememberCurrentlyExecutingCodeBlocks();
320     void resetAllocators();
321     void copyBackingStores();
322     void harvestWeakReferences();
323     void finalizeUnconditionalFinalizers();
324     void clearUnmarkedExecutables();
325     void deleteUnmarkedCompiledCode();
326     void updateAllocationLimits();
327     void didFinishCollection(double gcStartTime);
328     void resumeCompilerThreads();
329     void zombifyDeadObjects();
330     void markDeadObjects();
331
332     void sweepAllLogicallyEmptyWeakBlocks();
333     bool sweepNextLogicallyEmptyWeakBlock();
334
335     bool shouldDoFullCollection(HeapOperation requestedCollectionType) const;
336     size_t sizeAfterCollect();
337
338     JSStack& stack();
339     
340     void incrementDeferralDepth();
341     void decrementDeferralDepth();
342     void decrementDeferralDepthAndGCIfNeeded();
343
344     size_t threadVisitCount();
345     size_t threadBytesVisited();
346     size_t threadBytesCopied();
347     size_t threadDupStrings();
348
349     const HeapType m_heapType;
350     const size_t m_ramSize;
351     const size_t m_minBytesPerCycle;
352     size_t m_sizeAfterLastCollect;
353     size_t m_sizeAfterLastFullCollect;
354     size_t m_sizeBeforeLastFullCollect;
355     size_t m_sizeAfterLastEdenCollect;
356     size_t m_sizeBeforeLastEdenCollect;
357
358     size_t m_bytesAllocatedThisCycle;
359     size_t m_bytesAbandonedSinceLastFullCollect;
360     size_t m_maxEdenSize;
361     size_t m_maxHeapSize;
362     bool m_shouldDoFullCollection;
363     size_t m_totalBytesVisited;
364     size_t m_totalBytesCopied;
365     
366     HeapOperation m_operationInProgress;
367     StructureIDTable m_structureIDTable;
368     MarkedSpace m_objectSpace;
369     CopiedSpace m_storageSpace;
370     GCIncomingRefCountedSet<ArrayBuffer> m_arrayBuffers;
371     size_t m_extraMemorySize;
372     size_t m_deprecatedExtraMemorySize;
373
374     HashSet<const JSCell*> m_copyingRememberedSet;
375
376     ProtectCountSet m_protectedValues;
377     std::unique_ptr<HashSet<MarkedArgumentBuffer*>> m_markListSet;
378
379     MachineThreads m_machineThreads;
380     
381     SlotVisitor m_slotVisitor;
382
383     // We pool the slot visitors used by parallel marking threads. It's useful to be able to
384     // enumerate over them, and it's useful to have them cache some small amount of memory from
385     // one GC to the next. GC marking threads claim these at the start of marking, and return
386     // them at the end.
387     Vector<std::unique_ptr<SlotVisitor>> m_parallelSlotVisitors;
388     Vector<SlotVisitor*> m_availableParallelSlotVisitors;
389     Lock m_parallelSlotVisitorLock;
390
391     HandleSet m_handleSet;
392     HandleStack m_handleStack;
393     CodeBlockSet m_codeBlocks;
394     JITStubRoutineSet m_jitStubRoutines;
395     FinalizerOwner m_finalizerOwner;
396     
397     bool m_isSafeToCollect;
398
399     WriteBarrierBuffer m_writeBarrierBuffer;
400
401     VM* m_vm;
402     double m_lastFullGCLength;
403     double m_lastEdenGCLength;
404
405     Vector<ExecutableBase*> m_executables;
406
407     Vector<WeakBlock*> m_logicallyEmptyWeakBlocks;
408     size_t m_indexOfNextLogicallyEmptyWeakBlockToSweep { WTF::notFound };
409     
410     RefPtr<FullGCActivityCallback> m_fullActivityCallback;
411     RefPtr<GCActivityCallback> m_edenActivityCallback;
412     std::unique_ptr<IncrementalSweeper> m_sweeper;
413     Vector<MarkedBlock*> m_blockSnapshot;
414
415     Vector<HeapObserver*> m_observers;
416
417     unsigned m_deferralDepth;
418     Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
419
420     std::unique_ptr<HeapVerifier> m_verifier;
421 #if USE(CF)
422     Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
423     unsigned m_delayedReleaseRecursionCount;
424 #endif
425
426     HashMap<void*, std::function<void()>> m_weakGCMaps;
427
428     bool m_shouldHashCons { false };
429
430     Lock m_markingMutex;
431     Condition m_markingConditionVariable;
432     MarkStackArray m_sharedMarkStack;
433     unsigned m_numberOfActiveParallelMarkers { 0 };
434     unsigned m_numberOfWaitingParallelMarkers { 0 };
435     bool m_parallelMarkersShouldExit { false };
436
437     Lock m_opaqueRootsMutex;
438     HashSet<void*> m_opaqueRoots;
439
440     Vector<CopiedBlock*> m_blocksToCopy;
441     static const size_t s_blockFragmentLength = 32;
442
443     ListableHandler<WeakReferenceHarvester>::List m_weakReferenceHarvesters;
444     ListableHandler<UnconditionalFinalizer>::List m_unconditionalFinalizers;
445
446     ParallelHelperClient m_helperClient;
447 };
448
449 } // namespace JSC
450
451 #endif // Heap_h