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