/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2009, 2013-2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#ifndef Heap_h
#define Heap_h
-#include "BlockAllocator.h"
-#include "DFGCodeBlocks.h"
+#include "ArrayBuffer.h"
+#include "CodeBlockSet.h"
+#include "CopyVisitor.h"
+#include "GCIncomingRefCountedSet.h"
+#include "GCThreadSharedData.h"
#include "HandleSet.h"
#include "HandleStack.h"
+#include "HeapOperation.h"
+#include "JITStubRoutineSet.h"
#include "MarkedAllocator.h"
#include "MarkedBlock.h"
#include "MarkedBlockSet.h"
#include "MarkedSpace.h"
+#include "Options.h"
#include "SlotVisitor.h"
+#include "StructureIDTable.h"
#include "WeakHandleOwner.h"
-#include "WeakSet.h"
+#include "WriteBarrierBuffer.h"
#include "WriteBarrierSupport.h"
#include <wtf/HashCountedSet.h>
#include <wtf/HashSet.h>
-#define COLLECT_ON_EVERY_ALLOCATION 0
-
namespace JSC {
- class CopiedSpace;
- class CodeBlock;
- class FunctionExecutable;
- class GCActivityCallback;
- class GlobalCodeBlock;
- class Heap;
- class HeapRootVisitor;
- class JSCell;
- class JSGlobalData;
- class JSValue;
- class LiveObjectIterator;
- class LLIntOffsetsExtractor;
- class MarkedArgumentBuffer;
- class RegisterFile;
- class UString;
- class WeakGCHandlePool;
- class SlotVisitor;
-
- typedef std::pair<JSValue, UString> ValueStringPair;
- typedef HashCountedSet<JSCell*> ProtectCountSet;
- typedef HashCountedSet<const char*> TypeCountSet;
-
- enum OperationInProgress { NoOperation, Allocation, Collection };
-
- // Heap size hint.
- enum HeapSize { SmallHeap, LargeHeap };
-
- class Heap {
- WTF_MAKE_NONCOPYABLE(Heap);
- public:
- friend class JIT;
- friend class MarkStackThreadSharedData;
- static Heap* heap(const JSValue); // 0 for immediate values
- static Heap* heap(const JSCell*);
-
- // This constant determines how many blocks we iterate between checks of our
- // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect
- // overstepping our deadline more quickly, while increasing it will cause
- // our scan to run faster.
- static const unsigned s_timeCheckResolution = 16;
-
- static bool isMarked(const void*);
- static bool testAndSetMarked(const void*);
- static void setMarked(const void*);
-
- static void writeBarrier(const JSCell*, JSValue);
- static void writeBarrier(const JSCell*, JSCell*);
- static uint8_t* addressOfCardFor(JSCell*);
-
- Heap(JSGlobalData*, HeapSize);
- ~Heap();
- JS_EXPORT_PRIVATE void lastChanceToFinalize();
-
- JSGlobalData* globalData() const { return m_globalData; }
- MarkedSpace& objectSpace() { return m_objectSpace; }
- MachineThreads& machineThreads() { return m_machineThreads; }
-
- JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
- JS_EXPORT_PRIVATE void setActivityCallback(GCActivityCallback*);
-
- // true if an allocation or collection is in progress
- inline bool isBusy();
-
- MarkedAllocator& firstAllocatorWithoutDestructors() { return m_objectSpace.firstAllocator(); }
- MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
- MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
- CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
- CheckedBoolean tryAllocateStorage(size_t, void**);
- CheckedBoolean tryReallocateStorage(void**, size_t, size_t);
-
- typedef void (*Finalizer)(JSCell*);
- JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
- void addFunctionExecutable(FunctionExecutable*);
- void removeFunctionExecutable(FunctionExecutable*);
-
- void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
-
- JS_EXPORT_PRIVATE void collectAllGarbage();
- enum SweepToggle { DoNotSweep, DoSweep };
- bool shouldCollect();
- void collect(SweepToggle);
-
- void reportExtraMemoryCost(size_t cost);
- JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
-
- JS_EXPORT_PRIVATE void protect(JSValue);
- JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
-
- void jettisonDFGCodeBlock(PassOwnPtr<CodeBlock>);
-
- JS_EXPORT_PRIVATE size_t size();
- JS_EXPORT_PRIVATE size_t capacity();
- JS_EXPORT_PRIVATE size_t objectCount();
- JS_EXPORT_PRIVATE size_t globalObjectCount();
- JS_EXPORT_PRIVATE size_t protectedObjectCount();
- JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
- JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
- JS_EXPORT_PRIVATE PassOwnPtr<TypeCountSet> objectTypeCounts();
-
- void pushTempSortVector(Vector<ValueStringPair>*);
- void popTempSortVector(Vector<ValueStringPair>*);
+class CopiedSpace;
+class CodeBlock;
+class ExecutableBase;
+class EdenGCActivityCallback;
+class FullGCActivityCallback;
+class GCActivityCallback;
+class GCAwareJITStubRoutine;
+class GlobalCodeBlock;
+class Heap;
+class HeapRootVisitor;
+class HeapVerifier;
+class IncrementalSweeper;
+class JITStubRoutine;
+class JSCell;
+class VM;
+class JSStack;
+class JSValue;
+class LiveObjectIterator;
+class LLIntOffsetsExtractor;
+class MarkedArgumentBuffer;
+class WeakGCHandlePool;
+class SlotVisitor;
+
+namespace DFG {
+class Worklist;
+}
+
+static void* const zombifiedBits = reinterpret_cast<void*>(0xdeadbeef);
+
+typedef HashCountedSet<JSCell*> ProtectCountSet;
+typedef HashCountedSet<const char*> TypeCountSet;
+
+enum HeapType { SmallHeap, LargeHeap };
+
+class Heap {
+ WTF_MAKE_NONCOPYABLE(Heap);
+public:
+ friend class JIT;
+ friend class DFG::SpeculativeJIT;
+ friend class GCThreadSharedData;
+ static Heap* heap(const JSValue); // 0 for immediate values
+ static Heap* heap(const JSCell*);
+
+ // This constant determines how many blocks we iterate between checks of our
+ // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect
+ // overstepping our deadline more quickly, while increasing it will cause
+ // our scan to run faster.
+ static const unsigned s_timeCheckResolution = 16;
+
+ static bool isLive(const void*);
+ static bool isMarked(const void*);
+ static bool testAndSetMarked(const void*);
+ static void setMarked(const void*);
+ static bool isRemembered(const void*);
+
+ JS_EXPORT_PRIVATE void addToRememberedSet(const JSCell*);
+ static bool isWriteBarrierEnabled();
+ void writeBarrier(const JSCell*);
+ void writeBarrier(const JSCell*, JSValue);
+ void writeBarrier(const JSCell*, JSCell*);
+
+ WriteBarrierBuffer& writeBarrierBuffer() { return m_writeBarrierBuffer; }
+ void flushWriteBarrierBuffer(JSCell*);
+
+ Heap(VM*, HeapType);
+ ~Heap();
+ JS_EXPORT_PRIVATE void lastChanceToFinalize();
+ void releaseDelayedReleasedObjects();
+
+ VM* vm() const { return m_vm; }
+ MarkedSpace& objectSpace() { return m_objectSpace; }
+ CopiedSpace& storageSpace() { return m_storageSpace; }
+ MachineThreads& machineThreads() { return m_machineThreads; }
+
+ const SlotVisitor& slotVisitor() const { return m_slotVisitor; }
+
+ JS_EXPORT_PRIVATE GCActivityCallback* fullActivityCallback();
+ JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
+ JS_EXPORT_PRIVATE void setFullActivityCallback(PassRefPtr<FullGCActivityCallback>);
+ JS_EXPORT_PRIVATE void setEdenActivityCallback(PassRefPtr<EdenGCActivityCallback>);
+ JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
+
+ JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
+ JS_EXPORT_PRIVATE void setIncrementalSweeper(std::unique_ptr<IncrementalSweeper>);
+
+ // true if collection is in progress
+ bool isCollecting();
+ HeapOperation operationInProgress() { return m_operationInProgress; }
+ // true if an allocation or collection is in progress
+ bool isBusy();
+ MarkedSpace::Subspace& subspaceForObjectWithoutDestructor() { return m_objectSpace.subspaceForObjectsWithoutDestructor(); }
+ MarkedSpace::Subspace& subspaceForObjectDestructor() { return m_objectSpace.subspaceForObjectsWithDestructor(); }
+ template<typename ClassType> MarkedSpace::Subspace& subspaceForObjectOfType();
+ MarkedAllocator& allocatorForObjectWithoutDestructor(size_t bytes) { return m_objectSpace.allocatorFor(bytes); }
+ MarkedAllocator& allocatorForObjectWithDestructor(size_t bytes) { return m_objectSpace.destructorAllocatorFor(bytes); }
+ template<typename ClassType> MarkedAllocator& allocatorForObjectOfType(size_t bytes);
+ CopiedAllocator& storageAllocator() { return m_storageSpace.allocator(); }
+ CheckedBoolean tryAllocateStorage(JSCell* intendedOwner, size_t, void**);
+ CheckedBoolean tryReallocateStorage(JSCell* intendedOwner, void**, size_t, size_t);
+ void ascribeOwner(JSCell* intendedOwner, void*);
+
+ typedef void (*Finalizer)(JSCell*);
+ JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
+ void addCompiledCode(ExecutableBase*);
+
+ void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
+ bool isSafeToCollect() const { return m_isSafeToCollect; }
+
+ JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
+ void collectAllGarbage() { collectAndSweep(FullCollection); }
+ JS_EXPORT_PRIVATE void collectAndSweep(HeapOperation collectionType = AnyCollection);
+ bool shouldCollect();
+ JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
+ bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
+
+ // Use this API to report non-GC memory referenced by GC objects. Be sure to
+ // call both of these functions: Calling only one may trigger catastropic
+ // memory growth.
+ void reportExtraMemoryAllocated(size_t);
+ void reportExtraMemoryVisited(JSCell*, size_t);
+
+ // Use this API to report non-GC memory if you can't use the better API above.
+ void deprecatedReportExtraMemory(size_t);
+
+ JS_EXPORT_PRIVATE void reportAbandonedObjectGraph();
+
+ JS_EXPORT_PRIVATE void protect(JSValue);
+ JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0.
+
+ size_t extraMemorySize(); // Non-GC memory referenced by GC objects.
+ JS_EXPORT_PRIVATE size_t size();
+ JS_EXPORT_PRIVATE size_t capacity();
+ JS_EXPORT_PRIVATE size_t objectCount();
+ JS_EXPORT_PRIVATE size_t globalObjectCount();
+ JS_EXPORT_PRIVATE size_t protectedObjectCount();
+ JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount();
+ JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> protectedObjectTypeCounts();
+ JS_EXPORT_PRIVATE std::unique_ptr<TypeCountSet> objectTypeCounts();
+ void showStatistics();
+
+ HashSet<MarkedArgumentBuffer*>& markListSet();
- HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
-
- template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
- template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
-
- WeakSet* weakSet() { return &m_weakSet; }
- HandleSet* handleSet() { return &m_handleSet; }
- HandleStack* handleStack() { return &m_handleStack; }
-
- void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
-
- double lastGCLength() { return m_lastGCLength; }
- void increaseLastGCLength(double amount) { m_lastGCLength += amount; }
-
- JS_EXPORT_PRIVATE void discardAllCompiledCode();
-
- void didAllocate(size_t);
- void didAbandon(size_t);
-
- bool isPagedOut(double deadline);
-
- private:
- friend class CodeBlock;
- friend class LLIntOffsetsExtractor;
- friend class MarkedSpace;
- friend class MarkedAllocator;
- friend class MarkedBlock;
- friend class CopiedSpace;
- friend class SlotVisitor;
- template<typename T> friend void* allocateCell(Heap&);
-
- void* allocateWithDestructor(size_t);
- void* allocateWithoutDestructor(size_t);
-
- static const size_t minExtraCost = 256;
- static const size_t maxExtraCost = 1024 * 1024;
-
- class FinalizerOwner : public WeakHandleOwner {
- virtual void finalize(Handle<Unknown>, void* context);
- };
-
- JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
- JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
-
- // Call this function before any operation that needs to know which cells
- // in the heap are live. (For example, call this function before
- // conservative marking, eager sweeping, or iterating the cells in a MarkedBlock.)
- void canonicalizeCellLivenessData();
-
- void resetAllocators();
-
- void clearMarks();
- void markRoots(bool fullGC);
- void markProtectedObjects(HeapRootVisitor&);
- void markTempSortVectors(HeapRootVisitor&);
- void harvestWeakReferences();
- void finalizeUnconditionalFinalizers();
-
- void sweep();
-
- RegisterFile& registerFile();
- BlockAllocator& blockAllocator();
-
- const HeapSize m_heapSize;
- const size_t m_minBytesPerCycle;
- size_t m_sizeAfterLastCollect;
-
- size_t m_bytesAllocatedLimit;
- size_t m_bytesAllocated;
- size_t m_bytesAbandoned;
-
- OperationInProgress m_operationInProgress;
- MarkedSpace m_objectSpace;
- CopiedSpace m_storageSpace;
-
- BlockAllocator m_blockAllocator;
-
-#if ENABLE(SIMPLE_HEAP_PROFILING)
- VTableSpectrum m_destroyedTypeCounts;
+ template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&);
+ template<typename Functor> typename Functor::ReturnType forEachProtectedCell();
+ template<typename Functor> void forEachCodeBlock(Functor&);
+
+ HandleSet* handleSet() { return &m_handleSet; }
+ HandleStack* handleStack() { return &m_handleStack; }
+
+ void willStartIterating();
+ void didFinishIterating();
+ void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
+
+ double lastFullGCLength() const { return m_lastFullGCLength; }
+ double lastEdenGCLength() const { return m_lastEdenGCLength; }
+ void increaseLastFullGCLength(double amount) { m_lastFullGCLength += amount; }
+
+ size_t sizeBeforeLastEdenCollection() const { return m_sizeBeforeLastEdenCollect; }
+ size_t sizeAfterLastEdenCollection() const { return m_sizeAfterLastEdenCollect; }
+ size_t sizeBeforeLastFullCollection() const { return m_sizeBeforeLastFullCollect; }
+ size_t sizeAfterLastFullCollection() const { return m_sizeAfterLastFullCollect; }
+
+ JS_EXPORT_PRIVATE void deleteAllCompiledCode();
+ void deleteAllUnlinkedFunctionCode();
+
+ void didAllocate(size_t);
+ void didAbandon(size_t);
+
+ bool isPagedOut(double deadline);
+
+ const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; }
+
+ void addReference(JSCell*, ArrayBuffer*);
+
+ bool isDeferred() const { return !!m_deferralDepth || Options::disableGC(); }
+
+ StructureIDTable& structureIDTable() { return m_structureIDTable; }
+
+#if USE(CF)
+ template<typename T> void releaseSoon(RetainPtr<T>&&);
#endif
- ProtectCountSet m_protectedValues;
- Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
- HashSet<MarkedArgumentBuffer*>* m_markListSet;
-
- MachineThreads m_machineThreads;
-
- MarkStackThreadSharedData m_sharedData;
- SlotVisitor m_slotVisitor;
-
- WeakSet m_weakSet;
- HandleSet m_handleSet;
- HandleStack m_handleStack;
- DFGCodeBlocks m_dfgCodeBlocks;
- FinalizerOwner m_finalizerOwner;
-
- bool m_isSafeToCollect;
-
- JSGlobalData* m_globalData;
- double m_lastGCLength;
- double m_lastCodeDiscardTime;
-
- DoublyLinkedList<FunctionExecutable> m_functions;
-
- GCActivityCallback* m_activityCallback;
+ void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); }
+
+ static bool isZombified(JSCell* cell) { return *(void**)cell == zombifiedBits; }
+
+ void registerWeakGCMap(void* weakGCMap, std::function<void()> pruningCallback);
+ void unregisterWeakGCMap(void* weakGCMap);
+
+ void addLogicallyEmptyWeakBlock(WeakBlock*);
+
+private:
+ friend class CodeBlock;
+ friend class CopiedBlock;
+ friend class DeferGC;
+ friend class DeferGCForAWhile;
+ friend class GCAwareJITStubRoutine;
+ friend class GCLogging;
+ friend class HandleSet;
+ friend class HeapVerifier;
+ friend class JITStubRoutine;
+ friend class LLIntOffsetsExtractor;
+ friend class MarkedSpace;
+ friend class MarkedAllocator;
+ friend class MarkedBlock;
+ friend class CopiedSpace;
+ friend class CopyVisitor;
+ friend class RecursiveAllocationScope;
+ friend class SlotVisitor;
+ friend class SuperRegion;
+ friend class IncrementalSweeper;
+ friend class HeapStatistics;
+ friend class VM;
+ friend class WeakSet;
+ template<typename T> friend void* allocateCell(Heap&);
+ template<typename T> friend void* allocateCell(Heap&, size_t);
+
+ void* allocateWithDestructor(size_t); // For use with objects with destructors.
+ void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
+ template<typename ClassType> void* allocateObjectOfType(size_t); // Chooses one of the methods above based on type.
+
+ static const size_t minExtraMemory = 256;
+
+ class FinalizerOwner : public WeakHandleOwner {
+ virtual void finalize(Handle<Unknown>, void* context) override;
};
- inline bool Heap::shouldCollect()
- {
-#if ENABLE(GGC)
- return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect && m_operationInProgress == NoOperation;
-#else
- return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect && m_operationInProgress == NoOperation;
-#endif
- }
-
- bool Heap::isBusy()
- {
- return m_operationInProgress != NoOperation;
- }
-
- inline Heap* Heap::heap(const JSCell* cell)
- {
- return MarkedBlock::blockFor(cell)->heap();
- }
-
- inline Heap* Heap::heap(const JSValue v)
- {
- if (!v.isCell())
- return 0;
- return heap(v.asCell());
- }
-
- inline bool Heap::isMarked(const void* cell)
- {
- return MarkedBlock::blockFor(cell)->isMarked(cell);
- }
-
- inline bool Heap::testAndSetMarked(const void* cell)
- {
- return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
- }
-
- inline void Heap::setMarked(const void* cell)
- {
- MarkedBlock::blockFor(cell)->setMarked(cell);
- }
-
-#if ENABLE(GGC)
- inline uint8_t* Heap::addressOfCardFor(JSCell* cell)
- {
- return MarkedBlock::blockFor(cell)->addressOfCardFor(cell);
- }
-
- inline void Heap::writeBarrier(const JSCell* owner, JSCell*)
- {
- WriteBarrierCounters::countWriteBarrier();
- MarkedBlock* block = MarkedBlock::blockFor(owner);
- if (block->isMarked(owner))
- block->setDirtyObject(owner);
- }
-
- inline void Heap::writeBarrier(const JSCell* owner, JSValue value)
- {
- if (!value)
- return;
- if (!value.isCell())
- return;
- writeBarrier(owner, value.asCell());
- }
-#else
-
- inline void Heap::writeBarrier(const JSCell*, JSCell*)
- {
- WriteBarrierCounters::countWriteBarrier();
- }
-
- inline void Heap::writeBarrier(const JSCell*, JSValue)
- {
- WriteBarrierCounters::countWriteBarrier();
- }
-#endif
+ JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
+ JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
+ JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
+
+ void collectImpl(HeapOperation, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
+
+ void suspendCompilerThreads();
+ void willStartCollection(HeapOperation collectionType);
+ void deleteOldCode(double gcStartTime);
+ void flushOldStructureIDTables();
+ void flushWriteBarrierBuffer();
+ void stopAllocation();
+
+ void markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
+ void gatherStackRoots(ConservativeRoots&, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&);
+ void gatherJSStackRoots(ConservativeRoots&);
+ void gatherScratchBufferRoots(ConservativeRoots&);
+ void clearLivenessData();
+ void visitExternalRememberedSet();
+ void visitSmallStrings();
+ void visitConservativeRoots(ConservativeRoots&);
+ void visitCompilerWorklistWeakReferences();
+ void removeDeadCompilerWorklistEntries();
+ void visitProtectedObjects(HeapRootVisitor&);
+ void visitArgumentBuffers(HeapRootVisitor&);
+ void visitException(HeapRootVisitor&);
+ void visitStrongHandles(HeapRootVisitor&);
+ void visitHandleStack(HeapRootVisitor&);
+ void traceCodeBlocksAndJITStubRoutines();
+ void converge();
+ void visitWeakHandles(HeapRootVisitor&);
+ void clearRememberedSet(Vector<const JSCell*>&);
+ void updateObjectCounts(double gcStartTime);
+ void resetVisitors();
+
+ void reapWeakHandles();
+ void pruneStaleEntriesFromWeakGCMaps();
+ void sweepArrayBuffers();
+ void snapshotMarkedSpace();
+ void deleteSourceProviderCaches();
+ void notifyIncrementalSweeper();
+ void rememberCurrentlyExecutingCodeBlocks();
+ void resetAllocators();
+ void copyBackingStores();
+ void harvestWeakReferences();
+ void finalizeUnconditionalFinalizers();
+ void clearUnmarkedExecutables();
+ void deleteUnmarkedCompiledCode();
+ void updateAllocationLimits();
+ void didFinishCollection(double gcStartTime);
+ void resumeCompilerThreads();
+ void zombifyDeadObjects();
+ void markDeadObjects();
+
+ void sweepAllLogicallyEmptyWeakBlocks();
+ bool sweepNextLogicallyEmptyWeakBlock();
+
+ bool shouldDoFullCollection(HeapOperation requestedCollectionType) const;
+ size_t sizeAfterCollect();
+
+ JSStack& stack();
+
+ void incrementDeferralDepth();
+ void decrementDeferralDepth();
+ void decrementDeferralDepthAndGCIfNeeded();
+
+ const HeapType m_heapType;
+ const size_t m_ramSize;
+ const size_t m_minBytesPerCycle;
+ size_t m_sizeAfterLastCollect;
+ size_t m_sizeAfterLastFullCollect;
+ size_t m_sizeBeforeLastFullCollect;
+ size_t m_sizeAfterLastEdenCollect;
+ size_t m_sizeBeforeLastEdenCollect;
+
+ size_t m_bytesAllocatedThisCycle;
+ size_t m_bytesAbandonedSinceLastFullCollect;
+ size_t m_maxEdenSize;
+ size_t m_maxHeapSize;
+ bool m_shouldDoFullCollection;
+ size_t m_totalBytesVisited;
+ size_t m_totalBytesCopied;
+
+ HeapOperation m_operationInProgress;
+ StructureIDTable m_structureIDTable;
+ MarkedSpace m_objectSpace;
+ CopiedSpace m_storageSpace;
+ GCIncomingRefCountedSet<ArrayBuffer> m_arrayBuffers;
+ size_t m_extraMemorySize;
+ size_t m_deprecatedExtraMemorySize;
- inline void Heap::reportExtraMemoryCost(size_t cost)
- {
- if (cost > minExtraCost)
- reportExtraMemoryCostSlowCase(cost);
- }
-
- template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor)
- {
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- functor(it->first);
- m_handleSet.forEachStrongHandle(functor, m_protectedValues);
-
- return functor.returnValue();
- }
-
- template<typename Functor> inline typename Functor::ReturnType Heap::forEachProtectedCell()
- {
- Functor functor;
- return forEachProtectedCell(functor);
- }
-
- inline void* Heap::allocateWithDestructor(size_t bytes)
- {
- ASSERT(isValidAllocation(bytes));
- return m_objectSpace.allocateWithDestructor(bytes);
- }
+ HashSet<const JSCell*> m_copyingRememberedSet;
+
+ ProtectCountSet m_protectedValues;
+ std::unique_ptr<HashSet<MarkedArgumentBuffer*>> m_markListSet;
+
+ MachineThreads m_machineThreads;
+
+ GCThreadSharedData m_sharedData;
+ SlotVisitor m_slotVisitor;
+ CopyVisitor m_copyVisitor;
+
+ HandleSet m_handleSet;
+ HandleStack m_handleStack;
+ CodeBlockSet m_codeBlocks;
+ JITStubRoutineSet m_jitStubRoutines;
+ FinalizerOwner m_finalizerOwner;
- inline void* Heap::allocateWithoutDestructor(size_t bytes)
- {
- ASSERT(isValidAllocation(bytes));
- return m_objectSpace.allocateWithoutDestructor(bytes);
- }
+ bool m_isSafeToCollect;
+
+ WriteBarrierBuffer m_writeBarrierBuffer;
+
+ VM* m_vm;
+ double m_lastFullGCLength;
+ double m_lastEdenGCLength;
+ double m_lastCodeDiscardTime;
+
+ Vector<ExecutableBase*> m_compiledCode;
+
+ Vector<WeakBlock*> m_logicallyEmptyWeakBlocks;
+ size_t m_indexOfNextLogicallyEmptyWeakBlockToSweep { WTF::notFound };
- inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr)
- {
- return m_storageSpace.tryAllocate(bytes, outPtr);
- }
+ RefPtr<FullGCActivityCallback> m_fullActivityCallback;
+ RefPtr<GCActivityCallback> m_edenActivityCallback;
+ std::unique_ptr<IncrementalSweeper> m_sweeper;
+ Vector<MarkedBlock*> m_blockSnapshot;
- inline CheckedBoolean Heap::tryReallocateStorage(void** ptr, size_t oldSize, size_t newSize)
- {
- return m_storageSpace.tryReallocate(ptr, oldSize, newSize);
- }
-
- inline BlockAllocator& Heap::blockAllocator()
- {
- return m_blockAllocator;
- }
+ unsigned m_deferralDepth;
+ Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
+
+ std::unique_ptr<HeapVerifier> m_verifier;
+#if USE(CF)
+ Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
+ unsigned m_delayedReleaseRecursionCount;
+#endif
+
+ HashMap<void*, std::function<void()>> m_weakGCMaps;
+};
} // namespace JSC