Web Inspector: Native Memory Instrumentation: reportLeaf method doesn't report the...
[WebKit-https.git] / Source / WebCore / inspector / HeapGraphSerializer.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(INSPECTOR)
34
35 #include "HeapGraphSerializer.h"
36
37 #include "WebCoreMemoryInstrumentation.h"
38 #include <wtf/MemoryInstrumentationHashMap.h>
39 #include <wtf/MemoryInstrumentationVector.h>
40 #include <wtf/MemoryObjectInfo.h>
41 #include <wtf/text/CString.h>
42 #include <wtf/text/WTFString.h>
43
44 namespace WebCore {
45
46 HeapGraphSerializer::HeapGraphSerializer(Client* client)
47     : m_client(client)
48     , m_strings(Strings::create())
49     , m_edges(Edges::create())
50     , m_nodeEdgesCount(0)
51     , m_nodes(Nodes::create())
52     , m_baseToRealNodeIdMap(BaseToRealNodeIdMap::create())
53     , m_leafCount(0)
54 {
55     ASSERT(m_client);
56     m_strings->addItem(String()); // An empty string with 0 index.
57
58     memset(m_edgeTypes, 0, sizeof(m_edgeTypes));
59
60     m_edgeTypes[WTF::PointerMember] = addString("weak");
61     m_edgeTypes[WTF::OwnPtrMember] = addString("ownRef");
62     m_edgeTypes[WTF::RefPtrMember] = addString("countRef");
63
64     m_unknownClassNameId = addString("unknown");
65 }
66
67 HeapGraphSerializer::~HeapGraphSerializer()
68 {
69 }
70
71 void HeapGraphSerializer::pushUpdateIfNeeded()
72 {
73     static const size_t chunkSize = 10000;
74     static const size_t averageEdgesPerNode = 5;
75
76     if (m_strings->length() <= chunkSize
77         && m_nodes->length() <= chunkSize * s_nodeFieldsCount
78         && m_edges->length() <= chunkSize * averageEdgesPerNode * s_edgeFieldsCount
79         && m_baseToRealNodeIdMap->length() <= chunkSize * s_idMapEntryFieldCount)
80         return;
81
82     pushUpdate();
83 }
84
85 void HeapGraphSerializer::pushUpdate()
86 {
87     typedef TypeBuilder::Memory::HeapSnapshotChunk HeapSnapshotChunk;
88
89     RefPtr<HeapSnapshotChunk> chunk = HeapSnapshotChunk::create()
90         .setStrings(m_strings.release())
91         .setNodes(m_nodes.release())
92         .setEdges(m_edges.release())
93         .setBaseToRealNodeId(m_baseToRealNodeIdMap.release());
94
95     m_client->addNativeSnapshotChunk(chunk.release());
96
97     m_strings = Strings::create();
98     m_edges = Edges::create();
99     m_nodes = Nodes::create();
100     m_baseToRealNodeIdMap = BaseToRealNodeIdMap::create();
101 }
102
103 void HeapGraphSerializer::reportNode(const WTF::MemoryObjectInfo& info)
104 {
105     ASSERT(info.reportedPointer());
106     reportNodeImpl(info, m_nodeEdgesCount);
107     m_nodeEdgesCount = 0;
108     if (info.isRoot())
109         m_roots.append(info.reportedPointer());
110     pushUpdateIfNeeded();
111 }
112
113 int HeapGraphSerializer::reportNodeImpl(const WTF::MemoryObjectInfo& info, int edgesCount)
114 {
115     int nodeId = toNodeId(info.reportedPointer());
116
117     m_nodes->addItem(info.className().isEmpty() ? m_unknownClassNameId : addString(info.className()));
118     m_nodes->addItem(addString(info.name()));
119     m_nodes->addItem(nodeId);
120     m_nodes->addItem(info.objectSize());
121     m_nodes->addItem(edgesCount);
122
123     return nodeId;
124 }
125
126 void HeapGraphSerializer::reportEdge(const void* to, const char* name, WTF::MemberType memberType)
127 {
128     ASSERT(to);
129     reportEdgeImpl(toNodeId(to), name, m_edgeTypes[memberType]);
130     pushUpdateIfNeeded();
131 }
132
133 void HeapGraphSerializer::reportEdgeImpl(const int toNodeId, const char* name, int memberType)
134 {
135     ASSERT(memberType >= 0);
136     ASSERT(memberType < WTF::LastMemberTypeEntry);
137
138     m_edges->addItem(memberType);
139     m_edges->addItem(addString(name));
140     m_edges->addItem(toNodeId);
141
142     ++m_nodeEdgesCount;
143 }
144
145 void HeapGraphSerializer::reportLeaf(const WTF::MemoryObjectInfo& info, const char* edgeName)
146 {
147     int nodeId = reportNodeImpl(info, 0);
148     reportEdgeImpl(nodeId, edgeName, m_edgeTypes[WTF::OwnPtrMember]);
149     pushUpdateIfNeeded();
150 }
151
152 void HeapGraphSerializer::reportBaseAddress(const void* base, const void* real)
153 {
154     m_baseToRealNodeIdMap->addItem(toNodeId(base));
155     m_baseToRealNodeIdMap->addItem(toNodeId(real));
156 }
157
158 void HeapGraphSerializer::finish()
159 {
160     addRootNode();
161     pushUpdate();
162 }
163
164 void HeapGraphSerializer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
165 {
166     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Inspector);
167     info.addMember(m_stringToIndex, "stringToIndex");
168     info.addMember(m_strings, "strings");
169     info.addMember(m_edges, "edges");
170     info.addMember(m_nodes, "nodes");
171     info.addMember(m_baseToRealNodeIdMap, "baseToRealNodeIdMap");
172     info.addMember(m_roots, "roots");
173 }
174
175 int HeapGraphSerializer::addString(const String& string)
176 {
177     if (string.isEmpty())
178         return 0;
179     StringMap::AddResult result = m_stringToIndex.add(string.left(256), m_stringToIndex.size() + 1);
180     if (result.isNewEntry)
181         m_strings->addItem(string);
182     return result.iterator->value;
183 }
184
185 int HeapGraphSerializer::toNodeId(const void* to)
186 {
187     if (!to)
188         return s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount++;
189
190     Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, s_firstNodeId + m_leafCount + m_address2NodeIdMap.size());
191     return result.iterator->value;
192 }
193
194 void HeapGraphSerializer::addRootNode()
195 {
196     for (size_t i = 0; i < m_roots.size(); i++)
197         reportEdgeImpl(toNodeId(m_roots[i]), 0, m_edgeTypes[WTF::PointerMember]);
198
199     m_nodes->addItem(addString("Root"));
200     m_nodes->addItem(0);
201     m_nodes->addItem(s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount);
202     m_nodes->addItem(0);
203     m_nodes->addItem(m_roots.size());
204 }
205
206 } // namespace WebCore
207
208 #endif // ENABLE(INSPECTOR)