Changeset 141992 in webkit


Ignore:
Timestamp:
Feb 6, 2013 5:29:30 AM (11 years ago)
Author:
loislo@chromium.org
Message:

Web Inspector: Native Memory Instrumentation: assign class name to the heap graph node automatically
https://bugs.webkit.org/show_bug.cgi?id=107262

Reviewed by Yury Semikhatsky.

Source/JavaScriptCore:

Source/WTF:

We need a way to calculate class name for a pointer automatically.
Otherwise we need to write className manually in all the instrumentation methods.
And for all reported but not instrumented classes.

C++ can do that for us with help of typeid but unfortunatelly it requires rtti.
There is another way to do that. C++ preprocessor provides a define which has a function name.

For g++ and clang it is PRETTY_FUNCTION.
For MSVC it is FUNCTION.
The content of the string is a function signature.
We can use it because it has the name of the template argument.
The format is sligthly different. That's why I made two different parsers.
One for MSVC the other for GCC, Clang etc.
The other problem is the resulting binary size.
I made very simple function that does the only thing, returns the smallest possible function signature.
Unfortunatelly MSVC doesn't generate template argument name for functions.
It does this only for classes.

  • wtf/MemoryInstrumentation.cpp:

(WTF):
(WTF::className):
(WTF::MemoryClassInfo::callReportObjectInfo):
(WTF::MemoryClassInfo::init):

  • wtf/MemoryInstrumentation.h:

(WTF):
(WTF::FN::fn):
(WTF::fn):
(WTF::MemoryClassInfo::MemoryClassInfo):
(MemoryClassInfo):
(WTF::::reportObjectMemoryUsage):

