Bug 810526 - Add stack top to Thread{Info,Profile}. r=bgirard
authorJed Davis <jld@mozilla.com>
Wed, 11 Sep 2013 14:50:46 -0400
changeset 146643 a1ec4f620cfe421b38608c28e0a63cb5d4ae2bb9
parent 146642 4e104eb0e38198d7de054512c27642a67a15e707
child 146644 75f5cb9165605ae976bb8e1af3b11d614158f3ce
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbgirard
bugs810526
milestone26.0a1
Bug 810526 - Add stack top to Thread{Info,Profile}. r=bgirard
tools/profiler/ProfileEntry.cpp
tools/profiler/ProfileEntry.h
tools/profiler/TableTicker.cpp
tools/profiler/TableTicker.h
tools/profiler/platform-linux.cc
tools/profiler/platform-macos.cc
tools/profiler/platform-win32.cc
tools/profiler/platform.h
--- a/tools/profiler/ProfileEntry.cpp
+++ b/tools/profiler/ProfileEntry.cpp
@@ -133,27 +133,28 @@ std::ostream& operator<<(std::ostream& s
 ////////////////////////////////////////////////////////////////////////
 // BEGIN ThreadProfile
 
 #define DYNAMIC_MAX_STRING 512
 
 ThreadProfile::ThreadProfile(const char* aName, int aEntrySize,
                              PseudoStack *aStack, int aThreadId,
                              PlatformData* aPlatform,
-                             bool aIsMainThread)
+                             bool aIsMainThread, void *aStackTop)
   : mWritePos(0)
   , mLastFlushPos(0)
   , mReadPos(0)
   , mEntrySize(aEntrySize)
   , mPseudoStack(aStack)
   , mMutex("ThreadProfile::mMutex")
   , mName(strdup(aName))
   , mThreadId(aThreadId)
   , mIsMainThread(aIsMainThread)
   , mPlatformData(aPlatform)
+  , mStackTop(aStackTop)
 {
   mEntries = new ProfileEntry[mEntrySize];
 }
 
 ThreadProfile::~ThreadProfile()
 {
   free(mName);
   delete[] mEntries;
--- a/tools/profiler/ProfileEntry.h
+++ b/tools/profiler/ProfileEntry.h
@@ -53,17 +53,17 @@ private:
 
 typedef void (*IterateTagsCallback)(const ProfileEntry& entry, const char* tagStringData);
 
 class ThreadProfile
 {
 public:
   ThreadProfile(const char* aName, int aEntrySize, PseudoStack *aStack,
                 int aThreadId, PlatformData* aPlatformData,
-                bool aIsMainThread);
+                bool aIsMainThread, void *aStackTop);
   ~ThreadProfile();
   void addTag(ProfileEntry aTag);
   void flush();
   void erase();
   char* processDynamicTag(int readPos, int* tagsConsumed, char* tagBuff);
   void IterateTags(IterateTagsCallback aCallback);
   friend std::ostream& operator<<(std::ostream& stream,
                                   const ThreadProfile& profile);
@@ -73,27 +73,29 @@ public:
   mozilla::Mutex* GetMutex();
   void BuildJSObject(JSAObjectBuilder& b, JSCustomObject* profile);
 
   bool IsMainThread() const { return mIsMainThread; }
   const char* Name() const { return mName; }
   int ThreadId() const { return mThreadId; }
 
   PlatformData* GetPlatformData() { return mPlatformData; }
+  void* GetStackTop() const { return mStackTop; }
 private:
   // Circular buffer 'Keep One Slot Open' implementation
   // for simplicity
   ProfileEntry* mEntries;
   int            mWritePos; // points to the next entry we will write to
   int            mLastFlushPos; // points to the next entry since the last flush()
   int            mReadPos;  // points to the next entry we will read to
   int            mEntrySize;
   PseudoStack*   mPseudoStack;
   mozilla::Mutex mMutex;
   char*          mName;
   int            mThreadId;
   bool           mIsMainThread;
   PlatformData*  mPlatformData;  // Platform specific data.
+  void* const    mStackTop;
 };
 
 std::ostream& operator<<(std::ostream& stream, const ThreadProfile& profile);
 
 #endif /* ndef MOZ_PROFILE_ENTRY_H */
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -539,18 +539,23 @@ void mozilla_sampler_print_location1()
     profiler_init(NULL);
 
   PseudoStack *stack = tlsPseudoStack.get();
   if (!stack) {
     MOZ_ASSERT(false);
     return;
   }
 
+  // This won't allow unwinding past this function, but it will be safe.
+  void *stackTop = &stack;
+
   ThreadProfile threadProfile("Temp", PROFILE_DEFAULT_ENTRY, stack,
-                              0, Sampler::AllocPlatformData(0), false);
+                              0, Sampler::AllocPlatformData(0), false,
+                              stackTop);
+
   doSampleStackTrace(stack, threadProfile, NULL);
 
   threadProfile.flush();
 
   printf_stderr("Backtrace:\n");
   threadProfile.IterateTags(print_callback);
 }
 
