Title: [141992] trunk/Source
Revision
141992
Author
loi...@chromium.org
Date
2013-02-06 05:29:30 -0800 (Wed, 06 Feb 2013)

Log 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/_javascript_Core:

* _javascript_Core.vcproj/_javascript_Core/_javascript_CoreExports.def:

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

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (141991 => 141992)


--- trunk/Source/_javascript_Core/ChangeLog	2013-02-06 13:11:24 UTC (rev 141991)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-02-06 13:29:30 UTC (rev 141992)
@@ -1,3 +1,12 @@
+2013-02-06  Ilya Tikhonovsky  <loi...@chromium.org>
+
+        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.
+
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_CoreExports.def:
+
 2013-02-06  Mike West  <mk...@chromium.org>
 
         Add an ENABLE_NOSNIFF feature flag.

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_CoreExports.def (141991 => 141992)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_CoreExports.def	2013-02-06 13:11:24 UTC (rev 141991)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_CoreExports.def	2013-02-06 13:29:30 UTC (rev 141992)
@@ -102,7 +102,7 @@
     ?callHostFunctionAsConstructor@JSC@@YI_JPAVExecState@1@@Z
     ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
     ?callOnMainThreadAndWait@WTF@@YAXP6AXPAX@Z0@Z
-    ?callReportObjectInfo@MemoryInstrumentation@WTF@@CAXPAVMemoryObjectInfo@2@PBXPBDI@Z
+    ?callReportObjectInfo@MemoryClassInfo@WTF@@SAXPAVMemoryObjectInfo@2@PBXPBD2I@Z
     ?cancelCallOnMainThread@WTF@@YAXP6AXPAX@Z0@Z
     ?canShrink@StringBuilder@WTF@@QBE_NXZ
     ?capacity@Heap@JSC@@QAEIXZ
@@ -265,7 +265,7 @@
     ?indefiniteTime@MediaTime@WTF@@SAABV12@XZ 
     ?init@AtomicString@WTF@@SAXXZ
     ?init@JSGlobalObject@JSC@@AAEXPAVJSObject@2@@Z
-    ?init@MemoryClassInfo@WTF@@AAEXPBXPBDI@Z
+    ?init@MemoryClassInfo@WTF@@AAEXPBXPBD1I@Z
     ?initialize@double_conversion@WTF@@YAXXZ
     ?initializeMainThread@WTF@@YAXXZ
     ?initializeThreading@JSC@@YAXXZ

Modified: trunk/Source/WTF/ChangeLog (141991 => 141992)


--- trunk/Source/WTF/ChangeLog	2013-02-06 13:11:24 UTC (rev 141991)
+++ trunk/Source/WTF/ChangeLog	2013-02-06 13:29:30 UTC (rev 141992)
@@ -1,3 +1,41 @@
+2013-02-06  Ilya Tikhonovsky  <loi...@chromium.org>
+
+        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.
+
+        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):
+
 2013-02-05  Mark Lam  <mark....@apple.com>
 
         Fix EnumClass so that it can be used with switch statements.

Modified: trunk/Source/WTF/wtf/MemoryInstrumentation.cpp (141991 => 141992)


--- trunk/Source/WTF/wtf/MemoryInstrumentation.cpp	2013-02-06 13:11:24 UTC (rev 141991)
+++ trunk/Source/WTF/wtf/MemoryInstrumentation.cpp	2013-02-06 13:29:30 UTC (rev 141992)
@@ -59,11 +59,6 @@
     return objectInfo->objectType();
 }
 
-void MemoryInstrumentation::callReportObjectInfo(MemoryObjectInfo* memoryObjectInfo, const void* pointer, MemoryObjectType objectType, size_t objectSize)
-{
-    memoryObjectInfo->reportObjectInfo(pointer, objectType, objectSize);
-}
-
 void MemoryInstrumentation::reportLinkToBuffer(const void* buffer, MemoryObjectType ownerObjectType, size_t size, const char* className, const char* edgeName)
 {
     MemoryObjectInfo memoryObjectInfo(this, ownerObjectType, 0);
@@ -121,9 +116,63 @@
     memoryInstrumentation->m_client->reportNode(memoryObjectInfo);
 }
 
