From f51fe5ac338f853b05c0c0a45cea0769304b5e67 Mon Sep 17 00:00:00 2001 From: "yurys@chromium.org" Date: Mon, 2 Jul 2012 07:04:41 +0000 Subject: [PATCH] Web Inspector: add v8 bindings memory info to the native memory graph https://bugs.webkit.org/show_bug.cgi?id=90149 Reviewed by Pavel Feldman. Size of V8 binding maps is now reported on the memory chart. * bindings/js/ScriptProfiler.h: (WebCore::ScriptProfiler::collectBindingMemoryInfo): * bindings/v8/DOMDataStore.cpp: (WebCore::DOMDataStore::reportMemoryUsage): (WebCore): * bindings/v8/DOMDataStore.h: (WebCore): (DOMDataStore): * bindings/v8/IntrusiveDOMWrapperMap.h: (WebCore::ChunkedTable::reportMemoryUsage): (ChunkedTable): * bindings/v8/ScriptProfiler.cpp: (WebCore::ScriptProfiler::collectBindingMemoryInfo): (WebCore): * bindings/v8/ScriptProfiler.h: (WebCore): (ScriptProfiler): * bindings/v8/V8Binding.cpp: (WebCore::V8BindingPerIsolateData::reportMemoryUsage): (WebCore): (WebCore::StringCache::reportMemoryUsage): * bindings/v8/V8Binding.h: (WebCore): (StringCache): (V8BindingPerIsolateData): * bindings/v8/V8DOMMap.h: (WebCore): (AbstractWeakReferenceMap): * dom/MemoryInstrumentation.h: (MemoryInstrumentation): (WebCore): (WebCore::MemoryInstrumentation::reportHashMap): added a method for reporting size of a HashMap. * inspector/InspectorMemoryAgent.cpp: (MemoryBlockName): (WebCore): (WebCore::domTreeInfo): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121658 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 47 ++++++++++++++++++++++ Source/WebCore/bindings/js/ScriptProfiler.h | 3 ++ Source/WebCore/bindings/v8/DOMDataStore.cpp | 10 +++++ Source/WebCore/bindings/v8/DOMDataStore.h | 3 ++ .../WebCore/bindings/v8/IntrusiveDOMWrapperMap.h | 13 ++++++ Source/WebCore/bindings/v8/ScriptProfiler.cpp | 9 +++++ Source/WebCore/bindings/v8/ScriptProfiler.h | 2 + Source/WebCore/bindings/v8/V8Binding.cpp | 15 +++++++ Source/WebCore/bindings/v8/V8Binding.h | 5 +++ Source/WebCore/bindings/v8/V8DOMMap.h | 10 +++++ Source/WebCore/dom/MemoryInstrumentation.h | 10 +++++ Source/WebCore/inspector/InspectorMemoryAgent.cpp | 9 +++++ 12 files changed, 136 insertions(+) diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index bb250c8..67835c6 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,50 @@ +2012-06-28 Yury Semikhatsky + + Web Inspector: add v8 bindings memory info to the native memory graph + https://bugs.webkit.org/show_bug.cgi?id=90149 + + Reviewed by Pavel Feldman. + + Size of V8 binding maps is now reported on the memory chart. + + * bindings/js/ScriptProfiler.h: + (WebCore::ScriptProfiler::collectBindingMemoryInfo): + * bindings/v8/DOMDataStore.cpp: + (WebCore::DOMDataStore::reportMemoryUsage): + (WebCore): + * bindings/v8/DOMDataStore.h: + (WebCore): + (DOMDataStore): + * bindings/v8/IntrusiveDOMWrapperMap.h: + (WebCore::ChunkedTable::reportMemoryUsage): + (ChunkedTable): + * bindings/v8/ScriptProfiler.cpp: + (WebCore::ScriptProfiler::collectBindingMemoryInfo): + (WebCore): + * bindings/v8/ScriptProfiler.h: + (WebCore): + (ScriptProfiler): + * bindings/v8/V8Binding.cpp: + (WebCore::V8BindingPerIsolateData::reportMemoryUsage): + (WebCore): + (WebCore::StringCache::reportMemoryUsage): + * bindings/v8/V8Binding.h: + (WebCore): + (StringCache): + (V8BindingPerIsolateData): + * bindings/v8/V8DOMMap.h: + (WebCore): + (AbstractWeakReferenceMap): + * dom/MemoryInstrumentation.h: + (MemoryInstrumentation): + (WebCore): + (WebCore::MemoryInstrumentation::reportHashMap): added a method for reporting + size of a HashMap. + * inspector/InspectorMemoryAgent.cpp: + (MemoryBlockName): + (WebCore): + (WebCore::domTreeInfo): + 2012-07-01 Christophe Dumez [EFL] Add Gamepad support diff --git a/Source/WebCore/bindings/js/ScriptProfiler.h b/Source/WebCore/bindings/js/ScriptProfiler.h index 5768535..782eac8 100644 --- a/Source/WebCore/bindings/js/ScriptProfiler.h +++ b/Source/WebCore/bindings/js/ScriptProfiler.h @@ -38,6 +38,7 @@ namespace WebCore { class ExternalArrayVisitor; class ExternalStringVisitor; +class MemoryInstrumentation; class NodeWrapperVisitor; class Page; class ScriptObject; @@ -75,8 +76,10 @@ public: static bool hasHeapProfiler() { return false; } // FIXME: Implement this counter for JSC. See bug 73936 for more details. static void visitNodeWrappers(NodeWrapperVisitor*) { } + // FIXME: Support these methods for JSC. See bug 90358. static void visitExternalStrings(ExternalStringVisitor*) { } static void visitExternalArrays(ExternalArrayVisitor*) { } + static void collectBindingMemoryInfo(MemoryInstrumentation*) { } static size_t profilerSnapshotsSize() { return 0; } }; diff --git a/Source/WebCore/bindings/v8/DOMDataStore.cpp b/Source/WebCore/bindings/v8/DOMDataStore.cpp index 2d5b5e6..dbca395 100644 --- a/Source/WebCore/bindings/v8/DOMDataStore.cpp +++ b/Source/WebCore/bindings/v8/DOMDataStore.cpp @@ -32,6 +32,7 @@ #include "DOMDataStore.h" #include "DOMData.h" +#include "MemoryInstrumentation.h" #include "V8Binding.h" #include @@ -118,6 +119,15 @@ void* DOMDataStore::getDOMWrapperMap(DOMWrapperMapType type) return 0; } +void DOMDataStore::reportMemoryUsage(MemoryInstrumentation* instrumentation) +{ + instrumentation->reportPointer(this, MemoryInstrumentation::Binding); + domNodeMap().reportMemoryUsage(instrumentation); + activeDomNodeMap().reportMemoryUsage(instrumentation); + domObjectMap().reportMemoryUsage(instrumentation); + activeDomObjectMap().reportMemoryUsage(instrumentation); +} + // Called when the object is near death (not reachable from JS roots). // It is time to remove the entry from the table and dispose the handle. void DOMDataStore::weakDOMObjectCallback(v8::Persistent v8Object, void* domObject) diff --git a/Source/WebCore/bindings/v8/DOMDataStore.h b/Source/WebCore/bindings/v8/DOMDataStore.h index 089d86d..b5bdfc3 100644 --- a/Source/WebCore/bindings/v8/DOMDataStore.h +++ b/Source/WebCore/bindings/v8/DOMDataStore.h @@ -47,6 +47,7 @@ namespace WebCore { class DOMData; class DOMDataStore; + class MemoryInstrumentation; typedef WTF::Vector DOMDataList; @@ -86,6 +87,8 @@ namespace WebCore { static void weakActiveDOMObjectCallback(v8::Persistent v8Object, void* domObject); static void weakNodeCallback(v8::Persistent v8Object, void* domObject); + void reportMemoryUsage(MemoryInstrumentation*); + protected: static void weakDOMObjectCallback(v8::Persistent v8Object, void* domObject); diff --git a/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h b/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h index 5c066f0..5d61668 100644 --- a/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h +++ b/Source/WebCore/bindings/v8/IntrusiveDOMWrapperMap.h @@ -32,6 +32,7 @@ #define IntrusiveDOMWrapperMap_h #include "DOMDataStore.h" +#include "MemoryInstrumentation.h" #include "V8Node.h" namespace WebCore { @@ -101,6 +102,12 @@ class ChunkedTable { visitEntries(store, chunk->m_entries, chunk->m_entries + CHUNK_SIZE, visitor); } + void reportMemoryUsage(MemoryInstrumentation* instrumentation) + { + for (Chunk* chunk = m_chunks; chunk; chunk = chunk->m_previous) + instrumentation->reportPointer(chunk, MemoryInstrumentation::Binding); + } + private: struct Chunk { explicit Chunk(Chunk* previous) : m_previous(previous) { } @@ -176,6 +183,12 @@ public: m_table.clear(); } + virtual void reportMemoryUsage(MemoryInstrumentation* instrumentation) OVERRIDE + { + instrumentation->reportPointer(this, MemoryInstrumentation::Binding); + m_table.reportMemoryUsage(instrumentation); + } + private: static int const numberOfEntries = (1 << 10) - 1; diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.cpp b/Source/WebCore/bindings/v8/ScriptProfiler.cpp index 57bb808..8d6c502 100644 --- a/Source/WebCore/bindings/v8/ScriptProfiler.cpp +++ b/Source/WebCore/bindings/v8/ScriptProfiler.cpp @@ -33,6 +33,7 @@ #include "ScriptProfiler.h" #include "BindingVisitors.h" +#include "MemoryInstrumentation.h" #include "RetainedDOMInfo.h" #include "ScriptObject.h" #include "V8ArrayBufferView.h" @@ -219,6 +220,14 @@ void ScriptProfiler::visitExternalArrays(ExternalArrayVisitor* visitor) } +void ScriptProfiler::collectBindingMemoryInfo(MemoryInstrumentation* instrumentation) +{ + V8BindingPerIsolateData* data = V8BindingPerIsolateData::current(); + if (!data) + return; + data->reportMemoryUsage(instrumentation); +} + size_t ScriptProfiler::profilerSnapshotsSize() { return v8::HeapProfiler::GetMemorySizeUsedByProfiler(); diff --git a/Source/WebCore/bindings/v8/ScriptProfiler.h b/Source/WebCore/bindings/v8/ScriptProfiler.h index 25f6e12..7ffa50d 100644 --- a/Source/WebCore/bindings/v8/ScriptProfiler.h +++ b/Source/WebCore/bindings/v8/ScriptProfiler.h @@ -42,6 +42,7 @@ namespace WebCore { class ExternalArrayVisitor; class ExternalStringVisitor; +class MemoryInstrumentation; class NodeWrapperVisitor; class Page; class ScriptObject; @@ -81,6 +82,7 @@ public: static void visitNodeWrappers(NodeWrapperVisitor*); static void visitExternalStrings(ExternalStringVisitor*); static void visitExternalArrays(ExternalArrayVisitor*); + static void collectBindingMemoryInfo(MemoryInstrumentation*); static size_t profilerSnapshotsSize(); }; diff --git a/Source/WebCore/bindings/v8/V8Binding.cpp b/Source/WebCore/bindings/v8/V8Binding.cpp index aca0bb3..c29bcf8 100644 --- a/Source/WebCore/bindings/v8/V8Binding.cpp +++ b/Source/WebCore/bindings/v8/V8Binding.cpp @@ -34,6 +34,7 @@ #include "BindingVisitors.h" #include "DOMStringList.h" #include "Element.h" +#include "MemoryInstrumentation.h" #include "PlatformString.h" #include "QualifiedName.h" #include "V8DOMStringList.h" @@ -89,7 +90,16 @@ void V8BindingPerIsolateData::dispose(v8::Isolate* isolate) isolate->SetData(0); } +void V8BindingPerIsolateData::reportMemoryUsage(MemoryInstrumentation* instrumentation) +{ + instrumentation->reportPointer(this, MemoryInstrumentation::Binding); + instrumentation->reportHashMap(m_rawTemplates, MemoryInstrumentation::Binding); + instrumentation->reportHashMap(m_templates, MemoryInstrumentation::Binding); + m_stringCache.reportMemoryUsage(instrumentation); + for (size_t i = 0; i < m_domDataList.size(); i++) + m_domDataList[i]->reportMemoryUsage(instrumentation); +} // WebCoreStringResource is a helper class for v8ExternalString. It is used // to manage the life-cycle of the underlying buffer of the external string. @@ -576,6 +586,11 @@ v8::Persistent getToStringTemplate() toStringTemplate = v8::Persistent::New(v8::FunctionTemplate::New(constructorToString)); return toStringTemplate; } + +void StringCache::reportMemoryUsage(MemoryInstrumentation* instrumentation) +{ + instrumentation->reportHashMap(m_stringCache, MemoryInstrumentation::Binding); +} PassRefPtr v8ValueToWebCoreDOMStringList(v8::Handle value) { diff --git a/Source/WebCore/bindings/v8/V8Binding.h b/Source/WebCore/bindings/v8/V8Binding.h index 07c6615..4e45f7b 100644 --- a/Source/WebCore/bindings/v8/V8Binding.h +++ b/Source/WebCore/bindings/v8/V8Binding.h @@ -49,6 +49,7 @@ namespace WebCore { class EventListener; class EventTarget; class ExternalStringVisitor; + class MemoryInstrumentation; // FIXME: Remove V8Binding. class V8Binding { @@ -78,6 +79,8 @@ namespace WebCore { void remove(StringImpl*); + void reportMemoryUsage(MemoryInstrumentation*); + private: v8::Local v8ExternalStringSlow(StringImpl*, v8::Isolate*); @@ -214,6 +217,8 @@ namespace WebCore { GCEventData& gcEventData() { return m_gcEventData; } + void reportMemoryUsage(MemoryInstrumentation*); + private: explicit V8BindingPerIsolateData(v8::Isolate*); ~V8BindingPerIsolateData(); diff --git a/Source/WebCore/bindings/v8/V8DOMMap.h b/Source/WebCore/bindings/v8/V8DOMMap.h index bc51540..531d07d 100644 --- a/Source/WebCore/bindings/v8/V8DOMMap.h +++ b/Source/WebCore/bindings/v8/V8DOMMap.h @@ -31,6 +31,7 @@ #ifndef V8DOMMap_h #define V8DOMMap_h +#include "MemoryInstrumentation.h" #include #include #include @@ -38,6 +39,7 @@ namespace WebCore { class DOMDataStore; class Node; + class MemoryInstrumentation; template class AbstractWeakReferenceMap { public: @@ -61,6 +63,9 @@ namespace WebCore { virtual void clear() = 0; v8::WeakReferenceCallback weakReferenceCallback() { return m_weakReferenceCallback; } + + virtual void reportMemoryUsage(MemoryInstrumentation*) = 0; + private: v8::WeakReferenceCallback m_weakReferenceCallback; }; @@ -129,6 +134,11 @@ namespace WebCore { visitor->endMap(); } + virtual void reportMemoryUsage(MemoryInstrumentation* instrumentation) OVERRIDE + { + instrumentation->reportHashMap(m_map, MemoryInstrumentation::Binding); + } + protected: HashMap m_map; }; diff --git a/Source/WebCore/dom/MemoryInstrumentation.h b/Source/WebCore/dom/MemoryInstrumentation.h index 99fe46a..b81f5be 100644 --- a/Source/WebCore/dom/MemoryInstrumentation.h +++ b/Source/WebCore/dom/MemoryInstrumentation.h @@ -47,6 +47,7 @@ public: Other, DOM, CSS, + Binding, LastTypeEntry }; @@ -59,6 +60,7 @@ public: return; countObjectSize(objectType, sizeof(T)); } + template void reportHashMap(const HashMapType&, ObjectType); private: friend class MemoryObjectInfo; @@ -139,6 +141,14 @@ void MemoryInstrumentation::reportInstrumentedObject(const T& object) object.reportMemoryUsage(&memoryObjectInfo); } + +template +void MemoryInstrumentation::reportHashMap(const HashMapType& hashMap, ObjectType objectType) +{ + size_t size = sizeof(HashMapType) + hashMap.capacity() * sizeof(typename HashMapType::ValueType); + countObjectSize(objectType, size); +} + } // namespace WebCore #endif // !defined(MemoryInstrumentation_h) diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp index 0e25d70..b5fd836 100644 --- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp +++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp @@ -90,6 +90,7 @@ static const char dom[] = "DOM"; static const char domTreeOther[] = "DOMTreeOther"; static const char domTreeDOM[] = "DOMTreeDOM"; static const char domTreeCSS[] = "DOMTreeCSS"; +static const char domTreeBinding[] = "DOMTreeBinding"; } namespace { @@ -447,6 +448,7 @@ public: addMemoryBlockFor(domChildren.get(), m_totalSizes[Other], MemoryBlockName::domTreeOther); addMemoryBlockFor(domChildren.get(), m_totalSizes[DOM], MemoryBlockName::domTreeDOM); addMemoryBlockFor(domChildren.get(), m_totalSizes[CSS], MemoryBlockName::domTreeCSS); + addMemoryBlockFor(domChildren.get(), m_totalSizes[Binding], MemoryBlockName::domTreeBinding); RefPtr dom = InspectorMemoryBlock::create().setName(MemoryBlockName::dom); dom->setSize(totalSize); @@ -492,6 +494,11 @@ public: m_domMemoryUsage.reportInstrumentedPointer(node); } + void visitBindings() + { + ScriptProfiler::collectBindingMemoryInfo(&m_domMemoryUsage); + } + PassRefPtr dumpStatistics() { return m_domMemoryUsage.dumpStatistics(); } private: @@ -512,6 +519,8 @@ static PassRefPtr domTreeInfo(Page* page, VisitedObjects& domTreesIterator.visitNode(doc); } + domTreesIterator.visitBindings(); + return domTreesIterator.dumpStatistics(); } -- 2.7.4