Title: [137261] trunk
Revision
137261
Author
[email protected]
Date
2012-12-11 00:32:58 -0800 (Tue, 11 Dec 2012)

Log Message

Memory instrumentation: make sure each edge is reported only once
https://bugs.webkit.org/show_bug.cgi?id=104630

Reviewed by Pavel Feldman.

Source/_javascript_Core:

Changed exported symbols for MemoryInstrumentation.

* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:

Source/WTF:

Make sure that outgoing edges are reported only once if we come to the same
object twice: first by an address of a base class and then by a real address
of the object.

* wtf/MemoryInstrumentation.cpp:
(WTF::MemoryInstrumentation::MemoryInstrumentation):
(WTF::MemoryInstrumentation::reportLinkToBuffer):
(WTF::MemoryInstrumentation::InstrumentedPointerBase::InstrumentedPointerBase):
(WTF::MemoryInstrumentation::InstrumentedPointerBase::process):
(WTF::MemoryClassInfo::init):
(WTF::MemoryClassInfo::addRawBuffer):
(WTF::MemoryClassInfo::addPrivateBuffer):
* wtf/MemoryInstrumentation.h:
(InstrumentedPointerBase):
(MemoryInstrumentation):
(InstrumentedPointer):
(WTF::MemoryClassInfo::MemoryClassInfo):
(WTF::MemoryClassInfo::addMember):
(MemoryClassInfo):
(WTF::::InstrumentedPointer):
(WTF::::callReportMemoryUsage):
* wtf/MemoryObjectInfo.h:
(WTF::MemoryObjectInfo::MemoryObjectInfo):
(WTF::MemoryObjectInfo::firstVisit):
(WTF::MemoryObjectInfo::className):
(WTF::MemoryObjectInfo::name):
(WTF::MemoryObjectInfo::setAlreadyVisited):
(MemoryObjectInfo):

Tools:

Test that outgoing edges are reported only once if we come to the same
object twice: first by an address of a base class and then by a real address
of the object.

* TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (137260 => 137261)


--- trunk/Source/_javascript_Core/ChangeLog	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-12-11 08:32:58 UTC (rev 137261)
@@ -1,3 +1,14 @@
+2012-12-10  Yury Semikhatsky  <[email protected]>
+
+        Memory instrumentation: make sure each edge is reported only once
+        https://bugs.webkit.org/show_bug.cgi?id=104630
+
+        Reviewed by Pavel Feldman.
+
+        Changed exported symbols for MemoryInstrumentation.
+
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def:
+
 2012-12-10  Filip Pizlo  <[email protected]>
 
         Don't OSR exit just because a string is a rope

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (137260 => 137261)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-12-11 08:32:58 UTC (rev 137261)
@@ -12,7 +12,7 @@
     ??0DropAllLocks@JSLock@JSC@@QAE@PAVJSGlobalData@2@@Z
     ??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z 
     ??0ErrorHandlingMode@Interpreter@JSC@@QAE@PAVExecState@2@@Z
-    ??0InstrumentedPointerBase@MemoryInstrumentation@WTF@@QAE@PAVMemoryObjectInfo@2@@Z
+    ??0InstrumentedPointerBase@MemoryInstrumentation@WTF@@QAE@PAVMemoryObjectInfo@2@PBX@Z
     ??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z
     ??0JSGlobalObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@PBUGlobalObjectMethodTable@1@@Z
     ??0JSLockHolder@JSC@@QAE@AAVJSGlobalData@1@@Z

Modified: trunk/Source/WTF/ChangeLog (137260 => 137261)


