Bug 1196430 - part 4 - record allocation stacks for classes in XPCOM_MEM_LOG_CLASSES; r=mccr8
authorNathan Froyd <froydnj@mozilla.com>
Wed, 26 Aug 2015 18:47:03 -0400
changeset 294403 ecd7d8204d45eaa7c44031eb8024afe1351b99fb
parent 294402 f7734f2e5b0ce89339beda1a651b596cb9edc287
child 294404 c14dc117d23f191e6241bd20bce9a7a90eba83b3
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1196430
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1196430 - part 4 - record allocation stacks for classes in XPCOM_MEM_LOG_CLASSES; r=mccr8
xpcom/base/nsTraceRefcnt.cpp
--- a/xpcom/base/nsTraceRefcnt.cpp
+++ b/xpcom/base/nsTraceRefcnt.cpp
@@ -30,16 +30,19 @@
 #include <unistd.h>
 #endif
 
 #include "mozilla/Atomics.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BlockingResourceBase.h"
 #include "mozilla/PoisonIOInterposer.h"
 
+#include <string>
+#include <vector>
+
 #ifdef HAVE_DLOPEN
 #include <dlfcn.h>
 #endif
 
 #ifdef MOZ_DMD
 #include "base/process_util.h"
 #include "nsMemoryInfoDumper.h"
 #endif
@@ -103,27 +106,34 @@ static unsigned gActivityTLS = BAD_TLS_I
 static bool gInitialized;
 static nsrefcnt gInitCount;
 
 static FILE* gBloatLog = nullptr;
 static FILE* gRefcntsLog = nullptr;
 static FILE* gAllocLog = nullptr;
 static FILE* gCOMPtrLog = nullptr;
 
+static void
+WalkTheStackSavingLocations(std::vector<void*>& aLocations);
+
 struct SerialNumberRecord
 {
   SerialNumberRecord()
     : serialNumber(++gNextSerialNumber)
     , refCount(0)
     , COMPtrCount(0)
   {}
 
   intptr_t serialNumber;
   int32_t refCount;
   int32_t COMPtrCount;
+  // We use std:: classes here rather than the XPCOM equivalents because the
+  // XPCOM equivalents do leak-checking, and if you try to leak-check while
+  // leak-checking, you're gonna have a bad time.
+  std::vector<void*> allocationStack;
 };
 
 struct nsTraceRefcntStats
 {
   uint64_t mCreates;
   uint64_t mDestroys;
 
   bool HaveLeaks() const
@@ -582,16 +592,17 @@ GetSerialNumber(void* aPtr, bool aCreate
 {
   PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers,
                                             HashNumber(aPtr),
                                             aPtr);
   if (hep && *hep) {
     return reinterpret_cast<SerialNumberRecord*>((*hep)->value)->serialNumber;
   } else if (aCreate) {
     SerialNumberRecord* record = new SerialNumberRecord();
+    WalkTheStackSavingLocations(record->allocationStack);
     PL_HashTableRawAdd(gSerialNumbers, hep, HashNumber(aPtr),
                        aPtr, reinterpret_cast<void*>(record));
     return gNextSerialNumber;
   }
   return 0;
 }
 
 static int32_t*
@@ -866,16 +877,24 @@ PrintStackFrameCached(uint32_t aFrameNum
 {
   auto stream = static_cast<FILE*>(aClosure);
   static const size_t buflen = 1024;
   char buf[buflen];
   gCodeAddressService->GetLocation(aFrameNumber, aPC, buf, buflen);
   fprintf(stream, "    %s\n", buf);
   fflush(stream);
 }
+
+static void
+RecordStackFrame(uint32_t /*aFrameNumber*/, void* aPC, void* /*aSP*/,
+                 void* aClosure)
+{
+  auto locations = static_cast<std::vector<void*>*>(aClosure);
+  locations->push_back(aPC);
+}
 #endif
 
 }
 
 void
 nsTraceRefcnt::WalkTheStack(FILE* aStream)
 {
 #ifdef MOZ_STACKWALKING
@@ -891,16 +910,32 @@ nsTraceRefcnt::WalkTheStackCached(FILE* 
   if (!gCodeAddressService) {
     gCodeAddressService = new WalkTheStackCodeAddressService();
   }
   MozStackWalk(PrintStackFrameCached, /* skipFrames */ 2, /* maxFrames */ 0,
                aStream, 0, nullptr);
 #endif
 }
 
+static void
+WalkTheStackSavingLocations(std::vector<void*>& aLocations)
+{
+#ifdef MOZ_STACKWALKING
+  if (!gCodeAddressService) {
+    gCodeAddressService = new WalkTheStackCodeAddressService();
+  }
+  static const int kFramesToSkip =
+    0 +                         // this frame gets inlined
+    1 +                         // GetSerialNumber
+    1;                          // NS_LogCtor
+  MozStackWalk(RecordStackFrame, kFramesToSkip, /* maxFrames */ 0,
+               &aLocations, 0, nullptr);
+#endif
+}
+
 //----------------------------------------------------------------------
 
 // This thing is exported by libstdc++
 // Yes, this is a gcc only hack
 #if defined(MOZ_DEMANGLE_SYMBOLS)
 #include <cxxabi.h>
 #include <stdlib.h> // for free()
 #endif // MOZ_DEMANGLE_SYMBOLS