--- a/tools/profiler/TableTicker.h
+++ b/tools/profiler/TableTicker.h
@@ -115,17 +115,18 @@ class TableTicker: public Sampler {
       return;
     }
 
     ThreadProfile* profile = new ThreadProfile(aInfo->Name(),
                                                EntrySize(),
                                                aInfo->Stack(),
                                                aInfo->ThreadId(),
                                                aInfo->GetPlatformData(),
-                                               aInfo->IsMainThread());
+                                               aInfo->IsMainThread(),
+                                               aInfo->StackTop());
     profile->addTag(ProfileEntry('m', "Start"));
 
     aInfo->SetProfile(profile);
   }
 
   // Called within a signal. This function must be reentrant
   virtual void Tick(TickSample* sample);
 
--- a/tools/profiler/platform-linux.cc
+++ b/tools/profiler/platform-linux.cc
@@ -378,17 +378,17 @@ bool Sampler::RegisterCurrentThread(cons
                                     bool aIsMainThread, void* stackTop)
 {
   if (!Sampler::sRegisteredThreadsMutex)
     return false;
 
   mozilla::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
 
   ThreadInfo* info = new ThreadInfo(aName, gettid(),
-    aIsMainThread, aPseudoStack);
+    aIsMainThread, aPseudoStack, stackTop);
 
   if (sActiveSampler) {
     sActiveSampler->RegisterThread(info);
   }
 
   sRegisteredThreads->push_back(info);
 
   uwt__register_thread_for_profiling(stackTop);
--- a/tools/profiler/platform-macos.cc
+++ b/tools/profiler/platform-macos.cc
@@ -354,17 +354,17 @@ bool Sampler::RegisterCurrentThread(cons
                                     bool aIsMainThread, void* stackTop)
 {
   if (!Sampler::sRegisteredThreadsMutex)
     return false;
 
   mozilla::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
 
   ThreadInfo* info = new ThreadInfo(aName, gettid(),
-    aIsMainThread, aPseudoStack);
+    aIsMainThread, aPseudoStack, stackTop);
 
   if (sActiveSampler) {
     sActiveSampler->RegisterThread(info);
   }
 
   sRegisteredThreads->push_back(info);
 
   uwt__register_thread_for_profiling(stackTop);
--- a/tools/profiler/platform-win32.cc
+++ b/tools/profiler/platform-win32.cc
@@ -273,17 +273,17 @@ bool Sampler::RegisterCurrentThread(cons
                                     bool aIsMainThread, void* stackTop)
 {
   if (!Sampler::sRegisteredThreadsMutex)
     return false;
 
   mozilla::MutexAutoLock lock(*Sampler::sRegisteredThreadsMutex);
 
   ThreadInfo* info = new ThreadInfo(aName, GetCurrentThreadId(),
-    aIsMainThread, aPseudoStack);
+    aIsMainThread, aPseudoStack, stackTop);
 
   if (sActiveSampler) {
     sActiveSampler->RegisterThread(info);
   }
 
   sRegisteredThreads->push_back(info);
 
   uwt__register_thread_for_profiling(stackTop);
--- a/tools/profiler/platform.h
+++ b/tools/profiler/platform.h
@@ -373,38 +373,41 @@ class Sampler {
   struct sigaction old_sigsave_signal_handler_;
   bool signal_sender_launched_;
   pthread_t signal_sender_thread_;
 #endif
 };
 
 class ThreadInfo {
  public:
-  ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack)
+  ThreadInfo(const char* aName, int aThreadId, bool aIsMainThread, PseudoStack* aPseudoStack, void* aStackTop)
     : mName(strdup(aName))
     , mThreadId(aThreadId)
     , mIsMainThread(aIsMainThread)
     , mPseudoStack(aPseudoStack)
     , mPlatformData(Sampler::AllocPlatformData(aThreadId))
-    , mProfile(NULL) {}
+    , mProfile(NULL)
+    , mStackTop(aStackTop) {}
 
   virtual ~ThreadInfo();
 
   const char* Name() const { return mName; }
   int ThreadId() const { return mThreadId; }
 
   bool IsMainThread() const { return mIsMainThread; }
   PseudoStack* Stack() const { return mPseudoStack; }
   
   void SetProfile(ThreadProfile* aProfile) { mProfile = aProfile; }
   ThreadProfile* Profile() const { return mProfile; }
 
   PlatformData* GetPlatformData() const { return mPlatformData; }
+  void* StackTop() const { return mStackTop; }
  private:
   char* mName;
   int mThreadId;
   const bool mIsMainThread;
   PseudoStack* mPseudoStack;
   PlatformData* mPlatformData;
   ThreadProfile* mProfile;
+  void* const mStackTop;
 };
 
 #endif /* ndef TOOLS_PLATFORM_H_ */