Location:
trunk/Source
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r141985 r141992  
     12013-02-06  Ilya Tikhonovsky  <loislo@chromium.org>
     2
     3        Web Inspector: Native Memory Instrumentation: assign class name to the heap graph node automatically
     4        https://bugs.webkit.org/show_bug.cgi?id=107262
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreExports.def:
     9
    1102013-02-06  Mike West  <mkwst@chromium.org>
    211
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreExports.def

    r141716 r141992  
    103103    ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
    104104    ?callOnMainThreadAndWait@WTF@@YAXP6AXPAX@Z0@Z
    105     ?callReportObjectInfo@MemoryInstrumentation@WTF@@CAXPAVMemoryObjectInfo@2@PBXPBDI@Z
     105    ?callReportObjectInfo@MemoryClassInfo@WTF@@SAXPAVMemoryObjectInfo@2@PBXPBD2I@Z
    106106    ?cancelCallOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
    107107    ?canShrink@StringBuilder@WTF@@QBE_NXZ
     
    266266    ?init@AtomicString@WTF@@SAXXZ
    267267    ?init@JSGlobalObject@JSC@@AAEXPAVJSObject@2@@Z
    268     ?init@MemoryClassInfo@WTF@@AAEXPBXPBDI@Z
     268    ?init@MemoryClassInfo@WTF@@AAEXPBXPBD1I@Z
    269269    ?initialize@double_conversion@WTF@@YAXXZ
    270270    ?initializeMainThread@WTF@@YAXXZ
  • trunk/Source/WTF/ChangeLog

    r141965 r141992  
     12013-02-06  Ilya Tikhonovsky  <loislo@chromium.org>
     2
     3        Web Inspector: Native Memory Instrumentation: assign class name to the heap graph node automatically
     4        https://bugs.webkit.org/show_bug.cgi?id=107262
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        We need a way to calculate class name for a pointer automatically.
     9        Otherwise we need to write className manually in all the instrumentation methods.
     10        And for all reported but not instrumented classes.
     11
     12        C++ can do that for us with help of typeid but unfortunatelly it requires rtti.
     13        There is another way to do that. C++ preprocessor provides a define which has a function name.
     14
     15        For g++ and clang it is __PRETTY_FUNCTION__.
     16        For MSVC it is __FUNCTION__.
     17        The content of the string is a function signature.
     18        We can use it because it has the name of the template argument.
     19        The format is sligthly different. That's why I made two different parsers.
     20        One for MSVC the other for GCC, Clang etc.
     21        The other problem is the resulting binary size.
     22        I made very simple function that does the only thing, returns the smallest possible function signature.
     23        Unfortunatelly MSVC doesn't generate template argument name for functions.
     24        It does this only for classes.
     25
     26        * wtf/MemoryInstrumentation.cpp:
     27        (WTF):
     28        (WTF::className):
     29        (WTF::MemoryClassInfo::callReportObjectInfo):
     30        (WTF::MemoryClassInfo::init):
     31        * wtf/MemoryInstrumentation.h:
     32        (WTF):
     33        (WTF::FN::fn):
     34        (WTF::fn):
     35        (WTF::MemoryClassInfo::MemoryClassInfo):
     36        (MemoryClassInfo):
     37        (WTF::::reportObjectMemoryUsage):
     38
    1392013-02-05  Mark Lam  <mark.lam@apple.com>
    240
  • trunk/Source/WTF/wtf/MemoryInstrumentation.cpp

    r141539 r141992  
    6060}
    6161
    62 void MemoryInstrumentation::callReportObjectInfo(MemoryObjectInfo* memoryObjectInfo, const void* pointer, MemoryObjectType objectType, size_t objectSize)
    63 {
    64     memoryObjectInfo->reportObjectInfo(pointer, objectType, objectSize);
    65 }
    66 
    6762void MemoryInstrumentation::reportLinkToBuffer(const void* buffer, MemoryObjectType ownerObjectType, size_t size, const char* className, const char* edgeName)
    6863{
     
    122117}
    123118
    124 void MemoryClassInfo::init(const void* objectAddress, MemoryObjectType objectType, size_t actualSize)
    125 {
    126     m_memoryObjectInfo->reportObjectInfo(objectAddress, objectType, actualSize);
     119#if COMPILER(MSVC)
     120static const char* className(const char* functionName, char* buffer, const int maxLength)
     121{
     122    // MSVC generates names like this: 'WTF::FN<class WebCore::SharedBuffer>::fn'
     123    static const char prefix[] = "WTF::FN<";
     124    ASSERT(!strncmp(functionName, prefix, sizeof(prefix) - 1));
     125    const char* begin = strchr(functionName, ' ');
     126    if (!begin) { // Fallback.
     127        strncpy(buffer, functionName, maxLength);
     128        buffer[maxLength - 1] = 0;
     129        return buffer;
     130    }
     131    const char* end = strrchr(begin, '>');
     132    ASSERT(end);
     133    int length = end - begin;
     134    length = length < maxLength ? length : maxLength - 1;
     135    memcpy(buffer, begin, length);
     136    buffer[length] = 0;
     137    return buffer;
     138}
     139#else
     140static const char* className(const char* functionName, char* buffer, const int maxLength)
     141{
     142#if COMPILER(CLANG)
     143    static const char prefix[] = "[T =";
     144#elif COMPILER(GCC)
     145    static const char prefix[] = "[with T =";
     146#else
     147    static const char prefix[] = "T =";
     148#endif
     149    const char* begin = strstr(functionName, prefix);
     150    if (!begin) { // Fallback.
     151        strncpy(buffer, functionName, maxLength);
     152        buffer[maxLength - 1] = 0;
     153        return buffer;
     154    }
     155    begin += sizeof(prefix);
     156    const char* end = strchr(begin, ']');
     157    ASSERT(end);
     158    int length = end - begin;
     159    length = length < maxLength ? length : maxLength - 1;
     160    memcpy(buffer, begin, length);
     161    buffer[length] = 0;
     162    return buffer;
     163}
     164#endif
     165
     166void MemoryClassInfo::callReportObjectInfo(MemoryObjectInfo* memoryObjectInfo, const void* objectAddress, const char* stringWithClassName, MemoryObjectType objectType, size_t actualSize)
     167{
     168    memoryObjectInfo->reportObjectInfo(objectAddress, objectType, actualSize);
     169    char buffer[256];
     170    memoryObjectInfo->setClassName(className(stringWithClassName, buffer, sizeof(buffer)));
     171}
     172
     173void MemoryClassInfo::init(const void* objectAddress, const char* stringWithClassName, MemoryObjectType objectType, size_t actualSize)
     174{
     175    callReportObjectInfo(m_memoryObjectInfo, objectAddress, stringWithClassName, objectType, actualSize);
    127176    m_memoryInstrumentation = m_memoryObjectInfo->memoryInstrumentation();
    128177    m_objectType = m_memoryObjectInfo->objectType();
  • trunk/Source/WTF/wtf/MemoryInstrumentation.h

    r141539 r141992  
    159159    };
    160160
    161     WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const void* pointer, MemoryObjectType, size_t objectSize);
    162 
    163161    template<typename T> class Wrapper : public WrapperBase {
    164162    public:
     
    213211};
    214212
    215 template <>
    216 template <typename T>
    217 void MemoryInstrumentation::InstrumentationSelector<true>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
    218 {
    219     object->reportMemoryUsage(memoryObjectInfo);
    220 }
    221 
    222 template <>
    223 template <typename T>
    224 void MemoryInstrumentation::InstrumentationSelector<false>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
    225 {
    226     callReportObjectInfo(memoryObjectInfo, object, 0, sizeof(T));
    227 }
     213// We are trying to keep the signature of the function as small as possible
     214// because it significantly affects the binary size.
     215// We caluclates class name for 624 classes at the moment.
     216// So one extra byte of the function signature increases the binary size to 624 extra bytes.
     217#if COMPILER(MSVC)
     218template <typename T> struct FN {
     219    static char* fn() { return const_cast<char*>(__FUNCTION__); }
     220};
     221
     222template <typename T> char* fn() { return FN<T>::fn(); }
     223#else
     224template <typename T> char* fn() { return const_cast<char*>(__PRETTY_FUNCTION__); }
     225#endif
    228226
    229227class MemoryClassInfo {
     
    236234        , m_skipMembers(false)
    237235    {
    238         init(pointer, objectType, actualSize);
     236        init(pointer, fn<T>(), objectType, actualSize);
    239237    }
    240238
     
    252250    template<typename M> void ignoreMember(const M&) { }
    253251
     252    WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const void* pointer, const char* stringWithClassName, MemoryObjectType, size_t actualSize);
     253
    254254private:
    255     WTF_EXPORT_PRIVATE void init(const void* pointer, MemoryObjectType, size_t actualSize);
     255    WTF_EXPORT_PRIVATE void init(const void* pointer, const char* stringWithClassName, MemoryObjectType, size_t actualSize);
    256256
    257257    MemoryObjectInfo* m_memoryObjectInfo;
     
    260260    bool m_skipMembers;
    261261};
     262
     263template <>
     264template <typename T>
     265void MemoryInstrumentation::InstrumentationSelector<true>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
     266{
     267    object->reportMemoryUsage(memoryObjectInfo);
     268}
     269
     270template <>
     271template <typename T>
     272void MemoryInstrumentation::InstrumentationSelector<false>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
     273{
     274    MemoryClassInfo::callReportObjectInfo(memoryObjectInfo, object, fn<T>(), 0, sizeof(T));
     275}
    262276
    263277template<typename T>
Note: See TracChangeset for help on using the changeset viewer.