OLD | NEW |
| (Empty) |
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 #ifndef MemoryInstrumentation_h | |
32 #define MemoryInstrumentation_h | |
33 | |
34 #include <wtf/OwnPtr.h> | |
35 #include <wtf/PassOwnPtr.h> | |
36 #include <wtf/RefPtr.h> | |
37 | |
38 #define DEBUG_POINTER_INSTRUMENTATION 0 | |
39 | |
40 namespace WTF { | |
41 | |
42 class MemoryClassInfo; | |
43 class MemoryObjectInfo; | |
44 class MemoryInstrumentation; | |
45 | |
46 typedef const char* MemoryObjectType; | |
47 | |
48 enum MemberType { | |
49 PointerMember, | |
50 ReferenceMember, | |
51 RetainingPointer, | |
52 LastMemberTypeEntry | |
53 }; | |
54 | |
55 template<typename T> void reportMemoryUsage(const T*, MemoryObjectInfo*); | |
56 | |
57 class MemoryInstrumentationClient { | |
58 public: | |
59 virtual ~MemoryInstrumentationClient() { } | |
60 virtual void countObjectSize(const void*, MemoryObjectType, size_t) = 0; | |
61 virtual bool visited(const void*) = 0; | |
62 virtual bool checkCountedObject(const void*) = 0; | |
63 | |
64 virtual void reportNode(const MemoryObjectInfo&) = 0; | |
65 virtual void reportEdge(const void* target, const char* edgeName, MemberType
) = 0; | |
66 virtual void reportLeaf(const MemoryObjectInfo&, const char* edgeName) = 0; | |
67 virtual void reportBaseAddress(const void* base, const void* real) = 0; | |
68 virtual int registerString(const char*) = 0; | |
69 }; | |
70 | |
71 class MemoryInstrumentation { | |
72 public: | |
73 WTF_EXPORT_PRIVATE explicit MemoryInstrumentation(MemoryInstrumentationClien
t*); | |
74 WTF_EXPORT_PRIVATE virtual ~MemoryInstrumentation(); | |
75 | |
76 template <typename T> void addRootObject(const T& t, MemoryObjectType object
Type = 0) | |
77 { | |
78 MemberTypeTraits<T>::addRootObject(this, t, objectType); | |
79 processDeferredObjects(); | |
80 } | |
81 | |
82 template <typename T> void addRootObject(const OwnPtr<T>&, MemoryObjectType
= 0); // Link time guard. | |
83 template <typename T> void addRootObject(const RefPtr<T>&, MemoryObjectType
= 0); // Link time guard. | |
84 | |
85 protected: | |
86 class WrapperBase { | |
87 public: | |
88 WTF_EXPORT_PRIVATE WrapperBase(MemoryObjectType, const void* pointer); | |
89 virtual ~WrapperBase() { } | |
90 WTF_EXPORT_PRIVATE void process(MemoryInstrumentation*); | |
91 WTF_EXPORT_PRIVATE void processPointer(MemoryInstrumentation*, bool isRo
ot); | |
92 WTF_EXPORT_PRIVATE void processRootObjectRef(MemoryInstrumentation*); | |
93 | |
94 protected: | |
95 virtual void callReportMemoryUsage(MemoryObjectInfo*) = 0; | |
96 const void* m_pointer; | |
97 const MemoryObjectType m_ownerObjectType; | |
98 | |
99 private: | |
100 #if DEBUG_POINTER_INSTRUMENTATION | |
101 static const int s_maxCallStackSize = 32; | |
102 void* m_callStack[s_maxCallStackSize]; | |
103 int m_callStackSize; | |
104 #endif | |
105 }; | |
106 | |
107 private: | |
108 void countObjectSize(const void* object, MemoryObjectType objectType, size_t
size) { m_client->countObjectSize(object, objectType, size); } | |
109 bool visited(const void* pointer) { return m_client->visited(pointer); } | |
110 bool checkCountedObject(const void* pointer) { return m_client->checkCounted
Object(pointer); } | |
111 | |
112 WTF_EXPORT_PRIVATE void reportEdge(const void* target, const char* edgeName,
MemberType); | |
113 | |
114 virtual void deferObject(PassOwnPtr<WrapperBase>) = 0; | |
115 virtual void processDeferredObjects() = 0; | |
116 | |
117 WTF_EXPORT_PRIVATE static MemoryObjectType getObjectType(MemoryObjectInfo*); | |
118 | |
119 friend class MemoryObjectInfo; | |
120 friend class MemoryClassInfo; | |
121 template<typename T> friend void reportMemoryUsage(const T*, MemoryObjectInf
o*); | |
122 | |
123 template <typename Type> | |
124 class IsInstrumented { | |
125 class yes { | |
126 char m; | |
127 }; | |
128 | |
129 class no { | |
130 yes m[2]; | |
131 }; | |
132 | |
133 struct BaseMixin { | |
134 void reportMemoryUsage(MemoryObjectInfo*) const { } | |
135 }; | |
136 | |
137 #if COMPILER(MSVC) | |
138 #pragma warning(push) | |
139 #pragma warning(disable: 4624) // Disable warning: destructor could not be gener
ated because a base class destructor is inaccessible. | |
140 #endif | |
141 struct Base : public Type, public BaseMixin { }; | |
142 #if COMPILER(MSVC) | |
143 #pragma warning(pop) | |
144 #endif | |
145 | |
146 template <typename T, T t> class Helper { }; | |
147 | |
148 template <typename U> static no deduce(U*, Helper<void (BaseMixin::*)(Me
moryObjectInfo*) const, &U::reportMemoryUsage>* = 0); | |
149 static yes deduce(...); | |
150 | |
151 public: | |
152 static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0))); | |
153 | |
154 }; | |
155 | |
156 template <int> | |
157 struct InstrumentationSelector { | |
158 template <typename T> static void reportObjectMemoryUsage(const T*, Memo
ryObjectInfo*); | |
159 }; | |
160 | |
161 template<typename T> class Wrapper : public WrapperBase { | |
162 public: | |
163 Wrapper(const T* pointer, MemoryObjectType); | |
164 | |
165 protected: | |
166 virtual void callReportMemoryUsage(MemoryObjectInfo*) OVERRIDE; | |
167 }; | |
168 | |
169 template<typename T> void addObject(const T& t, MemoryObjectInfo* ownerObjec
tInfo, const char* edgeName, MemberType memberType) | |
170 { | |
171 MemberTypeTraits<T>::addObject(this, t, ownerObjectInfo, edgeName, membe
rType); | |
172 } | |
173 void addRawBuffer(const void* buffer, MemoryObjectType ownerObjectType, size
_t size, const char* className = 0, const char* edgeName = 0) | |
174 { | |
175 if (!buffer || visited(buffer)) | |
176 return; | |
177 countObjectSize(buffer, ownerObjectType, size); | |
178 reportLinkToBuffer(buffer, ownerObjectType, size, className, edgeName); | |
179 } | |
180 WTF_EXPORT_PRIVATE void reportLinkToBuffer(const void* buffer, MemoryObjectT
ype ownerObjectType, size_t, const char* nodeName, const char* edgeName); | |
181 | |
182 template<typename T> | |
183 struct MemberTypeTraits { // Default ReferenceMember implementation. | |
184 static void addObject(MemoryInstrumentation* instrumentation, const T& t
, MemoryObjectInfo* ownerObjectInfo, const char* edgeName, MemberType) | |
185 { | |
186 instrumentation->addObjectImpl(&t, ownerObjectInfo, ReferenceMember,
edgeName); | |
187 } | |
188 | |
189 static void addRootObject(MemoryInstrumentation* instrumentation, const
T& t, MemoryObjectType objectType) | |
190 { | |
191 Wrapper<T>(&t, objectType).processRootObjectRef(instrumentation); | |
192 } | |
193 }; | |
194 | |
195 template<typename T> | |
196 struct MemberTypeTraits<T*> { // Custom PointerMember implementation. | |
197 static void addObject(MemoryInstrumentation* instrumentation, const T* c
onst& t, MemoryObjectInfo* ownerObjectInfo, const char* edgeName, MemberType mem
berType) | |
198 { | |
199 instrumentation->addObjectImpl(t, ownerObjectInfo, memberType != Las
tMemberTypeEntry ? memberType : PointerMember, edgeName); | |
200 } | |
201 | |
202 static void addRootObject(MemoryInstrumentation* instrumentation, const
T* const& t, MemoryObjectType objectType) | |
203 { | |
204 if (t && !instrumentation->visited(t)) | |
205 Wrapper<T>(t, objectType).processPointer(instrumentation, true); | |
206 } | |
207 }; | |
208 | |
209 template<typename T> void addObjectImpl(const T*, MemoryObjectInfo*, MemberT
ype, const char* edgeName); | |
210 template<typename T> void addObjectImpl(const OwnPtr<T>*, MemoryObjectInfo*,
MemberType, const char* edgeName); | |
211 template<typename T> void addObjectImpl(const RefPtr<T>*, MemoryObjectInfo*,
MemberType, const char* edgeName); | |
212 | |
213 MemoryInstrumentationClient* m_client; | |
214 }; | |
215 | |
216 // We are trying to keep the signature of the function as small as possible | |
217 // because it significantly affects the binary size. | |
218 // We caluclates class name for 624 classes at the moment. | |
219 // So one extra byte of the function signature increases the binary size to 624
extra bytes. | |
220 #if COMPILER(MSVC) | |
221 template <typename T> struct FN { | |
222 static char* fn() { return const_cast<char*>(__FUNCTION__); } | |
223 }; | |
224 | |
225 template <typename T> char* fn() { return FN<T>::fn(); } | |
226 #else | |
227 template <typename T> char* fn() { return const_cast<char*>(__PRETTY_FUNCTION__)
; } | |
228 #endif | |
229 | |
230 class MemoryClassInfo { | |
231 public: | |
232 template<typename T> | |
233 MemoryClassInfo(MemoryObjectInfo* memoryObjectInfo, const T* pointer, Memory
ObjectType objectType = 0, size_t actualSize = sizeof(T)) | |
234 : m_memoryObjectInfo(memoryObjectInfo) | |
235 , m_memoryInstrumentation(0) | |
236 , m_objectType(0) | |
237 , m_skipMembers(false) | |
238 { | |
239 init(pointer, fn<T>(), objectType, actualSize); | |
240 } | |
241 | |
242 template<typename M> void addMember(const M& member, const char* edgeName =
0, MemberType memberType = LastMemberTypeEntry) | |
243 { | |
244 if (!m_skipMembers) | |
245 m_memoryInstrumentation->addObject(member, m_memoryObjectInfo, edgeN
ame, memberType); | |
246 } | |
247 | |
248 WTF_EXPORT_PRIVATE void addRawBuffer(const void* buffer, size_t, const char*
className = 0, const char* edgeName = 0); | |
249 WTF_EXPORT_PRIVATE void addPrivateBuffer(size_t, MemoryObjectType ownerObjec
tType = 0, const char* className = 0, const char* edgeName = 0); | |
250 WTF_EXPORT_PRIVATE void setCustomAllocation(bool); | |
251 | |
252 void addWeakPointer(void*) { } | |
253 template<typename M> void ignoreMember(const M&) { } | |
254 | |
255 WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const
void* pointer, const char* stringWithClassName, MemoryObjectType, size_t actual
Size); | |
256 | |
257 private: | |
258 WTF_EXPORT_PRIVATE void init(const void* pointer, const char* stringWithClas
sName, MemoryObjectType, size_t actualSize); | |
259 | |
260 MemoryObjectInfo* m_memoryObjectInfo; | |
261 MemoryInstrumentation* m_memoryInstrumentation; | |
262 MemoryObjectType m_objectType; | |
263 bool m_skipMembers; | |
264 }; | |
265 | |
266 template <> | |
267 template <typename T> | |
268 void MemoryInstrumentation::InstrumentationSelector<true>::reportObjectMemoryUsa
ge(const T* object, MemoryObjectInfo* memoryObjectInfo) | |
269 { | |
270 object->reportMemoryUsage(memoryObjectInfo); | |
271 } | |
272 | |
273 template <> | |
274 template <typename T> | |
275 void MemoryInstrumentation::InstrumentationSelector<false>::reportObjectMemoryUs
age(const T* object, MemoryObjectInfo* memoryObjectInfo) | |
276 { | |
277 MemoryClassInfo::callReportObjectInfo(memoryObjectInfo, object, fn<T>(), 0,
sizeof(T)); | |
278 } | |
279 | |
280 template<typename T> | |
281 void reportMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo) | |
282 { | |
283 MemoryInstrumentation::InstrumentationSelector<MemoryInstrumentation::IsInst
rumented<T>::result>::reportObjectMemoryUsage(object, memoryObjectInfo); | |
284 } | |
285 | |
286 template<typename T> | |
287 void MemoryInstrumentation::addObjectImpl(const T* object, MemoryObjectInfo* own
erObjectInfo, MemberType memberType, const char* edgeName) | |
288 { | |
289 if (memberType == PointerMember) | |
290 return; | |
291 if (memberType == ReferenceMember) | |
292 reportMemoryUsage(object, ownerObjectInfo); | |
293 else { | |
294 if (!object) | |
295 return; | |
296 reportEdge(object, edgeName, memberType); | |
297 if (visited(object)) | |
298 return; | |
299 deferObject(adoptPtr(new Wrapper<T>(object, getObjectType(ownerObjectInf
o)))); | |
300 } | |
301 } | |
302 | |
303 template<typename T> | |
304 void MemoryInstrumentation::addObjectImpl(const OwnPtr<T>* object, MemoryObjectI
nfo* ownerObjectInfo, MemberType memberType, const char* edgeName) | |
305 { | |
306 if (memberType == PointerMember && !visited(object)) | |
307 countObjectSize(object, getObjectType(ownerObjectInfo), sizeof(*object))
; | |
308 addObjectImpl(object->get(), ownerObjectInfo, RetainingPointer, edgeName); | |
309 } | |
310 | |
311 template<typename T> | |
312 void MemoryInstrumentation::addObjectImpl(const RefPtr<T>* object, MemoryObjectI
nfo* ownerObjectInfo, MemberType memberType, const char* edgeName) | |
313 { | |
314 if (memberType == PointerMember && !visited(object)) | |
315 countObjectSize(object, getObjectType(ownerObjectInfo), sizeof(*object))
; | |
316 addObjectImpl(object->get(), ownerObjectInfo, RetainingPointer, edgeName); | |
317 } | |
318 | |
319 template<typename T> | |
320 MemoryInstrumentation::Wrapper<T>::Wrapper(const T* pointer, MemoryObjectType ow
nerObjectType) | |
321 : WrapperBase(ownerObjectType, pointer) | |
322 { | |
323 } | |
324 | |
325 template<typename T> | |
326 void MemoryInstrumentation::Wrapper<T>::callReportMemoryUsage(MemoryObjectInfo*
memoryObjectInfo) | |
327 { | |
328 reportMemoryUsage(static_cast<const T*>(m_pointer), memoryObjectInfo); | |
329 } | |
330 | |
331 // Link time guard for classes with external memory instrumentation. | |
332 template<typename T, size_t inlineCapacity> class Vector; | |
333 template<typename T, size_t inlineCapacity> void reportMemoryUsage(const Vector<
T, inlineCapacity>*, MemoryObjectInfo*); | |
334 | |
335 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTrai
tsArg, typename MappedTraitsArg> class HashMap; | |
336 template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTrai
tsArg, typename MappedTraitsArg> void reportMemoryUsage(const HashMap<KeyArg, Ma
ppedArg, HashArg, KeyTraitsArg, MappedTraitsArg>*, MemoryObjectInfo*); | |
337 | |
338 template<typename ValueArg, typename HashArg, typename TraitsArg> class HashCoun
tedSet; | |
339 template<typename ValueArg, typename HashArg, typename TraitsArg> void reportMem
oryUsage(const HashCountedSet<ValueArg, HashArg, TraitsArg>*, MemoryObjectInfo*)
; | |
340 | |
341 template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListH
ashSet; | |
342 template<typename ValueArg, size_t inlineCapacity, typename HashArg> void report
MemoryUsage(const ListHashSet<ValueArg, inlineCapacity, HashArg>*, MemoryObjectI
nfo*); | |
343 | |
344 class String; | |
345 void reportMemoryUsage(const String*, MemoryObjectInfo*); | |
346 | |
347 class StringImpl; | |
348 void reportMemoryUsage(const StringImpl*, MemoryObjectInfo*); | |
349 | |
350 class AtomicString; | |
351 void reportMemoryUsage(const AtomicString*, MemoryObjectInfo*); | |
352 | |
353 class CString; | |
354 void reportMemoryUsage(const CString*, MemoryObjectInfo*); | |
355 | |
356 class CStringBuffer; | |
357 void reportMemoryUsage(const CStringBuffer*, MemoryObjectInfo*); | |
358 | |
359 class ParsedURL; | |
360 void reportMemoryUsage(const ParsedURL*, MemoryObjectInfo*); | |
361 | |
362 class URLString; | |
363 void reportMemoryUsage(const URLString*, MemoryObjectInfo*); | |
364 | |
365 } // namespace WTF | |
366 | |
367 #endif // !defined(MemoryInstrumentation_h) | |
OLD | NEW |