2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
35 #include "HeapGraphSerializer.h"
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>
46 HeapGraphSerializer::HeapGraphSerializer(Client* client)
48 , m_strings(Strings::create())
49 , m_edges(Edges::create())
51 , m_nodes(Nodes::create())
52 , m_baseToRealNodeIdMap(BaseToRealNodeIdMap::create())
56 m_strings->addItem(String()); // An empty string with 0 index.
58 memset(m_edgeTypes, 0, sizeof(m_edgeTypes));
60 m_edgeTypes[WTF::PointerMember] = addString("weak");
61 m_edgeTypes[WTF::OwnPtrMember] = addString("ownRef");
62 m_edgeTypes[WTF::RefPtrMember] = addString("countRef");
64 m_unknownClassNameId = addString("unknown");
67 HeapGraphSerializer::~HeapGraphSerializer()
71 void HeapGraphSerializer::pushUpdateIfNeeded()
73 static const size_t chunkSize = 10000;
74 static const size_t averageEdgesPerNode = 5;
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)
85 void HeapGraphSerializer::pushUpdate()
87 typedef TypeBuilder::Memory::HeapSnapshotChunk HeapSnapshotChunk;
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());
95 m_client->addNativeSnapshotChunk(chunk.release());
97 m_strings = Strings::create();
98 m_edges = Edges::create();
99 m_nodes = Nodes::create();
100 m_baseToRealNodeIdMap = BaseToRealNodeIdMap::create();
103 void HeapGraphSerializer::reportNode(const WTF::MemoryObjectInfo& info)
105 ASSERT(info.reportedPointer());
106 reportNodeImpl(info, m_nodeEdgesCount);
107 m_nodeEdgesCount = 0;
109 m_roots.append(info.reportedPointer());
110 pushUpdateIfNeeded();
113 int HeapGraphSerializer::reportNodeImpl(const WTF::MemoryObjectInfo& info, int edgesCount)
115 int nodeId = toNodeId(info.reportedPointer());
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);
126 void HeapGraphSerializer::reportEdge(const void* to, const char* name, WTF::MemberType memberType)
129 reportEdgeImpl(toNodeId(to), name, m_edgeTypes[memberType]);
130 pushUpdateIfNeeded();
133 void HeapGraphSerializer::reportEdgeImpl(const int toNodeId, const char* name, int memberType)
135 ASSERT(memberType >= 0);
136 ASSERT(memberType < WTF::LastMemberTypeEntry);
138 m_edges->addItem(memberType);
139 m_edges->addItem(addString(name));
140 m_edges->addItem(toNodeId);
145 void HeapGraphSerializer::reportLeaf(const WTF::MemoryObjectInfo& info, const char* edgeName)
147 int nodeId = reportNodeImpl(info, 0);
148 reportEdgeImpl(nodeId, edgeName, m_edgeTypes[WTF::OwnPtrMember]);
149 pushUpdateIfNeeded();
152 void HeapGraphSerializer::reportBaseAddress(const void* base, const void* real)
154 m_baseToRealNodeIdMap->addItem(toNodeId(base));
155 m_baseToRealNodeIdMap->addItem(toNodeId(real));
158 void HeapGraphSerializer::finish()
164 void HeapGraphSerializer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
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");
175 int HeapGraphSerializer::addString(const String& string)
177 if (string.isEmpty())
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;
185 int HeapGraphSerializer::toNodeId(const void* to)
188 return s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount++;
190 Address2NodeId::AddResult result = m_address2NodeIdMap.add(to, s_firstNodeId + m_leafCount + m_address2NodeIdMap.size());
191 return result.iterator->value;
194 void HeapGraphSerializer::addRootNode()
196 for (size_t i = 0; i < m_roots.size(); i++)
197 reportEdgeImpl(toNodeId(m_roots[i]), 0, m_edgeTypes[WTF::PointerMember]);
199 m_nodes->addItem(addString("Root"));
201 m_nodes->addItem(s_firstNodeId + m_address2NodeIdMap.size() + m_leafCount);
203 m_nodes->addItem(m_roots.size());
206 } // namespace WebCore
208 #endif // ENABLE(INSPECTOR)