Bug 1062709 (part 1, attempt 2) - Add a frame number argument to NS_WalkStackCallback. r=dbaron.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 10 Sep 2014 21:47:01 -0700
changeset 233436 4ca3b16e24bddaae93abf3efe49f69df01cd4642
parent 233435 ef1cd14c8cac8a4bf009bfcda46d1628cc637aa1
child 233437 0b61bbe1dda70ac8b27e0199c892a527d70aac53
push id611
push userraliiev@mozilla.com
push dateMon, 05 Jan 2015 23:23:16 +0000
treeherdermozilla-release@345cd3b9c445 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1062709
milestone35.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 1062709 (part 1, attempt 2) - Add a frame number argument to NS_WalkStackCallback. r=dbaron.
memory/replace/dmd/DMD.cpp
security/sandbox/win/src/warnonlysandbox/wosCallbacks.h
toolkit/xre/nsSigHandlers.cpp
tools/profiler/TableTicker.cpp
tools/trace-malloc/lib/nsTraceMalloc.c
xpcom/base/CodeAddressService.h
xpcom/base/nsStackWalk.cpp
xpcom/base/nsStackWalk.h
xpcom/base/nsTraceRefcnt.cpp
xpcom/build/LateWriteChecks.cpp
xpcom/glue/BlockingResourceBase.cpp
xpcom/glue/BlockingResourceBase.h
xpcom/threads/HangMonitor.cpp
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -714,22 +714,24 @@ public:
   static bool match(const StackTrace* const& aA,
                     const StackTrace* const& aB)
   {
     return aA->mLength == aB->mLength &&
            memcmp(aA->mPcs, aB->mPcs, aA->Size()) == 0;
   }
 
 private:
-  static void StackWalkCallback(void* aPc, void* aSp, void* aClosure)
+  static void StackWalkCallback(uint32_t aFrameNumber, void* aPc, void* aSp,
+                                void* aClosure)
   {
     StackTrace* st = (StackTrace*) aClosure;
     MOZ_ASSERT(st->mLength < MaxFrames);
     st->mPcs[st->mLength] = aPc;
     st->mLength++;
+    MOZ_ASSERT(st->mLength == aFrameNumber);
   }
 
   static int Cmp(const void* aA, const void* aB)
   {
     const void* const a = *static_cast<const void* const*>(aA);
     const void* const b = *static_cast<const void* const*>(aB);
     if (a < b) return -1;
     if (a > b) return  1;
@@ -750,17 +752,17 @@ StackTrace::Print(const Writer& aWriter,
   if (mLength == 0) {
     W("    (empty)\n");  // StackTrace::Get() must have failed
     return;
   }
 
   static const size_t buflen = 1024;
   char buf[buflen];
   for (uint32_t i = 0; i < mLength; i++) {
-    aLocService->GetLocation(Pc(i), buf, buflen);
+    aLocService->GetLocation(i + 1, Pc(i), buf, buflen);
     aWriter.Write("    %s\n", buf);
   }
 }
 
 /* static */ const StackTrace*
 StackTrace::Get(Thread* aT)
 {
   MOZ_ASSERT(gStateLock->IsLocked());
@@ -1569,17 +1571,18 @@ Options::BadArg(const char* aArg)
 }
 
 //---------------------------------------------------------------------------
 // DMD start-up
 //---------------------------------------------------------------------------
 
 #ifdef XP_MACOSX
 static void
-NopStackWalkCallback(void* aPc, void* aSp, void* aClosure)
+NopStackWalkCallback(uint32_t aFrameNumber, void* aPc, void* aSp,
+                     void* aClosure)
 {
 }
 #endif
 
 // Note that fopen() can allocate.
 static FILE*
 OpenOutputFile(const char* aFilename)
 {
--- a/security/sandbox/win/src/warnonlysandbox/wosCallbacks.h
+++ b/security/sandbox/win/src/warnonlysandbox/wosCallbacks.h
@@ -54,23 +54,24 @@ SetProvideLogFunctionCb(ProvideLogFuncti
   sProvideLogFunctionCb = aProvideLogFunctionCb;
 }
 
 #ifdef MOZ_STACKWALKING
 static uint32_t sStackTraceDepth = 0;
 
 // NS_WalkStackCallback to write a formatted stack frame to an ostringstream.
 static void
-StackFrameToOStringStream(void* aPC, void* aSP, void* aClosure)
+StackFrameToOStringStream(uint32_t aFrameNumber, void* aPC, void* aSP,
+                          void* aClosure)
 {
   std::ostringstream* stream = static_cast<std::ostringstream*>(aClosure);
   nsCodeAddressDetails details;
   char buf[1024];
   NS_DescribeCodeAddress(aPC, &details);
-  NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
+  NS_FormatCodeAddressDetails(aFrameNumber, aPC, &details, buf, sizeof(buf));
   *stream << "--" << buf;
 }
 #endif
 
 // Log to the browser console and, if DEBUG build, stderr.
 static void
 Log(const char* aMessageType,
     const char* aFunctionName,
--- a/toolkit/xre/nsSigHandlers.cpp
+++ b/toolkit/xre/nsSigHandlers.cpp
@@ -51,23 +51,24 @@ static unsigned int _gdb_sleep_duration 
 #include "nsStackWalk.h"
 
 // NB: keep me up to date with the same variable in
 // ipc/chromium/chrome/common/ipc_channel_posix.cc
 static const int kClientChannelFd = 3;
 
 extern "C" {
 
-static void PrintStackFrame(void *aPC, void *aSP, void *aClosure)
+static void PrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP,
+                            void *aClosure)
 {
   char buf[1024];
   nsCodeAddressDetails details;
 
   NS_DescribeCodeAddress(aPC, &details);
-  NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
+  NS_FormatCodeAddressDetails(aFrameNumber, aPC, &details, buf, sizeof(buf));
   fputs(buf, stdout);
 }
 
 }
 
 void
 ah_crap_handler(int signum)
 {
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -538,17 +538,18 @@ void mergeStacksIntoProfile(ThreadProfil
     MOZ_ASSERT(nativeIndex >= 0);
     aProfile.addTag(ProfileEntry('l', (void*)aNativeStack.pc_array[nativeIndex]));
     nativeIndex--;
   }
 }
 
 #ifdef USE_NS_STACKWALK
 static
-void StackWalkCallback(void* aPC, void* aSP, void* aClosure)
+void StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP,
+                       void* aClosure)
 {
   NativeStack* nativeStack = static_cast<NativeStack*>(aClosure);
   MOZ_ASSERT(nativeStack->count < nativeStack->size);
   nativeStack->sp_array[nativeStack->count] = aSP;
   nativeStack->pc_array[nativeStack->count] = aPC;
   nativeStack->count++;
 }
 
@@ -562,18 +563,21 @@ void TableTicker::doNativeBacktrace(Thre
   void* sp_array[1000];
   NativeStack nativeStack = {
     pc_array,
     sp_array,
     mozilla::ArrayLength(pc_array),
     0
   };
 
-  // Start with the current function.
-  StackWalkCallback(aSample->pc, aSample->sp, &nativeStack);
+  // Start with the current function. We use 0 as the frame number here because
+  // the FramePointerStackWalk() and NS_StackWalk() calls below will use 1..N.
+  // This is a bit weird but it doesn't matter because StackWalkCallback()
+  // doesn't use the frame number argument.
+  StackWalkCallback(/* frameNumber */ 0, aSample->pc, aSample->sp, &nativeStack);
 
   uint32_t maxFrames = uint32_t(nativeStack.size - nativeStack.count);
 #ifdef XP_MACOSX
   pthread_t pt = GetProfiledThread(aSample->threadProfile->GetPlatformData());
   void *stackEnd = reinterpret_cast<void*>(-1);
   if (pt)
     stackEnd = static_cast<char*>(pthread_get_stackaddr_np(pt));
   nsresult rv = NS_OK;
--- a/tools/trace-malloc/lib/nsTraceMalloc.c
+++ b/tools/trace-malloc/lib/nsTraceMalloc.c
@@ -888,17 +888,17 @@ calltree(void **stack, size_t num_stack_
     return NULL;
 }
 
 /*
  * Buffer the stack from top at low index to bottom at high, so that we can
  * reverse it in calltree.
  */
 static void
-stack_callback(void *pc, void *sp, void *closure)
+stack_callback(uint32_t frameNumber, void *pc, void *sp, void *closure)
 {
     stack_buffer_info *info = (stack_buffer_info*) closure;
 
     /*
      * If we run out of buffer, keep incrementing entries so that
      * backtrace can call us again with a bigger buffer.
      */
     if (info->entries < info->size)
--- a/xpcom/base/CodeAddressService.h
+++ b/xpcom/base/CodeAddressService.h
@@ -127,17 +127,18 @@ class CodeAddressService
   size_t mNumCacheMisses;
 
 public:
   CodeAddressService()
     : mEntries(), mNumCacheHits(0), mNumCacheMisses(0)
   {
   }
 
-  void GetLocation(const void* aPc, char* aBuf, size_t aBufLen)
+  void GetLocation(uint32_t aFrameNumber, const void* aPc, char* aBuf,
+                   size_t aBufLen)
   {
     MOZ_ASSERT(DescribeCodeAddressLock::IsLocked());
 
     uint32_t index = HashGeneric(aPc) & kMask;
     MOZ_ASSERT(index < kNumEntries);
     Entry& entry = mEntries[index];
 
     if (!entry.mInUse || entry.mPc != aPc) {
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -49,17 +49,17 @@ static CriticalAddress gCriticalAddress;
 
 typedef void
 malloc_logger_t(uint32_t aType,
                 uintptr_t aArg1, uintptr_t aArg2, uintptr_t aArg3,
                 uintptr_t aResult, uint32_t aNumHotFramesToSkip);
 extern malloc_logger_t* malloc_logger;
 
 static void
-stack_callback(void* aPc, void* aSp, void* aClosure)
+stack_callback(uint32_t aFrameNumber, void* aPc, void* aSp, void* aClosure)
 {
   const char* name = static_cast<char*>(aClosure);
   Dl_info info;
 
   // On Leopard dladdr returns the wrong value for "new_sem_from_pool". The
   // stack shows up as having two pthread_cond_wait$UNIX2003 frames. The
   // correct one is the first that we find on our way up, so the
   // following check for gCriticalAddress.mAddr is critical.
@@ -607,17 +607,17 @@ NS_StackWalk(NS_WalkStackCallback aCallb
 
     ::CloseHandle(data.eventStart);
     ::CloseHandle(data.eventEnd);
   }
 
   ::CloseHandle(myThread);
 
   for (uint32_t i = 0; i < data.pc_count; ++i) {
-    (*aCallback)(data.pcs[i], data.sps[i], aClosure);
+    (*aCallback)(i + 1, data.pcs[i], data.sps[i], aClosure);
   }
 
   return data.pc_count == 0 ? NS_ERROR_FAILURE : NS_OK;
 }
 
 
 static BOOL CALLBACK
 callbackEspecial64(
@@ -823,17 +823,18 @@ NS_DescribeCodeAddress(void* aPC, nsCode
     aDetails->foffset = static_cast<ptrdiff_t>(displacement);
   }
 
   LeaveCriticalSection(&gDbgHelpCS); // release our lock
   return NS_OK;
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_FormatCodeAddressDetails(void* aPC, const nsCodeAddressDetails* aDetails,
+NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
+                            const nsCodeAddressDetails* aDetails,
                             char* aBuffer, uint32_t aBufferSize)
 {
   if (aDetails->function[0]) {
     _snprintf(aBuffer, aBufferSize, "%s+0x%08lX [%s +0x%016lX]",
               aDetails->function, aDetails->foffset,
               aDetails->library, aDetails->loffset);
   } else if (aDetails->library[0]) {
     _snprintf(aBuffer, aBufferSize, "UNKNOWN [%s +0x%016lX]",
@@ -942,18 +943,18 @@ FramePointerStackWalk(NS_WalkStackCallba
     if (IsCriticalAddress(pc)) {
       return NS_ERROR_UNEXPECTED;
     }
     if (--skip < 0) {
       // Assume that the SP points to the BP of the function
       // it called. We can't know the exact location of the SP
       // but this should be sufficient for our use the SP
       // to order elements on the stack.
-      (*aCallback)(pc, bp, aClosure);
       numFrames++;
+      (*aCallback)(numFrames, pc, bp, aClosure);
       if (aMaxFrames != 0 && numFrames == aMaxFrames) {
         break;
       }
     }
     bp = next;
   }
   return numFrames == 0 ? NS_ERROR_FAILURE : NS_OK;
 }
@@ -986,17 +987,16 @@ NS_StackWalk(NS_WalkStackCallback aCallb
   void* stackEnd;
 #if HAVE___LIBC_STACK_END
   stackEnd = __libc_stack_end;
 #else
   stackEnd = reinterpret_cast<void*>(-1);
 #endif
   return FramePointerStackWalk(aCallback, aSkipFrames, aMaxFrames,
                                aClosure, bp, stackEnd);
-
 }
 
 #elif defined(HAVE__UNWIND_BACKTRACE)
 
 // libgcc_s.so symbols _Unwind_Backtrace@@GCC_3.3 and _Unwind_GetIP@@GCC_3.0
 #include <unwind.h>
 
 struct unwind_info
@@ -1018,18 +1018,18 @@ unwind_callback(struct _Unwind_Context* 
   if (IsCriticalAddress(pc)) {
     info->isCriticalAbort = true;
     // We just want to stop the walk, so any error code will do.  Using
     // _URC_NORMAL_STOP would probably be the most accurate, but it is not
     // defined on Android for ARM.
     return _URC_FOREIGN_EXCEPTION_CAUGHT;
   }
   if (--info->skip < 0) {
-    (*info->callback)(pc, nullptr, info->closure);
     info->numFrames++;
+    (*info->callback)(info->numFrames, pc, nullptr, info->closure);
     if (info->maxFrames != 0 && info->numFrames == info->maxFrames) {
       // Again, any error code that stops the walk will do.
       return _URC_FOREIGN_EXCEPTION_CAUGHT;
     }
   }
   return _URC_NO_REASON;
 }
 
@@ -1098,17 +1098,18 @@ NS_DescribeCodeAddress(void* aPC, nsCode
     PL_strncpyz(aDetails->function, symbol, sizeof(aDetails->function));
   }
 
   aDetails->foffset = (char*)aPC - (char*)info.dli_saddr;
   return NS_OK;
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_FormatCodeAddressDetails(void* aPC, const nsCodeAddressDetails* aDetails,
+NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
+                            const nsCodeAddressDetails* aDetails,
                             char* aBuffer, uint32_t aBufferSize)
 {
   if (!aDetails->library[0]) {
     snprintf(aBuffer, aBufferSize, "UNKNOWN %p\n", aPC);
   } else if (!aDetails->function[0]) {
     snprintf(aBuffer, aBufferSize, "UNKNOWN [%s +0x%08" PRIXPTR "]\n",
              aDetails->library, aDetails->loffset);
   } else {
@@ -1149,16 +1150,17 @@ NS_DescribeCodeAddress(void* aPC, nsCode
   aDetails->filename[0] = '\0';
   aDetails->lineno = 0;
   aDetails->function[0] = '\0';
   aDetails->foffset = 0;
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_FormatCodeAddressDetails(void* aPC, const nsCodeAddressDetails* aDetails,
+NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
+                            const nsCodeAddressDetails* aDetails,
                             char* aBuffer, uint32_t aBufferSize)
 {
   aBuffer[0] = '\0';
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 #endif
--- a/xpcom/base/nsStackWalk.h
+++ b/xpcom/base/nsStackWalk.h
@@ -13,21 +13,30 @@
 
 #include "nscore.h"
 #include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-// aSP will be the best approximation possible of what the stack pointer will be
-// pointing to when the execution returns to executing that at that PC.
-// If no approximation can be made it will be nullptr.
+/**
+ * The callback for NS_StackWalk.
+ *
+ * @param aFrameNumber  The frame number (starts at 1, not 0).
+ * @param aPC           The program counter value.
+ * @param aSP           The best approximation possible of what the stack
+ *                      pointer will be pointing to when the execution returns
+ *                      to executing that at aPC. If no approximation can
+ *                      be made it will be nullptr.
+ * @param aClosure      Extra data passed in via NS_StackWalk().
+ */
 typedef void
-(*NS_WalkStackCallback)(void* aPC, void* aSP, void* aClosure);
+(*NS_WalkStackCallback)(uint32_t aFrameNumber, void* aPC, void* aSP,
+                        void* aClosure);
 
 /**
  * Call aCallback for the C/C++ stack frames on the current thread, from
  * the caller of NS_StackWalk to main (or above).
  *
  * @param aCallback    Callback function, called once per frame.
  * @param aSkipFrames  Number of initial frames to skip.  0 means that
  *                     the first callback will be for the caller of
@@ -104,27 +113,29 @@ NS_DescribeCodeAddress(void* aPC, nsCode
 
 /**
  * Format the information about a code address in a format suitable for
  * stack traces on the current platform.  When available, this string
  * should contain the function name, source file, and line number.  When
  * these are not available, library and offset should be reported, if
  * possible.
  *
- * @param aPC         The code address.
- * @param aDetails    The value filled in by NS_DescribeCodeAddress(aPC).
- * @param aBuffer     A string to be filled in with the description.
- *                    The string will always be null-terminated.
- * @param aBufferSize The size, in bytes, of aBuffer, including
- *                    room for the terminating null.  If the information
- *                    to be printed would be larger than aBuffer, it
- *                    will be truncated so that aBuffer[aBufferSize-1]
- *                    is the terminating null.
+ * @param aFrameNumber The frame number (starts at 1, not 0).
+ * @param aPC          The code address.
+ * @param aDetails     The value filled in by NS_DescribeCodeAddress(aPC).
+ * @param aBuffer      A string to be filled in with the description.
+ *                     The string will always be null-terminated.
+ * @param aBufferSize  The size, in bytes, of aBuffer, including
+ *                     room for the terminating null.  If the information
+ *                     to be printed would be larger than aBuffer, it
+ *                     will be truncated so that aBuffer[aBufferSize-1]
+ *                     is the terminating null.
  */
 XPCOM_API(nsresult)
-NS_FormatCodeAddressDetails(void* aPC, const nsCodeAddressDetails* aDetails,
+NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
+                            const nsCodeAddressDetails* aDetails,
                             char* aBuffer, uint32_t aBufferSize);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* !defined(nsStackWalk_h_) */
--- a/xpcom/base/nsTraceRefcnt.cpp
+++ b/xpcom/base/nsTraceRefcnt.cpp
@@ -924,34 +924,35 @@ InitTraceLog()
 }
 
 #endif
 
 extern "C" {
 
 #ifdef MOZ_STACKWALKING
 static void
-PrintStackFrame(void* aPC, void* aSP, void* aClosure)
+PrintStackFrame(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure)
 {
   FILE* stream = (FILE*)aClosure;
   nsCodeAddressDetails details;
   char buf[1024];
 
   NS_DescribeCodeAddress(aPC, &details);
-  NS_FormatCodeAddressDetails(aPC, &details, buf, sizeof(buf));
+  NS_FormatCodeAddressDetails(aFrameNumber, aPC, &details, buf, sizeof(buf));
   fputs(buf, stream);
 }
 
 static void
-PrintStackFrameCached(void* aPC, void* aSP, void* aClosure)
+PrintStackFrameCached(uint32_t aFrameNumber, void* aPC, void* aSP,
+                      void* aClosure)
 {
   auto stream = static_cast<FILE*>(aClosure);
   static const size_t buflen = 1024;
   char buf[buflen];
-  gCodeAddressService->GetLocation(aPC, buf, buflen);
+  gCodeAddressService->GetLocation(aFrameNumber, aPC, buf, buflen);
   fprintf(stream, "    %s\n", buf);
 }
 #endif
 
 }
 
 void
 nsTraceRefcnt::WalkTheStack(FILE* aStream)
--- a/xpcom/build/LateWriteChecks.cpp
+++ b/xpcom/build/LateWriteChecks.cpp
@@ -74,17 +74,17 @@ public:
     mFile = nullptr;
   }
 private:
   FILE* mFile;
   SHA1Sum mSHA1;
 };
 
 static void
-RecordStackWalker(void* aPC, void* aSP, void* aClosure)
+RecordStackWalker(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure)
 {
   std::vector<uintptr_t>* stack =
     static_cast<std::vector<uintptr_t>*>(aClosure);
   stack->push_back(reinterpret_cast<uintptr_t>(aPC));
 }
 
 /**************************** Late-Write Observer  ****************************/
 
--- a/xpcom/glue/BlockingResourceBase.cpp
+++ b/xpcom/glue/BlockingResourceBase.cpp
@@ -43,17 +43,18 @@ const char* const BlockingResourceBase::
 #ifdef DEBUG
 
 PRCallOnceType BlockingResourceBase::sCallOnce;
 unsigned BlockingResourceBase::sResourceAcqnChainFrontTPI = (unsigned)-1;
 BlockingResourceBase::DDT* BlockingResourceBase::sDeadlockDetector;
 
 
 void
-BlockingResourceBase::StackWalkCallback(void* aPc, void* aSp, void* aClosure)
+BlockingResourceBase::StackWalkCallback(uint32_t aFrameNumber, void* aPc,
+                                        void* aSp, void* aClosure)
 {
 #ifndef MOZ_CALLSTACK_DISABLED
   AcquisitionState* state = (AcquisitionState*)aClosure;
   state->AppendElement(aPc);
 #endif
 }
 
 void
@@ -62,18 +63,17 @@ BlockingResourceBase::GetStackTrace(Acqu
 #ifndef MOZ_CALLSTACK_DISABLED
   // Skip this function and the calling function.
   const uint32_t kSkipFrames = 2;
 
   aState.Clear();
 
   // NB: Ignore the return value, there's nothing useful we can do if this
   //     this fails.
-  NS_StackWalk(StackWalkCallback, kSkipFrames,
-               24, &aState, 0, nullptr);
+  NS_StackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr);
 #endif
 }
 
 /**
  * PrintCycle
  * Append to |aOut| detailed information about the circular
  * dependency in |aCycle|.  Returns true if it *appears* that this
  * cycle may represent an imminent deadlock, but this is merely a
--- a/xpcom/glue/BlockingResourceBase.h
+++ b/xpcom/glue/BlockingResourceBase.h
@@ -314,17 +314,18 @@ private:
   /**
    * Shutdown
    * Free static members.
    *
    * *NOT* thread safe.
    */
   static void Shutdown();
 
-  static void StackWalkCallback(void* aPc, void* aSp, void* aClosure);
+  static void StackWalkCallback(uint32_t aFrameNumber, void* aPc,
+                                void* aSp, void* aClosure);
   static void GetStackTrace(AcquisitionState& aState);
 
 #  ifdef MOZILLA_INTERNAL_API
   // so it can call BlockingResourceBase::Shutdown()
   friend void LogTerm();
 #  endif  // ifdef MOZILLA_INTERNAL_API
 
 #else  // non-DEBUG implementation
--- a/xpcom/threads/HangMonitor.cpp
+++ b/xpcom/threads/HangMonitor.cpp
@@ -109,17 +109,17 @@ Crash()
                                      NS_LITERAL_CSTRING("1"));
 #endif
 
   NS_RUNTIMEABORT("HangMonitor triggered");
 }
 
 #ifdef REPORT_CHROME_HANGS
 static void
-ChromeStackWalker(void* aPC, void* aSP, void* aClosure)
+ChromeStackWalker(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure)
 {
   MOZ_ASSERT(aClosure);
   std::vector<uintptr_t>* stack =
     static_cast<std::vector<uintptr_t>*>(aClosure);
   if (stack->size() == MAX_CALL_STACK_PCS) {
     return;
   }
   MOZ_ASSERT(stack->size() < MAX_CALL_STACK_PCS);