Web Inspector: partially instrument DOM Tree native memory.
authorloislo@chromium.org <loislo@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 14:08:05 +0000 (14:08 +0000)
committerloislo@chromium.org <loislo@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 22 Jun 2012 14:08:05 +0000 (14:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=89568

PerformanceTests:

This patch adds MemoryInstrumentation class that counts all visited
objects and calls reportMemoryUsage.

Reviewed by Yury Semikhatsky.

* inspector/native-memory-snapshot.html:

Source/WebCore:

This patch adds MemoryInstrumentation class that counts all visited
objects and calls reportMemoryUsage for the instrumented classes.

Reviewed by Yury Semikhatsky.

* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ScriptWrappable.h:
(WebCore::ScriptWrappable::reportMemoryUsage):
(ScriptWrappable):
* bindings/v8/ScriptWrappable.h:
(WebCore::ScriptWrappable::reportMemoryUsage):
(ScriptWrappable):
* css/StylePropertySet.h:
(WebCore::StylePropertySet::reportMemoryUsage):
(StylePropertySet):
* dom/ContainerNode.h:
(WebCore::ContainerNode::reportMemoryUsage):
(ContainerNode):
* dom/Element.h:
(WebCore::Element::reportMemoryUsage):
(Element):
* dom/ElementAttributeData.h:
(WebCore::ElementAttributeData::reportMemoryUsage):
(ElementAttributeData):
* dom/MemoryInstrumentation.h: Added.
(WebCore):
(MemoryInstrumentation):
(WebCore::MemoryInstrumentation::~MemoryInstrumentation):
(WebCore::MemoryInstrumentation::reportObject):
(WebCore::MemoryInstrumentation::reportPointer):
(MemoryObjectInfo):
(WebCore::MemoryObjectInfo::MemoryObjectInfo):
(WebCore::MemoryObjectInfo::reportInstrumentedPointer):
(WebCore::MemoryObjectInfo::reportPointer):
(WebCore::MemoryObjectInfo::reportInstrumentedObject):
(WebCore::MemoryObjectInfo::reportObject):
(WebCore::MemoryObjectInfo::reportObjectInfo):
(WebCore::MemoryObjectInfo::objectType):
(WebCore::MemoryObjectInfo::objectSize):
(WebCore::MemoryInstrumentation::reportInstrumentedPointer):
(WebCore::MemoryInstrumentation::reportInstrumentedObject):
* dom/Node.cpp:
(WebCore::Node::reportMemoryUsage):
(WebCore):
* dom/Node.h:
(Node):
* dom/QualifiedName.h:
(WebCore::QualifiedName::QualifiedNameImpl::reportMemoryUsage):
(WebCore::QualifiedName::reportMemoryUsage):
* inspector/InspectorMemoryAgent.cpp:
(MemoryBlockName):
(WebCore):
(WebCore::addMemoryBlockFor):
(WebCore::domTreeInfo):
(WebCore::memoryCacheInfo):
(WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
* platform/TreeShared.h:
(WebCore::TreeShared::reportMemoryUsage):
(TreeShared):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121022 268f45cc-cd09-0410-ab3c-d52691b4dbfc

20 files changed:
PerformanceTests/ChangeLog
PerformanceTests/inspector/native-memory-snapshot.html
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/ScriptWrappable.h
Source/WebCore/bindings/v8/ScriptWrappable.h
Source/WebCore/css/StylePropertySet.h
Source/WebCore/dom/ContainerNode.h
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementAttributeData.h
Source/WebCore/dom/MemoryInstrumentation.h [new file with mode: 0644]
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/QualifiedName.h
Source/WebCore/inspector/InspectorMemoryAgent.cpp
Source/WebCore/platform/TreeShared.h

index df58794..6a172ec 100644 (file)
@@ -1,3 +1,15 @@
+2012-06-22  Ilya Tikhonovsky  <loislo@chromium.org>
+
+        Web Inspector: partially instrument DOM Tree native memory.
+        https://bugs.webkit.org/show_bug.cgi?id=89568
+
+        This patch adds MemoryInstrumentation class that counts all visited
+        objects and calls reportMemoryUsage.
+
+        Reviewed by Yury Semikhatsky.
+
+        * inspector/native-memory-snapshot.html:
+
 2012-06-21  Kentaro Hara  <haraken@chromium.org>
 
         Add a perf-test for innerHTML setter for a large DOM tree
index 2ae05ba..38653a7 100644 (file)
@@ -1,5 +1,17 @@
 <html>
 <head>
+  <style type="text/css">
+    span {
+      color:red;
+      width: 100px;
+      height: 20px;
+    }
+    div {
+      color:blue;
+      width: 50px;
+      height: 10px;
+    }
+  </style>
   <script src="../../LayoutTests/http/tests/inspector/inspector-test.js"></script>
   <script src="performance-test.js"></script>
 <script>
@@ -39,8 +51,12 @@ function createDOMTree(elementsCount)
 {
     var root = document.getElementById("testTreeRoot");
 
-    for (var i = 0; i < elementsCount; ++i)
-        root.appendChild(document.createElement("span"));
+    for (var i = 0; i < elementsCount; ++i) {
+        var span = document.createElement("span");
+        span.id = "span_" + i;
+        span.style.width = "10px";
+        root.appendChild(span);
+    }
 
     for (var i = 0; i < elementsCount; ++i)
         root.appendChild(document.createElement("div"));
index 95d28c7..f614519 100644 (file)
@@ -1,3 +1,72 @@
+2012-06-22  Ilya Tikhonovsky  <loislo@chromium.org>
+
+        Web Inspector: partially instrument DOM Tree native memory.
+        https://bugs.webkit.org/show_bug.cgi?id=89568
+
+        This patch adds MemoryInstrumentation class that counts all visited
+        objects and calls reportMemoryUsage for the instrumented classes.
+
+        Reviewed by Yury Semikhatsky.
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/ScriptWrappable.h:
+        (WebCore::ScriptWrappable::reportMemoryUsage):
+        (ScriptWrappable):
+        * bindings/v8/ScriptWrappable.h:
+        (WebCore::ScriptWrappable::reportMemoryUsage):
+        (ScriptWrappable):
+        * css/StylePropertySet.h:
+        (WebCore::StylePropertySet::reportMemoryUsage):
+        (StylePropertySet):
+        * dom/ContainerNode.h:
+        (WebCore::ContainerNode::reportMemoryUsage):
+        (ContainerNode):
+        * dom/Element.h:
+        (WebCore::Element::reportMemoryUsage):
+        (Element):
+        * dom/ElementAttributeData.h:
+        (WebCore::ElementAttributeData::reportMemoryUsage):
+        (ElementAttributeData):
+        * dom/MemoryInstrumentation.h: Added.
+        (WebCore):
+        (MemoryInstrumentation):
+        (WebCore::MemoryInstrumentation::~MemoryInstrumentation):
+        (WebCore::MemoryInstrumentation::reportObject):
+        (WebCore::MemoryInstrumentation::reportPointer):
+        (MemoryObjectInfo):
+        (WebCore::MemoryObjectInfo::MemoryObjectInfo):
+        (WebCore::MemoryObjectInfo::reportInstrumentedPointer):
+        (WebCore::MemoryObjectInfo::reportPointer):
+        (WebCore::MemoryObjectInfo::reportInstrumentedObject):
+        (WebCore::MemoryObjectInfo::reportObject):
+        (WebCore::MemoryObjectInfo::reportObjectInfo):
+        (WebCore::MemoryObjectInfo::objectType):
+        (WebCore::MemoryObjectInfo::objectSize):
+        (WebCore::MemoryInstrumentation::reportInstrumentedPointer):
+        (WebCore::MemoryInstrumentation::reportInstrumentedObject):
+        * dom/Node.cpp:
+        (WebCore::Node::reportMemoryUsage):
+        (WebCore):
+        * dom/Node.h:
+        (Node):
+        * dom/QualifiedName.h:
+        (WebCore::QualifiedName::QualifiedNameImpl::reportMemoryUsage):
+        (WebCore::QualifiedName::reportMemoryUsage):
+        * inspector/InspectorMemoryAgent.cpp:
+        (MemoryBlockName):
+        (WebCore):
+        (WebCore::addMemoryBlockFor):
+        (WebCore::domTreeInfo):
+        (WebCore::memoryCacheInfo):
+        (WebCore::InspectorMemoryAgent::getProcessMemoryDistribution):
+        * platform/TreeShared.h:
+        (WebCore::TreeShared::reportMemoryUsage):
+        (TreeShared):
+
 2012-06-22  Peter Rybin  <peter.rybin@gmail.com>
 
         Web Inspector: Support 'Restart frame' in inspector frontend
index 759e935..1ba1a6d 100644 (file)
@@ -1907,6 +1907,7 @@ webcore_sources += \
        Source/WebCore/dom/HashChangeEvent.h \
        Source/WebCore/dom/KeyboardEvent.cpp \
        Source/WebCore/dom/KeyboardEvent.h \
+       Source/WebCore/dom/MemoryInstrumentation.h \
        Source/WebCore/dom/MessageChannel.cpp \
        Source/WebCore/dom/MessageChannel.h \
        Source/WebCore/dom/MessageEvent.cpp \
index 1d6cf48..47d5230 100644 (file)
@@ -1745,6 +1745,7 @@ HEADERS += \
     dom/ExceptionCode.h \
     dom/FragmentScriptingPermission.h \
     dom/KeyboardEvent.h \
+    dom/MemoryInstrumentation.h \
     dom/MessageChannel.h \
     dom/MessageEvent.h \
     dom/MessagePortChannel.h \
index 8ae0e0c..5a03f9c 100644 (file)
             'dom/IconURL.cpp',
             'dom/IconURL.h',
             'dom/KeyboardEvent.cpp',
+            'dom/MemoryInstrumentation.h',
             'dom/MessageChannel.cpp',
             'dom/MessageChannel.h',
             'dom/MessageEvent.cpp',
index 3ef8f43..bc34b52 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\dom\MemoryInstrumentation.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\dom\MessageChannel.cpp"
                                >
                                <FileConfiguration
index 9efbe64..db6d8ac 100644 (file)
                4F1534DE11B532EC0021FD86 /* EditingBehavior.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F1534DD11B532EC0021FD86 /* EditingBehavior.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4F1534E011B533020021FD86 /* EditingBehaviorTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F1534DF11B533020021FD86 /* EditingBehaviorTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4F2D205412EAE7B3005C2874 /* InspectorAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F2D205212EAE7B3005C2874 /* InspectorAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               4F32BB1B14FA85E800F6C1A3 /* MemoryInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F32BB1A14FA85AA00F6C1A3 /* MemoryInstrumentation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4F2D205512EAE7B3005C2874 /* InspectorAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4F2D205312EAE7B3005C2874 /* InspectorAgent.cpp */; };
                4F3289B511A42AAB005ABE7E /* InspectorValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4F3289B311A42AAB005ABE7E /* InspectorValues.cpp */; };
                4F3289B611A42AAB005ABE7E /* InspectorValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F3289B411A42AAB005ABE7E /* InspectorValues.h */; settings = {ATTRIBUTES = (Private, ); }; };
                4F1534DD11B532EC0021FD86 /* EditingBehavior.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingBehavior.h; sourceTree = "<group>"; };
                4F1534DF11B533020021FD86 /* EditingBehaviorTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingBehaviorTypes.h; sourceTree = "<group>"; };
                4F2D205212EAE7B3005C2874 /* InspectorAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorAgent.h; sourceTree = "<group>"; };
+               4F32BB1A14FA85AA00F6C1A3 /* MemoryInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentation.h; sourceTree = "<group>"; };
                4F2D205312EAE7B3005C2874 /* InspectorAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorAgent.cpp; sourceTree = "<group>"; };
                4F3289B311A42AAB005ABE7E /* InspectorValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorValues.cpp; sourceTree = "<group>"; };
                4F3289B411A42AAB005ABE7E /* InspectorValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorValues.h; sourceTree = "<group>"; };
                                BC9A6144146859D9006057FD /* make_dom_exceptions.pl */,
                                BC9A6145146859D9006057FD /* make_event_factory.pl */,
                                BC9A6146146859D9006057FD /* make_names.pl */,
