| 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 |