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