+                               4F32BB1A14FA85AA00F6C1A3 /* MemoryInstrumentation.h */,
                                E1ADECCD0E76AD8B004A1A5E /* MessageChannel.cpp */,
                                E1ADECCC0E76AD8B004A1A5E /* MessageChannel.h */,
                                E1ADECD00E76ADAB004A1A5E /* MessageChannel.idl */,
                                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */,
                                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */,
                                50987C27157D676D00BDA835 /* CustomFilterGlobalContext.h in Headers */,
+                               4F32BB1B14FA85E800F6C1A3 /* MemoryInstrumentation.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 508a937..2d92bb4 100644 (file)
@@ -54,6 +54,12 @@ public:
         weakClear(m_wrapper, wrapper);
     }
 
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        memoryObjectInfo->reportObject(m_wrapper);
+    }
+
 private:
     JSC::Weak<JSDOMWrapper> m_wrapper;
 };
index 850994a..1c28232 100644 (file)
@@ -52,6 +52,12 @@ public:
 
     void clearWrapper() { m_wrapper = 0; }
 
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        memoryObjectInfo->reportPointer(m_wrapper, MemoryInstrumentation::DOM);
+    }
+
 private:
     v8::Persistent<v8::Object>* m_wrapper;
 };
index 74ce079..559cfe6 100644 (file)
@@ -25,6 +25,7 @@
 #include "CSSPrimitiveValue.h"
 #include "CSSProperty.h"
 #include "CSSPropertyNames.h"
+#include "MemoryInstrumentation.h"
 #include <wtf/ListHashSet.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
@@ -115,6 +116,13 @@ public:
     void showStyle();
 #endif
     
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::CSS);
+        if (m_isMutable)
+            memoryObjectInfo->reportPointer(m_mutablePropertyVector, MemoryInstrumentation::CSS);
+    }
+
 private:
     StylePropertySet(CSSParserMode);
     StylePropertySet(const CSSProperty* properties, unsigned count, CSSParserMode, bool makeMutable);
index be8c78e..5f55c7b 100644 (file)
@@ -99,6 +99,14 @@ public:
     Node* traverseNextNode() const;
     Node* traverseNextNode(const Node* stayWithin) const;
 
+    virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        Node::reportMemoryUsage(memoryObjectInfo);
+        memoryObjectInfo->reportInstrumentedPointer(m_firstChild);
+        memoryObjectInfo->reportInstrumentedPointer(m_lastChild);
+    }
+
 protected:
     ContainerNode(Document*, ConstructionType = CreateContainer);
 
index de3f0c5..6c52a60 100644 (file)
@@ -421,6 +421,14 @@ public:
     IntSize savedLayerScrollOffset() const;
     void setSavedLayerScrollOffset(const IntSize&);
 
+    virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        ContainerNode::reportMemoryUsage(memoryObjectInfo);
+        memoryObjectInfo->reportInstrumentedObject(m_tagName);
+        memoryObjectInfo->reportInstrumentedPointer(m_attributeData.get());
+    }
+
 protected:
     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
         : ContainerNode(document, type)
index 8b1b318..90f1b91 100644 (file)
@@ -27,6 +27,7 @@
 #define ElementAttributeData_h
 
 #include "Attribute.h"
+#include "MemoryInstrumentation.h"
 #include "SpaceSplitString.h"
 #include "StylePropertySet.h"
 #include <wtf/NotFound.h>
@@ -99,6 +100,16 @@ public:
     PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&);
     PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&);
 
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        memoryObjectInfo->reportInstrumentedPointer(m_inlineStyleDecl.get());
+        memoryObjectInfo->reportInstrumentedPointer(m_attributeStyle.get());
+        memoryObjectInfo->reportObject(m_classNames);
+        memoryObjectInfo->reportObject(m_idForStyleResolution);
+        memoryObjectInfo->reportObject(m_attributes);
+    }
+
 private:
     friend class Element;
     friend class HTMLConstructionSite;
diff --git a/Source/WebCore/dom/MemoryInstrumentation.h b/Source/WebCore/dom/MemoryInstrumentation.h
new file mode 100644 (file)
index 0000000..6f0e7a4
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MemoryInstrumentation_h
+#define MemoryInstrumentation_h
+
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class MemoryObjectInfo;
+
+class MemoryInstrumentation {
+public:
+    virtual ~MemoryInstrumentation() { }
+
+    enum ObjectType {
+        Other,
+        DOM,
+        CSS,
+        LastTypeEntry
+    };
+
+    template <typename T> void reportInstrumentedObject(const T&);
+    template <typename T> void reportObject(const T&) { }
+    template <typename T> void reportInstrumentedPointer(const T*);
+    template <typename T> void reportPointer(const T* object, ObjectType objectType)
+    {
+        if (!object || visited(object))
+            return;
+        countObjectSize(objectType, sizeof(T));
+    }
+
+private:
+    friend class MemoryObjectInfo;
+
+    virtual void countObjectSize(ObjectType, size_t) = 0;
+    virtual bool visited(const void*) = 0;
+};
+
+class MemoryObjectInfo {
+public:
+    MemoryObjectInfo(MemoryInstrumentation* memoryInstrumentation)
+        : m_memoryInstrumentation(memoryInstrumentation)
+        , m_objectType(MemoryInstrumentation::Other)
+        , m_objectSize(0)
+     { }
+
+    template <typename P>
+    void reportInstrumentedPointer(const P* memberPointer)
+    {
+        m_memoryInstrumentation->reportInstrumentedPointer(memberPointer);
+    }
+
+    template <typename P>
+    void reportPointer(const P* pointer, MemoryInstrumentation::ObjectType objectType)
+    {
+        m_memoryInstrumentation->reportPointer(pointer, objectType);
+    }
+
+    template <typename T>
+    void reportInstrumentedObject(const T& memberObject)
+    {
+        m_memoryInstrumentation->reportInstrumentedObject(memberObject);
+    }
+
+    template <typename T>
+    void reportObject(const T& object) { m_memoryInstrumentation->reportObject(object); }
+
+    template <typename T>
+    void reportObjectInfo(const T*, MemoryInstrumentation::ObjectType objectType)
+    {
+        if (m_objectType != MemoryInstrumentation::Other)
+            return;
+        m_objectType = objectType;
+        m_objectSize = sizeof(T);
+    }
+
+    MemoryInstrumentation::ObjectType objectType() const { return m_objectType; }
+    size_t objectSize() const { return m_objectSize; }
+
+ private:
+    MemoryInstrumentation* m_memoryInstrumentation;
+    MemoryInstrumentation::ObjectType m_objectType;
+    size_t m_objectSize;
+};
+
+template <typename T>
+void MemoryInstrumentation::reportInstrumentedPointer(const T* const object)
+{
+    if (!object || visited(object))
+        return;
+    MemoryObjectInfo memoryObjectInfo(this);
+    object->reportMemoryUsage(&memoryObjectInfo);
+    countObjectSize(memoryObjectInfo.objectType(), memoryObjectInfo.objectSize());
+}
+
+template<typename T>
+void MemoryInstrumentation::reportInstrumentedObject(const T& object)
+{
+    if (visited(&object))
+        return;
+    MemoryObjectInfo memoryObjectInfo(this);
+    object.reportMemoryUsage(&memoryObjectInfo);
+}
+
+} // namespace WebCore
+
+#endif // !defined(MemoryInstrumentation_h)
index 24c6158..7446cfa 100644 (file)
@@ -2785,6 +2785,16 @@ void Node::removedLastRef()
     delete this;
 }
 
+void Node::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+    TreeShared<Node, ContainerNode>::reportMemoryUsage(memoryObjectInfo);
+    ScriptWrappable::reportMemoryUsage(memoryObjectInfo);
+    memoryObjectInfo->reportPointer(m_document, MemoryInstrumentation::DOM);
+    memoryObjectInfo->reportInstrumentedPointer(m_next);
+    memoryObjectInfo->reportInstrumentedPointer(m_previous);
+}
+
 } // namespace WebCore
 
 #ifndef NDEBUG
index e8fde30..c9c2674 100644 (file)
@@ -29,6 +29,7 @@
 #include "EventTarget.h"
 #include "KURLHash.h"
 #include "LayoutTypes.h"
+#include "MemoryInstrumentation.h"
 #include "RenderStyleConstants.h"
 #include "ScriptWrappable.h"
 #include "TreeShared.h"
@@ -648,6 +649,8 @@ public:
     bool hasScopedHTMLStyleChild() const;
     size_t numberOfScopedHTMLStyleChildren() const;
 
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
 private:
     enum NodeFlags {
         IsTextFlag = 1,
index 636b2a5..1907b87 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef QualifiedName_h
 #define QualifiedName_h
 
+#include "MemoryInstrumentation.h"
+
 #include <wtf/HashTraits.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/AtomicString.h>
@@ -48,6 +50,14 @@ public:
         const AtomicString m_namespace;
         mutable AtomicString m_localNameUpper;
 
+        void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+        {
+            memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+            memoryObjectInfo->reportObject(m_prefix);
+            memoryObjectInfo->reportObject(m_localName);
+            memoryObjectInfo->reportObject(m_namespace);
+            memoryObjectInfo->reportObject(m_localNameUpper);
+        }
     private:
         QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI)
             : m_prefix(prefix)
@@ -92,6 +102,11 @@ public:
     // Init routine for globals
     static void init();
     
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        memoryObjectInfo->reportInstrumentedPointer(m_impl);
+    }
 private:
     void init(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI);
     void ref() const { m_impl->ref(); }
index 0fb2aac..e396542 100644 (file)
@@ -44,6 +44,7 @@
 #include "InspectorValues.h"
 #include "InstrumentingAgents.h"
 #include "MemoryCache.h"
+#include "MemoryInstrumentation.h"
 #include "MemoryUsageSupport.h"
 #include "Node.h"
 #include "Page.h"
@@ -77,6 +78,11 @@ static const char cachedXslStyleSheets[] = "CachedXslStyleSheets";
 static const char cachedFonts[] = "CachedFonts";
 static const char renderTreeUsed[] = "RenderTreeUsed";
 static const char renderTreeAllocated[] = "RenderTreeAllocated";
+
+static const char dom[] = "DOM";
+static const char domTreeOther[] = "DOMTreeOther";
+static const char domTreeDOM[] = "DOMTreeDOM";
+static const char domTreeCSS[] = "DOMTreeCSS";
 }
 
 namespace {
@@ -177,10 +183,6 @@ private:
         collectListenersInfo(node);
     }
 
-    void collectCharacterData(Node*)
-    {
-    }
-
     void collectNodeNameInfo(Node* node)
     {
         String name = nodeName(node);
@@ -372,13 +374,93 @@ static PassRefPtr<InspectorMemoryBlock> renderTreeInfo(Page* page)
     return renderTreeAllocated.release();
 }
 
-static void addMemoryBlockFor(TypeBuilder::Array<InspectorMemoryBlock>* array, const MemoryCache::TypeStatistic& statistic, const char* name)
+static void addMemoryBlockFor(TypeBuilder::Array<InspectorMemoryBlock>* array, size_t size, const char* name)
 {
     RefPtr<InspectorMemoryBlock> result = InspectorMemoryBlock::create().setName(name);
-    result->setSize(statistic.size);
+    result->setSize(size);
     array->addItem(result);
 }
 
+namespace {
+
+class MemoryInstrumentationImpl : public MemoryInstrumentation {
+public:
+    MemoryInstrumentationImpl()
+    {
+        for (int i = 0; i < LastTypeEntry; ++i)
+            m_totalSizes[i] = 0;
+    }
+
+    PassRefPtr<InspectorMemoryBlock> dumpStatistics()
+    {
+        size_t totalSize = 0;
+        for (int i = Other; i < LastTypeEntry; ++i)
+            totalSize += m_totalSizes[i];
+
+        RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > domChildren = TypeBuilder::Array<InspectorMemoryBlock>::create();
+        addMemoryBlockFor(domChildren.get(), m_totalSizes[Other], MemoryBlockName::domTreeOther);
+        addMemoryBlockFor(domChildren.get(), m_totalSizes[DOM], MemoryBlockName::domTreeDOM);
+        addMemoryBlockFor(domChildren.get(), m_totalSizes[CSS], MemoryBlockName::domTreeCSS);
+
+        RefPtr<InspectorMemoryBlock> dom = InspectorMemoryBlock::create().setName(MemoryBlockName::dom);
+        dom->setSize(totalSize);
+        dom->setChildren(domChildren.release());
+        return dom.release();
+    }
+
+private:
+    virtual void countObjectSize(ObjectType objectType, size_t size)
+    {
+        ASSERT(objectType >= 0 && objectType < LastTypeEntry);
+        m_totalSizes[objectType] += size;
+    }
+
+    virtual bool visited(const void* object)
+    {
+        return !m_visitedObjects.add(object).isNewEntry;
+    }
+    size_t m_totalSizes[LastTypeEntry];
+    typedef HashSet<const void*> VisitedObjects;
+    VisitedObjects m_visitedObjects;
+};
+
+class DOMTreesIterator : public DOMWrapperVisitor {
+public:
+    explicit DOMTreesIterator(Page* page) : m_page(page) { }
+
+    virtual void visitNode(Node* node)
+    {
+        if (node->document() && node->document()->frame() && m_page != node->document()->frame()->page())
+            return;
+
+        m_domMemoryUsage.reportInstrumentedPointer(node);
+    }
+
+    virtual void visitJSExternalString(StringImpl*) { }
+
+    PassRefPtr<InspectorMemoryBlock> dumpStatistics() { return m_domMemoryUsage.dumpStatistics(); }
+
+private:
+    Page* m_page;
+    MemoryInstrumentationImpl m_domMemoryUsage;
+};
+
+}
+
+static PassRefPtr<InspectorMemoryBlock> domTreeInfo(Page* page)
+{
+    DOMTreesIterator domTreesIterator(page);
+    ScriptProfiler::visitJSDOMWrappers(&domTreesIterator);
+
+    // Make sure all documents reachable from the main frame are accounted.
+    for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (Document* doc = frame->document())
+            domTreesIterator.visitNode(doc);
+    }
+
+    return domTreesIterator.dumpStatistics();
+}
+
 static PassRefPtr<InspectorMemoryBlock> memoryCacheInfo()
 {
     MemoryCache::Statistics stats = memoryCache()->getStatistics();
@@ -391,12 +473,12 @@ static PassRefPtr<InspectorMemoryBlock> memoryCacheInfo()
     memoryCacheStats->setSize(totalSize);
 
     RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create();
-    addMemoryBlockFor(children.get(), stats.images, MemoryBlockName::cachedImages);
-    addMemoryBlockFor(children.get(), stats.cssStyleSheets, MemoryBlockName::cachedCssStyleSheets);
-    addMemoryBlockFor(children.get(), stats.scripts, MemoryBlockName::cachedScripts);
-    addMemoryBlockFor(children.get(), stats.xslStyleSheets, MemoryBlockName::cachedXslStyleSheets);
-    addMemoryBlockFor(children.get(), stats.fonts, MemoryBlockName::cachedFonts);
-    memoryCacheStats->setChildren(children);
+    addMemoryBlockFor(children.get(), stats.images.size, MemoryBlockName::cachedImages);
+    addMemoryBlockFor(children.get(), stats.cssStyleSheets.size, MemoryBlockName::cachedCssStyleSheets);
+    addMemoryBlockFor(children.get(), stats.scripts.size, MemoryBlockName::cachedScripts);
+    addMemoryBlockFor(children.get(), stats.xslStyleSheets.size, MemoryBlockName::cachedXslStyleSheets);
+    addMemoryBlockFor(children.get(), stats.fonts.size, MemoryBlockName::cachedFonts);
+    memoryCacheStats->setChildren(children.get());
     return memoryCacheStats.release();
 }
 
@@ -413,6 +495,7 @@ void InspectorMemoryAgent::getProcessMemoryDistribution(ErrorString*, RefPtr<Ins
     children->addItem(inspectorData());
     children->addItem(memoryCacheInfo());
     children->addItem(renderTreeInfo(m_page)); // TODO: collect for all pages?
+    children->addItem(domTreeInfo(m_page)); // TODO: collect for all pages?
     processMemory->setChildren(children);
 }
 
index 2ebdb1d..6c4154e 100644 (file)
@@ -111,6 +111,12 @@ public:
     bool m_inRemovedLastRefFunction;
 #endif
 
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+        memoryObjectInfo->reportInstrumentedPointer(m_parent);
+    }
+
 private:
 #ifndef NDEBUG
     friend void adopted<>(TreeShared<NodeType, ParentNodeType>*);