dd4cfec63685accb02399e97501f8788b13e80b8
[WebKit.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 "CellState.h"
26 #include "CollectionScope.h"
27 #include "DeleteAllCodeEffort.h"
28 #include "GCIncomingRefCountedSet.h"
29 #include "HandleSet.h"
30 #include "HandleStack.h"
31 #include "HeapObserver.h"
32 #include "ListableHandler.h"
33 #include "MachineStackMarker.h"
34 #include "MarkedAllocator.h"
35 #include "MarkedBlock.h"
36 #include "MarkedBlockSet.h"
37 #include "MarkedSpace.h"
38 #include "MutatorState.h"
39 #include "Options.h"
40 #include "StructureIDTable.h"
41 #include "TinyBloomFilter.h"
42 #include "UnconditionalFinalizer.h"
43 #include "VisitRaceKey.h"
44 #include "WeakHandleOwner.h"
45 #include "WeakReferenceHarvester.h"
46 #include "WriteBarrierBuffer.h"
47 #include "WriteBarrierSupport.h"
48 #include <wtf/AutomaticThread.h>
49 #include <wtf/Deque.h>
50 #include <wtf/HashCountedSet.h>
51 #include <wtf/HashSet.h>
52 #include <wtf/ParallelHelperPool.h>
53
54 namespace JSC {
55
56 class CodeBlock;
57 class CodeBlockSet;
58 class GCDeferralContext;
59 class EdenGCActivityCallback;
60 class ExecutableBase;
61 class FullGCActivityCallback;
62 class GCActivityCallback;
63 class GCAwareJITStubRoutine;
64 class Heap;
65 class HeapProfiler;
66 class HeapRootVisitor;
67 class HeapVerifier;
68 class HelpingGCScope;
69 class IncrementalSweeper;
70 class JITStubRoutine;
71 class JITStubRoutineSet;
72 class JSCell;
73 class JSValue;
74 class LLIntOffsetsExtractor;
75 class MarkStackArray;
76 class MarkedArgumentBuffer;
77 class SlotVisitor;
78 class SpaceTimeScheduler;
79 class StopIfNecessaryTimer;
80 class VM;
81
82 namespace DFG {
83 class SpeculativeJIT;
84 class Worklist;
85 }
86
87 static void* const zombifiedBits = reinterpret_cast<void*>(static_cast<uintptr_t>(0xdeadbeef));
88
89 typedef HashCountedSet<JSCell*> ProtectCountSet;
90 typedef HashCountedSet<const char*> TypeCountSet;
91
92 enum HeapType { SmallHeap, LargeHeap };
93
94 class HeapUtil;
95
96 class Heap {
97     WTF_MAKE_NONCOPYABLE(Heap);
98 public:
99     friend class JIT;
100     friend class DFG::SpeculativeJIT;
101     static Heap* heap(const JSValue); // 0 for immediate values
102     static Heap* heap(const HeapCell*);
103
104     // This constant determines how many blocks we iterate between checks of our 
105     // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect 
106     // overstepping our deadline more quickly, while increasing it will cause 
107     // our scan to run faster. 
108     static const unsigned s_timeCheckResolution = 16;
109
110     static bool isMarked(const void*);
111     static bool isMarkedConcurrently(const void*);
112     static bool testAndSetMarked(HeapVersion, const void*);
113     
114     static size_t cellSize(const void*);
115
116     void writeBarrier(const JSCell* from);
117     void writeBarrier(const JSCell* from, JSValue to);
118     void writeBarrier(const JSCell* from, JSCell* to);
119     
120     void writeBarrierWithoutFence(const JSCell* from);
121     
122     void mutatorFence();
123     
124     // Take this if you know that from->cellState() < barrierThreshold.
125     JS_EXPORT_PRIVATE void writeBarrierSlowPath(const JSCell* from);
126
127     WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; }
128     void flushWriteBarrierBuffer(JSCell*);
129     
130     Heap(VM*, HeapType);
131     ~Heap();
132     void lastChanceToFinalize();
133     void releaseDelayedReleasedObjects();
134
135     VM* vm() const { return m_vm; }
136     MarkedSpace& objectSpace() { return m_objectSpace; }
137     MachineThreads& machineThreads() { return m_machineThreads; }
138
139     SlotVisitor& collectorSlotVisitor() { return *m_collectorSlotVisitor; }
140     MarkStackArray& mutatorMarkStack() { return *m_mutatorMarkStack; }
141
142     JS_EXPORT_PRIVATE GCActivityCallback* fullActivityCallback();
143     JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
144     JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
145
146     JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
147
148     void addObserver(HeapObserver* observer) { m_observers.append(observer); }
149     void removeObserver(HeapObserver* observer) { m_observers.removeFirst(observer); }
150
151     MutatorState mutatorState() const { return m_mutatorState; }
152     std::optional<CollectionScope> collectionScope() const { return m_collectionScope; }
153     bool hasHeapAccess() const;
154     bool mutatorIsStopped() const;
155     bool collectorBelievesThatTheWorldIsStopped() const;
156
157     // We're always busy on the collection threads. On the main thread, this returns true if we're
158     // helping heap.
159     JS_EXPORT_PRIVATE bool isCurrentThreadBusy();
160     
161     MarkedSpace::Subspace& subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
162     MarkedSpace::Subspace& subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); }
163     MarkedSpace::Subspace& subspaceForAuxiliaryData() { return m_objectSpace.subspaceForAuxiliaryData(); }
164     template<typename ClassType> MarkedSpace::Subspace& subspaceForObjectOfType();
165     MarkedAllocator* allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
166     MarkedAllocator* allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
167     template<typename ClassType> MarkedAllocator* allocatorForObjectOfType(size_t bytes);
168     MarkedAllocator* allocatorForAuxiliaryData(size_t bytes) { return m_objectSpace.auxiliaryAllocatorFor(bytes); }
169     void* allocateAuxiliary(JSCell* intendedOwner, size_t);
170     void* tryAllocateAuxiliary(JSCell* intendedOwner, size_t);
171     void* tryAllocateAuxiliary(GCDeferralContext*, JSCell* intendedOwner, size_t);
172     void* tryReallocateAuxiliary(JSCell* intendedOwner, void* oldBase, size_t oldSize, size_t newSize);
173     void ascribeOwner(JSCell* intendedOwner, void*);
174
175     typedef void (*Finalizer)(JSCell*);
176     JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
177     void addExecutable(ExecutableBase*);
178
179     void notifyIsSafeToCollect();
180     bool isSafeToCollect() const { return m_isSafeToCollect; }
181
182     JS_EXPORT_PRIVATE bool isHeapSnapshotting() const;
183
184     JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
185     JS_EXPORT_PRIVATE void collectAllGarbage();
186
187     bool canCollect();
188     bool shouldCollectHeuristic();
189     bool shouldCollect();
190     
191     // Queue up a collection. Returns immediately. This will not queue a collection if a collection
192     // of equal or greater strength exists. Full collections are stronger than std::nullopt collections
193     // and std::nullopt collections are stronger than Eden collections. std::nullopt means that the GC can
194     // choose Eden or Full. This implies that if you request a GC while that GC is ongoing, nothing
195     // will happen.
196     JS_EXPORT_PRIVATE void collectAsync(std::optional<CollectionScope> = std::nullopt);
197     
198     // Queue up a collection and wait for it to complete. This won't return until you get your own
199     // complete collection. For example, if there was an ongoing asynchronous collection at the time
200     // you called this, then this would wait for that one to complete and then trigger your
201     // collection and then return. In weird cases, there could be multiple GC requests in the backlog
202     // and this will wait for that backlog before running its GC and returning.
203     JS_EXPORT_PRIVATE void collectSync(std::optional<CollectionScope> = std::nullopt);
204     
205     bool collectIfNecessaryOrDefer(GCDeferralContext* = nullptr); // Returns true if it did collect.
206     void collectAccordingToDeferGCProbability();
207
208     void completeAllJITPlans();
209     
210     // Use this API to report non-GC memory referenced by GC objects. Be sure to
211     // call both of these functions: Calling only one may trigger catastropic
212     // memory growth.
213     void reportExtraMemoryAllocated(size_t);
214     JS_EXPORT_PRIVATE void reportExtraMemoryVisited(size_t);
215
216 #if ENABLE(RESOURCE_USAGE)
217     // Use this API to report the subset of extra memory that lives outside this process.
218     JS_EXPORT_PRIVATE void reportExternalMemoryVisited(size_t);
219     size_t externalMemorySize() { return m_externalMemorySize; }
220 #endif
221
222     // Use this API to report non-GC memory if you can't use the better API above.
223     void deprecatedReportExtraMemory(size_t);
224
225     JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
226
227     JS_EXPORT_PRIVATE void protect(JSValue);
228     JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
229     
230     JS_EXPORT_PRIVATE size_t extraMemorySize(); // Non-GC memory referenced by GC objects.
231     JS_EXPORT_PRIVATE size_t size();
232     JS_EXPORT_PRIVATE size_t capacity();
233     JS_EXPORT_PRIVATE size_t objectCount();
234     JS_EXPORT_PRIVATE size_t globalObjectCount();
235     JS_EXPORT_PRIVATE size_t protectedObjectCount();
236     JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
237     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> protectedObjectTypeCounts();
238     JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> objectTypeCounts();
239
240     HashSet<MarkedArgumentBuffer*>& markListSet();
241     
242     template<typename Functor> void forEachProtectedCell(const Functor&);
243     template<typename Functor> void forEachCodeBlock(const Functor&);
244
245     HandleSet* handleSet() { return &m_handleSet; }
246     HandleStack* handleStack() { return &m_handleStack; }
247
248     void willStartIterating();
249     void didFinishIterating();
250
251     double lastFullGCLength() const { return m_lastFullGCLength; }
252     double lastEdenGCLength() const { return m_lastEdenGCLength; }
253     void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
254
255     size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
256     size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
257     size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
258     size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
259
260     void deleteAllCodeBlocks(DeleteAllCodeEffort);
261     void deleteAllUnlinkedCodeBlocks(DeleteAllCodeEffort);
262
263     void didAllocate(size_t);
264     bool isPagedOut(double deadline);
265     
266     const JITStubRoutineSet& jitStubRoutines() { return *m_jitStubRoutines; }
267     
268     void addReference(JSCell*, ArrayBuffer*);
269     
270     bool isDeferred() const { return !!m_deferralDepth || !Options::useGC(); }
271
272     StructureIDTable& structureIDTable() { return m_structureIDTable; }
273
274     CodeBlockSet& codeBlockSet() { return *m_codeBlocks; }
275
276 #if USE(FOUNDATION)
277     template<typename T> void releaseSoon(RetainPtr<T>&&);
278 #endif
279
280     static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
281
282     JS_EXPORT_PRIVATE void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
283     JS_EXPORT_PRIVATE void unregisterWeakGCMap(void* weakGCMap);
284
285     void addLogicallyEmptyWeakBlock(WeakBlock*);
286
287 #if ENABLE(RESOURCE_USAGE)
288     size_t blockBytesAllocated() const { return m_blockBytesAllocated; }
289 #endif
290
291     void didAllocateBlock(size_t capacity);
292     void didFreeBlock(size_t capacity);
293     
294     bool mutatorShouldBeFenced() const { return m_mutatorShouldBeFenced; }
295     const bool* addressOfMutatorShouldBeFenced() const { return &m_mutatorShouldBeFenced; }
296     
297     unsigned barrierThreshold() const { return m_barrierThreshold; }
298     const unsigned* addressOfBarrierThreshold() const { return &m_barrierThreshold; }
299
300     // If true, the GC believes that the mutator is currently messing with the heap. We call this
301     // "having heap access". The GC may block if the mutator is in this state. If false, the GC may
302     // currently be doing things to the heap that make the heap unsafe to access for the mutator.
303     bool hasAccess() const;
304     
305     // If the mutator does not currently have heap access, this function will acquire it. If the GC
306     // is currently using the lack of heap access to do dangerous things to the heap then this
307     // function will block, waiting for the GC to finish. It's not valid to call this if the mutator
308     // already has heap access. The mutator is required to precisely track whether or not it has
309     // heap access.
310     //
311     // It's totally fine to acquireAccess() upon VM instantiation and keep it that way. This is how
312     // WebCore uses us. For most other clients, JSLock does acquireAccess()/releaseAccess() for you.
313     void acquireAccess();
314     
315     // Releases heap access. If the GC is blocking waiting to do bad things to the heap, it will be
316     // allowed to run now.
317     //
318     // Ordinarily, you should use the ReleaseHeapAccessScope to release and then reacquire heap
319     // access. You should do this anytime you're about do perform a blocking operation, like waiting
320     // on the ParkingLot.
321     void releaseAccess();
322     
323     // This is like a super optimized way of saying:
324     //
325     //     releaseAccess()
326     //     acquireAccess()
327     //
328     // The fast path is an inlined relaxed load and branch. The slow path will block the mutator if
329     // the GC wants to do bad things to the heap.
330     //
331     // All allocations logically call this. As an optimization to improve GC progress, you can call
332     // this anywhere that you can afford a load-branch and where an object allocation would have been
333     // safe.
334     //
335     // The GC will also push a stopIfNecessary() event onto the runloop of the thread that
336     // instantiated the VM whenever it wants the mutator to stop. This means that if you never block
337     // but instead use the runloop to wait for events, then you could safely run in a mode where the
338     // mutator has permanent heap access (like the DOM does). If you have good event handling
339     // discipline (i.e. you don't block the runloop) then you can be sure that stopIfNecessary() will
340     // already be called for you at the right times.
341     void stopIfNecessary();
342     
343     // This is a much stronger kind of stopping of the collector, and it may require waiting for a
344     // while. This is meant to be a legacy API for clients of collectAllGarbage that expect that there
345     // is no GC before or after that function call. After calling this, you are free to start GCs
346     // yourself but you can be sure that none are running.
347     //
348     // This both prevents new collections from being started asynchronously and waits for any
349     // outstanding collections to complete.
350     void preventCollection();
351     void allowCollection();
352     
353 #if USE(CF)
354     CFRunLoopRef runLoop() const { return m_runLoop.get(); }
355     JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
356 #endif // USE(CF)
357
358 private:
359     friend class AllocatingScope;
360     friend class CodeBlock;
361     friend class DeferGC;
362     friend class DeferGCForAWhile;
363     friend class GCAwareJITStubRoutine;
364     friend class GCLogging;
365     friend class GCThread;
366     friend class HandleSet;
367     friend class HeapUtil;
368     friend class HeapVerifier;
369     friend class HelpingGCScope;
370     friend class JITStubRoutine;
371     friend class LLIntOffsetsExtractor;
372     friend class MarkedSpace;
373     friend class MarkedAllocator;
374     friend class MarkedBlock;
375     friend class SlotVisitor;
376     friend class SpaceTimeScheduler;
377     friend class IncrementalSweeper;
378     friend class HeapStatistics;
379     friend class VM;
380     friend class WeakSet;
381
382     class Thread;
383     friend class Thread;
384
385     template<typename T> friend void* allocateCell(Heap&);
386     template<typename T> friend void* allocateCell(Heap&, size_t);
387     template<typename T> friend void* allocateCell(Heap&, GCDeferralContext*);
388     template<typename T> friend void* allocateCell(Heap&, GCDeferralContext*, size_t);
389
390     void* allocateWithDestructor(size_t); // For use with objects with destructors.
391     void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
392     void* allocateWithDestructor(GCDeferralContext*, size_t);
393     void* allocateWithoutDestructor(GCDeferralContext*, size_t);
394     template<typename ClassType> void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type.
395     template<typename ClassType> void* allocateObjectOfType(GCDeferralContext*, size_t);
396
397     static const size_t minExtraMemory = 256;
398     
399     class FinalizerOwner : public WeakHandleOwner {
400         void finalize(Handle<Unknown>, void* context) override;
401     };
402
403     JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
404     JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
405     JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
406     
407     bool shouldCollectInThread(const LockHolder&);
408     void collectInThread();
409     
410     void stopTheWorld();
411     void resumeTheWorld();
412     
413     class ResumeTheWorldScope;
414     friend class ResumeTheWorldScope;
415     
416     void stopTheMutator();
417     void resumeTheMutator();
418     
419     void stopIfNecessarySlow();
420     bool stopIfNecessarySlow(unsigned extraStateBits);
421     
422     template<typename Func>
423     void waitForCollector(const Func&);
424     
425     JS_EXPORT_PRIVATE void acquireAccessSlow();
426     JS_EXPORT_PRIVATE void releaseAccessSlow();
427     
428     bool handleGCDidJIT(unsigned);
429     bool handleNeedFinalize(unsigned);
430     void handleGCDidJIT();
431     void handleNeedFinalize();
432     
433     void setGCDidJIT();
434     void setNeedFinalize();
435     void waitWhileNeedFinalize();
436     
437     void setMutatorWaiting();
438     void clearMutatorWaiting();
439     void notifyThreadStopping(const LockHolder&);
440     
441     typedef uint64_t Ticket;
442     Ticket requestCollection(std::optional<CollectionScope>);
443     void waitForCollection(Ticket);
444     
445     void suspendCompilerThreads();
446     void willStartCollection(std::optional<CollectionScope>);
447     void flushWriteBarrierBuffer();
448     void prepareForMarking();
449     
450     void markToFixpoint(double gcStartTime);
451     void gatherStackRoots(ConservativeRoots&);
452     void gatherJSStackRoots(ConservativeRoots&);
453     void gatherScratchBufferRoots(ConservativeRoots&);
454     void beginMarking();
455     void visitConservativeRoots(ConservativeRoots&);
456     void visitCompilerWorklistWeakReferences();
457     void removeDeadCompilerWorklistEntries();
458     void markToFixpoint(HeapRootVisitor&);
459     void updateObjectCounts(double gcStartTime);
460     void endMarking();
461
462     void reapWeakHandles();
463     void pruneStaleEntriesFromWeakGCMaps();
464     void sweepArrayBuffers();
465     void snapshotUnswept();
466     void deleteSourceProviderCaches();
467     void notifyIncrementalSweeper();
468     void harvestWeakReferences();
469     void finalizeUnconditionalFinalizers();
470     void clearUnmarkedExecutables();
471     void deleteUnmarkedCompiledCode();
472     JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
473     void updateAllocationLimits();
474     void didFinishCollection(double gcStartTime);
475     void resumeCompilerThreads();
476     void zombifyDeadObjects();
477     void gatherExtraHeapSnapshotData(HeapProfiler&);
478     void removeDeadHeapSnapshotNodes(HeapProfiler&);
479     void finalize();
480     void sweepLargeAllocations();
481     
482     void sweepAllLogicallyEmptyWeakBlocks();
483     bool sweepNextLogicallyEmptyWeakBlock();
484
485     bool shouldDoFullCollection(std::optional<CollectionScope> requestedCollectionScope) const;
486
487     void incrementDeferralDepth();
488     void decrementDeferralDepth();
489     JS_EXPORT_PRIVATE void decrementDeferralDepthAndGCIfNeeded();
490
491     size_t threadVisitCount();
492     size_t threadBytesVisited();
493     
494     void forEachCodeBlockImpl(const ScopedLambda<bool(CodeBlock*)>&);
495     
496     void setMutatorShouldBeFenced(bool value);
497
498     const HeapType m_heapType;
499     const size_t m_ramSize;
500     const size_t m_minBytesPerCycle;
501     size_t m_sizeAfterLastCollect;
502     size_t m_sizeAfterLastFullCollect;
503     size_t m_sizeBeforeLastFullCollect;
504     size_t m_sizeAfterLastEdenCollect;
505     size_t m_sizeBeforeLastEdenCollect;
506
507     size_t m_bytesAllocatedThisCycle;
508     size_t m_bytesAbandonedSinceLastFullCollect;
509     size_t m_maxEdenSize;
510     size_t m_maxHeapSize;
511     bool m_shouldDoFullCollection;
512     size_t m_totalBytesVisited;
513     size_t m_totalBytesVisitedThisCycle;
514     
515     std::optional<CollectionScope> m_collectionScope;
516     std::optional<CollectionScope> m_lastCollectionScope;
517     MutatorState m_mutatorState { MutatorState::Running };
518     StructureIDTable m_structureIDTable;
519     MarkedSpace m_objectSpace;
520     GCIncomingRefCountedSet<ArrayBuffer> m_arrayBuffers;
521     size_t m_extraMemorySize;
522     size_t m_deprecatedExtraMemorySize;
523
524     HashSet<const JSCell*> m_copyingRememberedSet;
525
526     ProtectCountSet m_protectedValues;
527     std::unique_ptr<HashSet<MarkedArgumentBuffer*>> m_markListSet;
528
529     MachineThreads m_machineThreads;
530     
531     std::unique_ptr<SlotVisitor> m_collectorSlotVisitor;
532     std::unique_ptr<MarkStackArray> m_mutatorMarkStack;
533
534     // We pool the slot visitors used by parallel marking threads. It's useful to be able to
535     // enumerate over them, and it's useful to have them cache some small amount of memory from
536     // one GC to the next. GC marking threads claim these at the start of marking, and return
537     // them at the end.
538     Vector<std::unique_ptr<SlotVisitor>> m_parallelSlotVisitors;
539     Vector<SlotVisitor*> m_availableParallelSlotVisitors;
540     Lock m_parallelSlotVisitorLock;
541     
542     template<typename Func>
543     void forEachSlotVisitor(const Func&);
544
545     HandleSet m_handleSet;
546     HandleStack m_handleStack;
547     std::unique_ptr<CodeBlockSet> m_codeBlocks;
548     std::unique_ptr<JITStubRoutineSet> m_jitStubRoutines;
549     FinalizerOwner m_finalizerOwner;
550     
551     bool m_isSafeToCollect;
552
553     WriteBarrierBuffer m_writeBarrierBuffer;
554     bool m_mutatorShouldBeFenced { Options::forceFencedBarrier() };
555     unsigned m_barrierThreshold { Options::forceFencedBarrier() ? tautologicalThreshold : blackThreshold };
556
557     VM* m_vm;
558     double m_lastFullGCLength;
559     double m_lastEdenGCLength;
560
561     Vector<ExecutableBase*> m_executables;
562
563     Vector<WeakBlock*> m_logicallyEmptyWeakBlocks;
564     size_t m_indexOfNextLogicallyEmptyWeakBlockToSweep { WTF::notFound };
565     
566 #if USE(CF)
567     RetainPtr<CFRunLoopRef> m_runLoop;
568 #endif // USE(CF)
569     RefPtr<FullGCActivityCallback> m_fullActivityCallback;
570     RefPtr<GCActivityCallback> m_edenActivityCallback;
571     RefPtr<IncrementalSweeper> m_sweeper;
572     RefPtr<StopIfNecessaryTimer> m_stopIfNecessaryTimer;
573
574     Vector<HeapObserver*> m_observers;
575
576     unsigned m_deferralDepth;
577
578     std::unique_ptr<HeapVerifier> m_verifier;
579
580 #if USE(FOUNDATION)
581     Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
582     unsigned m_delayedReleaseRecursionCount;
583 #endif
584
585     HashMap<void*, std::function<void()>> m_weakGCMaps;
586     
587     HashSet<VisitRaceKey> m_visitRaces;
588     Lock m_visitRaceLock;
589
590     Lock m_markingMutex;
591     Condition m_markingConditionVariable;
592     std::unique_ptr<MarkStackArray> m_sharedCollectorMarkStack;
593     std::unique_ptr<MarkStackArray> m_sharedMutatorMarkStack;
594     unsigned m_numberOfActiveParallelMarkers { 0 };
595     unsigned m_numberOfWaitingParallelMarkers { 0 };
596     bool m_parallelMarkersShouldExit { false };
597
598     Lock m_opaqueRootsMutex;
599     HashSet<const void*> m_opaqueRoots;
600     HashSet<JSCell*> m_constraints;
601
602     static const size_t s_blockFragmentLength = 32;
603
604     ListableHandler<WeakReferenceHarvester>::List m_weakReferenceHarvesters;
605     ListableHandler<UnconditionalFinalizer>::List m_unconditionalFinalizers;
606
607     ParallelHelperClient m_helperClient;
608
609 #if ENABLE(RESOURCE_USAGE)
610     size_t m_blockBytesAllocated { 0 };
611     size_t m_externalMemorySize { 0 };
612 #endif
613     
614     static const unsigned shouldStopBit = 1u << 0u;
615     static const unsigned stoppedBit = 1u << 1u;
616     static const unsigned hasAccessBit = 1u << 2u;
617     static const unsigned gcDidJITBit = 1u << 3u; // Set when the GC did some JITing, so on resume we need to cpuid.
618     static const unsigned needFinalizeBit = 1u << 4u;
619     static const unsigned mutatorWaitingBit = 1u << 5u; // Allows the mutator to use this as a condition variable.
620     Atomic<unsigned> m_worldState;
621     bool m_collectorBelievesThatTheWorldIsStopped { false };
622     MonotonicTime m_stopTime;
623     
624     Deque<std::optional<CollectionScope>> m_requests;
625     Ticket m_lastServedTicket { 0 };
626     Ticket m_lastGrantedTicket { 0 };
627     bool m_threadShouldStop { false };
628     bool m_threadIsStopping { false };
629     Box<Lock> m_threadLock;
630     RefPtr<AutomaticThreadCondition> m_threadCondition; // The mutator must not wait on this. It would cause a deadlock.
631     RefPtr<AutomaticThread> m_thread;
632     
633     Lock m_collectContinuouslyLock;
634     Condition m_collectContinuouslyCondition;
635     bool m_shouldStopCollectingContinuously { false };
636     ThreadIdentifier m_collectContinuouslyThread { 0 };
637     
638     MonotonicTime m_lastGCStartTime;
639     MonotonicTime m_lastGCEndTime;
640     MonotonicTime m_currentGCStartTime;
641     
642     uintptr_t m_barriersExecuted { 0 };
643 };
644
645 } // namespace JSC