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

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: 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 4b07285edcc5fec4f7301044bcb89b3f1f6ac21b..e961657d1f12d327d7e502671efd4f410ff268de 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -37,6 +37,8 @@
#include "platform/heap/Handle.h"
#include "platform/heap/Heap.h"
#include "platform/heap/MarkingVisitor.h"
+#include "platform/heap/PageMemory.h"
+#include "platform/heap/PagePool.h"
#include "platform/heap/SafePoint.h"
#include "public/platform/Platform.h"
#include "public/platform/WebMemoryAllocatorDump.h"
@@ -78,9 +80,10 @@ RecursiveMutex& ThreadState::threadAttachMutex()
return mutex;
}
-ThreadState::ThreadState()
+ThreadState::ThreadState(PerThreadHeapState perThreadHeap)
: m_thread(currentThread())
, m_persistentRegion(adoptPtr(new PersistentRegion()))
+ , m_xThreadPersistentRegion(adoptPtr(new XThreadPersistentRegion()))
#if OS(WIN) && COMPILER(MSVC)
, m_threadStackSize(0)
#endif
@@ -106,6 +109,13 @@ ThreadState::ThreadState()
#if defined(LEAK_SANITIZER)
, m_disabledStaticPersistentsRegistration(0)
#endif
+ , m_markingStack(adoptPtr(new CallbackStack()))
+ , m_postMarkingCallbackStack(adoptPtr(new CallbackStack()))
+ , m_globalWeakCallbackStack(adoptPtr(new CallbackStack()))
+ , m_ephemeronStack(adoptPtr(new CallbackStack()))
+ , m_heapDoesNotContainCache(adoptPtr(new HeapDoesNotContainCache()))
+ , m_regionTree(nullptr)
+ , m_perThreadHeapEnabled(perThreadHeap == PerThreadHeapEnabled)
{
ASSERT(checkThread());
ASSERT(!**s_threadSpecific);
@@ -116,7 +126,13 @@ ThreadState::ThreadState()
size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStackSize();
if (underestimatedStackSize > sizeof(void*))
s_mainThreadUnderestimatedStackSize = underestimatedStackSize - sizeof(void*);
+ m_heapStats = new GCHeapStats();
+ } else if (perThreadHeapEnabled()) {
+ m_heapStats = new GCHeapStats();
+ } else {
+ m_heapStats = ThreadState::mainThreadState()->heapStats();
}
+ ASSERT(m_heapStats);
for (int heapIndex = 0; heapIndex < BlinkGC::LargeObjectHeapIndex; heapIndex++)
m_heaps[heapIndex] = new NormalPageHeap(this, heapIndex);
@@ -138,9 +154,17 @@ ThreadState::~ThreadState()
**s_threadSpecific = nullptr;
if (isMainThread()) {
+ delete m_heapStats;
+ m_heapStats = nullptr;
s_mainThreadStackStart = 0;
s_mainThreadUnderestimatedStackSize = 0;
}
+ if (perThreadHeapEnabled()) {
+ delete m_heapStats;
+ m_heapStats = nullptr;
+ }
+ delete m_regionTree;
+ m_regionTree = nullptr;
}
void ThreadState::init()
@@ -196,7 +220,7 @@ void ThreadState::attachMainThread()
{
RELEASE_ASSERT(!Heap::s_shutdownCalled);
MutexLocker locker(threadAttachMutex());
- ThreadState* state = new(s_mainThreadStateStorage) ThreadState();
+ ThreadState* state = new(s_mainThreadStateStorage) ThreadState(PerThreadHeapDisabled);
attachedThreads().add(state);
}
@@ -207,7 +231,6 @@ void ThreadState::detachMainThread()
// threadAttachMutex and waiting for other threads to pause or reach a
// safepoint.
ThreadState* state = mainThreadState();
-
// 1. Finish sweeping.
state->completeSweep();
{
@@ -228,7 +251,7 @@ void ThreadState::shutdownHeapIfNecessary()
{
// We don't need to enter a safe point before acquiring threadAttachMutex
// because this thread is already detached.
-
+ ASSERT(!ThreadState::current());
MutexLocker locker(threadAttachMutex());
// We start shutting down the heap if there is no running thread
// and Heap::shutdown() is already called.
@@ -236,12 +259,13 @@ void ThreadState::shutdownHeapIfNecessary()
Heap::doShutdown();
}
-void ThreadState::attach()
+void ThreadState::attach(PerThreadHeapState perThreadHeap)
{
RELEASE_ASSERT(!Heap::s_shutdownCalled);
MutexLocker locker(threadAttachMutex());
- ThreadState* state = new ThreadState();
- attachedThreads().add(state);
+ ThreadState* state = new ThreadState(perThreadHeap);
+ if (perThreadHeap == PerThreadHeapDisabled)
+ attachedThreads().add(state);
}
void ThreadState::cleanupPages()
@@ -298,8 +322,10 @@ void ThreadState::cleanup()
// on will not trace objects on this thread's heaps.
cleanupPages();
- ASSERT(attachedThreads().contains(this));
- attachedThreads().remove(this);
+ if (!perThreadHeapEnabled()) {
+ ASSERT(attachedThreads().contains(this));
+ attachedThreads().remove(this);
+ }
}
}
@@ -317,15 +343,17 @@ void ThreadState::visitPersistentRoots(Visitor* visitor)
TRACE_EVENT0("blink_gc", "ThreadState::visitPersistentRoots");
crossThreadPersistentRegion().tracePersistentNodes(visitor);
- for (ThreadState* state : attachedThreads())
+ for (ThreadState* state : attachedThreads()) {
state->visitPersistents(visitor);
+ }
}
void ThreadState::visitStackRoots(Visitor* visitor)
{
TRACE_EVENT0("blink_gc", "ThreadState::visitStackRoots");
- for (ThreadState* state : attachedThreads())
+ for (ThreadState* state : attachedThreads()) {
state->visitStack(visitor);
+ }
}
NO_SANITIZE_ADDRESS
@@ -403,6 +431,7 @@ void ThreadState::visitStack(Visitor* visitor)
void ThreadState::visitPersistents(Visitor* visitor)
{
m_persistentRegion->tracePersistentNodes(visitor);
+ m_xThreadPersistentRegion->tracePersistentNodes(visitor);
if (m_traceDOMWrappers) {
TRACE_EVENT0("blink_gc", "V8GCController::traceDOMWrappers");
m_traceDOMWrappers(m_isolate, visitor);
@@ -499,18 +528,18 @@ CrossThreadPersistentRegion& ThreadState::crossThreadPersistentRegion()
size_t ThreadState::totalMemorySize()
{
- return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
+ return allocatedObjectSize() + markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages();
}
size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLastGC)
{
- if (Heap::wrapperCountAtLastGC() == 0) {
+ if (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 / wrapperCountAtLastGC() * collectedWrapperCount());
if (estimationBaseSize < sizeRetainedByCollectedPersistents)
return 0;
return estimationBaseSize - sizeRetainedByCollectedPersistents;
@@ -518,8 +547,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 = allocatedObjectSize() + markedObjectSize();
+ size_t estimatedSize = estimatedLiveSize(markedObjectSizeAtLastCompleteSweep(), 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;
@@ -531,7 +560,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, 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;
@@ -545,7 +574,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 (allocatedObjectSize() < 100 * 1024 || totalMemorySize() < totalMemorySizeThreshold)
return false;
// If the growing rate of Oilpan's heap or PartitionAlloc is high enough,
// trigger a GC.
@@ -590,7 +619,7 @@ bool ThreadState::shouldForceMemoryPressureGC()
void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType)
{
ASSERT(checkThread());
- Heap::reportMemoryUsageForTracing();
+ reportMemoryUsageForTracing();
#if PRINT_HEAP_STATS
dataLogF("ThreadState::scheduleV8FollowupGCIfNeeded (gcType=%s)\n", gcType == BlinkGC::V8MajorGC ? "MajorGC" : "MinorGC");
@@ -611,7 +640,10 @@ void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType)
#if PRINT_HEAP_STATS
dataLogF("Scheduled MemoryPressureGC\n");
#endif
- Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::MemoryPressureGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
haraken 2016/01/07 08:06:22 It wouldn't be a good idea to introduce Heap::coll
+ else
+ Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::MemoryPressureGC);
return;
}
if (shouldScheduleV8FollowupGC()) {
@@ -649,14 +681,17 @@ void ThreadState::willStartV8GC()
#if PRINT_HEAP_STATS
dataLogF("Scheduled PageNavigationGC\n");
#endif
- Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::PageNavigationGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
+ else
+ Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::PageNavigationGC);
}
}
void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio)
{
ASSERT(checkThread());
- Heap::reportMemoryUsageForTracing();
+ reportMemoryUsageForTracing();
#if PRINT_HEAP_STATS
dataLogF("ThreadState::schedulePageNavigationGCIfNeeded (estimatedRemovalRatio=%.2lf)\n", estimatedRemovalRatio);
@@ -698,7 +733,7 @@ void ThreadState::schedulePageNavigationGC()
void ThreadState::scheduleGCIfNeeded()
{
ASSERT(checkThread());
- Heap::reportMemoryUsageForTracing();
+ reportMemoryUsageForTracing();
#if PRINT_HEAP_STATS
dataLogF("ThreadState::scheduleGCIfNeeded\n");
@@ -730,7 +765,10 @@ void ThreadState::scheduleGCIfNeeded()
#if PRINT_HEAP_STATS
dataLogF("Scheduled ConservativeGC\n");
#endif
- Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::ConservativeGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
+ else
+ Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::ConservativeGC);
return;
}
}
@@ -753,15 +791,18 @@ 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", m_heapStats->estimatedMarkingTime());
+ if (idleDeltaInSeconds <= m_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();
return;
}
- Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::IdleGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
+ else
+ Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::IdleGC);
}
void ThreadState::performIdleLazySweep(double deadlineSeconds)
@@ -940,10 +981,16 @@ void ThreadState::runScheduledGC(BlinkGC::StackState stackState)
Heap::collectAllGarbage();
break;
case PreciseGCScheduled:
- Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::PreciseGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
+ else
+ Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep, BlinkGC::PreciseGC);
break;
case PageNavigationGCScheduled:
- Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::PageNavigationGC);
+ if (perThreadHeapEnabled())
+ Heap::collectGarbageForIsolatedThread(this);
+ else
+ Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::PageNavigationGC);
break;
case IdleGCScheduled:
// Idle time GC will be scheduled by Blink Scheduler.
@@ -956,7 +1003,7 @@ void ThreadState::runScheduledGC(BlinkGC::StackState stackState)
void ThreadState::flushHeapDoesNotContainCacheIfNeeded()
{
if (m_shouldFlushHeapDoesNotContainCache) {
- Heap::flushHeapDoesNotContainCache();
+ flushHeapDoesNotContainCache();
m_shouldFlushHeapDoesNotContainCache = false;
}
}
@@ -1125,12 +1172,12 @@ void ThreadState::completeSweep()
void ThreadState::postSweep()
{
ASSERT(checkThread());
- Heap::reportMemoryUsageForTracing();
+ reportMemoryUsageForTracing();
if (isMainThread()) {
double collectionRate = 0;
- if (Heap::objectSizeAtLastGC() > 0)
- collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSizeAtLastGC();
+ if (objectSizeAtLastGC() > 0)
+ collectionRate = 1 - 1.0 * markedObjectSize() / objectSizeAtLastGC();
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadState::collectionRate", static_cast<int>(100 * collectionRate));
#if PRINT_HEAP_STATS
@@ -1139,10 +1186,10 @@ void ThreadState::postSweep()
// Heap::markedObjectSize() may be underestimated here if any other
// thread has not yet finished lazy sweeping.
- Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize());
+ m_heapStats->setMarkedObjectSizeAtLastCompleteSweep(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", objectSizeAtLastGC() / 1024, 1, 4 * 1024 * 1024, 50);
+ Platform::current()->histogramCustomCounts("BlinkGC.ObjectSizeAfterGC", 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);
}
@@ -1202,7 +1249,7 @@ void ThreadState::resumeThreads()
void ThreadState::safePoint(BlinkGC::StackState stackState)
{
ASSERT(checkThread());
- Heap::reportMemoryUsageForTracing();
+ reportMemoryUsageForTracing();
runScheduledGC(stackState);
ASSERT(!m_atSafePoint);
@@ -1521,4 +1568,182 @@ void ThreadState::takeSnapshot(SnapshotType type)
BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwnershipEdge(classesDump->guid(), heapsDump->guid());
}
+void ThreadState::reportMemoryUsageHistogram()
+{
+ static size_t supportedMaxSizeInMB = 4 * 1024;
+ static size_t observedMaxSizeInMB = 0;
+
+ // FIXME: Separate report per thread
+
+ // +1 is for rounding up the sizeInMB.
+ size_t sizeInMB = allocatedSpace() / 1024 / 1024 + 1;
+ if (sizeInMB >= supportedMaxSizeInMB)
+ sizeInMB = supportedMaxSizeInMB - 1;
+ if (sizeInMB > observedMaxSizeInMB) {
+ // Send a UseCounter only when we see the highest memory usage
+ // we've ever seen.
+ Platform::current()->histogramEnumeration("BlinkGC.CommittedSize", sizeInMB, supportedMaxSizeInMB);
+ observedMaxSizeInMB = sizeInMB;
+ }
+}
+
+void ThreadState::reportMemoryUsageForTracing()
+{
+ // FIXME: Separate report per thread
haraken 2016/01/07 08:06:22 In practice, we're just interested in the memory c
+#if PRINT_HEAP_STATS
+ // dataLogF("allocatedSpace=%ldMB, allocatedObjectSize=%ldMB, markedObjectSize=%ldMB, partitionAllocSize=%ldMB, wrapperCount=%ld, collectedWrapperCount=%ld\n", Heap::allocatedSpace() / 1024 / 1024, Heap::allocatedObjectSize() / 1024 / 1024, Heap::markedObjectSize() / 1024 / 1024, WTF::Partitions::totalSizeOfCommittedPages() / 1024 / 1024, Heap::wrapperCount(), Heap::collectedWrapperCount());
haraken 2016/01/07 08:06:22 Heap:: => ThreadState::
+#endif
+
+ bool gcTracingEnabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled);
+ if (!gcTracingEnabled)
+ return;
+
+ // These values are divided by 1024 to avoid overflow in practical cases (TRACE_COUNTER values are 32-bit ints).
+ // They are capped to INT_MAX just in case.
+ TRACE_COUNTER1("blink_gc", "Heap::allocatedObjectSizeKB", std::min(allocatedObjectSize() / 1024, static_cast<size_t>(INT_MAX)));
haraken 2016/01/07 08:06:22 Heap:: => ThreadState::
+ TRACE_COUNTER1("blink_gc", "Heap::markedObjectSizeKB", std::min(markedObjectSize() / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::markedObjectSizeAtLastCompleteSweepKB", std::min(markedObjectSizeAtLastCompleteSweep() / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1("blink_gc", "Heap::allocatedSpaceKB", std::min(allocatedSpace() / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::objectSizeAtLastGCKB", std::min(objectSizeAtLastGC() / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::wrapperCount", std::min(wrapperCount(), static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::wrapperCountAtLastGC", std::min(wrapperCountAtLastGC(), static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::collectedWrapperCount", std::min(collectedWrapperCount(), static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::partitionAllocSizeAtLastGCKB", std::min(partitionAllocSizeAtLastGC() / 1024, static_cast<size_t>(INT_MAX)));
+ TRACE_COUNTER1("blink_gc", "Partitions::totalSizeOfCommittedPagesKB", std::min(WTF::Partitions::totalSizeOfCommittedPages() / 1024, static_cast<size_t>(INT_MAX)));
+}
+
+void ThreadState::resetHeapCounters()
+{
+ ASSERT(isInGC());
+
+ reportMemoryUsageForTracing();
+
+ m_heapStats->reset();
+}
+
+void ThreadState::flushHeapDoesNotContainCache()
+{
+ m_heapDoesNotContainCache->flush();
+}
+
+ThreadState::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)
+#if ENABLE(ASSERT)
+ // 0 is used to figure non-assigned area, so avoid to use 0 in s_gcGeneration.
+ , m_gcGeneration(1)
+#endif
+{
+}
+
+double ThreadState::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 ThreadState::GCHeapStats::reset()
+{
+ m_objectSizeAtLastGC = m_allocatedObjectSize + m_markedObjectSize;
+ m_partitionAllocSizeAtLastGC = WTF::Partitions::totalSizeOfCommittedPages();
+ m_allocatedObjectSize = 0;
+ m_markedObjectSize = 0;
+ m_wrapperCountAtLastGC = m_wrapperCount;
+ m_collectedWrapperCount = 0;
+}
+
+PageMemoryRegion* ThreadState::RegionTree::lookup(Address address)
+{
+ RegionTree* current = this;
+ while (current) {
+ Address base = current->m_region->base();
+ if (address < base) {
+ current = current->m_left;
+ continue;
+ }
+ if (address >= base + current->m_region->size()) {
+ current = current->m_right;
+ continue;
+ }
+ ASSERT(current->m_region->contains(address));
+ return current->m_region;
+ }
+ return nullptr;
+}
+
+void ThreadState::RegionTree::add(RegionTree* newTree, RegionTree** context)
+{
+ ASSERT(newTree);
+ Address base = newTree->m_region->base();
+ for (RegionTree* current = *context; current; current = *context) {
+ ASSERT(!current->m_region->contains(base));
+ context = (base < current->m_region->base()) ? &current->m_left : &current->m_right;
+ }
+ *context = newTree;
+}
+
+void ThreadState::RegionTree::remove(PageMemoryRegion* region, RegionTree** context)
+{
+ ASSERT(region);
+ ASSERT(context);
+ Address base = region->base();
+ RegionTree* current = *context;
+ for (; current; current = *context) {
+ if (region == current->m_region)
+ break;
+ context = (base < current->m_region->base()) ? &current->m_left : &current->m_right;
+ }
+
+ // Shutdown via detachMainThread might not have populated the region tree.
+ if (!current)
+ return;
+
+ *context = nullptr;
+ if (current->m_left) {
+ add(current->m_left, context);
+ current->m_left = nullptr;
+ }
+ if (current->m_right) {
+ add(current->m_right, context);
+ current->m_right = nullptr;
+ }
+ delete current;
+}
+
+void ThreadState::removeFromRegionTree(PageMemoryRegion* region)
+{
+ if (m_regionTree)
+ RegionTree::remove(region, &m_regionTree);
+}
+
+ThreadState* ThreadState::forObject(const void* object)
+{
+ if (!object)
+ return nullptr;
+ BasePage* page = pageFromObject(object);
+ ASSERT(page);
+ ASSERT(page->heap());
+ return page->heap()->threadState();
+}
+
+size_t ThreadState::s_totalAllocatedSpace = 0;
+size_t ThreadState::s_totalAllocatedObjectSize = 0;
+size_t ThreadState::s_totalMarkedObjectSize = 0;
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698