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