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
+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
<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>
{
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"));
+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
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 \
dom/ExceptionCode.h \
dom/FragmentScriptingPermission.h \
dom/KeyboardEvent.h \
+ dom/MemoryInstrumentation.h \
dom/MessageChannel.h \
dom/MessageEvent.h \
dom/MessagePortChannel.h \
'dom/IconURL.cpp',
'dom/IconURL.h',
'dom/KeyboardEvent.cpp',
+ 'dom/MemoryInstrumentation.h',
'dom/MessageChannel.cpp',
'dom/MessageChannel.h',
'dom/MessageEvent.cpp',
>
</File>
<File
+ RelativePath="..\dom\MemoryInstrumentation.h"
+ >
+ </File>
+ <File
RelativePath="..\dom\MessageChannel.cpp"
>
<FileConfiguration
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;
};
weakClear(m_wrapper, wrapper);
}
+ void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+ {
+ memoryObjectInfo->reportObjectInfo(this, MemoryInstrumentation::DOM);
+ memoryObjectInfo->reportObject(m_wrapper);
+ }
+
private:
JSC::Weak<JSDOMWrapper> m_wrapper;
};
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;
};
#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>
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);
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);
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)
#define ElementAttributeData_h
#include "Attribute.h"
+#include "MemoryInstrumentation.h"
#include "SpaceSplitString.h"
#include "StylePropertySet.h"
#include <wtf/NotFound.h>
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;
--- /dev/null
+/*
+ * 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)
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
#include "EventTarget.h"
#include "KURLHash.h"
#include "LayoutTypes.h"
+#include "MemoryInstrumentation.h"
#include "RenderStyleConstants.h"
#include "ScriptWrappable.h"
#include "TreeShared.h"
bool hasScopedHTMLStyleChild() const;
size_t numberOfScopedHTMLStyleChildren() const;
+ virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
private:
enum NodeFlags {
IsTextFlag = 1,
#ifndef QualifiedName_h
#define QualifiedName_h
+#include "MemoryInstrumentation.h"
+
#include <wtf/HashTraits.h>
#include <wtf/RefCounted.h>
#include <wtf/text/AtomicString.h>
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)
// 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(); }
#include "InspectorValues.h"
#include "InstrumentingAgents.h"
#include "MemoryCache.h"
+#include "MemoryInstrumentation.h"
#include "MemoryUsageSupport.h"
#include "Node.h"
#include "Page.h"
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 {
collectListenersInfo(node);
}
- void collectCharacterData(Node*)
- {
- }
-
void collectNodeNameInfo(Node* node)
{
String name = nodeName(node);
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();
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();
}
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);
}
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>*);