Chromium Code Reviews| Index: third_party/WebKit/Source/platform/heap/ThreadState.cpp |
| diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp |
| index ce9f9f8ba011a45581217a76cb6c1985175b0d9f..92d36dd2860161b9ee601a12046bafcac4c13fc5 100644 |
| --- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp |
| +++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp |
| @@ -72,13 +72,6 @@ WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr; |
| uintptr_t ThreadState::s_mainThreadStackStart = 0; |
| uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0; |
| uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; |
| -SafePointBarrier* ThreadState::s_safePointBarrier = nullptr; |
| - |
| -RecursiveMutex& ThreadState::threadAttachMutex() |
| -{ |
| - DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, (new RecursiveMutex)); |
| - return mutex; |
| -} |
| ThreadState::ThreadState() |
| : m_thread(currentThread()) |
| @@ -95,7 +88,7 @@ ThreadState::ThreadState() |
| , m_noAllocationCount(0) |
| , m_gcForbiddenCount(0) |
| , m_accumulatedSweepingTime(0) |
| - , m_vectorBackingHeapIndex(BlinkGC::Vector1HeapIndex) |
| + , m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex) |
| , m_currentHeapAges(0) |
| , m_isTerminating(false) |
| , m_gcMixinMarker(nullptr) |
| @@ -122,11 +115,16 @@ ThreadState::ThreadState() |
| size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStackSize(); |
| if (underestimatedStackSize > sizeof(void*)) |
| s_mainThreadUnderestimatedStackSize = underestimatedStackSize - sizeof(void*); |
| + m_heap = new Heap(); |
| + } else { |
| + m_heap = &ThreadState::mainThreadState()->heap(); |
| } |
| + ASSERT(m_heap); |
| + m_heap->attach(this); |
| - for (int heapIndex = 0; heapIndex < BlinkGC::LargeObjectHeapIndex; heapIndex++) |
| - m_heaps[heapIndex] = new NormalPageHeap(this, heapIndex); |
| - m_heaps[BlinkGC::LargeObjectHeapIndex] = new LargeObjectHeap(this, BlinkGC::LargeObjectHeapIndex); |
| + for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaIndex++) |
| + m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); |
| + m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectArena(this, BlinkGC::LargeObjectArenaIndex); |
| m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArraySize]); |
| clearHeapAges(); |
| @@ -139,8 +137,8 @@ ThreadState::~ThreadState() |
| ASSERT(checkThread()); |
| delete m_threadLocalWeakCallbackStack; |
| m_threadLocalWeakCallbackStack = nullptr; |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - delete m_heaps[i]; |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + delete m_arenas[i]; |
| **s_threadSpecific = nullptr; |
| if (isMainThread()) { |
| @@ -152,14 +150,10 @@ ThreadState::~ThreadState() |
| void ThreadState::init() |
| { |
| s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); |
| - s_safePointBarrier = new SafePointBarrier; |
| } |
| void ThreadState::shutdown() |
| { |
| - delete s_safePointBarrier; |
| - s_safePointBarrier = nullptr; |
| - |
| // Thread-local storage shouldn't be disposed, so we don't call ~ThreadSpecific(). |
| } |
| @@ -201,137 +195,100 @@ size_t ThreadState::threadStackSize() |
| void ThreadState::attachMainThread() |
| { |
| RELEASE_ASSERT(!Heap::s_shutdownCalled); |
| - MutexLocker locker(threadAttachMutex()); |
| - ThreadState* state = new(s_mainThreadStateStorage) ThreadState(); |
| - attachedThreads().add(state); |
| -} |
| - |
| -void ThreadState::detachMainThread() |
| -{ |
| - // Enter a safe point before trying to acquire threadAttachMutex |
| - // to avoid dead lock if another thread is preparing for GC, has acquired |
| - // threadAttachMutex and waiting for other threads to pause or reach a |
| - // safepoint. |
| - ThreadState* state = mainThreadState(); |
| - |
| - // 1. Finish sweeping. |
| - state->completeSweep(); |
| - { |
| - SafePointAwareMutexLocker locker(threadAttachMutex(), BlinkGC::NoHeapPointersOnStack); |
| - |
| - // 2. Add the main thread's heap pages to the orphaned pool. |
| - state->cleanupPages(); |
| - |
| - // 3. Detach the main thread. |
| - ASSERT(attachedThreads().contains(state)); |
| - attachedThreads().remove(state); |
| - state->~ThreadState(); |
| - } |
| - shutdownHeapIfNecessary(); |
| -} |
| - |
| -void ThreadState::shutdownHeapIfNecessary() |
| -{ |
| - // We don't need to enter a safe point before acquiring threadAttachMutex |
| - // because this thread is already detached. |
| - |
| - MutexLocker locker(threadAttachMutex()); |
| - // We start shutting down the heap if there is no running thread |
| - // and Heap::shutdown() is already called. |
| - if (!attachedThreads().size() && Heap::s_shutdownCalled) |
| - Heap::doShutdown(); |
| + new(s_mainThreadStateStorage) ThreadState(); |
| } |
| void ThreadState::attach() |
| { |
| RELEASE_ASSERT(!Heap::s_shutdownCalled); |
| - MutexLocker locker(threadAttachMutex()); |
| - ThreadState* state = new ThreadState(); |
| - attachedThreads().add(state); |
| + new ThreadState(); |
| } |
| void ThreadState::cleanupPages() |
| { |
| ASSERT(checkThread()); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - m_heaps[i]->cleanupPages(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + m_arenas[i]->cleanupPages(); |
| } |
| void ThreadState::cleanup() |
|
haraken
2016/02/29 11:17:45
cleanup => runThreadTerminationGC
keishi
2016/03/02 06:01:03
Done.
|
| { |
| + if (isMainThread()) { |
| + cleanupPages(); |
| + return; |
| + } |
| ASSERT(checkThread()); |
| - { |
| - // Grab the threadAttachMutex to ensure only one thread can shutdown at |
| - // a time and that no other thread can do a global GC. It also allows |
| - // safe iteration of the attachedThreads set which happens as part of |
| - // thread local GC asserts. We enter a safepoint while waiting for the |
| - // lock to avoid a dead-lock where another thread has already requested |
| - // GC. |
| - SafePointAwareMutexLocker locker(threadAttachMutex(), BlinkGC::NoHeapPointersOnStack); |
| - |
| - // Finish sweeping. |
| - completeSweep(); |
| - // From here on ignore all conservatively discovered |
| - // pointers into the heap owned by this thread. |
| - m_isTerminating = true; |
| - |
| - // Set the terminate flag on all heap pages of this thread. This is used to |
| - // ensure we don't trace pages on other threads that are not part of the |
| - // thread local GC. |
| - prepareForThreadStateTermination(); |
| - |
| - Heap::crossThreadPersistentRegion().prepareForThreadStateTermination(this); |
| - |
| - // Do thread local GC's as long as the count of thread local Persistents |
| - // changes and is above zero. |
| - int oldCount = -1; |
| - int currentCount = persistentRegion()->numberOfPersistents(); |
| - ASSERT(currentCount >= 0); |
| - while (currentCount != oldCount) { |
| - Heap::collectGarbageForTerminatingThread(this); |
| - oldCount = currentCount; |
| - currentCount = persistentRegion()->numberOfPersistents(); |
| - } |
| - // We should not have any persistents left when getting to this point, |
| - // if we have it is probably a bug so adding a debug ASSERT to catch this. |
| - ASSERT(!currentCount); |
| - // All of pre-finalizers should be consumed. |
| - ASSERT(m_orderedPreFinalizers.isEmpty()); |
| - RELEASE_ASSERT(gcState() == NoGCScheduled); |
| - |
| - // Add pages to the orphaned page pool to ensure any global GCs from this point |
| - // on will not trace objects on this thread's heaps. |
| - cleanupPages(); |
| + // Grab the threadAttachMutex to ensure only one thread can shutdown at |
| + // a time and that no other thread can do a global GC. It also allows |
| + // safe iteration of the attachedThreads set which happens as part of |
| + // thread local GC asserts. We enter a safepoint while waiting for the |
| + // lock to avoid a dead-lock where another thread has already requested |
| + // GC. |
| + // MEMO: move comment |
| - ASSERT(attachedThreads().contains(this)); |
| - attachedThreads().remove(this); |
| + // Finish sweeping. |
| + completeSweep(); |
| + |
| + // From here on ignore all conservatively discovered |
| + // pointers into the heap owned by this thread. |
| + m_isTerminating = true; |
| + |
| + // Set the terminate flag on all heap pages of this thread. This is used to |
| + // ensure we don't trace pages on other threads that are not part of the |
| + // thread local GC. |
| + prepareForThreadStateTermination(); |
| + |
| + Heap::crossThreadPersistentRegion().prepareForThreadStateTermination(this); |
| + |
| + // Do thread local GC's as long as the count of thread local Persistents |
| + // changes and is above zero. |
| + int oldCount = -1; |
| + int currentCount = persistentRegion()->numberOfPersistents(); |
| + ASSERT(currentCount >= 0); |
| + while (currentCount != oldCount) { |
| + Heap::collectGarbageForTerminatingThread(this); |
| + oldCount = currentCount; |
| + currentCount = persistentRegion()->numberOfPersistents(); |
| } |
| + // We should not have any persistents left when getting to this point, |
| + // if we have it is probably a bug so adding a debug ASSERT to catch this. |
| + ASSERT(!currentCount); |
| + // All of pre-finalizers should be consumed. |
| + ASSERT(m_orderedPreFinalizers.isEmpty()); |
| + RELEASE_ASSERT(gcState() == NoGCScheduled); |
| + |
| + // Add pages to the orphaned page pool to ensure any global GCs from this point |
| + // on will not trace objects on this thread's heaps. |
| + cleanupPages(); |
| } |
| -void ThreadState::detach() |
| +void ThreadState::detachMainThread() |
| { |
| - ThreadState* state = current(); |
| - state->cleanup(); |
| - RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); |
| - delete state; |
| - shutdownHeapIfNecessary(); |
| + // Enter a safe point before trying to acquire threadAttachMutex |
| + // to avoid dead lock if another thread is preparing for GC, has acquired |
| + // threadAttachMutex and waiting for other threads to pause or reach a |
| + // safepoint. |
| + ThreadState* state = mainThreadState(); |
| + |
| + // 1. Finish sweeping. |
| + state->completeSweep(); |
| + state->detach(); |
| } |
| -void ThreadState::visitPersistentRoots(Visitor* visitor) |
| +void ThreadState::detachCurrentThread() |
| { |
| - TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots"); |
| - Heap::crossThreadPersistentRegion().tracePersistentNodes(visitor); |
| - |
| - for (ThreadState* state : attachedThreads()) |
| - state->visitPersistents(visitor); |
| + current()->detach(); |
| } |
| -void ThreadState::visitStackRoots(Visitor* visitor) |
| +void ThreadState::detach() |
| { |
| - TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots"); |
| - for (ThreadState* state : attachedThreads()) |
| - state->visitStack(visitor); |
| + m_heap->detach(this); |
| + RELEASE_ASSERT(gcState() == ThreadState::NoGCScheduled); |
| + if (isMainThread()) |
| + this->~ThreadState(); |
|
haraken
2016/02/29 11:17:45
Is this different from 'delete this'?
keishi
2016/03/02 06:01:03
mainThreadState is stored in s_mainThreadStateStor
|
| + else |
| + delete this; |
| } |
| NO_SANITIZE_ADDRESS |
| @@ -356,7 +313,7 @@ void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) |
| // within the stack range that we need to scan so we need |
| // to visit the values in the fake frame. |
| for (Address* p = fakeFrameStart; p < fakeFrameEnd; ++p) |
| - Heap::checkAndMarkPointer(visitor, *p); |
| + m_heap->checkAndMarkPointer(visitor, *p); |
| } |
| } |
| #endif |
| @@ -392,7 +349,7 @@ void ThreadState::visitStack(Visitor* visitor) |
| // variable because we don't want to unpoison the original stack. |
| __msan_unpoison(&ptr, sizeof(ptr)); |
| #endif |
| - Heap::checkAndMarkPointer(visitor, ptr); |
| + m_heap->checkAndMarkPointer(visitor, ptr); |
| visitAsanFakeStackForPointer(visitor, ptr); |
| } |
| @@ -401,7 +358,7 @@ void ThreadState::visitStack(Visitor* visitor) |
| // See the comment above. |
| __msan_unpoison(&ptr, sizeof(ptr)); |
| #endif |
| - Heap::checkAndMarkPointer(visitor, ptr); |
| + m_heap->checkAndMarkPointer(visitor, ptr); |
| visitAsanFakeStackForPointer(visitor, ptr); |
| } |
| } |
| @@ -502,18 +459,18 @@ void ThreadState::threadLocalWeakProcessing() |
| size_t ThreadState::totalMemorySize() |
| { |
| - return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
| + return m_heap->heapStats().allocatedObjectSize() + m_heap->heapStats().markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); |
| } |
| size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLastGC) |
| { |
| - if (Heap::wrapperCountAtLastGC() == 0) { |
| + if (m_heap->heapStats().wrapperCountAtLastGC() == 0) { |
| // We'll reach here only before hitting the first GC. |
| return 0; |
| } |
| // (estimated size) = (estimation base size) - (heap size at the last GC) / (# of persistent handles at the last GC) * (# of persistent handles collected since the last GC); |
| - size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAtLastGC / Heap::wrapperCountAtLastGC() * Heap::collectedWrapperCount()); |
| + size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAtLastGC / m_heap->heapStats().wrapperCountAtLastGC() * m_heap->heapStats().collectedWrapperCount()); |
| if (estimationBaseSize < sizeRetainedByCollectedPersistents) |
| return 0; |
| return estimationBaseSize - sizeRetainedByCollectedPersistents; |
| @@ -521,8 +478,8 @@ size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa |
| double ThreadState::heapGrowingRate() |
| { |
| - size_t currentSize = Heap::allocatedObjectSize() + Heap::markedObjectSize(); |
| - size_t estimatedSize = estimatedLiveSize(Heap::markedObjectSizeAtLastCompleteSweep(), Heap::markedObjectSizeAtLastCompleteSweep()); |
| + size_t currentSize = m_heap->heapStats().allocatedObjectSize() + m_heap->heapStats().markedObjectSize(); |
| + size_t estimatedSize = estimatedLiveSize(m_heap->heapStats().markedObjectSizeAtLastCompleteSweep(), m_heap->heapStats().markedObjectSizeAtLastCompleteSweep()); |
| // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; |
| @@ -534,7 +491,7 @@ double ThreadState::heapGrowingRate() |
| double ThreadState::partitionAllocGrowingRate() |
| { |
| size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); |
| - size_t estimatedSize = estimatedLiveSize(currentSize, Heap::partitionAllocSizeAtLastGC()); |
| + size_t estimatedSize = estimatedLiveSize(currentSize, m_heap->heapStats().partitionAllocSizeAtLastGC()); |
| // If the estimatedSize is 0, we set a high growing rate to trigger a GC. |
| double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; |
| @@ -548,7 +505,7 @@ double ThreadState::partitionAllocGrowingRate() |
| bool ThreadState::judgeGCThreshold(size_t totalMemorySizeThreshold, double heapGrowingRateThreshold) |
| { |
| // If the allocated object size or the total memory size is small, don't trigger a GC. |
| - if (Heap::allocatedObjectSize() < 100 * 1024 || totalMemorySize() < totalMemorySizeThreshold) |
| + if (m_heap->heapStats().allocatedObjectSize() < 100 * 1024 || totalMemorySize() < totalMemorySizeThreshold) |
| return false; |
| // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, |
| // trigger a GC. |
| @@ -731,6 +688,16 @@ void ThreadState::scheduleGCIfNeeded() |
| } |
| } |
| +ThreadState* ThreadState::fromObject(const void* object) |
| +{ |
| + if (!object) |
| + return nullptr; |
| + BasePage* page = pageFromObject(object); |
| + ASSERT(page); |
| + ASSERT(page->arena()); |
| + return page->arena()->threadState(); |
| +} |
| + |
| void ThreadState::performIdleGC(double deadlineSeconds) |
| { |
| ASSERT(checkThread()); |
| @@ -741,8 +708,8 @@ void ThreadState::performIdleGC(double deadlineSeconds) |
| return; |
| double idleDeltaInSeconds = deadlineSeconds - monotonicallyIncreasingTime(); |
| - TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", Heap::estimatedMarkingTime()); |
| - if (idleDeltaInSeconds <= Heap::estimatedMarkingTime() && !Platform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired()) { |
| + TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", idleDeltaInSeconds, "estimatedMarkingTime", m_heap->heapStats().estimatedMarkingTime()); |
| + if (idleDeltaInSeconds <= m_heap->heapStats().estimatedMarkingTime() && !Platform::current()->currentThread()->scheduler()->canExceedIdleDeadlineIfRequired()) { |
| // If marking is estimated to take longer than the deadline and we can't |
| // exceed the deadline, then reschedule for the next idle period. |
| scheduleIdleGC(); |
| @@ -775,12 +742,12 @@ void ThreadState::performIdleLazySweep(double deadlineSeconds) |
| double startTime = WTF::currentTimeMS(); |
| ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) { |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; i++) { |
| // lazySweepWithDeadline() won't check the deadline until it sweeps |
| // 10 pages. So we give a small slack for safety. |
| double slack = 0.001; |
| double remainingBudget = deadlineSeconds - slack - monotonicallyIncreasingTime(); |
| - if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadlineSeconds)) { |
| + if (remainingBudget <= 0 || !m_arenas[i]->lazySweepWithDeadline(deadlineSeconds)) { |
| // We couldn't finish the sweeping within the deadline. |
| // We request another idle task for the remaining sweeping. |
| scheduleIdleLazySweep(); |
| @@ -944,7 +911,7 @@ void ThreadState::runScheduledGC(BlinkGC::StackState stackState) |
| void ThreadState::flushHeapDoesNotContainCacheIfNeeded() |
| { |
| if (m_shouldFlushHeapDoesNotContainCache) { |
| - Heap::flushHeapDoesNotContainCache(); |
| + m_heap->flushHeapDoesNotContainCache(); |
| m_shouldFlushHeapDoesNotContainCache = false; |
| } |
| } |
| @@ -953,15 +920,15 @@ void ThreadState::makeConsistentForGC() |
| { |
| ASSERT(isInGC()); |
| TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - m_heaps[i]->makeConsistentForGC(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + m_arenas[i]->makeConsistentForGC(); |
| } |
| void ThreadState::makeConsistentForMutator() |
| { |
| ASSERT(isInGC()); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - m_heaps[i]->makeConsistentForMutator(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + m_arenas[i]->makeConsistentForMutator(); |
| } |
| void ThreadState::preGC() |
| @@ -976,8 +943,8 @@ void ThreadState::preGC() |
| void ThreadState::postGC(BlinkGC::GCType gcType) |
| { |
| ASSERT(isInGC()); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) |
| - m_heaps[i]->prepareForSweep(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; i++) |
| + m_arenas[i]->prepareForSweep(); |
| if (gcType == BlinkGC::GCWithSweep) { |
| setGCState(EagerSweepScheduled); |
| @@ -1042,8 +1009,8 @@ void ThreadState::poisonAllHeaps() |
| // Unpoison the live objects remaining in the eager heaps.. |
| poisonEagerHeap(BlinkGC::ClearPoison); |
| // ..along with poisoning all unmarked objects in the other heaps. |
| - for (int i = 1; i < BlinkGC::NumberOfHeaps; i++) |
| - m_heaps[i]->poisonHeap(BlinkGC::UnmarkedOnly, BlinkGC::SetPoison); |
| + for (int i = 1; i < BlinkGC::NumberOfArenas; i++) |
| + m_arenas[i]->poisonHeap(BlinkGC::UnmarkedOnly, BlinkGC::SetPoison); |
| #endif |
| } |
| @@ -1051,7 +1018,7 @@ void ThreadState::poisonEagerHeap(BlinkGC::Poisoning poisoning) |
| { |
| // TODO(Oilpan): enable the poisoning always. |
| #if ENABLE(OILPAN) |
| - m_heaps[BlinkGC::EagerSweepHeapIndex]->poisonHeap(BlinkGC::MarkedAndUnmarked, poisoning); |
| + m_arenas[BlinkGC::EagerSweepArenaIndex]->poisonHeap(BlinkGC::MarkedAndUnmarked, poisoning); |
| #endif |
| } |
| #endif |
| @@ -1072,7 +1039,7 @@ void ThreadState::eagerSweep() |
| ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| double startTime = WTF::currentTimeMS(); |
| - m_heaps[BlinkGC::EagerSweepHeapIndex]->completeSweep(); |
| + m_arenas[BlinkGC::EagerSweepArenaIndex]->completeSweep(); |
| accumulateSweepingTime(WTF::currentTimeMS() - startTime); |
| } |
| @@ -1096,9 +1063,9 @@ void ThreadState::completeSweep() |
| TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep"); |
| double startTime = WTF::currentTimeMS(); |
| - static_assert(BlinkGC::EagerSweepHeapIndex == 0, "Eagerly swept heaps must be processed first."); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) |
| - m_heaps[i]->completeSweep(); |
| + static_assert(BlinkGC::EagerSweepArenaIndex == 0, "Eagerly swept heaps must be processed first."); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; i++) |
| + m_arenas[i]->completeSweep(); |
| double timeForCompleteSweep = WTF::currentTimeMS() - startTime; |
| accumulateSweepingTime(timeForCompleteSweep); |
| @@ -1119,8 +1086,8 @@ void ThreadState::postSweep() |
| if (isMainThread()) { |
| double collectionRate = 0; |
| - if (Heap::objectSizeAtLastGC() > 0) |
| - collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC(); |
| + if (m_heap->heapStats().objectSizeAtLastGC() > 0) |
| + collectionRate = 1 - 1.0 * m_heap->heapStats().markedObjectSize() / m_heap->heapStats().objectSizeAtLastGC(); |
| TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::collectionRate", static_cast<int>(100 * collectionRate)); |
| #if PRINT_HEAP_STATS |
| @@ -1129,12 +1096,12 @@ void ThreadState::postSweep() |
| // Heap::markedObjectSize() may be underestimated here if any other |
| // thread has not yet finished lazy sweeping. |
| - Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize()); |
| + m_heap->heapStats().setMarkedObjectSizeAtLastCompleteSweep(m_heap->heapStats().markedObjectSize()); |
| DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeBeforeGCHistogram, ("BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50)); |
| - objectSizeBeforeGCHistogram.count(Heap::objectSizeAtLastGC() / 1024); |
| + objectSizeBeforeGCHistogram.count(m_heap->heapStats().objectSizeAtLastGC() / 1024); |
| DEFINE_STATIC_LOCAL(CustomCountHistogram, objectSizeAfterGCHistogram, ("BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50)); |
| - objectSizeAfterGCHistogram.count(Heap::markedObjectSize() / 1024); |
| + objectSizeAfterGCHistogram.count(m_heap->heapStats().markedObjectSize() / 1024); |
| DEFINE_STATIC_LOCAL(CustomCountHistogram, collectionRateHistogram, ("BlinkGC.CollectionRate", 1, 100, 20)); |
| collectionRateHistogram.count(static_cast<int>(100 * collectionRate)); |
| DEFINE_STATIC_LOCAL(CustomCountHistogram, timeForSweepHistogram, ("BlinkGC.TimeForSweepingAllObjects", 1, 10 * 1000, 50)); |
| @@ -1160,15 +1127,15 @@ void ThreadState::postSweep() |
| void ThreadState::prepareForThreadStateTermination() |
| { |
| ASSERT(checkThread()); |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - m_heaps[i]->prepareHeapForTermination(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + m_arenas[i]->prepareHeapForTermination(); |
| } |
| #if ENABLE(ASSERT) |
| BasePage* ThreadState::findPageFromAddress(Address address) |
| { |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) { |
| - if (BasePage* page = m_heaps[i]->findPageFromAddress(address)) |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) { |
| + if (BasePage* page = m_arenas[i]->findPageFromAddress(address)) |
| return page; |
| } |
| return nullptr; |
| @@ -1178,21 +1145,11 @@ BasePage* ThreadState::findPageFromAddress(Address address) |
| size_t ThreadState::objectPayloadSizeForTesting() |
| { |
| size_t objectPayloadSize = 0; |
| - for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) |
| - objectPayloadSize += m_heaps[i]->objectPayloadSizeForTesting(); |
| + for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| + objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); |
| return objectPayloadSize; |
| } |
| -bool ThreadState::stopThreads() |
| -{ |
| - return s_safePointBarrier->parkOthers(); |
| -} |
| - |
| -void ThreadState::resumeThreads() |
| -{ |
| - s_safePointBarrier->resumeOthers(); |
| -} |
| - |
| void ThreadState::safePoint(BlinkGC::StackState stackState) |
| { |
| ASSERT(checkThread()); |
| @@ -1202,7 +1159,7 @@ void ThreadState::safePoint(BlinkGC::StackState stackState) |
| ASSERT(!m_atSafePoint); |
| m_stackState = stackState; |
| m_atSafePoint = true; |
| - s_safePointBarrier->checkAndPark(this); |
| + m_heap->checkAndPark(this, nullptr); |
| m_atSafePoint = false; |
| m_stackState = BlinkGC::HeapPointersOnStack; |
| preSweep(); |
| @@ -1246,14 +1203,14 @@ void ThreadState::enterSafePoint(BlinkGC::StackState stackState, void* scopeMark |
| m_atSafePoint = true; |
| m_stackState = stackState; |
| m_safePointScopeMarker = scopeMarker; |
| - s_safePointBarrier->enterSafePoint(this); |
| + m_heap->enterSafePoint(this); |
| } |
| void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) |
| { |
| ASSERT(checkThread()); |
| ASSERT(m_atSafePoint); |
| - s_safePointBarrier->leaveSafePoint(this, locker); |
| + m_heap->leaveSafePoint(this, locker); |
| m_atSafePoint = false; |
| m_stackState = BlinkGC::HeapPointersOnStack; |
| clearSafePointScopeMarker(); |
| @@ -1280,19 +1237,19 @@ void ThreadState::resetHeapCounters() |
| void ThreadState::increaseAllocatedObjectSize(size_t delta) |
| { |
| m_allocatedObjectSize += delta; |
| - Heap::increaseAllocatedObjectSize(delta); |
| + m_heap->heapStats().increaseAllocatedObjectSize(delta); |
| } |
| void ThreadState::decreaseAllocatedObjectSize(size_t delta) |
| { |
| m_allocatedObjectSize -= delta; |
| - Heap::decreaseAllocatedObjectSize(delta); |
| + m_heap->heapStats().decreaseAllocatedObjectSize(delta); |
| } |
| void ThreadState::increaseMarkedObjectSize(size_t delta) |
| { |
| m_markedObjectSize += delta; |
| - Heap::increaseMarkedObjectSize(delta); |
| + m_heap->heapStats().increaseMarkedObjectSize(delta); |
| } |
| void ThreadState::copyStackUntilSafePointScope() |
| @@ -1326,7 +1283,7 @@ void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor) |
| ASSERT(checkThread()); |
| SafePointScope scope(BlinkGC::HeapPointersOnStack); |
| { |
| - MutexLocker locker(threadAttachMutex()); |
| + MutexLocker locker(m_heap->threadAttachMutex()); |
| m_interruptors.append(interruptor); |
| } |
| } |
| @@ -1336,7 +1293,7 @@ void ThreadState::removeInterruptor(BlinkGCInterruptor* interruptor) |
| ASSERT(checkThread()); |
| SafePointScope scope(BlinkGC::HeapPointersOnStack); |
| { |
| - MutexLocker locker(threadAttachMutex()); |
| + MutexLocker locker(m_heap->threadAttachMutex()); |
| size_t index = m_interruptors.find(interruptor); |
| RELEASE_ASSERT(index != kNotFound); |
| m_interruptors.remove(index); |
| @@ -1373,22 +1330,6 @@ void ThreadState::leaveStaticReferenceRegistrationDisabledScope() |
| } |
| #endif |
| -ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads() |
| -{ |
| - DEFINE_STATIC_LOCAL(AttachedThreadStateSet, threads, ()); |
| - return threads; |
| -} |
| - |
| -void ThreadState::lockThreadAttachMutex() |
| -{ |
| - threadAttachMutex().lock(); |
| -} |
| - |
| -void ThreadState::unlockThreadAttachMutex() |
| -{ |
| - threadAttachMutex().unlock(); |
| -} |
| - |
| void ThreadState::invokePreFinalizers() |
| { |
| ASSERT(checkThread()); |
| @@ -1426,48 +1367,48 @@ void ThreadState::invokePreFinalizers() |
| void ThreadState::clearHeapAges() |
| { |
| - memset(m_heapAges, 0, sizeof(size_t) * BlinkGC::NumberOfHeaps); |
| + memset(m_arenaAges, 0, sizeof(size_t) * BlinkGC::NumberOfArenas); |
| memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyFreedArraySize); |
| m_currentHeapAges = 0; |
| } |
| -int ThreadState::heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHeapIndex) |
| +int ThreadState::arenaIndexOfVectorHeapLeastRecentlyExpanded(int beginArenaIndex, int endArenaIndex) |
| { |
| - size_t minHeapAge = m_heapAges[beginHeapIndex]; |
| - int heapIndexWithMinHeapAge = beginHeapIndex; |
| - for (int heapIndex = beginHeapIndex + 1; heapIndex <= endHeapIndex; heapIndex++) { |
| - if (m_heapAges[heapIndex] < minHeapAge) { |
| - minHeapAge = m_heapAges[heapIndex]; |
| - heapIndexWithMinHeapAge = heapIndex; |
| + size_t minHeapAge = m_arenaAges[beginArenaIndex]; |
| + int arenaIndexWithMinHeapAge = beginArenaIndex; |
| + for (int arenaIndex = beginArenaIndex + 1; arenaIndex <= endArenaIndex; arenaIndex++) { |
| + if (m_arenaAges[arenaIndex] < minHeapAge) { |
| + minHeapAge = m_arenaAges[arenaIndex]; |
| + arenaIndexWithMinHeapAge = arenaIndex; |
| } |
| } |
| - ASSERT(isVectorHeapIndex(heapIndexWithMinHeapAge)); |
| - return heapIndexWithMinHeapAge; |
| + ASSERT(isVectorArenaIndex(arenaIndexWithMinHeapAge)); |
| + return arenaIndexWithMinHeapAge; |
| } |
| -BaseHeap* ThreadState::expandedVectorBackingHeap(size_t gcInfoIndex) |
| +BaseArena* ThreadState::expandedVectorBackingArena(size_t gcInfoIndex) |
| { |
| ASSERT(checkThread()); |
| size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; |
| --m_likelyToBePromptlyFreed[entryIndex]; |
| - int heapIndex = m_vectorBackingHeapIndex; |
| - m_heapAges[heapIndex] = ++m_currentHeapAges; |
| - m_vectorBackingHeapIndex = heapIndexOfVectorHeapLeastRecentlyExpanded(BlinkGC::Vector1HeapIndex, BlinkGC::Vector4HeapIndex); |
| - return m_heaps[heapIndex]; |
| + int arenaIndex = m_vectorBackingArenaIndex; |
| + m_arenaAges[arenaIndex] = ++m_currentHeapAges; |
| + m_vectorBackingArenaIndex = arenaIndexOfVectorHeapLeastRecentlyExpanded(BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); |
| + return m_arenas[arenaIndex]; |
| } |
| -void ThreadState::allocationPointAdjusted(int heapIndex) |
| +void ThreadState::allocationPointAdjusted(int arenaIndex) |
| { |
| - m_heapAges[heapIndex] = ++m_currentHeapAges; |
| - if (m_vectorBackingHeapIndex == heapIndex) |
| - m_vectorBackingHeapIndex = heapIndexOfVectorHeapLeastRecentlyExpanded(BlinkGC::Vector1HeapIndex, BlinkGC::Vector4HeapIndex); |
| + m_arenaAges[arenaIndex] = ++m_currentHeapAges; |
| + if (m_vectorBackingArenaIndex == arenaIndex) |
| + m_vectorBackingArenaIndex = arenaIndexOfVectorHeapLeastRecentlyExpanded(BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); |
| } |
| void ThreadState::promptlyFreed(size_t gcInfoIndex) |
| { |
| ASSERT(checkThread()); |
| size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; |
| - // See the comment in vectorBackingHeap() for why this is +3. |
| + // See the comment in vectorBackingArena() for why this is +3. |
| m_likelyToBePromptlyFreed[entryIndex] += 3; |
| } |
| @@ -1488,10 +1429,10 @@ void ThreadState::takeSnapshot(SnapshotType type) |
| numberOfHeapsReported++; \ |
| switch (type) { \ |
| case SnapshotType::HeapSnapshot: \ |
| - m_heaps[BlinkGC::HeapType##HeapIndex]->takeSnapshot(heapsDumpName + "/" #HeapType, info); \ |
| + m_arenas[BlinkGC::HeapType##ArenaIndex]->takeSnapshot(heapsDumpName + "/" #HeapType, info); \ |
| break; \ |
| case SnapshotType::FreelistSnapshot: \ |
| - m_heaps[BlinkGC::HeapType##HeapIndex]->takeFreelistSnapshot(heapsDumpName + "/" #HeapType); \ |
| + m_arenas[BlinkGC::HeapType##ArenaIndex]->takeFreelistSnapshot(heapsDumpName + "/" #HeapType); \ |
| break; \ |
| default: \ |
| ASSERT_NOT_REACHED(); \ |
| @@ -1512,7 +1453,7 @@ void ThreadState::takeSnapshot(SnapshotType type) |
| SNAPSHOT_HEAP(LargeObject); |
| FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP); |
| - ASSERT(numberOfHeapsReported == BlinkGC::NumberOfHeaps); |
| + ASSERT(numberOfHeapsReported == BlinkGC::NumberOfArenas); |
| #undef SNAPSHOT_HEAP |