Index: third_party/WebKit/Source/platform/heap/Heap.cpp |
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp |
index bd3819fcb15931f2ec700d1170fef52f838932fb..2caa5131e65772fe009a04e9c2696f25c6723282 100644 |
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp |
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp |
@@ -469,6 +469,162 @@ |
state->postGC(gcType); |
} |
+const char* ThreadHeap::gcReasonString(BlinkGC::GCReason reason) |
+{ |
+ switch (reason) { |
+ case BlinkGC::IdleGC: |
+ return "IdleGC"; |
+ case BlinkGC::PreciseGC: |
+ return "PreciseGC"; |
+ case BlinkGC::ConservativeGC: |
+ return "ConservativeGC"; |
+ case BlinkGC::ForcedGC: |
+ return "ForcedGC"; |
+ case BlinkGC::MemoryPressureGC: |
+ return "MemoryPressureGC"; |
+ case BlinkGC::PageNavigationGC: |
+ return "PageNavigationGC"; |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ } |
+ return "<Unknown>"; |
+} |
+ |
+void ThreadHeap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType gcType, BlinkGC::GCReason reason) |
+{ |
+ ASSERT(gcType != BlinkGC::ThreadTerminationGC); |
+ |
+ ThreadState* state = ThreadState::current(); |
+ // Nested collectGarbage() invocations aren't supported. |
+ RELEASE_ASSERT(!state->isGCForbidden()); |
+ state->completeSweep(); |
+ |
+ std::unique_ptr<Visitor> visitor = Visitor::create(state, gcType); |
+ |
+ SafePointScope safePointScope(stackState, state); |
+ |
+ // Resume all parked threads upon leaving this scope. |
+ ParkThreadsScope parkThreadsScope(state); |
+ |
+ // Try to park the other threads. If we're unable to, bail out of the GC. |
+ if (!parkThreadsScope.parkThreads()) |
+ return; |
+ |
+ ScriptForbiddenIfMainThreadScope scriptForbidden; |
+ |
+ TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", |
+ "lazySweeping", gcType == BlinkGC::GCWithoutSweep, |
+ "gcReason", gcReasonString(reason)); |
+ TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); |
+ double startTime = WTF::currentTimeMS(); |
+ |
+ if (gcType == BlinkGC::TakeSnapshot) |
+ BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); |
+ |
+ // Disallow allocation during garbage collection (but not during the |
+ // finalization that happens when the visitorScope is torn down). |
+ ThreadState::NoAllocationScope noAllocationScope(state); |
+ |
+ state->heap().commitCallbackStacks(); |
+ state->heap().preGC(); |
+ |
+ StackFrameDepthScope stackDepthScope(&state->heap().stackFrameDepth()); |
+ |
+ size_t totalObjectSize = state->heap().heapStats().allocatedObjectSize() + state->heap().heapStats().markedObjectSize(); |
+ if (gcType != BlinkGC::TakeSnapshot) |
+ state->heap().resetHeapCounters(); |
+ |
+ { |
+ // Access to the CrossThreadPersistentRegion has to be prevented while |
+ // marking and global weak processing is in progress. If not, threads |
+ // not attached to Oilpan and participating in this GC are able |
+ // to allocate & free PersistentNodes, something the marking phase isn't |
+ // capable of handling. |
+ CrossThreadPersistentRegion::LockScope persistentLock(ProcessHeap::crossThreadPersistentRegion()); |
+ |
+ // 1. Trace persistent roots. |
+ state->heap().visitPersistentRoots(visitor.get()); |
+ |
+ // 2. Trace objects reachable from the stack. We do this independent of the |
+ // given stackState since other threads might have a different stack state. |
+ state->heap().visitStackRoots(visitor.get()); |
+ |
+ // 3. Transitive closure to trace objects including ephemerons. |
+ state->heap().processMarkingStack(visitor.get()); |
+ |
+ state->heap().postMarkingProcessing(visitor.get()); |
+ state->heap().globalWeakProcessing(visitor.get()); |
+ } |
+ |
+ // 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.) |
+ state->heap().getOrphanedPagePool()->decommitOrphanedPages(); |
+ |
+ double markingTimeInMilliseconds = WTF::currentTimeMS() - startTime; |
+ state->heap().heapStats().setEstimatedMarkingTimePerByte(totalObjectSize ? (markingTimeInMilliseconds / 1000 / totalObjectSize) : 0); |
+ |
+#if PRINT_HEAP_STATS |
+ dataLogF("ThreadHeap::collectGarbage (gcReason=%s, lazySweeping=%d, time=%.1lfms)\n", gcReasonString(reason), gcType == BlinkGC::GCWithoutSweep, markingTimeInMilliseconds); |
+#endif |
+ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, markingTimeHistogram, new CustomCountHistogram("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); |
+ markingTimeHistogram.count(markingTimeInMilliseconds); |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalObjectSpaceHistogram, new CustomCountHistogram("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50)); |
+ totalObjectSpaceHistogram.count(ProcessHeap::totalAllocatedObjectSize() / 1024); |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalAllocatedSpaceHistogram, new CustomCountHistogram("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 1024, 50)); |
+ totalAllocatedSpaceHistogram.count(ProcessHeap::totalAllocatedSpace() / 1024); |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, gcReasonHistogram, new EnumerationHistogram("BlinkGC.GCReason", BlinkGC::NumberOfGCReason)); |
+ gcReasonHistogram.count(reason); |
+ |
+ state->heap().m_lastGCReason = reason; |
+ |
+ ThreadHeap::reportMemoryUsageHistogram(); |
+ WTF::Partitions::reportMemoryUsageHistogram(); |
+ |
+ state->heap().postGC(gcType); |
+ state->heap().decommitCallbackStacks(); |
+} |
+ |
+void ThreadHeap::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. VisitorScope will not enter also a safepoint scope for |
+ // ThreadTerminationGC. |
+ std::unique_ptr<Visitor> visitor = Visitor::create(state, BlinkGC::ThreadTerminationGC); |
+ |
+ ThreadState::NoAllocationScope noAllocationScope(state); |
+ |
+ state->heap().commitCallbackStacks(); |
+ state->preGC(); |
+ |
+ // 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(visitor.get()); |
+ |
+ // 2. Trace objects reachable from the thread's persistent roots |
+ // including ephemerons. |
+ state->heap().processMarkingStack(visitor.get()); |
+ |
+ state->heap().postMarkingProcessing(visitor.get()); |
+ state->heap().globalWeakProcessing(visitor.get()); |
+ |
+ state->postGC(BlinkGC::GCWithSweep); |
+ state->heap().decommitCallbackStacks(); |
+ } |
+ state->preSweep(); |
+} |
+ |
void ThreadHeap::processMarkingStack(Visitor* visitor) |
{ |
// Ephemeron fixed point loop. |
@@ -522,6 +678,20 @@ |
double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; |
DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogram, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000, 50)); |
globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); |
+} |
+ |
+void ThreadHeap::collectAllGarbage() |
+{ |
+ // We need to run multiple GCs to collect a chain of persistent handles. |
+ size_t previousLiveObjects = 0; |
+ ThreadState* state = ThreadState::current(); |
+ for (int i = 0; i < 5; ++i) { |
+ collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::ForcedGC); |
+ size_t liveObjects = state->heap().heapStats().markedObjectSize(); |
+ if (liveObjects == previousLiveObjects) |
+ break; |
+ previousLiveObjects = liveObjects; |
+ } |
} |
void ThreadHeap::reportMemoryUsageHistogram() |