-void MemoryClassInfo::init(const void* objectAddress, MemoryObjectType objectType, size_t actualSize)
+#if COMPILER(MSVC)
+static const char* className(const char* functionName, char* buffer, const int maxLength)
 {
-    m_memoryObjectInfo->reportObjectInfo(objectAddress, objectType, actualSize);
+    // MSVC generates names like this: 'WTF::FN<class WebCore::SharedBuffer>::fn'
+    static const char prefix[] = "WTF::FN<";
+    ASSERT(!strncmp(functionName, prefix, sizeof(prefix) - 1));
+    const char* begin = strchr(functionName, ' ');
+    if (!begin) { // Fallback.
+        strncpy(buffer, functionName, maxLength);
+        buffer[maxLength - 1] = 0;
+        return buffer;
+    }
+    const char* end = strrchr(begin, '>');
+    ASSERT(end);
+    int length = end - begin;
+    length = length < maxLength ? length : maxLength - 1;
+    memcpy(buffer, begin, length);
+    buffer[length] = 0;
+    return buffer;
+}
+#else
+static const char* className(const char* functionName, char* buffer, const int maxLength)
+{
+#if COMPILER(CLANG)
+    static const char prefix[] = "[T =";
+#elif COMPILER(GCC)
+    static const char prefix[] = "[with T =";
+#else
+    static const char prefix[] = "T =";
+#endif
+    const char* begin = strstr(functionName, prefix);
+    if (!begin) { // Fallback.
+        strncpy(buffer, functionName, maxLength);
+        buffer[maxLength - 1] = 0;
+        return buffer;
+    }
+    begin += sizeof(prefix);
+    const char* end = strchr(begin, ']');
+    ASSERT(end);
+    int length = end - begin;
+    length = length < maxLength ? length : maxLength - 1;
+    memcpy(buffer, begin, length);
+    buffer[length] = 0;
+    return buffer;
+}
+#endif
+
+void MemoryClassInfo::callReportObjectInfo(MemoryObjectInfo* memoryObjectInfo, const void* objectAddress, const char* stringWithClassName, MemoryObjectType objectType, size_t actualSize)
+{
+    memoryObjectInfo->reportObjectInfo(objectAddress, objectType, actualSize);
+    char buffer[256];
+    memoryObjectInfo->setClassName(className(stringWithClassName, buffer, sizeof(buffer)));
+}
+
+void MemoryClassInfo::init(const void* objectAddress, const char* stringWithClassName, MemoryObjectType objectType, size_t actualSize)
+{
+    callReportObjectInfo(m_memoryObjectInfo, objectAddress, stringWithClassName, objectType, actualSize);
     m_memoryInstrumentation = m_memoryObjectInfo->memoryInstrumentation();
     m_objectType = m_memoryObjectInfo->objectType();
     m_skipMembers = !m_memoryObjectInfo->firstVisit();

Modified: trunk/Source/WTF/wtf/MemoryInstrumentation.h (141991 => 141992)


--- trunk/Source/WTF/wtf/MemoryInstrumentation.h	2013-02-06 13:11:24 UTC (rev 141991)
+++ trunk/Source/WTF/wtf/MemoryInstrumentation.h	2013-02-06 13:29:30 UTC (rev 141992)
@@ -158,8 +158,6 @@
         template <typename T> static void reportObjectMemoryUsage(const T*, MemoryObjectInfo*);
     };
 
-    WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const void* pointer, MemoryObjectType, size_t objectSize);
-
     template<typename T> class Wrapper : public WrapperBase {
     public:
         Wrapper(const T* pointer, MemoryObjectType);
@@ -212,19 +210,19 @@
     MemoryInstrumentationClient* m_client;
 };
 
-template <>
-template <typename T>
-void MemoryInstrumentation::InstrumentationSelector<true>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
-{
-    object->reportMemoryUsage(memoryObjectInfo);
-}
+// We are trying to keep the signature of the function as small as possible
+// because it significantly affects the binary size.
+// We caluclates class name for 624 classes at the moment.
+// So one extra byte of the function signature increases the binary size to 624 extra bytes.
+#if COMPILER(MSVC)
+template <typename T> struct FN {
+    static char* fn() { return const_cast<char*>(__FUNCTION__); }
+};
 
-template <>
-template <typename T>
-void MemoryInstrumentation::InstrumentationSelector<false>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
-{
-    callReportObjectInfo(memoryObjectInfo, object, 0, sizeof(T));
-}
+template <typename T> char* fn() { return FN<T>::fn(); }
+#else
+template <typename T> char* fn() { return const_cast<char*>(__PRETTY_FUNCTION__); }
+#endif
 
 class MemoryClassInfo {
 public:
@@ -235,7 +233,7 @@
         , m_objectType(0)
         , m_skipMembers(false)
     {
-        init(pointer, objectType, actualSize);
+        init(pointer, fn<T>(), objectType, actualSize);
     }
 
     template<typename M> void addMember(const M& member, const char* edgeName = 0)
@@ -251,8 +249,10 @@
     void addWeakPointer(void*) { }
     template<typename M> void ignoreMember(const M&) { }
 
+    WTF_EXPORT_PRIVATE static void callReportObjectInfo(MemoryObjectInfo*, const void* pointer, const char* stringWithClassName, MemoryObjectType, size_t actualSize);
+
 private:
-    WTF_EXPORT_PRIVATE void init(const void* pointer, MemoryObjectType, size_t actualSize);
+    WTF_EXPORT_PRIVATE void init(const void* pointer, const char* stringWithClassName, MemoryObjectType, size_t actualSize);
 
     MemoryObjectInfo* m_memoryObjectInfo;
     MemoryInstrumentation* m_memoryInstrumentation;
@@ -260,6 +260,20 @@
     bool m_skipMembers;
 };
 
+template <>
+template <typename T>
+void MemoryInstrumentation::InstrumentationSelector<true>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
+{
+    object->reportMemoryUsage(memoryObjectInfo);
+}
+
+template <>
+template <typename T>
+void MemoryInstrumentation::InstrumentationSelector<false>::reportObjectMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
+{
+    MemoryClassInfo::callReportObjectInfo(memoryObjectInfo, object, fn<T>(), 0, sizeof(T));
+}
+
 template<typename T>
 void reportMemoryUsage(const T* object, MemoryObjectInfo* memoryObjectInfo)
 {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to