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

Unified Diff: third_party/WebKit/Source/platform/heap/ThreadState.cpp

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: Refactored Created 4 years, 11 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/ThreadState.cpp
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index 05b9138f4a58a6ad7ea205c8ab6df4559431fb0e..19ac3d8d0ce3a8bdad45dff13aa8d97190c51350 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -36,7 +36,9 @@
#include "platform/heap/CallbackStack.h"
#include "platform/heap/Handle.h"
#include "platform/heap/Heap.h"
+#include "platform/heap/HeapPage.h"
#include "platform/heap/MarkingVisitor.h"
+#include "platform/heap/PagePool.h"
#include "platform/heap/SafePoint.h"
#include "public/platform/Platform.h"
#include "public/platform/WebMemoryAllocatorDump.h"
@@ -66,24 +68,281 @@ extern "C" void* __libc_stack_end; // NOLINT
namespace blink {
+GCHeapStats::GCHeapStats()
+ : m_allocatedSpace(0)
+ , m_allocatedObjectSize(0)
+ , m_objectSizeAtLastGC(0)
+ , m_markedObjectSize(0)
+ , m_markedObjectSizeAtLastCompleteSweep(0)
+ , m_wrapperCount(0)
+ , m_wrapperCountAtLastGC(0)
+ , m_collectedWrapperCount(0)
+ , m_partitionAllocSizeAtLastGC(WTF::Partitions::totalSizeOfCommittedPages())
+ , m_estimatedMarkingTimePerByte(0.0)
+{
+}
+
+double GCHeapStats::estimatedMarkingTime()
+{
+ // Use 8 ms as initial estimated marking time.
+ // 8 ms is long enough for low-end mobile devices to mark common
+ // real-world object graphs.
+ if (m_estimatedMarkingTimePerByte == 0)
+ return 0.008;
+
+ // Assuming that the collection rate of this GC will be mostly equal to
+ // the collection rate of the last GC, estimate the marking time of this GC.
+ return m_estimatedMarkingTimePerByte * (allocatedObjectSize() + markedObjectSize());
+}
+
+void GCHeapStats::reset()
+{
+ m_objectSizeAtLastGC = m_allocatedObjectSize + m_markedObjectSize;
+ m_partitionAllocSizeAtLastGC = WTF::Partitions::totalSizeOfCommittedPages();
haraken 2016/02/12 11:28:52 It would be problematic to simply use PartitionAll
+ m_allocatedObjectSize = 0;
+ m_markedObjectSize = 0;
+ m_wrapperCountAtLastGC = m_wrapperCount;
+ m_collectedWrapperCount = 0;
+}
+
+void GCHeapStats::increaseAllocatedObjectSize(size_t delta)
haraken 2016/02/12 11:28:52 These changes will be made by peria-san's CL: htt
+{
+ atomicAdd(&m_allocatedObjectSize, static_cast<long>(delta));
+ Heap::increaseTotalAllocatedObjectSize(delta);
+}
+
+void GCHeapStats::decreaseAllocatedObjectSize(size_t delta)
+{
+ atomicSubtract(&m_allocatedObjectSize, static_cast<long>(delta));
+ Heap::decreaseTotalAllocatedObjectSize(delta);
+}
+
+void GCHeapStats::increaseMarkedObjectSize(size_t delta)
+{
+ atomicAdd(&m_markedObjectSize, static_cast<long>(delta));
+ Heap::increaseTotalMarkedObjectSize(delta);
+}
+
+void GCHeapStats::increaseAllocatedSpace(size_t delta)
+{
+ atomicAdd(&m_allocatedSpace, static_cast<long>(delta));
+ Heap::increaseTotalAllocatedSpace(delta);
+}
+
+void GCHeapStats::decreaseAllocatedSpace(size_t delta)
+{
+ atomicSubtract(&m_allocatedSpace, static_cast<long>(delta));
+ Heap::decreaseTotalAllocatedSpace(delta);
+}
+
+HashSet<GCGroup*>& GCGroup::all()
+{
+ DEFINE_STATIC_LOCAL(HashSet<GCGroup*>, groups, ());
+ return groups;
+}
+
+GCGroup::GCGroup()
+ : m_regionTree(nullptr)
+ , m_heapDoesNotContainCache(adoptPtr(new HeapDoesNotContainCache))
+{
+}
+
+GCGroup::~GCGroup()
+{
+}
+
+void GCGroup::flushHeapDoesNotContainCache()
+{
+ m_heapDoesNotContainCache->flush();
+}
+
+MultiThreadGCGroup::MultiThreadGCGroup()
+ : m_safePointBarrier(adoptPtr(new SafePointBarrier(this)))
+ , m_freePagePool(adoptPtr(new FreePagePool))
haraken 2016/02/12 11:28:52 Maybe we should share the FreePagePool among all t
+ , m_orphanedPagePool(adoptPtr(new OrphanedPagePool))
+{
+ GCGroup::all().add(this);
+}
+
+MultiThreadGCGroup::~MultiThreadGCGroup()
+{
+ GCGroup::all().remove(this);
+}
+
+void MultiThreadGCGroup::attach(ThreadState* thread)
+{
+ MutexLocker locker(m_threadAttachMutex);
+ m_threads.add(thread);
+}
+
+void MultiThreadGCGroup::detach(ThreadState* thread)
+{
+ SafePointAwareMutexLocker locker(m_threadAttachMutex, BlinkGC::NoHeapPointersOnStack);
+ thread->cleanupCallback();
+ ASSERT(m_threads.contains(thread));
+ m_threads.remove(thread);
+}
+
+bool MultiThreadGCGroup::park()
+{
+ return m_safePointBarrier->parkOthers();
+}
+
+void MultiThreadGCGroup::resume()
+{
+ m_safePointBarrier->resumeOthers();
+}
+
+bool MultiThreadGCGroup::isParked() const
haraken 2016/02/12 11:28:52 Add #if ENABLE(ASSERT).
haraken 2016/02/12 11:28:52 isParked => isAtSafePoint
keishi 2016/02/29 06:02:33 Done.
keishi 2016/02/29 06:02:33 Done.
+{
+ for (ThreadState* state : m_threads) {
+ if (!state->isAtSafePoint())
+ return false;
+ }
+ return true;
+}
+
+void MultiThreadGCGroup::lockThreadAttachMutex()
+{
+ m_threadAttachMutex.lock();
+}
+
+void MultiThreadGCGroup::unlockThreadAttachMutex()
+{
+ m_threadAttachMutex.unlock();
+}
+
+#if ENABLE(ASSERT)
+BasePage* MultiThreadGCGroup::findPageFromAddress(Address address)
+{
+ for (ThreadState* state : m_threads) {
+ if (BasePage* page = state->findPageFromAddress(address))
+ return page;
+ }
+ return nullptr;
+}
+#endif
+
+void MultiThreadGCGroup::preGC()
+{
+ for (ThreadState* state : m_threads) {
+ state->preGC();
+ }
+}
+
+void MultiThreadGCGroup::postGC(BlinkGC::GCType gcType)
+{
+ for (ThreadState* state : m_threads) {
+ state->postGC(gcType);
+ }
+}
+
+size_t MultiThreadGCGroup::objectPayloadSizeForTesting()
+{
+ size_t objectPayloadSize = 0;
+ for (ThreadState* state : m_threads) {
+ state->setGCState(ThreadState::GCRunning);
+ state->makeConsistentForGC();
+ objectPayloadSize += state->objectPayloadSizeForTesting();
+ state->setGCState(ThreadState::EagerSweepScheduled);
+ state->setGCState(ThreadState::Sweeping);
+ state->setGCState(ThreadState::NoGCScheduled);
+ }
+ return objectPayloadSize;
+}
+
+size_t MultiThreadGCGroup::size() const
haraken 2016/02/12 11:28:52 size => threadCount ?
keishi 2016/02/29 06:02:34 Done.
+{
+ return m_threads.size();
+}
+
+void MultiThreadGCGroup::visitPersistentRoots(Visitor* visitor)
+{
+ TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots");
+ Heap::crossThreadPersistentRegion().tracePersistentNodes(visitor);
+
+ for (ThreadState* state : m_threads) {
+ state->visitPersistents(visitor);
+ }
+}
+
+void MultiThreadGCGroup::visitStackRoots(Visitor* visitor)
+{
+ TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots");
+ for (ThreadState* state : m_threads) {
+ state->visitStack(visitor);
+ }
+}
+
+void MultiThreadGCGroup::checkAndPark(ThreadState* threadState, SafePointAwareMutexLocker* locker)
+{
+ m_safePointBarrier->checkAndPark(threadState, locker);
+}
+
+void MultiThreadGCGroup::enterSafePoint(ThreadState* threadState)
+{
+ m_safePointBarrier->enterSafePoint(threadState);
+}
+
+void MultiThreadGCGroup::leaveSafePoint(ThreadState* threadState, SafePointAwareMutexLocker* locker)
+{
+ m_safePointBarrier->leaveSafePoint(threadState, locker);
+}
+
+void MultiThreadGCGroup::shutdown()
+{
+ Heap::shutdown();
+}
+
+void MultiThreadGCGroup::shutdownIfNecessary()
+{
+ MutexLocker locker(m_threadAttachMutex);
+ if (m_threads.size() == 0 && Heap::s_shutdownCalled) {
+ shutdown();
haraken 2016/02/12 11:28:52 As commented in Heap::shutdown(), I think we need
+ delete this;
+ }
+}
+
+BasePage* GCGroup::lookupPageForAddress(Address address)
+{
+ ASSERT(ThreadState::current()->isInGC());
+ if (!m_regionTree)
+ return nullptr;
+ if (PageMemoryRegion* region = m_regionTree->lookup(address)) {
+ BasePage* page = region->pageFromAddress(address);
+ return page && !page->orphaned() ? page : nullptr;
+ }
+ return nullptr;
+}
+
+void GCGroup::addPageMemoryRegion(PageMemoryRegion* region)
+{
+ MutexLocker locker(m_regionTreeMutex);
+ RegionTree::add(new RegionTree(region), &m_regionTree);
+}
+
+void GCGroup::removePageMemoryRegion(PageMemoryRegion* region)
+{
+ // Deletion of large objects (and thus their regions) can happen
+ // concurrently on sweeper threads. Removal can also happen during thread
+ // shutdown, but that case is safe. Regardless, we make all removals
+ // mutually exclusive.
+ MutexLocker locker(m_regionTreeMutex);
+ RegionTree::remove(region, &m_regionTree);
+}
+
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()
+ThreadState::ThreadState(bool perThreadHeapEnabled)
: m_thread(currentThread())
, m_persistentRegion(adoptPtr(new PersistentRegion()))
#if OS(WIN) && COMPILER(MSVC)
, m_threadStackSize(0)
#endif
+ , m_perThreadHeapEnabled(perThreadHeapEnabled)
, m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart()))
, m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart()))
, m_safePointScopeMarker(nullptr)
@@ -100,6 +359,7 @@ ThreadState::ThreadState()
, m_shouldFlushHeapDoesNotContainCache(false)
, m_gcState(NoGCScheduled)
, m_traceDOMWrappers(nullptr)
+ , m_gcGroup(nullptr)
#if defined(ADDRESS_SANITIZER)
, m_asanFakeStack(__asan_get_current_fake_stack())
#endif
@@ -116,7 +376,14 @@ ThreadState::ThreadState()
size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStackSize();
if (underestimatedStackSize > sizeof(void*))
s_mainThreadUnderestimatedStackSize = underestimatedStackSize - sizeof(void*);
+ m_gcGroup = new MultiThreadGCGroup();
+ } else if (m_perThreadHeapEnabled) {
+ m_gcGroup = new MultiThreadGCGroup();
+ } else {
+ m_gcGroup = ThreadState::mainThreadState()->gcGroup();
}
+ ASSERT(m_gcGroup);
+ m_gcGroup->attach(this);
for (int heapIndex = 0; heapIndex < BlinkGC::LargeObjectHeapIndex; heapIndex++)
m_heaps[heapIndex] = new NormalPageHeap(this, heapIndex);
@@ -146,14 +413,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().
}
@@ -192,12 +455,10 @@ size_t ThreadState::threadStackSize()
}
#endif
-void ThreadState::attachMainThread()
+void ThreadState::prepareForMainThread()
{
RELEASE_ASSERT(!Heap::s_shutdownCalled);
- MutexLocker locker(threadAttachMutex());
- ThreadState* state = new(s_mainThreadStateStorage) ThreadState();
- attachedThreads().add(state);
+ new(s_mainThreadStateStorage) ThreadState(false);
}
void ThreadState::detachMainThread()
@@ -207,41 +468,19 @@ void ThreadState::detachMainThread()
// threadAttachMutex and waiting for other threads to pause or reach a
// safepoint.
ThreadState* state = mainThreadState();
+ GCGroup* gcGroup = state->gcGroup();
// 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();
+ gcGroup->detach(state);
+ state->~ThreadState();
+ gcGroup->shutdownIfNecessary();
}
-void ThreadState::attach()
+void ThreadState::prepareForCurrentThread(bool perThreadHeap)
{
RELEASE_ASSERT(!Heap::s_shutdownCalled);
- MutexLocker locker(threadAttachMutex());
- ThreadState* state = new ThreadState();
- attachedThreads().add(state);
+ new ThreadState(perThreadHeap);
}
void ThreadState::cleanupPages()
@@ -251,81 +490,57 @@ void ThreadState::cleanupPages()
m_heaps[i]->cleanupPages();
}
-void ThreadState::cleanup()
+void ThreadState::cleanupCallback()
haraken 2016/02/12 11:28:52 cleanupCallback => cleanupThreadHeap ?
keishi 2016/02/29 06:02:33 Done.
{
- 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.
+ if (isMainThread()) {
haraken 2016/02/12 11:28:52 This should be: if (isMainThread() || m_perThre
keishi 2016/02/29 06:02:33 Done.
cleanupPages();
+ return;
+ }
- 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();
}
haraken 2016/02/12 11:28:52 If m_perThreadHeapEnabled is true, the termination
+ // 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()
{
ThreadState* state = current();
- state->cleanup();
+ GCGroup* gcGroup = state->gcGroup();
+ gcGroup->detach(state);
RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled);
delete state;
- shutdownHeapIfNecessary();
-}
-
-void ThreadState::visitPersistentRoots(Visitor* visitor)
-{
- TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots");
- Heap::crossThreadPersistentRegion().tracePersistentNodes(visitor);
-
- for (ThreadState* state : attachedThreads())
- state->visitPersistents(visitor);
-}
-
-void ThreadState::visitStackRoots(Visitor* visitor)
-{
- TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots");
- for (ThreadState* state : attachedThreads())
- state->visitStack(visitor);
+ gcGroup->shutdownIfNecessary();
}
NO_SANITIZE_ADDRESS
@@ -480,7 +695,7 @@ void ThreadState::threadLocalWeakProcessing()
// Due to the complexity, we just forbid allocations.
NoAllocationScope noAllocationScope(this);
- MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor;
+ MarkingVisitor<Visitor::WeakProcessing> weakProcessingVisitor(nullptr);
// Perform thread-specific weak processing.
while (popAndInvokeThreadLocalWeakCallback(&weakProcessingVisitor)) { }
@@ -493,18 +708,18 @@ void ThreadState::threadLocalWeakProcessing()
size_t ThreadState::totalMemorySize()
{
- return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
+ return gcGroup()->heapStats().allocatedObjectSize() + gcGroup()->heapStats().markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
}
size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLastGC)
{
- if (Heap::wrapperCountAtLastGC() == 0) {
+ if (gcGroup()->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 / gcGroup()->heapStats().wrapperCountAtLastGC() * gcGroup()->heapStats().collectedWrapperCount());
if (estimationBaseSize < sizeRetainedByCollectedPersistents)
return 0;
return estimationBaseSize - sizeRetainedByCollectedPersistents;
@@ -512,8 +727,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 = gcGroup()->heapStats().allocatedObjectSize() + gcGroup()->heapStats().markedObjectSize();
+ size_t estimatedSize = estimatedLiveSize(gcGroup()->heapStats().markedObjectSizeAtLastCompleteSweep(), gcGroup()->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;
@@ -525,7 +740,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, gcGroup()->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;
@@ -539,7 +754,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 (gcGroup()->heapStats().allocatedObjectSize() < 100 * 1024 || totalMemorySize() < totalMemorySizeThreshold)
return false;
// If the growing rate of Oilpan's heap or PartitionAlloc is high enough,
// trigger a GC.
@@ -747,8 +962,8 @@ void ThreadState::performIdleGC(double deadlineSeconds)
return;
double idleDeltaInSeconds = deadlineSeconds - Platform::current()->monotonicallyIncreasingTimeSeconds();
- 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", ThreadState::current()->gcGroup()->heapStats().estimatedMarkingTime());
+ if (idleDeltaInSeconds <= ThreadState::current()->gcGroup()->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();
@@ -950,7 +1165,7 @@ void ThreadState::runScheduledGC(BlinkGC::StackState stackState)
void ThreadState::flushHeapDoesNotContainCacheIfNeeded()
{
if (m_shouldFlushHeapDoesNotContainCache) {
- Heap::flushHeapDoesNotContainCache();
+ gcGroup()->flushHeapDoesNotContainCache();
m_shouldFlushHeapDoesNotContainCache = false;
}
}
@@ -1123,8 +1338,8 @@ void ThreadState::postSweep()
if (isMainThread()) {
double collectionRate = 0;
- if (Heap::objectSizeAtLastGC() > 0)
- collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC();
+ if (gcGroup()->heapStats().objectSizeAtLastGC() > 0)
+ collectionRate = 1 - 1.0 * gcGroup()->heapStats().markedObjectSize() / gcGroup()->heapStats().objectSizeAtLastGC();
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::collectionRate", static_cast<int>(100 * collectionRate));
#if PRINT_HEAP_STATS
@@ -1133,10 +1348,10 @@ void ThreadState::postSweep()
// Heap::markedObjectSize() may be underestimated here if any other
// thread has not yet finished lazy sweeping.
- Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize());
+ gcGroup()->heapStats().setMarkedObjectSizeAtLastCompleteSweep(gcGroup()->heapStats().markedObjectSize());
- Platform::current()->histogramCustomCounts("BlinkGC.ObjectSizeBeforeGC", Heap::objectSizeAtLastGC() / 1024, 1, 4 * 1024 * 1024, 50);
- Platform::current()->histogramCustomCounts("BlinkGC.ObjectSizeAfterGC", Heap::markedObjectSize() / 1024, 1, 4 * 1024 * 1024, 50);
+ Platform::current()->histogramCustomCounts("BlinkGC.ObjectSizeBeforeGC", gcGroup()->heapStats().objectSizeAtLastGC() / 1024, 1, 4 * 1024 * 1024, 50);
+ Platform::current()->histogramCustomCounts("BlinkGC.ObjectSizeAfterGC", gcGroup()->heapStats().markedObjectSize() / 1024, 1, 4 * 1024 * 1024, 50);
Platform::current()->histogramCustomCounts("BlinkGC.CollectionRate", static_cast<int>(100 * collectionRate), 1, 100, 20);
Platform::current()->histogramCustomCounts("BlinkGC.TimeForSweepingAllObjects", m_accumulatedSweepingTime, 1, 10 * 1000, 50);
}
@@ -1183,16 +1398,6 @@ size_t ThreadState::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 +1407,7 @@ void ThreadState::safePoint(BlinkGC::StackState stackState)
ASSERT(!m_atSafePoint);
m_stackState = stackState;
m_atSafePoint = true;
- s_safePointBarrier->checkAndPark(this);
+ m_gcGroup->checkAndPark(this, nullptr);
m_atSafePoint = false;
m_stackState = BlinkGC::HeapPointersOnStack;
preSweep();
@@ -1246,14 +1451,14 @@ void ThreadState::enterSafePoint(BlinkGC::StackState stackState, void* scopeMark
m_atSafePoint = true;
m_stackState = stackState;
m_safePointScopeMarker = scopeMarker;
- s_safePointBarrier->enterSafePoint(this);
+ m_gcGroup->enterSafePoint(this);
}
void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker)
{
ASSERT(checkThread());
ASSERT(m_atSafePoint);
- s_safePointBarrier->leaveSafePoint(this, locker);
+ m_gcGroup->leaveSafePoint(this, locker);
m_atSafePoint = false;
m_stackState = BlinkGC::HeapPointersOnStack;
clearSafePointScopeMarker();
@@ -1291,7 +1496,7 @@ void ThreadState::addInterruptor(PassOwnPtr<BlinkGCInterruptor> interruptor)
ASSERT(checkThread());
SafePointScope scope(BlinkGC::HeapPointersOnStack);
{
- MutexLocker locker(threadAttachMutex());
+ MutexLocker locker(gcGroup()->threadAttachMutex());
m_interruptors.append(interruptor);
}
}
@@ -1301,7 +1506,7 @@ void ThreadState::removeInterruptor(BlinkGCInterruptor* interruptor)
ASSERT(checkThread());
SafePointScope scope(BlinkGC::HeapPointersOnStack);
{
- MutexLocker locker(threadAttachMutex());
+ MutexLocker locker(gcGroup()->threadAttachMutex());
size_t index = m_interruptors.find(interruptor);
RELEASE_ASSERT(index != kNotFound);
m_interruptors.remove(index);
@@ -1344,16 +1549,6 @@ ThreadState::AttachedThreadStateSet& ThreadState::attachedThreads()
return threads;
}
-void ThreadState::lockThreadAttachMutex()
-{
- threadAttachMutex().lock();
-}
-
-void ThreadState::unlockThreadAttachMutex()
-{
- threadAttachMutex().unlock();
-}
-
void ThreadState::invokePreFinalizers()
{
ASSERT(checkThread());
@@ -1515,4 +1710,14 @@ void ThreadState::takeSnapshot(SnapshotType type)
BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwnershipEdge(classesDump->guid(), heapsDump->guid());
}
+ThreadState* ThreadState::forObject(const void* object)
haraken 2016/02/12 11:28:52 forObject => fromObject (for consistency with from
keishi 2016/02/29 06:02:34 Done.
+{
+ if (!object)
+ return nullptr;
+ BasePage* page = pageFromObject(object);
+ ASSERT(page);
+ ASSERT(page->heap());
+ return page->heap()->threadState();
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698