--- trunk/Source/WTF/ChangeLog	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/WTF/ChangeLog	2012-12-11 08:32:58 UTC (rev 137261)
@@ -1,3 +1,39 @@
+2012-12-10  Yury Semikhatsky  <[email protected]>
+
+        Memory instrumentation: make sure each edge is reported only once
+        https://bugs.webkit.org/show_bug.cgi?id=104630
+
+        Reviewed by Pavel Feldman.
+
+        Make sure that outgoing edges are reported only once if we come to the same
+        object twice: first by an address of a base class and then by a real address
+        of the object.
+
+        * wtf/MemoryInstrumentation.cpp:
+        (WTF::MemoryInstrumentation::MemoryInstrumentation):
+        (WTF::MemoryInstrumentation::reportLinkToBuffer):
+        (WTF::MemoryInstrumentation::InstrumentedPointerBase::InstrumentedPointerBase):
+        (WTF::MemoryInstrumentation::InstrumentedPointerBase::process):
+        (WTF::MemoryClassInfo::init):
+        (WTF::MemoryClassInfo::addRawBuffer):
+        (WTF::MemoryClassInfo::addPrivateBuffer):
+        * wtf/MemoryInstrumentation.h:
+        (InstrumentedPointerBase):
+        (MemoryInstrumentation):
+        (InstrumentedPointer):
+        (WTF::MemoryClassInfo::MemoryClassInfo):
+        (WTF::MemoryClassInfo::addMember):
+        (MemoryClassInfo):
+        (WTF::::InstrumentedPointer):
+        (WTF::::callReportMemoryUsage):
+        * wtf/MemoryObjectInfo.h:
+        (WTF::MemoryObjectInfo::MemoryObjectInfo):
+        (WTF::MemoryObjectInfo::firstVisit):
+        (WTF::MemoryObjectInfo::className):
+        (WTF::MemoryObjectInfo::name):
+        (WTF::MemoryObjectInfo::setAlreadyVisited):
+        (MemoryObjectInfo):
+
 2012-12-10  Benjamin Poulain  <[email protected]>
 
         Add convenience methods to use ListHashSet for a LRU cache

Modified: trunk/Source/WTF/wtf/MemoryInstrumentation.cpp (137260 => 137261)


--- trunk/Source/WTF/wtf/MemoryInstrumentation.cpp	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/WTF/wtf/MemoryInstrumentation.cpp	2012-12-11 08:32:58 UTC (rev 137261)
@@ -42,7 +42,7 @@
 
 MemoryInstrumentation::MemoryInstrumentation(MemoryInstrumentationClient* client)
     : m_client(client)
-    , m_rootObjectInfo(adoptPtr(new MemoryObjectInfo(this, 0)))
+    , m_rootObjectInfo(adoptPtr(new MemoryObjectInfo(this, 0, 0)))
 {
 }
 
@@ -67,14 +67,15 @@
 
 void MemoryInstrumentation::reportLinkToBuffer(const void* owner, const void* buffer, MemoryObjectType ownerObjectType, size_t size, const char* nodeName, const char* edgeName)
 {
-    MemoryObjectInfo memoryObjectInfo(this, ownerObjectType);
+    MemoryObjectInfo memoryObjectInfo(this, ownerObjectType, 0);
     memoryObjectInfo.reportObjectInfo(buffer, ownerObjectType, size);
     memoryObjectInfo.setName(nodeName);
     m_client->reportLeaf(owner, memoryObjectInfo, edgeName);
 }
 
