#include "platform/PlatformExport.h"
#include "platform/heap/AddressSanitizer.h"
+#include "public/platform/WebThread.h"
#include "wtf/HashSet.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
class HeapObjectHeader;
class PageMemory;
class PersistentNode;
+class WrapperPersistentRegion;
class Visitor;
class SafePointBarrier;
class SafePointAwareMutexLocker;
H(Node)
#define TypedHeapEnumName(Type) Type##Heap,
+#define TypedHeapEnumNameNonFinalized(Type) Type##HeapNonFinalized,
enum TypedHeaps {
- GeneralHeap,
+ GeneralHeap = 0,
+ CollectionBackingHeap,
FOR_EACH_TYPED_HEAP(TypedHeapEnumName)
- NumberOfHeaps
+ GeneralHeapNonFinalized,
+ CollectionBackingHeapNonFinalized,
+ FOR_EACH_TYPED_HEAP(TypedHeapEnumNameNonFinalized)
+ // Values used for iteration of heap segments.
+ NumberOfHeaps,
+ FirstFinalizedHeap = GeneralHeap,
+ FirstNonFinalizedHeap = GeneralHeapNonFinalized,
+ NumberOfFinalizedHeaps = GeneralHeapNonFinalized,
+ NumberOfNonFinalizedHeaps = NumberOfHeaps - NumberOfFinalizedHeaps,
+ NonFinalizedHeapOffset = FirstNonFinalizedHeap
};
-// Trait to give an index in the thread state to all the
-// type-specialized heaps. The general heap is at index 0 in the
-// thread state. The index for other type-specialized heaps are given
-// by the TypedHeaps enum above.
-template<typename T>
-struct HeapTrait {
- static const int index = GeneralHeap;
- typedef ThreadHeap<FinalizedHeapObjectHeader> HeapType;
+// Base implementation for HeapIndexTrait found below.
+template<int heapIndex>
+struct HeapIndexTraitBase {
+ typedef FinalizedHeapObjectHeader HeaderType;
+ typedef ThreadHeap<HeaderType> HeapType;
+ static const int finalizedIndex = heapIndex;
+ static const int nonFinalizedIndex = heapIndex + static_cast<int>(NonFinalizedHeapOffset);
+ static int index(bool isFinalized)
+ {
+ return isFinalized ? finalizedIndex : nonFinalizedIndex;
+ }
};
-#define DEFINE_HEAP_INDEX_TRAIT(Type) \
- class Type; \
- template<> \
- struct HeapTrait<class Type> { \
- static const int index = Type##Heap; \
- typedef ThreadHeap<HeapObjectHeader> HeapType; \
- };
+// HeapIndexTrait defines properties for each heap in the TypesHeaps enum.
+template<int index>
+struct HeapIndexTrait;
+
+template<>
+struct HeapIndexTrait<GeneralHeap> : public HeapIndexTraitBase<GeneralHeap> { };
+template<>
+struct HeapIndexTrait<GeneralHeapNonFinalized> : public HeapIndexTrait<GeneralHeap> { };
+
+template<>
+struct HeapIndexTrait<CollectionBackingHeap> : public HeapIndexTraitBase<CollectionBackingHeap> { };
+template<>
+struct HeapIndexTrait<CollectionBackingHeapNonFinalized> : public HeapIndexTrait<CollectionBackingHeap> { };
+
+#define DEFINE_TYPED_HEAP_INDEX_TRAIT(Type) \
+ template<> \
+ struct HeapIndexTrait<Type##Heap> : public HeapIndexTraitBase<Type##Heap> { \
+ typedef HeapObjectHeader HeaderType; \
+ typedef ThreadHeap<HeaderType> HeapType; \
+ }; \
+ template<> \
+ struct HeapIndexTrait<Type##HeapNonFinalized> : public HeapIndexTrait<Type##Heap> { };
+FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_INDEX_TRAIT)
+#undef DEFINE_TYPED_HEAP_INDEX_TRAIT
+
+// HeapTypeTrait defines which heap to use for particular types.
+// By default objects are allocated in the GeneralHeap.
+template<typename T>
+struct HeapTypeTrait : public HeapIndexTrait<GeneralHeap> { };
+
+// We don't have any type-based mappings to the CollectionBackingHeap.
-FOR_EACH_TYPED_HEAP(DEFINE_HEAP_INDEX_TRAIT)
+// Each typed-heap maps the respective type to its heap.
+#define DEFINE_TYPED_HEAP_TRAIT(Type) \
+ class Type; \
+ template<> \
+ struct HeapTypeTrait<class Type> : public HeapIndexTrait<Type##Heap> { };
+FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
+#undef DEFINE_TYPED_HEAP_TRAIT
// A HeapStats structure keeps track of the amount of memory allocated
// for a Blink heap and how much of that memory is used for actual
// when to perform garbage collections.
class HeapStats {
public:
+ HeapStats() : m_totalObjectSpace(0), m_totalAllocatedSpace(0) { }
+
size_t totalObjectSpace() const { return m_totalObjectSpace; }
size_t totalAllocatedSpace() const { return m_totalAllocatedSpace; }
HeapPointersOnStack
};
+ // When profiling we would like to identify forced GC requests.
+ enum CauseOfGC {
+ NormalGC,
+ ForcedGC
+ };
+
+ class NoSweepScope {
+ public:
+ explicit NoSweepScope(ThreadState* state) : m_state(state)
+ {
+ ASSERT(!m_state->m_sweepInProgress);
+ m_state->m_sweepInProgress = true;
+ }
+ ~NoSweepScope()
+ {
+ ASSERT(m_state->m_sweepInProgress);
+ m_state->m_sweepInProgress = false;
+ }
+ private:
+ ThreadState* m_state;
+ };
+
// The set of ThreadStates for all threads attached to the Blink
// garbage collector.
typedef HashSet<ThreadState*> AttachedThreadStateSet;
void leaveNoAllocationScope() { m_noAllocationCount--; }
// Before performing GC the thread-specific heap state should be
- // made consistent for garbage collection.
- bool isConsistentForGC();
- void makeConsistentForGC();
+ // made consistent for sweeping.
+ void makeConsistentForSweeping();
+#if ENABLE(ASSERT)
+ bool isConsistentForSweeping();
+#endif
// Is the thread corresponding to this thread state currently
// performing GC?
bool isInGC() const { return m_inGC; }
// Is any of the threads registered with the blink garbage collection
- // infrastructure currently perform GC?
+ // infrastructure currently performing GC?
static bool isAnyThreadInGC() { return s_inGC; }
void enterGC()
//
// The heap is split into multiple heap parts based on object
// types. To get the index for a given type, use
- // HeapTrait<Type>::index.
+ // HeapTypeTrait<Type>::index.
BaseHeap* heap(int index) const { return m_heaps[index]; }
// Infrastructure to determine if an address is within one of the
BaseHeapPage* contains(void* pointer) { return contains(reinterpret_cast<Address>(pointer)); }
BaseHeapPage* contains(const void* pointer) { return contains(const_cast<void*>(pointer)); }
+ WrapperPersistentRegion* wrapperRoots() const
+ {
+ ASSERT(m_liveWrapperPersistents);
+ return m_liveWrapperPersistents;
+ }
+ WrapperPersistentRegion* takeWrapperPersistentRegion();
+ void freeWrapperPersistentRegion(WrapperPersistentRegion*);
+
// List of persistent roots allocated on the given thread.
PersistentNode* roots() const { return m_persistents.get(); }
struct SnapshotInfo {
ThreadState* state;
- size_t liveSize;
- size_t deadSize;
size_t freeSize;
size_t pageCount;
// Map from base-classes to a snapshot class-ids (used as index below).
HashMap<const GCInfo*, size_t> classTags;
- // Map from class-id (index) to count.
+ // Map from class-id (index) to count/size.
Vector<int> liveCount;
Vector<int> deadCount;
+ Vector<size_t> liveSize;
+ Vector<size_t> deadSize;
// Map from class-id (index) to a vector of generation counts.
// For i < 7, the count is the number of objects that died after surviving |i| GCs.
// For i == 7, the count is the number of objects that survived at least 7 GCs.
Vector<Vector<int, 8> > generations;
- explicit SnapshotInfo(ThreadState* state) : state(state), liveSize(0), deadSize(0), freeSize(0), pageCount(0) { }
+ explicit SnapshotInfo(ThreadState* state) : state(state), freeSize(0), pageCount(0) { }
size_t getClassTag(const GCInfo*);
};
void setupHeapsForTermination();
+ void registerSweepingTask();
+ void unregisterSweepingTask();
+
+ Mutex& sweepMutex() { return m_sweepMutex; }
+
private:
explicit ThreadState();
~ThreadState();
void setLowCollectionRate(bool value) { m_lowCollectionRate = value; }
+ void waitUntilSweepersDone();
+
static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific;
static SafePointBarrier* s_safePointBarrier;
static uint8_t s_mainThreadStateStorage[];
ThreadIdentifier m_thread;
+ WrapperPersistentRegion* m_liveWrapperPersistents;
+ WrapperPersistentRegion* m_pooledWrapperPersistents;
+ size_t m_pooledWrapperPersistentRegionCount;
OwnPtr<PersistentNode> m_persistents;
StackState m_stackState;
intptr_t* m_startOfStack;
bool m_lowCollectionRate;
+ OwnPtr<blink::WebThread> m_sweeperThread;
+ int m_numberOfSweeperTasks;
+ Mutex m_sweepMutex;
+ ThreadCondition m_sweepThreadCondition;
+
CallbackStack* m_weakCallbackStack;
#if defined(ADDRESS_SANITIZER)
virtual void checkAndMarkPointer(Visitor*, Address) = 0;
virtual bool contains(Address) = 0;
-#if ENABLE(GC_TRACING)
+#if ENABLE(GC_PROFILE_MARKING)
virtual const GCInfo* findGCInfo(Address) = 0;
#endif
void setTerminating() { m_terminating = true; }
bool tracedAfterOrphaned() { return m_tracedAfterOrphaned; }
void setTracedAfterOrphaned() { m_tracedAfterOrphaned = true; }
+ size_t promptlyFreedSize() { return m_promptlyFreedSize; }
+ void resetPromptlyFreedSize() { m_promptlyFreedSize = 0; }
+ void addToPromptlyFreedSize(size_t size) { m_promptlyFreedSize += size; }
private:
PageMemory* m_storage;
// if the page is traced after being terminated (orphaned).
uintptr_t m_terminating : 1;
uintptr_t m_tracedAfterOrphaned : 1;
+ uintptr_t m_promptlyFreedSize : 17; // == blinkPageSizeLog2
};
}