Bug 809317 - Part 2: Support stackwalking. r=ehsan
☠☠ backed out by 76322fb13033 ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Mon, 19 Nov 2012 18:31:47 -0500
changeset 115120 b5c19fdea86e150a6625f04653e8ee404c779575
parent 115119 e8e24d4bed52d70cb31dac9e74e56aad680ca1ed
child 115121 84f3936e91a7ee4db6a398b5659d74b5a12aef99
push id23973
push useremorley@mozilla.com
push dateThu, 06 Dec 2012 10:04:18 +0000
treeherdermozilla-central@ddda5400c826 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs809317
milestone20.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 809317 - Part 2: Support stackwalking. r=ehsan
tools/profiler/TableTicker.cpp
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -796,43 +796,48 @@ void StackWalkCallback(void* aPC, void* 
     // too many frames, ignore
     return;
   }
   array->sp_array[array->count] = aSP;
   array->array[array->count] = aPC;
   array->count++;
 }
 
-void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
+static void doMergeBacktrace(ThreadProfile &aProfile, TickSample* aSample, void* aThread)
 {
-#ifndef XP_MACOSX
-  uintptr_t thread = GetThreadHandle(platform_data());
-  MOZ_ASSERT(thread);
-#endif
   void* pc_array[1000];
   void* sp_array[1000];
   PCArray array = {
     pc_array,
     sp_array,
     mozilla::ArrayLength(pc_array),
     0
   };
 
   // Start with the current function.
   StackWalkCallback(aSample->pc, aSample->sp, &array);
 
 #ifdef XP_MACOSX
-  pthread_t pt = GetProfiledThread(platform_data());
+  pthread_t pt;
+  if (aThread) {
+    pt = (pthread_t)aThread;
+  } else {
+    pt = pthread_self();
+  }
+
   void *stackEnd = reinterpret_cast<void*>(-1);
   if (pt)
     stackEnd = static_cast<char*>(pthread_get_stackaddr_np(pt));
   nsresult rv = NS_OK;
   if (aSample->fp >= aSample->sp && aSample->fp <= stackEnd)
     rv = FramePointerStackWalk(StackWalkCallback, 0, &array, reinterpret_cast<void**>(aSample->fp), stackEnd);
 #else
+  uintptr_t thread = (uintptr_t)aThread;
+  GetThreadHandle(platform_data());
+  MOZ_ASSERT(thread);
   nsresult rv = NS_StackWalk(StackWalkCallback, 0, &array, thread);
 #endif
   if (NS_SUCCEEDED(rv)) {
     aProfile.addTag(ProfileEntry('s', "(root)"));
 
     ProfileStack* stack = aProfile.GetStack();
     int pseudoStackPos = 0;
 
@@ -864,16 +869,26 @@ void TableTicker::doBacktrace(ThreadProf
         addProfileEntry(entry, aProfile, stack, array.array[0]);
         pseudoStackPos++;
       }
 
       aProfile.addTag(ProfileEntry('l', (void*)array.array[i-1]));
     }
   }
 }
+
+void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
+{
+#ifdef XP_MACOSX
+  doMergeBacktrace(aProfile, aSample, GetProfiledThread(platform_data()));
+#else
+  doMergeBacktrace(aProfile, aSample, GetThreadHandle(platform_data()));
+#endif
+}
+
 #endif
 
 #if defined(USE_LIBUNWIND) && defined(ANDROID)
 void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample)
 {
   void* pc_array[1000];
   size_t count = 0;
 
@@ -1260,30 +1275,61 @@ void mozilla_sampler_frame_number(int fr
   sFrameNumber = frameNumber;
 }
 
 void print_callback(const ProfileEntry& entry, const char* tagStringData) {
   switch (entry.mTagName) {
     case 's':
     case 'c':
       printf_stderr("  %s\n", tagStringData);
+      break;
+    case 'l':
+      unsigned long long pc = (unsigned long long)(uintptr_t)entry.mTagPtr;
+      nsCodeAddressDetails details;
+      NS_DescribeCodeAddress((void*)pc, &details);
+      if (details.function) {
+        printf_stderr("  %s\n", details.function);
+      } else {
+        printf_stderr("  %#llx\n", pc);
+      }
+      break;
   }
 }
 
 void mozilla_sampler_print_location()
 {
   if (!stack_key_initialized)
     mozilla_sampler_init();
 
   ProfileStack *stack = tlsStack.get();
   if (!stack) {
     MOZ_ASSERT(false);
     return;
   }
 
-  ThreadProfile threadProfile(1000, stack);
+  ThreadProfile threadProfile(2000, stack);
+#ifdef USE_NS_STACKWALK
+  // Get the frame pointer
+  void **bp;
+#if defined(__i386)
+  __asm__( "movl %%ebp, %0" : "=g"(bp));
+#else
+  // It would be nice if this worked uniformly, but at least on i386 and
+  // x86_64, it stopped working with gcc 4.1, because it points to the
+  // end of the saved registers instead of the start.
+  bp = (void**) __builtin_frame_address(0);
+#endif
+
+  TickSample sample;
+  sample.fp = (unsigned char*)bp;
+  sample.pc = nullptr;
+  sample.sp = (unsigned char*)&stack;
+
+  doMergeBacktrace(threadProfile, &sample, 0);
+#else
   doSampleStackTrace(stack, threadProfile, NULL);
+#endif
 
   threadProfile.flush();
 
   printf_stderr("Backtrace:\n");
   threadProfile.IterateTags(print_callback);
 }