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