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

Unified Diff: Source/platform/heap/HeapPage.cpp

Issue 1314793002: Oilpan: Split Heap.h into two files (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 4 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
« no previous file with comments | « Source/platform/heap/HeapPage.h ('k') | Source/platform/heap/blink_heap.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/HeapPage.cpp
diff --git a/Source/platform/heap/Heap.cpp b/Source/platform/heap/HeapPage.cpp
similarity index 72%
copy from Source/platform/heap/Heap.cpp
copy to Source/platform/heap/HeapPage.cpp
index d4a3a5dbbfdaa7b2b8d0e5cb974342bf94cf1c9f..9b6e4c3a7054f2d5f210df382211dfc3b5d8b027 100644
--- a/Source/platform/heap/Heap.cpp
+++ b/Source/platform/heap/HeapPage.cpp
@@ -29,13 +29,14 @@
*/
#include "config.h"
-#include "platform/heap/Heap.h"
+#include "platform/heap/HeapPage.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/Task.h"
#include "platform/TraceEvent.h"
#include "platform/heap/BlinkGCMemoryDumpProvider.h"
#include "platform/heap/CallbackStack.h"
+#include "platform/heap/Heap.h"
#include "platform/heap/MarkingVisitor.h"
#include "platform/heap/PageMemory.h"
#include "platform/heap/PagePool.h"
@@ -61,13 +62,6 @@
#include <utility>
#endif
-#if OS(POSIX)
-#include <sys/mman.h>
-#include <unistd.h>
-#elif OS(WIN)
-#include <windows.h>
-#endif
-
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
// FIXME: have ContainerAnnotations.h define an ENABLE_-style name instead.
#define ENABLE_ASAN_CONTAINER_ANNOTATIONS 1
@@ -112,91 +106,6 @@ static String classOf(const void* object)
}
#endif
-class GCForbiddenScope final {
-public:
- explicit GCForbiddenScope(ThreadState* state)
- : m_state(state)
- {
- // Prevent nested collectGarbage() invocations.
- m_state->enterGCForbiddenScope();
- }
-
- ~GCForbiddenScope()
- {
- m_state->leaveGCForbiddenScope();
- }
-
-private:
- ThreadState* m_state;
-};
-
-class GCScope final {
-public:
- GCScope(ThreadState* state, ThreadState::StackState stackState, ThreadState::GCType gcType)
- : m_state(state)
- , m_gcForbiddenScope(state)
- // See collectGarbageForTerminatingThread() comment on why a
- // safepoint scope isn't entered for its GCScope.
- , m_safePointScope(stackState, gcType != ThreadState::ThreadTerminationGC ? state : nullptr)
- , m_gcType(gcType)
- , m_parkedAllThreads(false)
- {
- TRACE_EVENT0("blink_gc", "Heap::GCScope");
- const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
- if (m_state->isMainThread())
- TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting");
-
- ASSERT(m_state->checkThread());
-
- // TODO(haraken): In an unlikely coincidence that two threads decide
- // to collect garbage at the same time, avoid doing two GCs in
- // a row.
- if (LIKELY(gcType != ThreadState::ThreadTerminationGC && ThreadState::stopThreads()))
- m_parkedAllThreads = true;
-
- switch (gcType) {
- case ThreadState::GCWithSweep:
- case ThreadState::GCWithoutSweep:
- m_visitor = adoptPtr(new MarkingVisitor<Visitor::GlobalMarking>());
- break;
- case ThreadState::TakeSnapshot:
- m_visitor = adoptPtr(new MarkingVisitor<Visitor::SnapshotMarking>());
- break;
- case ThreadState::ThreadTerminationGC:
- m_visitor = adoptPtr(new MarkingVisitor<Visitor::ThreadLocalMarking>());
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-
- if (m_state->isMainThread())
- TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState);
- }
-
- bool allThreadsParked() const { return m_parkedAllThreads; }
- Visitor* visitor() const { return m_visitor.get(); }
-
- ~GCScope()
- {
- // Only cleanup if we parked all threads in which case the GC happened
- // and we need to resume the other threads.
- if (LIKELY(m_gcType != ThreadState::ThreadTerminationGC && m_parkedAllThreads))
- ThreadState::resumeThreads();
- }
-
-private:
- ThreadState* m_state;
- // The ordering of the two scope objects matters: GCs must first be forbidden
- // before entering the safe point scope. Prior to reaching the safe point,
- // ThreadState::runScheduledGC() is called. See its comment why we need
- // to be in a GC forbidden scope when doing so.
- GCForbiddenScope m_gcForbiddenScope;
- SafePointScope m_safePointScope;
- ThreadState::GCType m_gcType;
- OwnPtr<Visitor> m_visitor;
- bool m_parkedAllThreads; // False if we fail to park all threads
-};
-
#if ENABLE(ASSERT)
NO_SANITIZE_ADDRESS
void HeapObjectHeader::zapMagic()
@@ -1915,644 +1824,4 @@ void HeapDoesNotContainCache::addEntry(Address address)
m_entries[index] = cachePage;
}
-void Heap::flushHeapDoesNotContainCache()
-{
- s_heapDoesNotContainCache->flush();
-}
-
-void Heap::init()
-{
- ThreadState::init();
- s_markingStack = new CallbackStack();
- s_postMarkingCallbackStack = new CallbackStack();
- s_globalWeakCallbackStack = new CallbackStack();
- s_ephemeronStack = new CallbackStack();
- s_heapDoesNotContainCache = new HeapDoesNotContainCache();
- s_freePagePool = new FreePagePool();
- s_orphanedPagePool = new OrphanedPagePool();
- s_allocatedSpace = 0;
- s_allocatedObjectSize = 0;
- s_objectSizeAtLastGC = 0;
- s_markedObjectSize = 0;
- s_markedObjectSizeAtLastCompleteSweep = 0;
- s_persistentCount = 0;
- s_persistentCountAtLastGC = 0;
- s_collectedPersistentCount = 0;
- s_partitionAllocSizeAtLastGC = WTF::Partitions::totalSizeOfCommittedPages();
- s_estimatedMarkingTimePerByte = 0.0;
-
- GCInfoTable::init();
-
- if (Platform::current() && Platform::current()->currentThread())
- Platform::current()->registerMemoryDumpProvider(BlinkGCMemoryDumpProvider::instance());
-}
-
-void Heap::shutdown()
-{
- if (Platform::current() && Platform::current()->currentThread())
- Platform::current()->unregisterMemoryDumpProvider(BlinkGCMemoryDumpProvider::instance());
- s_shutdownCalled = true;
- ThreadState::shutdownHeapIfNecessary();
-}
-
-void Heap::doShutdown()
-{
- // We don't want to call doShutdown() twice.
- if (!s_markingStack)
- return;
-
- ASSERT(!ThreadState::attachedThreads().size());
- delete s_heapDoesNotContainCache;
- s_heapDoesNotContainCache = nullptr;
- delete s_freePagePool;
- s_freePagePool = nullptr;
- delete s_orphanedPagePool;
- s_orphanedPagePool = nullptr;
- delete s_globalWeakCallbackStack;
- s_globalWeakCallbackStack = nullptr;
- delete s_postMarkingCallbackStack;
- s_postMarkingCallbackStack = nullptr;
- delete s_markingStack;
- s_markingStack = nullptr;
- delete s_ephemeronStack;
- s_ephemeronStack = nullptr;
- delete s_regionTree;
- s_regionTree = nullptr;
- GCInfoTable::shutdown();
- ThreadState::shutdown();
- ASSERT(Heap::allocatedSpace() == 0);
-}
-
-#if ENABLE(ASSERT)
-BasePage* Heap::findPageFromAddress(Address address)
-{
- MutexLocker lock(ThreadState::threadAttachMutex());
- for (ThreadState* state : ThreadState::attachedThreads()) {
- if (BasePage* page = state->findPageFromAddress(address))
- return page;
- }
- return nullptr;
-}
-#endif
-
-Address Heap::checkAndMarkPointer(Visitor* visitor, Address address)
-{
- ASSERT(ThreadState::current()->isInGC());
-
-#if !ENABLE(ASSERT)
- if (s_heapDoesNotContainCache->lookup(address))
- return nullptr;
-#endif
-
- if (BasePage* page = lookup(address)) {
- ASSERT(page->contains(address));
- ASSERT(!page->orphaned());
- ASSERT(!s_heapDoesNotContainCache->lookup(address));
- page->checkAndMarkPointer(visitor, address);
- return address;
- }
-
-#if !ENABLE(ASSERT)
- s_heapDoesNotContainCache->addEntry(address);
-#else
- if (!s_heapDoesNotContainCache->lookup(address))
- s_heapDoesNotContainCache->addEntry(address);
-#endif
- return nullptr;
-}
-
-#if ENABLE(GC_PROFILING)
-const GCInfo* Heap::findGCInfo(Address address)
-{
- return ThreadState::findGCInfoFromAllThreads(address);
-}
-#endif
-
-#if ENABLE(GC_PROFILING)
-String Heap::createBacktraceString()
-{
- int framesToShow = 3;
- int stackFrameSize = 16;
- ASSERT(stackFrameSize >= framesToShow);
- using FramePointer = void*;
- FramePointer* stackFrame = static_cast<FramePointer*>(alloca(sizeof(FramePointer) * stackFrameSize));
- WTFGetBacktrace(stackFrame, &stackFrameSize);
-
- StringBuilder builder;
- builder.append("Persistent");
- bool didAppendFirstName = false;
- // Skip frames before/including "blink::Persistent".
- bool didSeePersistent = false;
- for (int i = 0; i < stackFrameSize && framesToShow > 0; ++i) {
- FrameToNameScope frameToName(stackFrame[i]);
- if (!frameToName.nullableName())
- continue;
- if (strstr(frameToName.nullableName(), "blink::Persistent")) {
- didSeePersistent = true;
- continue;
- }
- if (!didSeePersistent)
- continue;
- if (!didAppendFirstName) {
- didAppendFirstName = true;
- builder.append(" ... Backtrace:");
- }
- builder.append("\n\t");
- builder.append(frameToName.nullableName());
- --framesToShow;
- }
- return builder.toString().replace("blink::", "");
-}
-#endif
-
-void Heap::pushTraceCallback(void* object, TraceCallback callback)
-{
- ASSERT(ThreadState::current()->isInGC());
-
- // Trace should never reach an orphaned page.
- ASSERT(!Heap::orphanedPagePool()->contains(object));
- CallbackStack::Item* slot = s_markingStack->allocateEntry();
- *slot = CallbackStack::Item(object, callback);
-}
-
-bool Heap::popAndInvokeTraceCallback(Visitor* visitor)
-{
- CallbackStack::Item* item = s_markingStack->pop();
- if (!item)
- return false;
- item->call(visitor);
- return true;
-}
-
-void Heap::pushPostMarkingCallback(void* object, TraceCallback callback)
-{
- ASSERT(ThreadState::current()->isInGC());
-
- // Trace should never reach an orphaned page.
- ASSERT(!Heap::orphanedPagePool()->contains(object));
- CallbackStack::Item* slot = s_postMarkingCallbackStack->allocateEntry();
- *slot = CallbackStack::Item(object, callback);
-}
-
-bool Heap::popAndInvokePostMarkingCallback(Visitor* visitor)
-{
- if (CallbackStack::Item* item = s_postMarkingCallbackStack->pop()) {
- item->call(visitor);
- return true;
- }
- return false;
-}
-
-void Heap::pushGlobalWeakCallback(void** cell, WeakCallback callback)
-{
- ASSERT(ThreadState::current()->isInGC());
-
- // Trace should never reach an orphaned page.
- ASSERT(!Heap::orphanedPagePool()->contains(cell));
- CallbackStack::Item* slot = s_globalWeakCallbackStack->allocateEntry();
- *slot = CallbackStack::Item(cell, callback);
-}
-
-void Heap::pushThreadLocalWeakCallback(void* closure, void* object, WeakCallback callback)
-{
- ASSERT(ThreadState::current()->isInGC());
-
- // Trace should never reach an orphaned page.
- ASSERT(!Heap::orphanedPagePool()->contains(object));
- ThreadState* state = pageFromObject(object)->heap()->threadState();
- state->pushThreadLocalWeakCallback(closure, callback);
-}
-
-bool Heap::popAndInvokeGlobalWeakCallback(Visitor* visitor)
-{
- if (CallbackStack::Item* item = s_globalWeakCallbackStack->pop()) {
- item->call(visitor);
- return true;
- }
- return false;
-}
-
-void Heap::registerWeakTable(void* table, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
-{
- ASSERT(ThreadState::current()->isInGC());
-
- // Trace should never reach an orphaned page.
- ASSERT(!Heap::orphanedPagePool()->contains(table));
- CallbackStack::Item* slot = s_ephemeronStack->allocateEntry();
- *slot = CallbackStack::Item(table, iterationCallback);
-
- // Register a post-marking callback to tell the tables that
- // ephemeron iteration is complete.
- pushPostMarkingCallback(table, iterationDoneCallback);
-}
-
-#if ENABLE(ASSERT)
-bool Heap::weakTableRegistered(const void* table)
-{
- ASSERT(s_ephemeronStack);
- return s_ephemeronStack->hasCallbackForObject(table);
-}
-#endif
-
-void Heap::preGC()
-{
- ASSERT(!ThreadState::current()->isInGC());
- for (ThreadState* state : ThreadState::attachedThreads())
- state->preGC();
-}
-
-void Heap::postGC(ThreadState::GCType gcType)
-{
- ASSERT(ThreadState::current()->isInGC());
- for (ThreadState* state : ThreadState::attachedThreads())
- state->postGC(gcType);
-}
-
-const char* Heap::gcReasonString(GCReason reason)
-{
- switch (reason) {
-#define STRINGIFY_REASON(reason) case reason: return #reason;
- STRINGIFY_REASON(IdleGC);
- STRINGIFY_REASON(PreciseGC);
- STRINGIFY_REASON(ConservativeGC);
- STRINGIFY_REASON(ForcedGC);
-#undef STRINGIFY_REASON
- case NumberOfGCReason: ASSERT_NOT_REACHED();
- }
- return "<Unknown>";
-}
-
-void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCType gcType, GCReason reason)
-{
- ThreadState* state = ThreadState::current();
- // Nested collectGarbage() invocations aren't supported.
- RELEASE_ASSERT(!state->isGCForbidden());
- state->completeSweep();
-
- GCScope gcScope(state, stackState, gcType);
- // Check if we successfully parked the other threads. If not we bail out of
- // the GC.
- if (!gcScope.allThreadsParked())
- return;
-
- if (state->isMainThread())
- ScriptForbiddenScope::enter();
-
- TRACE_EVENT2("blink_gc", "Heap::collectGarbage",
- "lazySweeping", gcType == ThreadState::GCWithoutSweep,
- "gcReason", gcReasonString(reason));
- TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC");
- double timeStamp = WTF::currentTimeMS();
-
- if (gcType == ThreadState::TakeSnapshot)
- BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC();
-
- // Disallow allocation during garbage collection (but not during the
- // finalization that happens when the gcScope is torn down).
- ThreadState::NoAllocationScope noAllocationScope(state);
-
- preGC();
-
- StackFrameDepthScope stackDepthScope;
-
- size_t totalObjectSize = Heap::allocatedObjectSize() + Heap::markedObjectSize();
- if (gcType != ThreadState::TakeSnapshot)
- Heap::resetHeapCounters();
-
- // 1. Trace persistent roots.
- ThreadState::visitPersistentRoots(gcScope.visitor());
-
- // 2. Trace objects reachable from the stack. We do this independent of the
- // given stackState since other threads might have a different stack state.
- ThreadState::visitStackRoots(gcScope.visitor());
-
- // 3. Transitive closure to trace objects including ephemerons.
- processMarkingStack(gcScope.visitor());
-
- postMarkingProcessing(gcScope.visitor());
- globalWeakProcessing(gcScope.visitor());
-
- // Now we can delete all orphaned pages because there are no dangling
- // pointers to the orphaned pages. (If we have such dangling pointers,
- // we should have crashed during marking before getting here.)
- orphanedPagePool()->decommitOrphanedPages();
-
- double markingTimeInMilliseconds = WTF::currentTimeMS() - timeStamp;
- s_estimatedMarkingTimePerByte = totalObjectSize ? (markingTimeInMilliseconds / 1000 / totalObjectSize) : 0;
-
- Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", markingTimeInMilliseconds, 0, 10 * 1000, 50);
- Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", Heap::allocatedObjectSize() / 1024, 0, 4 * 1024 * 1024, 50);
- Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace", Heap::allocatedSpace() / 1024, 0, 4 * 1024 * 1024, 50);
- Platform::current()->histogramEnumeration("BlinkGC.GCReason", reason, NumberOfGCReason);
- Heap::reportMemoryUsageHistogram();
- WTF::Partitions::reportMemoryUsageHistogram();
-
- postGC(gcType);
-
- if (state->isMainThread())
- ScriptForbiddenScope::exit();
-}
-
-void Heap::collectGarbageForTerminatingThread(ThreadState* state)
-{
- {
- // A thread-specific termination GC must not allow other global GCs to go
- // ahead while it is running, hence the termination GC does not enter a
- // safepoint. GCScope will not enter also a safepoint scope for
- // ThreadTerminationGC.
- GCScope gcScope(state, ThreadState::NoHeapPointersOnStack, ThreadState::ThreadTerminationGC);
-
- ThreadState::NoAllocationScope noAllocationScope(state);
-
- state->preGC();
- StackFrameDepthScope stackDepthScope;
-
- // 1. Trace the thread local persistent roots. For thread local GCs we
- // don't trace the stack (ie. no conservative scanning) since this is
- // only called during thread shutdown where there should be no objects
- // on the stack.
- // We also assume that orphaned pages have no objects reachable from
- // persistent handles on other threads or CrossThreadPersistents. The
- // only cases where this could happen is if a subsequent conservative
- // global GC finds a "pointer" on the stack or due to a programming
- // error where an object has a dangling cross-thread pointer to an
- // object on this heap.
- state->visitPersistents(gcScope.visitor());
-
- // 2. Trace objects reachable from the thread's persistent roots
- // including ephemerons.
- processMarkingStack(gcScope.visitor());
-
- postMarkingProcessing(gcScope.visitor());
- globalWeakProcessing(gcScope.visitor());
-
- state->postGC(ThreadState::GCWithSweep);
- }
- state->preSweep();
-}
-
-void Heap::processMarkingStack(Visitor* visitor)
-{
- // Ephemeron fixed point loop.
- do {
- {
- // Iteratively mark all objects that are reachable from the objects
- // currently pushed onto the marking stack.
- TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded");
- while (popAndInvokeTraceCallback(visitor)) { }
- }
-
- {
- // Mark any strong pointers that have now become reachable in
- // ephemeron maps.
- TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack");
- s_ephemeronStack->invokeEphemeronCallbacks(visitor);
- }
-
- // Rerun loop if ephemeron processing queued more objects for tracing.
- } while (!s_markingStack->isEmpty());
-}
-
-void Heap::postMarkingProcessing(Visitor* visitor)
-{
- TRACE_EVENT0("blink_gc", "Heap::postMarkingProcessing");
- // Call post-marking callbacks including:
- // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup
- // (specifically to clear the queued bits for weak hash tables), and
- // 2. the markNoTracing callbacks on collection backings to mark them
- // if they are only reachable from their front objects.
- while (popAndInvokePostMarkingCallback(visitor)) { }
-
- s_ephemeronStack->clear();
-
- // Post-marking callbacks should not trace any objects and
- // therefore the marking stack should be empty after the
- // post-marking callbacks.
- ASSERT(s_markingStack->isEmpty());
-}
-
-void Heap::globalWeakProcessing(Visitor* visitor)
-{
- TRACE_EVENT0("blink_gc", "Heap::globalWeakProcessing");
- // Call weak callbacks on objects that may now be pointing to dead objects.
- while (popAndInvokeGlobalWeakCallback(visitor)) { }
-
- // It is not permitted to trace pointers of live objects in the weak
- // callback phase, so the marking stack should still be empty here.
- ASSERT(s_markingStack->isEmpty());
-}
-
-void Heap::collectAllGarbage()
-{
- // FIXME: Oilpan: we should perform a single GC and everything
- // should die. Unfortunately it is not the case for all objects
- // because the hierarchy was not completely moved to the heap and
- // some heap allocated objects own objects that contain persistents
- // pointing to other heap allocated objects.
- size_t previousLiveObjects = 0;
- for (int i = 0; i < 5; ++i) {
- collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWithSweep, ForcedGC);
- size_t liveObjects = Heap::markedObjectSize();
- if (liveObjects == previousLiveObjects)
- break;
- previousLiveObjects = liveObjects;
- }
-}
-
-double Heap::estimatedMarkingTime()
-{
- ASSERT(ThreadState::current()->isMainThread());
-
- // 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 (s_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 s_estimatedMarkingTimePerByte * (Heap::allocatedObjectSize() + Heap::markedObjectSize());
-}
-
-void Heap::reportMemoryUsageHistogram()
-{
- static size_t supportedMaxSizeInMB = 4 * 1024;
- static size_t observedMaxSizeInMB = 0;
-
- // We only report the memory in the main thread.
- if (!isMainThread())
- return;
- // +1 is for rounding up the sizeInMB.
- size_t sizeInMB = Heap::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 Heap::reportMemoryUsageForTracing()
-{
- 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(Heap::allocatedObjectSize() / 1024, static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::markedObjectSizeKB", std::min(Heap::markedObjectSize() / 1024, static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::markedObjectSizeAtLastCompleteSweepKB", std::min(Heap::markedObjectSizeAtLastCompleteSweep() / 1024, static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::allocatedSpaceKB", std::min(Heap::allocatedSpace() / 1024, static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::objectSizeAtLastGCKB", std::min(Heap::objectSizeAtLastGC() / 1024, static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::persistentCount", std::min(Heap::persistentCount(), static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::persistentCountAtLastGC", std::min(Heap::persistentCountAtLastGC(), static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::collectedPersistentCount", std::min(Heap::collectedPersistentCount(), static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1("blink_gc", "Heap::partitionAllocSizeAtLastGCKB", std::min(Heap::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)));
-}
-
-size_t Heap::objectPayloadSizeForTesting()
-{
- size_t objectPayloadSize = 0;
- for (ThreadState* state : ThreadState::attachedThreads()) {
- state->setGCState(ThreadState::GCRunning);
- state->makeConsistentForGC();
- objectPayloadSize += state->objectPayloadSizeForTesting();
- state->setGCState(ThreadState::EagerSweepScheduled);
- state->setGCState(ThreadState::Sweeping);
- state->setGCState(ThreadState::NoGCScheduled);
- }
- return objectPayloadSize;
-}
-
-BasePage* Heap::lookup(Address address)
-{
- ASSERT(ThreadState::current()->isInGC());
- if (!s_regionTree)
- return nullptr;
- if (PageMemoryRegion* region = s_regionTree->lookup(address)) {
- BasePage* page = region->pageFromAddress(address);
- return page && !page->orphaned() ? page : nullptr;
- }
- return nullptr;
-}
-
-static Mutex& regionTreeMutex()
-{
- AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
- return mutex;
-}
-
-void Heap::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(regionTreeMutex());
- RegionTree::remove(region, &s_regionTree);
-}
-
-void Heap::addPageMemoryRegion(PageMemoryRegion* region)
-{
- MutexLocker locker(regionTreeMutex());
- RegionTree::add(new RegionTree(region), &s_regionTree);
-}
-
-PageMemoryRegion* Heap::RegionTree::lookup(Address address)
-{
- RegionTree* current = s_regionTree;
- 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 Heap::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 Heap::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 Heap::resetHeapCounters()
-{
- ASSERT(ThreadState::current()->isInGC());
-
- Heap::reportMemoryUsageForTracing();
-
- s_objectSizeAtLastGC = s_allocatedObjectSize + s_markedObjectSize;
- s_partitionAllocSizeAtLastGC = WTF::Partitions::totalSizeOfCommittedPages();
- s_allocatedObjectSize = 0;
- s_markedObjectSize = 0;
- s_persistentCountAtLastGC = s_persistentCount;
- s_collectedPersistentCount = 0;
-}
-
-CallbackStack* Heap::s_markingStack;
-CallbackStack* Heap::s_postMarkingCallbackStack;
-CallbackStack* Heap::s_globalWeakCallbackStack;
-CallbackStack* Heap::s_ephemeronStack;
-HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache;
-bool Heap::s_shutdownCalled = false;
-FreePagePool* Heap::s_freePagePool;
-OrphanedPagePool* Heap::s_orphanedPagePool;
-Heap::RegionTree* Heap::s_regionTree = nullptr;
-size_t Heap::s_allocatedSpace = 0;
-size_t Heap::s_allocatedObjectSize = 0;
-size_t Heap::s_objectSizeAtLastGC = 0;
-size_t Heap::s_markedObjectSize = 0;
-size_t Heap::s_markedObjectSizeAtLastCompleteSweep = 0;
-size_t Heap::s_persistentCount = 0;
-size_t Heap::s_persistentCountAtLastGC = 0;
-size_t Heap::s_collectedPersistentCount = 0;
-size_t Heap::s_partitionAllocSizeAtLastGC = 0;
-double Heap::s_estimatedMarkingTimePerByte = 0.0;
-
} // namespace blink
« no previous file with comments | « Source/platform/heap/HeapPage.h ('k') | Source/platform/heap/blink_heap.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698