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