diff options
Diffstat (limited to 'Source/web/WebLeakDetector.cpp')
-rw-r--r-- | Source/web/WebLeakDetector.cpp | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/Source/web/WebLeakDetector.cpp b/Source/web/WebLeakDetector.cpp index 3ab45bee4..33f11d9ca 100644 --- a/Source/web/WebLeakDetector.cpp +++ b/Source/web/WebLeakDetector.cpp @@ -33,55 +33,101 @@ #include "public/web/WebLeakDetector.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8GCController.h" #include "core/fetch/MemoryCache.h" #include "core/fetch/ResourceFetcher.h" -#include "core/frame/DOMWindow.h" #include "core/inspector/InspectorCounters.h" +#include "platform/Timer.h" #include "public/web/WebDocument.h" -#include "public/web/WebFrame.h" +#include "public/web/WebLocalFrame.h" #include <v8.h> using namespace WebCore; +namespace blink { + namespace { -void cleanUpDOMObjects(blink::WebFrame* frame) +// FIXME: Oilpan: It may take multiple GC to collect on-heap objects referenced from off-heap objects. +// Please see comment in Heap::collectAllGarbage() +static const int kNumberOfGCsToClaimChains = 5; + +class WebLeakDetectorImpl FINAL : public WebLeakDetector { +WTF_MAKE_NONCOPYABLE(WebLeakDetectorImpl); +public: + explicit WebLeakDetectorImpl(WebLeakDetectorClient* client) + : m_client(client) + , m_delayedGCAndReportTimer(this, &WebLeakDetectorImpl::delayedGCAndReport) + , m_delayedReportTimer(this, &WebLeakDetectorImpl::delayedReport) + { + ASSERT(m_client); + } + + virtual ~WebLeakDetectorImpl() { } + + virtual void collectGarbageAndGetDOMCounts(WebLocalFrame*) OVERRIDE; + +private: + void delayedGCAndReport(Timer<WebLeakDetectorImpl>*); + void delayedReport(Timer<WebLeakDetectorImpl>*); + + WebLeakDetectorClient* m_client; + Timer<WebLeakDetectorImpl> m_delayedGCAndReportTimer; + Timer<WebLeakDetectorImpl> m_delayedReportTimer; +}; + +void WebLeakDetectorImpl::collectGarbageAndGetDOMCounts(WebLocalFrame* frame) { - v8::HandleScope handleScope(v8::Isolate::GetCurrent()); - v8::Local<v8::Context> context(frame->mainWorldScriptContext()); - v8::Context::Scope contextScope(context); + memoryCache()->evictResources(); + + { + RefPtr<Document> document = PassRefPtr<Document>(frame->document()); + if (ResourceFetcher* fetcher = document->fetcher()) + fetcher->garbageCollectDocumentResources(); + } // FIXME: HTML5 Notification should be closed because notification affects the result of number of DOM objects. - ResourceFetcher* fetcher = currentDOMWindow(context->GetIsolate())->document()->fetcher(); - if (fetcher) - fetcher->garbageCollectDocumentResources(); + for (int i = 0; i < kNumberOfGCsToClaimChains; ++i) + V8GCController::collectGarbage(v8::Isolate::GetCurrent()); + // Note: Oilpan precise GC is scheduled at the end of the event loop. - memoryCache()->evictResources(); + // Task queue may contain delayed object destruction tasks. + // This method is called from navigation hook inside FrameLoader, + // so previous document is still held by the loader until the next event loop. + // Complete all pending tasks before proceeding to gc. + m_delayedGCAndReportTimer.startOneShot(0, FROM_HERE); +} + +void WebLeakDetectorImpl::delayedGCAndReport(Timer<WebLeakDetectorImpl>*) +{ + // We do a second GC here to address flakiness: Resource GC may have postponed clean-up tasks to next event loop. - v8::V8::LowMemoryNotification(); + for (int i = 0; i < kNumberOfGCsToClaimChains; ++i) + V8GCController::collectGarbage(V8PerIsolateData::mainThreadIsolate()); + // Note: Oilpan precise GC is scheduled at the end of the event loop. + + // Inspect counters on the next event loop. + m_delayedReportTimer.startOneShot(0, FROM_HERE); } -void numberOfDOMObjects(blink::WebFrame *frame, unsigned* numberOfLiveDocuments, unsigned* numberOfLiveNodes) +void WebLeakDetectorImpl::delayedReport(Timer<WebLeakDetectorImpl>*) { - v8::HandleScope handleScope(v8::Isolate::GetCurrent()); - v8::Local<v8::Context> context(frame->mainWorldScriptContext()); - v8::Context::Scope contextScope(context); + ASSERT(m_client); + + WebLeakDetectorClient::Result result; + result.numberOfLiveDocuments = InspectorCounters::counterValue(InspectorCounters::DocumentCounter); + result.numberOfLiveNodes = InspectorCounters::counterValue(InspectorCounters::NodeCounter); - *numberOfLiveDocuments = InspectorCounters::counterValue(InspectorCounters::DocumentCounter); - *numberOfLiveNodes = InspectorCounters::counterValue(InspectorCounters::NodeCounter); + m_client->onLeakDetectionComplete(result); } } // namespace -namespace blink { - -void WebLeakDetector::collectGarbargeAndGetDOMCounts(WebLocalFrame* frame, unsigned* numberOfLiveDocuments, unsigned* numberOfLiveNodes) +WebLeakDetector* WebLeakDetector::create(WebLeakDetectorClient* client) { - // FIXME: Count other DOM objects using WTF::dumpRefCountedInstanceCounts. - cleanUpDOMObjects(frame); - numberOfDOMObjects(frame, numberOfLiveDocuments, numberOfLiveNodes); + return new WebLeakDetectorImpl(client); } } // namespace blink |