Diff
Modified: trunk/Source/WebCore/ChangeLog (105156 => 105157)
--- trunk/Source/WebCore/ChangeLog 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/ChangeLog 2012-01-17 15:37:06 UTC (rev 105157)
@@ -1,3 +1,35 @@
+2012-01-11 Yury Semikhatsky <[email protected]>
+
+ Web Inspector: provide basic information about DOM character data size
+ https://bugs.webkit.org/show_bug.cgi?id=76059
+
+ Memory agent allows to estimate size of DOM character data and size of WebCore
+ strings held by _javascript_ objects.
+
+ Reviewed by Pavel Feldman.
+
+ * bindings/js/ScriptProfiler.h:
+ (WebCore::ScriptProfiler::visitExternalJSStrings):
+ * bindings/v8/ScriptProfiler.cpp:
+ (WebCore::ScriptProfiler::visitExternalJSStrings):
+ * bindings/v8/ScriptProfiler.h:
+ * bindings/v8/V8Binding.cpp:
+ (WebCore::WebCoreStringResource::visitStrings):
+ (WebCore::V8BindingPerIsolateData::visitJSExternalStrings):
+ * bindings/v8/V8Binding.h:
+ * inspector/DOMWrapperVisitor.h:
+ * inspector/Inspector.json:
+ * inspector/InspectorMemoryAgent.cpp:
+ (WebCore::CharacterDataStatistics::DOMTreeStatistics::DOMTreeStatistics):
+ (WebCore::CharacterDataStatistics::DOMTreeStatistics::collectNodeStatistics):
+ (WebCore::CharacterDataStatistics::CounterVisitor::CounterVisitor):
+ (WebCore::CharacterDataStatistics::CounterVisitor::domGroups):
+ (WebCore::CharacterDataStatistics::CounterVisitor::strings):
+ (WebCore::CharacterDataStatistics::CounterVisitor::visitNode):
+ (WebCore::CharacterDataStatistics::CounterVisitor::visitJSExternalString):
+ (WebCore::InspectorMemoryAgent::getDOMNodeCount):
+ * inspector/InspectorMemoryAgent.h:
+
2012-01-17 Vsevolod Vlasov <[email protected]>
Web Inspector: Dialogs style and DialogDelegate interface fixes.
Modified: trunk/Source/WebCore/bindings/js/ScriptProfiler.h (105156 => 105157)
--- trunk/Source/WebCore/bindings/js/ScriptProfiler.h 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/js/ScriptProfiler.h 2012-01-17 15:37:06 UTC (rev 105157)
@@ -62,6 +62,7 @@
static bool hasHeapProfiler() { return false; }
// FIXME: Implement this counter for JSC. See bug 73936 for more details.
static void visitJSDOMWrappers(DOMWrapperVisitor*) { }
+ static void visitExternalJSStrings(DOMWrapperVisitor*) { }
};
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp (105156 => 105157)
--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp 2012-01-17 15:37:06 UTC (rev 105157)
@@ -159,4 +159,9 @@
visitDOMNodes(&adapter);
}
+void ScriptProfiler::visitExternalJSStrings(DOMWrapperVisitor* visitor)
+{
+ V8BindingPerIsolateData::current()->visitJSExternalStrings(visitor);
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.h (105156 => 105157)
--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.h 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.h 2012-01-17 15:37:06 UTC (rev 105157)
@@ -66,6 +66,7 @@
static bool hasHeapProfiler() { return true; }
static void initialize();
static void visitJSDOMWrappers(DOMWrapperVisitor*);
+ static void visitExternalJSStrings(DOMWrapperVisitor*);
};
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/v8/V8Binding.cpp (105156 => 105157)
--- trunk/Source/WebCore/bindings/v8/V8Binding.cpp 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.cpp 2012-01-17 15:37:06 UTC (rev 105157)
@@ -32,6 +32,7 @@
#include "V8Binding.h"
#include "DOMStringList.h"
+#include "DOMWrapperVisitor.h"
#include "Element.h"
#include "MathExtras.h"
#include "PlatformString.h"
@@ -145,6 +146,13 @@
return m_atomicString;
}
+ void visitStrings(DOMWrapperVisitor* visitor)
+ {
+ visitor->visitJSExternalString(m_plainString.impl());
+ if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull())
+ visitor->visitJSExternalString(m_atomicString.impl());
+ }
+
static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String)
{
return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource());
@@ -165,6 +173,25 @@
#endif
};
+void V8BindingPerIsolateData::visitJSExternalStrings(DOMWrapperVisitor* visitor)
+{
+ v8::HandleScope handleScope;
+ class VisitorImpl : public v8::ExternalResourceVisitor {
+ public:
+ VisitorImpl(DOMWrapperVisitor* visitor) : m_visitor(visitor) { }
+ virtual ~VisitorImpl() { }
+ virtual void VisitExternalString(v8::Handle<v8::String> string)
+ {
+ WebCoreStringResource* resource = static_cast<WebCoreStringResource*>(string->GetExternalStringResource());
+ if (resource)
+ resource->visitStrings(m_visitor);
+ }
+ private:
+ DOMWrapperVisitor* m_visitor;
+ } v8Visitor(visitor);
+ v8::V8::VisitExternalResources(&v8Visitor);
+}
+
String v8ValueToWebCoreString(v8::Handle<v8::Value> value)
{
if (value->IsString())
@@ -502,7 +529,6 @@
m_stringCache.remove(stringImpl);
}
-
v8::Local<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl)
{
if (!stringImpl->length())
Modified: trunk/Source/WebCore/bindings/v8/V8Binding.h (105156 => 105157)
--- trunk/Source/WebCore/bindings/v8/V8Binding.h 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/bindings/v8/V8Binding.h 2012-01-17 15:37:06 UTC (rev 105157)
@@ -46,6 +46,7 @@
namespace WebCore {
class DOMStringList;
+ class DOMWrapperVisitor;
class EventListener;
class EventTarget;
@@ -123,6 +124,7 @@
}
StringCache* stringCache() { return &m_stringCache; }
+ void visitJSExternalStrings(DOMWrapperVisitor*);
DOMDataList& allStores() { return m_domDataList; }
Modified: trunk/Source/WebCore/inspector/DOMWrapperVisitor.h (105156 => 105157)
--- trunk/Source/WebCore/inspector/DOMWrapperVisitor.h 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/DOMWrapperVisitor.h 2012-01-17 15:37:06 UTC (rev 105157)
@@ -36,6 +36,7 @@
class DOMWrapperVisitor {
public:
virtual void visitNode(Node*) = 0;
+ virtual void visitJSExternalString(StringImpl*) = 0;
protected:
virtual ~DOMWrapperVisitor() { }
};
Modified: trunk/Source/WebCore/inspector/Inspector.json (105156 => 105157)
--- trunk/Source/WebCore/inspector/Inspector.json 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/Inspector.json 2012-01-17 15:37:06 UTC (rev 105157)
@@ -68,6 +68,16 @@
"description": "Number of JS event listeners by event type."
},
{
+ "id": "StringStatistics",
+ "type": "object",
+ "properties": [
+ { "name": "dom", "type": "integer" },
+ { "name": "js", "type": "integer" },
+ { "name": "shared", "type": "integer" }
+ ],
+ "description": "Character data statistics for the page."
+ },
+ {
"id": "DOMGroup",
"type": "object",
"properties": [
@@ -83,7 +93,8 @@
{
"name": "getDOMNodeCount",
"returns": [
- { "name": "count", "type": "array", "items": { "$ref": "DOMGroup" }}
+ { "name": "domGroups", "type": "array", "items": { "$ref": "DOMGroup" }},
+ { "name": "strings", "$ref": "StringStatistics" }
]
}
]
Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp (105156 => 105157)
--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp 2012-01-17 15:37:06 UTC (rev 105157)
@@ -33,6 +33,7 @@
#if ENABLE(INSPECTOR)
+#include "CharacterData.h"
#include "DOMWrapperVisitor.h"
#include "Document.h"
#include "EventListenerMap.h"
@@ -51,6 +52,7 @@
using WebCore::TypeBuilder::Memory::DOMGroup;
using WebCore::TypeBuilder::Memory::ListenerCount;
using WebCore::TypeBuilder::Memory::NodeCount;
+using WebCore::TypeBuilder::Memory::StringStatistics;
namespace WebCore {
@@ -63,11 +65,50 @@
return node->nodeName().lower();
}
+int stringSize(StringImpl* string)
+{
+ int size = string->length();
+ if (!string->is8Bit())
+ size *= 2;
+ return size + sizeof(*string);
+}
+
typedef HashSet<StringImpl*, PtrHash<StringImpl*> > StringImplIdentitySet;
+class CharacterDataStatistics {
+ WTF_MAKE_NONCOPYABLE(CharacterDataStatistics);
+public:
+ CharacterDataStatistics() : m_characterDataSize(0) { }
+
+ void collectCharacterData(Node* node)
+ {
+ if (!node->isCharacterDataNode())
+ return;
+
+ CharacterData* characterData = static_cast<CharacterData*>(node);
+ StringImpl* dataImpl = characterData->dataImpl();
+ if (m_domStringImplSet.contains(dataImpl))
+ return;
+ m_domStringImplSet.add(dataImpl);
+
+ m_characterDataSize += stringSize(dataImpl);
+ }
+
+ bool contains(StringImpl* s) { return m_domStringImplSet.contains(s); }
+
+ int characterDataSize() { return m_characterDataSize; }
+
+private:
+ StringImplIdentitySet m_domStringImplSet;
+ int m_characterDataSize;
+};
+
class DOMTreeStatistics {
+ WTF_MAKE_NONCOPYABLE(DOMTreeStatistics);
public:
- DOMTreeStatistics(Node* rootNode) : m_totalNodeCount(0)
+ DOMTreeStatistics(Node* rootNode, CharacterDataStatistics& characterDataStatistics)
+ : m_totalNodeCount(0)
+ , m_characterDataStatistics(characterDataStatistics)
{
collectTreeStatistics(rootNode);
}
@@ -108,7 +149,7 @@
}
void collectNodeStatistics(Node* node)
{
- collectCharacterData(node);
+ m_characterDataStatistics.collectCharacterData(node);
collectNodeNameInfo(node);
collectListenersInfo(node);
}
@@ -149,15 +190,28 @@
int m_totalNodeCount;
HashMap<AtomicString, int> m_eventTypeToCount;
HashMap<String, int> m_nodeNameToCount;
- StringImplIdentitySet m_domStringImplSet;
+ CharacterDataStatistics& m_characterDataStatistics;
};
class CounterVisitor : public DOMWrapperVisitor {
public:
- CounterVisitor(Page* page) : m_page(page), m_counters(InspectorArray::create()) { }
+ CounterVisitor(Page* page)
+ : m_page(page)
+ , m_domGroups(InspectorArray::create())
+ , m_jsExternalStringSize(0)
+ , m_sharedStringSize(0) { }
- InspectorArray* counters() { return m_counters.get(); }
+ InspectorArray* domGroups() { return m_domGroups.get(); }
+ PassRefPtr<InspectorObject> strings()
+ {
+ RefPtr<StringStatistics> stringStatistics = StringStatistics::create()
+ .setDom(m_characterDataStatistics.characterDataSize())
+ .setJs(m_jsExternalStringSize)
+ .setShared(m_sharedStringSize);
+ return stringStatistics.release();
+ }
+
virtual void visitNode(Node* node)
{
if (node->document()->frame() && m_page != node->document()->frame()->page())
@@ -171,7 +225,7 @@
return;
m_roots.add(rootNode);
- DOMTreeStatistics domTreeStats(rootNode);
+ DOMTreeStatistics domTreeStats(rootNode, m_characterDataStatistics);
RefPtr<DOMGroup> domGroup = DOMGroup::create()
.setSize(domTreeStats.totalNodeCount())
@@ -181,9 +235,17 @@
if (rootNode->nodeType() == Node::DOCUMENT_NODE)
domGroup->setDocumentURI(static_cast<Document*>(rootNode)->documentURI());
- m_counters->pushObject(domGroup);
+ m_domGroups->pushObject(domGroup);
}
+ virtual void visitJSExternalString(StringImpl* string)
+ {
+ int size = stringSize(string);
+ m_jsExternalStringSize += size;
+ if (m_characterDataStatistics.contains(string))
+ m_sharedStringSize += size;
+ }
+
private:
String elementTitle(Element* element)
{
@@ -215,7 +277,10 @@
HashSet<Node*> m_roots;
Page* m_page;
- RefPtr<InspectorArray> m_counters;
+ RefPtr<InspectorArray> m_domGroups;
+ CharacterDataStatistics m_characterDataStatistics;
+ int m_jsExternalStringSize;
+ int m_sharedStringSize;
};
} // namespace
@@ -224,7 +289,7 @@
{
}
-void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& result)
+void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& domGroups, RefPtr<InspectorObject>& strings)
{
CounterVisitor counterVisitor(m_page);
ScriptProfiler::visitJSDOMWrappers(&counterVisitor);
@@ -235,7 +300,10 @@
counterVisitor.visitNode(doc);
}
- result = counterVisitor.counters();
+ ScriptProfiler::visitExternalJSStrings(&counterVisitor);
+
+ domGroups = counterVisitor.domGroups();
+ strings = counterVisitor.strings();
}
InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, Page* page, InspectorDOMAgent* domAgent)
Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.h (105156 => 105157)
--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.h 2012-01-17 15:34:35 UTC (rev 105156)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.h 2012-01-17 15:37:06 UTC (rev 105157)
@@ -57,7 +57,7 @@
return adoptPtr(new InspectorMemoryAgent(instrumentingAgents, state, page, domAgent));
}
- void getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& result);
+ void getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>& domGroups, RefPtr<InspectorObject>& strings);
~InspectorMemoryAgent();