-MemoryInstrumentation::InstrumentedPointerBase::InstrumentedPointerBase(MemoryObjectInfo* memoryObjectInfo)
-    : m_ownerObjectType(memoryObjectInfo->objectType())
+MemoryInstrumentation::InstrumentedPointerBase::InstrumentedPointerBase(MemoryObjectInfo* memoryObjectInfo, const void* pointer)
+    : m_pointer(pointer)
+    , m_ownerObjectType(memoryObjectInfo->objectType())
 {
 #if DEBUG_POINTER_INSTRUMENTATION
     m_callStackSize = s_maxCallStackSize;
@@ -84,19 +85,19 @@
 
 void MemoryInstrumentation::InstrumentedPointerBase::process(MemoryInstrumentation* memoryInstrumentation)
 {
-    MemoryObjectInfo memoryObjectInfo(memoryInstrumentation, m_ownerObjectType);
-    const void* originalPointer = callReportMemoryUsage(&memoryObjectInfo);
+    MemoryObjectInfo memoryObjectInfo(memoryInstrumentation, m_ownerObjectType, m_pointer);
+    callReportMemoryUsage(&memoryObjectInfo);
 
-    const void* pointer = memoryObjectInfo.reportedPointer();
-    ASSERT(pointer);
-    if (pointer != originalPointer) {
-        memoryInstrumentation->m_client->reportBaseAddress(originalPointer, pointer);
-        if (memoryInstrumentation->visited(pointer))
+    const void* realAddress = memoryObjectInfo.reportedPointer();
+    ASSERT(realAddress);
+    if (realAddress != m_pointer) {
+        memoryInstrumentation->m_client->reportBaseAddress(m_pointer, realAddress);
+        if (!memoryObjectInfo.firstVisit())
             return;
     }
-    memoryInstrumentation->countObjectSize(pointer, memoryObjectInfo.objectType(), memoryObjectInfo.objectSize());
+    memoryInstrumentation->countObjectSize(realAddress, memoryObjectInfo.objectType(), memoryObjectInfo.objectSize());
     memoryInstrumentation->m_client->reportNode(memoryObjectInfo);
-    if (!memoryInstrumentation->checkCountedObject(pointer)) {
+    if (!memoryInstrumentation->checkCountedObject(realAddress)) {
 #if DEBUG_POINTER_INSTRUMENTATION
         fputs("Unknown object counted:\n", stderr);
         WTFPrintBacktrace(m_callStack, m_callStackSize);
@@ -104,22 +105,26 @@
     }
 }
 
-void MemoryClassInfo::init(const void* pointer, MemoryObjectType objectType, size_t actualSize)
+void MemoryClassInfo::init(const void* objectAddress, MemoryObjectType objectType, size_t actualSize)
 {
-    m_memoryObjectInfo->reportObjectInfo(pointer, objectType, actualSize);
+    m_memoryObjectInfo->reportObjectInfo(objectAddress, objectType, actualSize);
     m_memoryInstrumentation = m_memoryObjectInfo->memoryInstrumentation();
     m_objectType = m_memoryObjectInfo->objectType();
+    m_skipMembers = !m_memoryObjectInfo->firstVisit();
 }
 
 void MemoryClassInfo::addRawBuffer(const void* buffer, size_t size, const char* nodeName, const char* edgeName)
 {
-    m_memoryInstrumentation->addRawBuffer(m_memoryObjectInfo->reportedPointer(), buffer, m_objectType, size, nodeName, edgeName);
+    if (!m_skipMembers)
+        m_memoryInstrumentation->addRawBuffer(m_memoryObjectInfo->reportedPointer(), buffer, m_objectType, size, nodeName, edgeName);
 }
 
 void MemoryClassInfo::addPrivateBuffer(size_t size, MemoryObjectType ownerObjectType, const char* nodeName, const char* edgeName)
 {
     if (!size)
         return;
+    if (m_skipMembers)
+        return;
     if (!ownerObjectType)
         ownerObjectType = m_objectType;
     m_memoryInstrumentation->countObjectSize(0, ownerObjectType, size);

Modified: trunk/Source/WTF/wtf/MemoryInstrumentation.h (137260 => 137261)


--- trunk/Source/WTF/wtf/MemoryInstrumentation.h	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/WTF/wtf/MemoryInstrumentation.h	2012-12-11 08:32:58 UTC (rev 137261)
@@ -79,12 +79,13 @@
 protected:
     class InstrumentedPointerBase {
     public:
-        WTF_EXPORT_PRIVATE explicit InstrumentedPointerBase(MemoryObjectInfo*);
+        WTF_EXPORT_PRIVATE InstrumentedPointerBase(MemoryObjectInfo*, const void* pointer);
         virtual ~InstrumentedPointerBase() { }
         WTF_EXPORT_PRIVATE void process(MemoryInstrumentation*);
 
     protected:
-        virtual const void* callReportMemoryUsage(MemoryObjectInfo*) = 0;
+        virtual void callReportMemoryUsage(MemoryObjectInfo*) = 0;
+        const void* m_pointer;
 
     private:
         const MemoryObjectType m_ownerObjectType;
@@ -107,6 +108,7 @@
 
     WTF_EXPORT_PRIVATE static MemoryObjectType getObjectType(MemoryObjectInfo*);
 
+    friend class MemoryObjectInfo;
     friend class MemoryClassInfo;
     template<typename T> friend void reportMemoryUsage(const T*, MemoryObjectInfo*);
 
@@ -136,10 +138,7 @@
         InstrumentedPointer(const T* pointer, MemoryObjectInfo* ownerObjectInfo);
 
     protected:
-        virtual const void* callReportMemoryUsage(MemoryObjectInfo*) OVERRIDE;
-
-    private:
-        const T* m_pointer;
+        virtual void callReportMemoryUsage(MemoryObjectInfo*) OVERRIDE;
     };
 
     template<typename T> void addObject(const T& t, MemoryObjectInfo* ownerObjectInfo, const char* edgeName) { OwningTraits<T>::addObject(this, t, ownerObjectInfo, edgeName); }
@@ -183,13 +182,15 @@
         : m_memoryObjectInfo(memoryObjectInfo)
         , m_memoryInstrumentation(0)
         , m_objectType(0)
+        , m_skipMembers(false)
     {
         init(pointer, objectType, actualSize);
     }
 
     template<typename M> void addMember(const M& member, const char* edgeName = 0)
     {
-        m_memoryInstrumentation->addObject(member, m_memoryObjectInfo, edgeName);
+        if (!m_skipMembers)
+            m_memoryInstrumentation->addObject(member, m_memoryObjectInfo, edgeName);
     }
     WTF_EXPORT_PRIVATE void addRawBuffer(const void* buffer, size_t, const char* nodeName = 0, const char* edgeName = 0);
     WTF_EXPORT_PRIVATE void addPrivateBuffer(size_t, MemoryObjectType ownerObjectType = 0, const char* nodeName = 0, const char* edgeName = 0);
@@ -202,6 +203,7 @@
     MemoryObjectInfo* m_memoryObjectInfo;
     MemoryInstrumentation* m_memoryInstrumentation;
     MemoryObjectType m_objectType;
+    bool m_skipMembers;
 };
 
 template<typename T>
@@ -241,16 +243,14 @@
 
 template<typename T>
 MemoryInstrumentation::InstrumentedPointer<T>::InstrumentedPointer(const T* pointer, MemoryObjectInfo* ownerObjectInfo)
-    : InstrumentedPointerBase(ownerObjectInfo)
-    , m_pointer(pointer)
+    : InstrumentedPointerBase(ownerObjectInfo, pointer)
 {
 }
 
 template<typename T>
-const void* MemoryInstrumentation::InstrumentedPointer<T>::callReportMemoryUsage(MemoryObjectInfo* memoryObjectInfo)
+void MemoryInstrumentation::InstrumentedPointer<T>::callReportMemoryUsage(MemoryObjectInfo* memoryObjectInfo)
 {
-    reportMemoryUsage(m_pointer, memoryObjectInfo);
-    return m_pointer;
+    reportMemoryUsage(static_cast<const T*>(m_pointer), memoryObjectInfo);
 }
 
 // Link time guard for classes with external memory instrumentation.

Modified: trunk/Source/WTF/wtf/MemoryObjectInfo.h (137260 => 137261)


--- trunk/Source/WTF/wtf/MemoryObjectInfo.h	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Source/WTF/wtf/MemoryObjectInfo.h	2012-12-11 08:32:58 UTC (rev 137261)
@@ -31,6 +31,7 @@
 #ifndef MemoryObjectInfo_h
 #define MemoryObjectInfo_h
 
+#include <wtf/MemoryInstrumentation.h>
 #include <wtf/text/WTFString.h>
 
 namespace WTF {
@@ -42,11 +43,12 @@
 
 class MemoryObjectInfo {
 public:
-    MemoryObjectInfo(MemoryInstrumentation* memoryInstrumentation, MemoryObjectType ownerObjectType)
+    MemoryObjectInfo(MemoryInstrumentation* memoryInstrumentation, MemoryObjectType ownerObjectType, const void* pointer)
         : m_memoryInstrumentation(memoryInstrumentation)
         , m_objectType(ownerObjectType)
         , m_objectSize(0)
-        , m_pointer(0)
+        , m_pointer(pointer)
+        , m_firstVisit(true)
     { }
 
     typedef MemoryClassInfo ClassInfo;
@@ -54,9 +56,12 @@
     MemoryObjectType objectType() const { return m_objectType; }
     size_t objectSize() const { return m_objectSize; }
     const void* reportedPointer() const { return m_pointer; }
+    bool firstVisit() const { return m_firstVisit; }
 
     void setClassName(const String& className) { m_className = className; }
+    const String& className() const { return m_className; }
     void setName(const String& name) { m_name = name; }
+    const String& name() const { return m_name; }
 
     MemoryInstrumentation* memoryInstrumentation() { return m_memoryInstrumentation; }
 
@@ -67,6 +72,8 @@
     void reportObjectInfo(const void* pointer, MemoryObjectType objectType, size_t objectSize)
     {
         if (!m_objectSize) {
+            if (m_pointer != pointer && m_pointer && m_memoryInstrumentation->visited(pointer))
+                m_firstVisit = false;
             m_pointer = pointer;
             m_objectSize = objectSize;
             if (objectType)
@@ -78,6 +85,7 @@
     MemoryObjectType m_objectType;
     size_t m_objectSize;
     const void* m_pointer;
+    bool m_firstVisit;
     String m_className;
     String m_name;
 };

Modified: trunk/Tools/ChangeLog (137260 => 137261)


--- trunk/Tools/ChangeLog	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Tools/ChangeLog	2012-12-11 08:32:58 UTC (rev 137261)
@@ -1,3 +1,16 @@
+2012-12-10  Yury Semikhatsky  <[email protected]>
+
+        Memory instrumentation: make sure each edge is reported only once
+        https://bugs.webkit.org/show_bug.cgi?id=104630
+
+        Reviewed by Pavel Feldman.
+
+        Test that outgoing edges are reported only once if we come to the same
+        object twice: first by an address of a base class and then by a real address
+        of the object.
+
+        * TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp:
+
 2012-12-10  Dana Jansens  <[email protected]>
 
         [chromium] Remove WebCompositorOutputSurface implementations from DRT

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp (137260 => 137261)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp	2012-12-11 08:05:47 UTC (rev 137260)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MemoryInstrumentationTest.cpp	2012-12-11 08:32:58 UTC (rev 137261)
@@ -167,13 +167,21 @@
 class Instrumented {
 public:
     Instrumented() : m_notInstrumented(new NotInstrumented) { }
-    virtual ~Instrumented() { delete m_notInstrumented; }
+    virtual ~Instrumented() { disposeOwnedObject(); }
 
     virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
     {
         MemoryClassInfo info(memoryObjectInfo, this, TestType);
-        info.addMember(m_notInstrumented);
+        memoryObjectInfo->setClassName("Instrumented");
+        info.addMember(m_notInstrumented, "m_notInstrumented");
     }
+
+    void disposeOwnedObject()
+    {
+        delete m_notInstrumented;
+        m_notInstrumented = 0;
+    }
+
     NotInstrumented* m_notInstrumented;
 };
 
@@ -799,6 +807,7 @@
     virtual void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
     {
         MemoryClassInfo info(memoryObjectInfo, this, TestType);
+        Instrumented::reportMemoryUsage(memoryObjectInfo);
     }
 };
 
@@ -814,8 +823,8 @@
 
     helper.addRootObject(descendantPointerOwner);
     helper.addRootObject(ancestorPointerOwner);
-    EXPECT_EQ(sizeof(ClassWithTwoAncestors), helper.reportedSizeForAllTypes());
-    EXPECT_EQ(2u, helper.visitedObjects());
+    EXPECT_EQ(sizeof(ClassWithTwoAncestors) + sizeof(NotInstrumented), helper.reportedSizeForAllTypes());
+    EXPECT_EQ(3u, helper.visitedObjects());
 }
 
 class CheckCountedObjectsClient : public MemoryInstrumentationTestClient {
@@ -837,6 +846,7 @@
 TEST(MemoryInstrumentationTest, checkCountedObjectWithMultipleAncestors)
 {
     OwnPtr<ClassWithTwoAncestors> instance = adoptPtr(new ClassWithTwoAncestors());
+    instance->disposeOwnedObject();
     ClassWithTwoAncestors* descendantPointer = instance.get();
     InstrumentedOwner<ClassWithTwoAncestors*> descendantPointerOwner(descendantPointer);
     Instrumented* ancestorPointer = descendantPointer;
@@ -850,5 +860,49 @@
     EXPECT_TRUE(client.expectedPointerFound());
 }
 
+class TwoPointersToSameInsrumented {
+public:
+    TwoPointersToSameInsrumented()
+        : m_ownPtr(adoptPtr(new ClassWithTwoAncestors()))
+        , m_baseClassPtr(m_ownPtr.get())
+    {
+        EXPECT_NE(static_cast<void*>(m_ownPtr.get()), static_cast<void*>(m_baseClassPtr));
+    }
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        MemoryClassInfo info(memoryObjectInfo, this, TestType);
+        info.addMember(m_ownPtr);
+        info.addMember(m_baseClassPtr);
+    }
+
+private:
+    OwnPtr<ClassWithTwoAncestors> m_ownPtr;
+    Instrumented* m_baseClassPtr;
+};
+
+class CountLinksFromInstrumentedObject : public MemoryInstrumentationTestClient {
+public:
+    CountLinksFromInstrumentedObject() : m_linkCount(0) { }
+    virtual void reportEdge(const void* source, const void* destination, const char* name) OVERRIDE
+    {
+        if (name && !strcmp("m_notInstrumented", name))
+            m_linkCount++;
+    }
+    int linkCount() const { return m_linkCount; }
+
+private:
+    int m_linkCount;
+};
+
+
+TEST(MemoryInstrumentationTest, doNotReportEdgeTwice)
+{
+    OwnPtr<TwoPointersToSameInsrumented> instance = adoptPtr(new TwoPointersToSameInsrumented());
+
+    CountLinksFromInstrumentedObject client;
+    InstrumentationTestImpl instrumentation(&client);
+    instrumentation.addRootObject(instance);
+    EXPECT_EQ(1, client.linkCount());
+}
 } // namespace
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to