diff --git a/tools/profiler/sps/TableTicker.cpp b/tools/profiler/sps/TableTicker.cpp index 135d103f24d..3ba86420fdb 100644 --- a/tools/profiler/sps/TableTicker.cpp +++ b/tools/profiler/sps/TableTicker.cpp @@ -56,6 +56,13 @@ #include #endif +#ifdef XP_WIN + #define USE_NS_STACKWALK +#endif +#ifdef USE_NS_STACKWALK + #include "nsStackWalk.h" +#endif + using std::string; using namespace mozilla; @@ -272,7 +279,12 @@ class TableTicker: public Sampler { { return &mProfile; } - private: + +private: + // Not implemented on platforms which do not support backtracing + void doBacktrace(Profile &aProfile); + +private: Profile mProfile; Stack *mStack; bool mSaveRequested; @@ -337,8 +349,7 @@ void TableTicker::HandleSaveRequest() } #ifdef USE_BACKTRACE -static -void doBacktrace(Profile &aProfile) +void TableTicker::doBacktrace(Profile &aProfile) { void *array[100]; int count = backtrace (array, 100); @@ -352,6 +363,45 @@ void doBacktrace(Profile &aProfile) } #endif +#ifdef USE_NS_STACKWALK +typedef struct { + void* array[]; + size_t size; + size_t count; +} PCArray; + +static +void StackWalkCallback(void* aPC, void* aClosure) +{ + PCArray* array = static_cast(aClosure); + if (array->count >= array->size) { + // too many frames, ignore + return; + } + array->array[array->count++] = aPC; +} + +void TableTicker::doBacktrace(Profile &aProfile) +{ + uintptr_t thread = GetThreadHandle(platform_data()); + MOZ_ASSERT(thread); + void* pc_array[1000]; + PCArray array = { + pc_array, + mozilla::ArrayLength(array), + 0 + }; + nsresult rv = NS_StackWalk(StackWalkCallback, 0, &array, thread); + if (NS_SUCCEEDED(rv)) { + aProfile.addTag(ProfileEntry('s', "XRE_Main", 0)); + + for (size_t i = array.count; i > 0; --i) { + aProfile.addTag(ProfileEntry('l', (const char*)array.array[i - 1])); + } + } +} +#endif + static void doSampleStackTrace(Stack *aStack, Profile &aProfile, TickSample *sample) { @@ -395,7 +445,7 @@ void TableTicker::Tick(TickSample* sample) } if (recordSample) { -#ifdef USE_BACKTRACE +#if defined(USE_BACKTRACE) || defined(USE_NS_STACKWALK) if (mUseStackWalk) { doBacktrace(mProfile); } else { diff --git a/tools/profiler/sps/platform-win32.cc b/tools/profiler/sps/platform-win32.cc index f59ad45a315..952e2441974 100644 --- a/tools/profiler/sps/platform-win32.cc +++ b/tools/profiler/sps/platform-win32.cc @@ -33,6 +33,11 @@ class Sampler::PlatformData : public Malloced { HANDLE profiled_thread_; }; +uintptr_t +Sampler::GetThreadHandle(Sampler::PlatformData* aData) +{ + return (uintptr_t) aData->profiled_thread(); +} class SamplerThread : public Thread { public: diff --git a/tools/profiler/sps/platform.h b/tools/profiler/sps/platform.h index 87fdf0f54a3..2e5495c844f 100644 --- a/tools/profiler/sps/platform.h +++ b/tools/profiler/sps/platform.h @@ -203,6 +203,11 @@ class Sampler { PlatformData* platform_data() { return data_; } +#ifdef XP_WIN + // xxxehsan sucky hack :( + static uintptr_t GetThreadHandle(PlatformData*); +#endif + private: void SetActive(bool value) { NoBarrier_Store(&active_, value); }