Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Unified Diff: third_party/WebKit/Source/platform/heap/Heap.h

Issue 1477023003: Refactor the Heap into ThreadHeap to prepare for per thread heaps Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/heap/Heap.h
diff --git a/third_party/WebKit/Source/platform/heap/Heap.h b/third_party/WebKit/Source/platform/heap/Heap.h
index 9762d092378cd86c26cb7a15f283c1e230bcb974..6131e703e12ff8c3e9dbee16c824268bb8ebfcad 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.h
+++ b/third_party/WebKit/Source/platform/heap/Heap.h
@@ -114,20 +114,147 @@ public:
}
};
+// Stats for the heap.
+class GCHeapStats {
+public:
+ GCHeapStats();
+ void setMarkedObjectSizeAtLastCompleteSweep(size_t size) { releaseStore(&m_markedObjectSizeAtLastCompleteSweep, size); }
+ size_t markedObjectSizeAtLastCompleteSweep() { return acquireLoad(&m_markedObjectSizeAtLastCompleteSweep); }
+ void increaseAllocatedObjectSize(size_t delta);
+ void decreaseAllocatedObjectSize(size_t delta);
+ size_t allocatedObjectSize() { return acquireLoad(&m_allocatedObjectSize); }
+ void increaseMarkedObjectSize(size_t delta);
+ size_t markedObjectSize() { return acquireLoad(&m_markedObjectSize); }
+ void increaseAllocatedSpace(size_t delta);
+ void decreaseAllocatedSpace(size_t delta);
+ size_t allocatedSpace() { return acquireLoad(&m_allocatedSpace); }
+ size_t objectSizeAtLastGC() { return acquireLoad(&m_objectSizeAtLastGC); }
+ void increaseWrapperCount(size_t delta) { atomicAdd(&m_wrapperCount, static_cast<long>(delta)); }
+ void decreaseWrapperCount(size_t delta) { atomicSubtract(&m_wrapperCount, static_cast<long>(delta)); }
+ size_t wrapperCount() { return acquireLoad(&m_wrapperCount); }
+ size_t wrapperCountAtLastGC() { return acquireLoad(&m_wrapperCountAtLastGC); }
+ void increaseCollectedWrapperCount(size_t delta) { atomicAdd(&m_collectedWrapperCount, static_cast<long>(delta)); }
+ size_t collectedWrapperCount() { return acquireLoad(&m_collectedWrapperCount); }
+ size_t partitionAllocSizeAtLastGC() { return acquireLoad(&m_partitionAllocSizeAtLastGC); }
+ void setEstimatedMarkingTimePerByte(double estimatedMarkingTimePerByte) { m_estimatedMarkingTimePerByte = estimatedMarkingTimePerByte; }
+ double estimatedMarkingTimePerByte() const { return m_estimatedMarkingTimePerByte; }
+ double estimatedMarkingTime();
+ void reset();
+
+private:
+ size_t m_allocatedSpace;
+ size_t m_allocatedObjectSize;
+ size_t m_objectSizeAtLastGC;
+ size_t m_markedObjectSize;
+ size_t m_markedObjectSizeAtLastCompleteSweep;
+ size_t m_wrapperCount;
+ size_t m_wrapperCountAtLastGC;
+ size_t m_collectedWrapperCount;
+ size_t m_partitionAllocSizeAtLastGC;
+ double m_estimatedMarkingTimePerByte;
+};
+
+using ThreadStateSet = HashSet<ThreadState*>;
+
class PLATFORM_EXPORT Heap {
- STATIC_ONLY(Heap);
public:
- static void init();
- static void shutdown();
- static void doShutdown();
+ Heap();
+ ~Heap();
+
+ RecursiveMutex& threadAttachMutex() { return m_threadAttachMutex; }
+ const ThreadStateSet& threads() const { return m_threads; }
+ GCHeapStats& heapStats() { return m_stats; }
+ SafePointBarrier* safePointBarrier() { return m_safePointBarrier.get(); }
+ FreePagePool* freePagePool() { return m_freePagePool.get(); }
+ OrphanedPagePool* orphanedPagePool() { return m_orphanedPagePool.get(); }
+ CallbackStack* markingStack() const { return m_markingStack.get(); }
+ CallbackStack* postMarkingCallbackStack() const { return m_postMarkingCallbackStack.get(); }
+ CallbackStack* globalWeakCallbackStack() const { return m_globalWeakCallbackStack.get(); }
+ CallbackStack* ephemeronStack() const { return m_ephemeronStack.get(); }
+
+ void attach(ThreadState*);
+ void detach(ThreadState*);
+ void lockThreadAttachMutex();
+ void unlockThreadAttachMutex();
+ bool park();
+ void resume();
+#if ENABLE(ASSERT)
+ bool isAtSafePoint() const;
+ BasePage* findPageFromAddress(Address);
+#endif
+ void preGC();
+ void postGC(BlinkGC::GCType);
+ size_t objectPayloadSizeForTesting();
+ void visitPersistentRoots(Visitor*);
+ void visitStackRoots(Visitor*);
+ void checkAndPark(ThreadState*, SafePointAwareMutexLocker*);
+ void enterSafePoint(ThreadState*);
+ void leaveSafePoint(ThreadState*, SafePointAwareMutexLocker*);
+ void flushHeapDoesNotContainCache();
- static CrossThreadPersistentRegion& crossThreadPersistentRegion();
+ // This look-up uses the region search tree and a negative contains cache to
+ // provide an efficient mapping from arbitrary addresses to the containing
+ // heap-page if one exists.
+ BasePage* lookupPageForAddress(Address);
+ void addPageMemoryRegion(PageMemoryRegion*);
+ void removePageMemoryRegion(PageMemoryRegion*);
+
+ // Push a trace callback on the marking stack.
+ void pushTraceCallback(void* containerObject, TraceCallback);
+
+ // Push a trace callback on the post-marking callback stack. These
+ // callbacks are called after normal marking (including ephemeron
+ // iteration).
+ void pushPostMarkingCallback(void*, TraceCallback);
+
+ // Similar to the more general pushThreadLocalWeakCallback, but cell
+ // pointer callbacks are added to a static callback work list and the weak
+ // callback is performed on the thread performing garbage collection. This
+ // is OK because cells are just cleared and no deallocation can happen.
+ void pushGlobalWeakCallback(void** cell, WeakCallback);
+
+ // Pop the top of a marking stack and call the callback with the visitor
+ // and the object. Returns false when there is nothing more to do.
+ bool popAndInvokeTraceCallback(Visitor*);
+
+ // Remove an item from the post-marking callback stack and call
+ // the callback with the visitor and the object pointer. Returns
+ // false when there is nothing more to do.
+ bool popAndInvokePostMarkingCallback(Visitor*);
+
+ // Remove an item from the weak callback work list and call the callback
+ // with the visitor and the closure pointer. Returns false when there is
+ // nothing more to do.
+ bool popAndInvokeGlobalWeakCallback(Visitor*);
+ // Register an ephemeron table for fixed-point iteration.
+ void registerWeakTable(void* containerObject, EphemeronCallback, EphemeronCallback);
#if ENABLE(ASSERT)
- static BasePage* findPageFromAddress(Address);
- static BasePage* findPageFromAddress(const void* pointer) { return findPageFromAddress(reinterpret_cast<Address>(const_cast<void*>(pointer))); }
+ bool weakTableRegistered(const void*);
#endif
+ void decommitCallbackStacks();
+
+ // Conservatively checks whether an address is a pointer in any of the
+ // thread heaps. If so marks the object pointed to as live.
+ Address checkAndMarkPointer(Visitor*, Address);
+
+ void processMarkingStack(Visitor*);
+ void postMarkingProcessing(Visitor*);
+ void globalWeakProcessing(Visitor*);
+
+ // Reset counters that track live and allocated-since-last-GC sizes.
+ void resetHeapCounters();
+
+ // Add a weak pointer callback to the weak callback work list. General
+ // object pointer callbacks are added to a thread local weak callback work
+ // list and the callback is called on the thread that owns the object, with
+ // the closure pointer as an argument. Most of the time, the closure and
+ // the containerObject can be the same thing, but the containerObject is
+ // constrained to be on the heap, since the heap is used to identify the
+ // correct thread.
+ void pushThreadLocalWeakCallback(void* closure, void* containerObject, WeakCallback);
+
template<typename T>
static inline bool isHeapObjectAlive(T* object)
{
@@ -178,54 +305,11 @@ public:
BasePage* page = pageFromObject(objectPointer);
if (page->hasBeenSwept())
return false;
- ASSERT(page->heap()->threadState()->isSweepingInProgress());
+ ASSERT(page->arena()->threadState()->isSweepingInProgress());
return !Heap::isHeapObjectAlive(const_cast<T*>(objectPointer));
}
- // Push a trace callback on the marking stack.
- static void pushTraceCallback(void* containerObject, TraceCallback);
-
- // Push a trace callback on the post-marking callback stack. These
- // callbacks are called after normal marking (including ephemeron
- // iteration).
- static void pushPostMarkingCallback(void*, TraceCallback);
-
- // Add a weak pointer callback to the weak callback work list. General
- // object pointer callbacks are added to a thread local weak callback work
- // list and the callback is called on the thread that owns the object, with
- // the closure pointer as an argument. Most of the time, the closure and
- // the containerObject can be the same thing, but the containerObject is
- // constrained to be on the heap, since the heap is used to identify the
- // correct thread.
- static void pushThreadLocalWeakCallback(void* closure, void* containerObject, WeakCallback);
-
- // Similar to the more general pushThreadLocalWeakCallback, but cell
- // pointer callbacks are added to a static callback work list and the weak
- // callback is performed on the thread performing garbage collection. This
- // is OK because cells are just cleared and no deallocation can happen.
- static void pushGlobalWeakCallback(void** cell, WeakCallback);
-
- // Pop the top of a marking stack and call the callback with the visitor
- // and the object. Returns false when there is nothing more to do.
- static bool popAndInvokeTraceCallback(Visitor*);
-
- // Remove an item from the post-marking callback stack and call
- // the callback with the visitor and the object pointer. Returns
- // false when there is nothing more to do.
- static bool popAndInvokePostMarkingCallback(Visitor*);
-
- // Remove an item from the weak callback work list and call the callback
- // with the visitor and the closure pointer. Returns false when there is
- // nothing more to do.
- static bool popAndInvokeGlobalWeakCallback(Visitor*);
-
- // Register an ephemeron table for fixed-point iteration.
- static void registerWeakTable(void* containerObject, EphemeronCallback, EphemeronCallback);
-#if ENABLE(ASSERT)
- static bool weakTableRegistered(const void*);
-#endif
-
static inline size_t allocationSizeFromSize(size_t size)
{
// Check the size before computing the actual allocation size. The
@@ -239,41 +323,14 @@ public:
allocationSize = (allocationSize + allocationMask) & ~allocationMask;
return allocationSize;
}
- static Address allocateOnHeapIndex(ThreadState*, size_t, int heapIndex, size_t gcInfoIndex);
+ static Address allocateOnArenaIndex(ThreadState*, size_t, int arenaIndex, size_t gcInfoIndex);
template<typename T> static Address allocate(size_t, bool eagerlySweep = false);
template<typename T> static Address reallocate(void* previous, size_t);
- static const char* gcReasonString(BlinkGC::GCReason);
static void collectGarbage(BlinkGC::StackState, BlinkGC::GCType, BlinkGC::GCReason);
static void collectGarbageForTerminatingThread(ThreadState*);
static void collectAllGarbage();
- static void processMarkingStack(Visitor*);
- static void postMarkingProcessing(Visitor*);
- static void globalWeakProcessing(Visitor*);
- static void setForcePreciseGCForTesting();
-
- static void preGC();
- static void postGC(BlinkGC::GCType);
-
- // Conservatively checks whether an address is a pointer in any of the
- // thread heaps. If so marks the object pointed to as live.
- static Address checkAndMarkPointer(Visitor*, Address);
-
- static size_t objectPayloadSizeForTesting();
-
- static void flushHeapDoesNotContainCache();
-
- static FreePagePool* freePagePool() { return s_freePagePool; }
- static OrphanedPagePool* orphanedPagePool() { return s_orphanedPagePool; }
-
- // This look-up uses the region search tree and a negative contains cache to
- // provide an efficient mapping from arbitrary addresses to the containing
- // heap-page if one exists.
- static BasePage* lookup(Address);
- static void addPageMemoryRegion(PageMemoryRegion*);
- static void removePageMemoryRegion(PageMemoryRegion*);
-
static const GCInfo* gcInfo(size_t gcInfoIndex)
{
ASSERT(gcInfoIndex >= 1);
@@ -284,66 +341,59 @@ public:
return info;
}
- static void setMarkedObjectSizeAtLastCompleteSweep(size_t size) { releaseStore(&s_markedObjectSizeAtLastCompleteSweep, size); }
- static size_t markedObjectSizeAtLastCompleteSweep() { return acquireLoad(&s_markedObjectSizeAtLastCompleteSweep); }
- static void increaseAllocatedObjectSize(size_t delta) { atomicAdd(&s_allocatedObjectSize, static_cast<long>(delta)); }
- static void decreaseAllocatedObjectSize(size_t delta) { atomicSubtract(&s_allocatedObjectSize, static_cast<long>(delta)); }
- static size_t allocatedObjectSize() { return acquireLoad(&s_allocatedObjectSize); }
- static void increaseMarkedObjectSize(size_t delta) { atomicAdd(&s_markedObjectSize, static_cast<long>(delta)); }
- static size_t markedObjectSize() { return acquireLoad(&s_markedObjectSize); }
- static void increaseAllocatedSpace(size_t delta) { atomicAdd(&s_allocatedSpace, static_cast<long>(delta)); }
- static void decreaseAllocatedSpace(size_t delta) { atomicSubtract(&s_allocatedSpace, static_cast<long>(delta)); }
- static size_t allocatedSpace() { return acquireLoad(&s_allocatedSpace); }
- static size_t objectSizeAtLastGC() { return acquireLoad(&s_objectSizeAtLastGC); }
- static void increaseWrapperCount(size_t delta) { atomicAdd(&s_wrapperCount, static_cast<long>(delta)); }
- static void decreaseWrapperCount(size_t delta) { atomicSubtract(&s_wrapperCount, static_cast<long>(delta)); }
- static size_t wrapperCount() { return acquireLoad(&s_wrapperCount); }
- static size_t wrapperCountAtLastGC() { return acquireLoad(&s_wrapperCountAtLastGC); }
- static void increaseCollectedWrapperCount(size_t delta) { atomicAdd(&s_collectedWrapperCount, static_cast<long>(delta)); }
- static size_t collectedWrapperCount() { return acquireLoad(&s_collectedWrapperCount); }
- static size_t partitionAllocSizeAtLastGC() { return acquireLoad(&s_partitionAllocSizeAtLastGC); }
-
- static double estimatedMarkingTime();
+ static CrossThreadPersistentRegion& crossThreadPersistentRegion();
+
+ static const char* gcReasonString(BlinkGC::GCReason);
+
static void reportMemoryUsageHistogram();
static void reportMemoryUsageForTracing();
- static bool isLowEndDevice() { return s_isLowEndDevice; }
-#if ENABLE(ASSERT)
- static uint16_t gcGeneration() { return s_gcGeneration; }
-#endif
+ static void increaseTotalAllocatedObjectSize(size_t delta) { atomicAdd(&s_totalAllocatedObjectSize, static_cast<long>(delta)); }
+ static void decreaseTotalAllocatedObjectSize(size_t delta) { atomicSubtract(&s_totalAllocatedObjectSize, static_cast<long>(delta)); }
+ static size_t totalAllocatedObjectSize() { return acquireLoad(&s_totalAllocatedObjectSize); }
+ static void increaseTotalMarkedObjectSize(size_t delta) { atomicAdd(&s_totalMarkedObjectSize, static_cast<long>(delta)); }
+ static size_t totalMarkedObjectSize() { return acquireLoad(&s_totalMarkedObjectSize); }
+ static void increaseTotalAllocatedSpace(size_t delta) { atomicAdd(&s_totalAllocatedSpace, static_cast<long>(delta)); }
+ static void decreaseTotalAllocatedSpace(size_t delta) { atomicSubtract(&s_totalAllocatedSpace, static_cast<long>(delta)); }
+ static size_t totalAllocatedSpace() { return acquireLoad(&s_totalAllocatedSpace); }
-private:
- // Reset counters that track live and allocated-since-last-GC sizes.
- static void resetHeapCounters();
+ static bool isLowEndDevice() { return s_isLowEndDevice; }
- static int heapIndexForObjectSize(size_t);
- static bool isNormalHeapIndex(int);
+ static void init();
+ // Shutdown tears down the global objects. If threads are still attached the actual shutdown task is delayed.
+ static void shutdown();
+ // Run the shutdown task if necessary.
+ static void doShutdownIfNecessary();
- static void decommitCallbackStacks();
+ static HashSet<Heap*>& all();
+ static RecursiveMutex& heapAttachMutex();
+
+private:
+ static int arenaIndexForObjectSize(size_t);
+ static bool isNormalArenaIndex(int);
+
+ RecursiveMutex m_threadAttachMutex;
+ ThreadStateSet m_threads;
+ GCHeapStats m_stats;
+ Mutex m_regionTreeMutex;
+ RegionTree* m_regionTree;
+ OwnPtr<HeapDoesNotContainCache> m_heapDoesNotContainCache;
+ OwnPtr<SafePointBarrier> m_safePointBarrier;
+ OwnPtr<FreePagePool> m_freePagePool;
+ OwnPtr<OrphanedPagePool> m_orphanedPagePool;
+ OwnPtr<CallbackStack> m_markingStack;
+ OwnPtr<CallbackStack> m_postMarkingCallbackStack;
+ OwnPtr<CallbackStack> m_globalWeakCallbackStack;
+ OwnPtr<CallbackStack> m_ephemeronStack;
- static CallbackStack* s_markingStack;
- static CallbackStack* s_postMarkingCallbackStack;
- static CallbackStack* s_globalWeakCallbackStack;
- static CallbackStack* s_ephemeronStack;
- static HeapDoesNotContainCache* s_heapDoesNotContainCache;
static bool s_shutdownCalled;
- static FreePagePool* s_freePagePool;
- static OrphanedPagePool* s_orphanedPagePool;
- static RegionTree* s_regionTree;
- static size_t s_allocatedSpace;
- static size_t s_allocatedObjectSize;
- static size_t s_objectSizeAtLastGC;
- static size_t s_markedObjectSize;
- static size_t s_markedObjectSizeAtLastCompleteSweep;
- static size_t s_wrapperCount;
- static size_t s_wrapperCountAtLastGC;
- static size_t s_collectedWrapperCount;
- static size_t s_partitionAllocSizeAtLastGC;
- static double s_estimatedMarkingTimePerByte;
+ static bool s_shutdownComplete;
static bool s_isLowEndDevice;
-#if ENABLE(ASSERT)
- static uint16_t s_gcGeneration;
-#endif
+
+ // Stats for the entire Oilpan heap.
+ static size_t s_totalAllocatedSpace;
+ static size_t s_totalAllocatedObjectSize;
+ static size_t s_totalMarkedObjectSize;
haraken 2016/02/29 11:17:45 Shall we factor out these static variables to anot
friend class ThreadState;
};
@@ -427,21 +477,21 @@ protected:
// for a class.
//
-inline int Heap::heapIndexForObjectSize(size_t size)
+inline int Heap::arenaIndexForObjectSize(size_t size)
{
if (size < 64) {
if (size < 32)
- return BlinkGC::NormalPage1HeapIndex;
- return BlinkGC::NormalPage2HeapIndex;
+ return BlinkGC::NormalPage1ArenaIndex;
+ return BlinkGC::NormalPage2ArenaIndex;
}
if (size < 128)
- return BlinkGC::NormalPage3HeapIndex;
- return BlinkGC::NormalPage4HeapIndex;
+ return BlinkGC::NormalPage3ArenaIndex;
+ return BlinkGC::NormalPage4ArenaIndex;
}
-inline bool Heap::isNormalHeapIndex(int index)
+inline bool Heap::isNormalArenaIndex(int index)
{
- return index >= BlinkGC::NormalPage1HeapIndex && index <= BlinkGC::NormalPage4HeapIndex;
+ return index >= BlinkGC::NormalPage1ArenaIndex && index <= BlinkGC::NormalPage4ArenaIndex;
}
#define DECLARE_EAGER_FINALIZATION_OPERATOR_NEW() \
@@ -452,7 +502,7 @@ public: \
return allocateObject(size, true); \
}
-#define IS_EAGERLY_FINALIZED() (pageFromObject(this)->heap()->heapIndex() == BlinkGC::EagerSweepHeapIndex)
+#define IS_EAGERLY_FINALIZED() (pageFromObject(this)->arena()->arenaIndex() == BlinkGC::EagerSweepArenaIndex)
#if ENABLE(ASSERT) && ENABLE(OILPAN)
class VerifyEagerFinalization {
DISALLOW_NEW();
@@ -485,11 +535,11 @@ public: \
#define EAGERLY_FINALIZE_WILL_BE_REMOVED()
#endif
-inline Address Heap::allocateOnHeapIndex(ThreadState* state, size_t size, int heapIndex, size_t gcInfoIndex)
+inline Address Heap::allocateOnArenaIndex(ThreadState* state, size_t size, int arenaIndex, size_t gcInfoIndex)
{
ASSERT(state->isAllocationAllowed());
- ASSERT(heapIndex != BlinkGC::LargeObjectHeapIndex);
- NormalPageHeap* heap = static_cast<NormalPageHeap*>(state->heap(heapIndex));
+ ASSERT(arenaIndex != BlinkGC::LargeObjectArenaIndex);
+ NormalPageArena* heap = static_cast<NormalPageArena*>(state->arena(arenaIndex));
return heap->allocateObject(allocationSizeFromSize(size), gcInfoIndex);
}
@@ -497,7 +547,7 @@ template<typename T>
Address Heap::allocate(size_t size, bool eagerlySweep)
{
ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
- Address address = Heap::allocateOnHeapIndex(state, size, eagerlySweep ? BlinkGC::EagerSweepHeapIndex : Heap::heapIndexForObjectSize(size), GCInfoTrait<T>::index());
+ Address address = Heap::allocateOnArenaIndex(state, size, eagerlySweep ? BlinkGC::EagerSweepArenaIndex : Heap::arenaIndexForObjectSize(size), GCInfoTrait<T>::index());
const char* typeName = WTF_HEAP_PROFILER_TYPE_NAME(T);
HeapAllocHooks::allocationHookIfEnabled(address, size, typeName);
return address;
@@ -519,16 +569,16 @@ Address Heap::reallocate(void* previous, size_t size)
HeapObjectHeader* previousHeader = HeapObjectHeader::fromPayload(previous);
BasePage* page = pageFromObject(previousHeader);
ASSERT(page);
- int heapIndex = page->heap()->heapIndex();
+ int arenaIndex = page->arena()->arenaIndex();
// Recompute the effective heap index if previous allocation
// was on the normal heaps or a large object.
- if (isNormalHeapIndex(heapIndex) || heapIndex == BlinkGC::LargeObjectHeapIndex)
- heapIndex = heapIndexForObjectSize(size);
+ if (isNormalArenaIndex(arenaIndex) || arenaIndex == BlinkGC::LargeObjectArenaIndex)
+ arenaIndex = arenaIndexForObjectSize(size);
// TODO(haraken): We don't support reallocate() for finalizable objects.
ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer());
ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index());
- Address address = Heap::allocateOnHeapIndex(state, size, heapIndex, GCInfoTrait<T>::index());
+ Address address = Heap::allocateOnArenaIndex(state, size, arenaIndex, GCInfoTrait<T>::index());
size_t copySize = previousHeader->payloadSize();
if (copySize > size)
copySize = size;

Powered by Google App Engine
This is Rietveld 408576698