From 82d4c11201069c81519fedf169f633305410fd00 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Jan 2017 15:05:16 +1100 Subject: [PATCH] Bug 1332577 (part 9) - Remove all mozilla_sampler_*() functions. r=mstange. There are lots of profiler_*() functions that simply call onto equivalent or nearly-equivalent mozilla_sampler_*() functions. This patch removes the unnecessary indirection by removing the mozilla_sampler_*() functions. The most important changes: - In platform.cpp, all the mozilla_sampler_*() definitions are renamed as profiler_*(). - In GeckoProfiler.h, the new PROFILER_FUNC{,_VOID} macros provide a neat way to declare the functions that must be present whether the profiler is enabled or not. - In GeckoProfiler.h, all the mozilla_sampler_*() declarations are removed, as are all the profiler_*() definitions that corresponded to a mozilla_sampler_*() function. Other things of note: - profiler_log(const char* str) is now defined in platform.cpp, instead of in GeckoProfiler.h, for consistency with all the other profiler_*() functions. Likewise with profiler_js_operation_callback() and profiler_in_privacy_mode(). - ProfilerBacktraceDestructor::operator() is treated slightly different to all the profiler_*() functions. - Both variants of profiler_tracing() got some early-return conditions moved into them from GeckoProfiler.h. - There were some cases where the profiler_*() and mozilla_sampler_*() name didn't quite match. Specifically: * mozilla_sampler_get_profile_data() and profiler_get_profiler_jsobject(): name mismatch. Kept the latter. * mozilla_sampler_get_profile_data_async() and profiler_get_profile_jsobject_async(): name mismatch. Kept the latter. * mozilla_sampler_register_thread() and profiler_register_thread(): return type mismatch. Changed to void. * mozilla_sampler_frame_number() and profiler_set_frame_number(): name mismatch. Kept the latter. * mozilla_sampler_save_profile_to_file() and profile_sampler_save_profile_to_file(): the former was 'extern "C"' so it could be called from a debugger easily. The latter now is 'extern "C"'. - profiler_get_buffer_info() didn't fit the patterns handled by PROFILER_FUNC{,VOID}, so the patch makes it call onto the new function profiler_get_buffer_info_helper(), which does fit the pattern. --HG-- extra : rebase_source : fa1817854ade81e8a3027907d1476ff2563f1cc2 --- tools/profiler/core/platform.cpp | 206 ++++++---- tools/profiler/public/GeckoProfiler.h | 529 ++++++-------------------- 2 files changed, 256 insertions(+), 479 deletions(-) diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index 073a3db3e1b6..7f63d6d4c40e 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -463,7 +463,13 @@ bool is_main_thread_name(const char* aName) { #endif void -mozilla_sampler_log(const char *fmt, va_list args) +profiler_log(const char* str) +{ + profiler_tracing("log", str, TRACING_EVENT); +} + +void +profiler_log(const char* fmt, va_list args) { if (profiler_is_active()) { // nsAutoCString AppendPrintf would be nicer but @@ -496,7 +502,8 @@ mozilla_sampler_log(const char *fmt, va_list args) //////////////////////////////////////////////////////////////////////// // BEGIN externally visible functions -void mozilla_sampler_init(void* stackTop) +void +profiler_init(void* stackTop) { sInitCount++; @@ -507,7 +514,7 @@ void mozilla_sampler_init(void* stackTop) mozilla::tasktracer::InitTaskTracer(); #endif - LOG("BEGIN mozilla_sampler_init"); + LOG("BEGIN profiler_init"); if (!tlsPseudoStack.init() || !tlsTicker.init()) { LOG("Failed to init."); return; @@ -534,7 +541,7 @@ void mozilla_sampler_init(void* stackTop) // platform specific initialization OS::Startup(); - set_stderr_callback(mozilla_sampler_log); + set_stderr_callback(profiler_log); #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK) if (mozilla::jni::IsFennec()) { @@ -568,10 +575,11 @@ void mozilla_sampler_init(void* stackTop) profiler_start(PROFILE_DEFAULT_ENTRY, PROFILE_DEFAULT_INTERVAL, features, MOZ_ARRAY_LENGTH(features), threadFilters, MOZ_ARRAY_LENGTH(threadFilters)); - LOG("END mozilla_sampler_init"); + LOG("END profiler_init"); } -void mozilla_sampler_shutdown() +void +profiler_shutdown() { sInitCount--; @@ -607,7 +615,8 @@ void mozilla_sampler_shutdown() #endif } -mozilla::UniquePtr mozilla_sampler_get_profile(double aSinceTime) +mozilla::UniquePtr +profiler_get_profile(double aSinceTime) { GeckoSampler *t = tlsTicker.get(); if (!t) { @@ -617,7 +626,8 @@ mozilla::UniquePtr mozilla_sampler_get_profile(double aSinceTime) return t->ToJSON(aSinceTime); } -JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, double aSinceTime) +JSObject* +profiler_get_profile_jsobject(JSContext *aCx, double aSinceTime) { GeckoSampler *t = tlsTicker.get(); if (!t) { @@ -627,8 +637,9 @@ JSObject *mozilla_sampler_get_profile_data(JSContext *aCx, double aSinceTime) return t->ToJSObject(aCx, aSinceTime); } -void mozilla_sampler_get_profile_data_async(double aSinceTime, - mozilla::dom::Promise* aPromise) +void +profiler_get_profile_jsobject_async(double aSinceTime, + mozilla::dom::Promise* aPromise) { GeckoSampler *t = tlsTicker.get(); if (NS_WARN_IF(!t)) { @@ -638,8 +649,8 @@ void mozilla_sampler_get_profile_data_async(double aSinceTime, t->ToJSObjectAsync(aSinceTime, aPromise); } -void mozilla_sampler_save_profile_to_file_async(double aSinceTime, - const char* aFileName) +void +profiler_save_profile_to_file_async(double aSinceTime, const char* aFileName) { nsCString filename(aFileName); NS_DispatchToMainThread(NS_NewRunnableFunction([=] () { @@ -652,10 +663,11 @@ void mozilla_sampler_save_profile_to_file_async(double aSinceTime, })); } -void mozilla_sampler_get_profiler_start_params(int* aEntrySize, - double* aInterval, - mozilla::Vector* aFilters, - mozilla::Vector* aFeatures) +void +profiler_get_start_params(int* aEntrySize, + double* aInterval, + mozilla::Vector* aFilters, + mozilla::Vector* aFeatures) { if (NS_WARN_IF(!aEntrySize) || NS_WARN_IF(!aInterval) || NS_WARN_IF(!aFilters) || NS_WARN_IF(!aFeatures)) { @@ -683,7 +695,8 @@ void mozilla_sampler_get_profiler_start_params(int* aEntrySize, } } -void mozilla_sampler_get_gatherer(nsISupports** aRetVal) +void +profiler_get_gatherer(nsISupports** aRetVal) { if (!aRetVal) { return; @@ -703,7 +716,8 @@ void mozilla_sampler_get_gatherer(nsISupports** aRetVal) t->GetGatherer(aRetVal); } -void mozilla_sampler_save_profile_to_file(const char* aFilename) +void +profiler_save_profile_to_file(const char* aFilename) { GeckoSampler *t = tlsTicker.get(); if (!t) { @@ -721,8 +735,8 @@ void mozilla_sampler_save_profile_to_file(const char* aFilename) } } - -const char** mozilla_sampler_get_features() +const char** +profiler_get_features() { static const char* features[] = { #if defined(MOZ_PROFILING) && defined(HAVE_NATIVE_UNWIND) @@ -768,12 +782,13 @@ const char** mozilla_sampler_get_features() return features; } -void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, - uint32_t *aGeneration) +void +profiler_get_buffer_info_helper(uint32_t *aCurrentPosition, + uint32_t *aTotalSize, + uint32_t *aGeneration) { - *aCurrentPosition = 0; - *aTotalSize = 0; - *aGeneration = 0; + // This function is called by profiler_get_buffer_info(), which has already + // zeroed the outparams. if (!stack_key_initialized) return; @@ -786,12 +801,13 @@ void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTota } // Values are only honored on the first start -void mozilla_sampler_start(int aProfileEntries, double aInterval, - const char** aFeatures, uint32_t aFeatureCount, - const char** aThreadNameFilters, uint32_t aFilterCount) +void +profiler_start(int aProfileEntries, double aInterval, + const char** aFeatures, uint32_t aFeatureCount, + const char** aThreadNameFilters, uint32_t aFilterCount) { - LOG("BEGIN mozilla_sampler_start"); + LOG("BEGIN profiler_start"); if (!stack_key_initialized) profiler_init(nullptr); @@ -887,19 +903,20 @@ void mozilla_sampler_start(int aProfileEntries, double aInterval, } } - LOG("END mozilla_sampler_start"); + LOG("END profiler_start"); } -void mozilla_sampler_stop() +void +profiler_stop() { - LOG("BEGIN mozilla_sampler_stop"); + LOG("BEGIN profiler_stop"); if (!stack_key_initialized) return; GeckoSampler *t = tlsTicker.get(); if (!t) { - LOG("END mozilla_sampler_stop-early"); + LOG("END profiler_stop-early"); return; } @@ -931,10 +948,12 @@ void mozilla_sampler_stop() os->NotifyObservers(nullptr, "profiler-stopped", nullptr); } - LOG("END mozilla_sampler_stop"); + LOG("END profiler_stop"); } -bool mozilla_sampler_is_paused() { +bool +profiler_is_paused() +{ if (Sampler::GetActiveSampler()) { return Sampler::GetActiveSampler()->IsPaused(); } else { @@ -942,7 +961,9 @@ bool mozilla_sampler_is_paused() { } } -void mozilla_sampler_pause() { +void +profiler_pause() +{ if (Sampler::GetActiveSampler()) { Sampler::GetActiveSampler()->SetPaused(true); if (Sampler::CanNotifyObservers()) { @@ -953,7 +974,9 @@ void mozilla_sampler_pause() { } } -void mozilla_sampler_resume() { +void +profiler_resume() +{ if (Sampler::GetActiveSampler()) { Sampler::GetActiveSampler()->SetPaused(false); if (Sampler::CanNotifyObservers()) { @@ -964,7 +987,8 @@ void mozilla_sampler_resume() { } } -bool mozilla_sampler_feature_active(const char* aName) +bool +profiler_feature_active(const char* aName) { if (!profiler_is_active()) { return false; @@ -989,22 +1013,26 @@ bool mozilla_sampler_feature_active(const char* aName) return false; } -bool mozilla_sampler_is_active() +bool +profiler_is_active() { return sIsProfiling; } -void mozilla_sampler_responsiveness(const mozilla::TimeStamp& aTime) +void +profiler_responsiveness(const mozilla::TimeStamp& aTime) { sLastTracerEvent = aTime; } -void mozilla_sampler_frame_number(int frameNumber) +void +profiler_set_frame_number(int frameNumber) { sFrameNumber = frameNumber; } -void mozilla_sampler_lock() +void +profiler_lock() { profiler_stop(); nsCOMPtr os = mozilla::services::GetObserverService(); @@ -1012,17 +1040,19 @@ void mozilla_sampler_lock() os->NotifyObservers(nullptr, "profiler-locked", nullptr); } -void mozilla_sampler_unlock() +void +profiler_unlock() { nsCOMPtr os = mozilla::services::GetObserverService(); if (os) os->NotifyObservers(nullptr, "profiler-unlocked", nullptr); } -bool mozilla_sampler_register_thread(const char* aName, void* aGuessStackTop) +void +profiler_register_thread(const char* aName, void* aGuessStackTop) { if (sInitCount == 0) { - return false; + return; } #if defined(MOZ_WIDGET_GONK) && !defined(MOZ_PROFILING) @@ -1030,7 +1060,7 @@ bool mozilla_sampler_register_thread(const char* aName, void* aGuessStackTop) // is to build with profiling OR have the profiler // running on startup. if (!profiler_is_active()) { - return false; + return; } #endif @@ -1039,10 +1069,11 @@ bool mozilla_sampler_register_thread(const char* aName, void* aGuessStackTop) tlsPseudoStack.set(stack); bool isMainThread = is_main_thread_name(aName); void* stackTop = GetStackTop(aGuessStackTop); - return Sampler::RegisterCurrentThread(aName, stack, isMainThread, stackTop); + Sampler::RegisterCurrentThread(aName, stack, isMainThread, stackTop); } -void mozilla_sampler_unregister_thread() +void +profiler_unregister_thread() { // Don't check sInitCount count here -- we may be unregistering the // thread after the sampler was shut down. @@ -1060,7 +1091,9 @@ void mozilla_sampler_unregister_thread() Sampler::UnregisterCurrentThread(); } -void mozilla_sampler_sleep_start() { +void +profiler_sleep_start() +{ if (sInitCount == 0) { return; } @@ -1072,7 +1105,9 @@ void mozilla_sampler_sleep_start() { stack->setSleeping(1); } -void mozilla_sampler_sleep_end() { +void +profiler_sleep_end() +{ if (sInitCount == 0) { return; } @@ -1084,7 +1119,9 @@ void mozilla_sampler_sleep_end() { stack->setSleeping(0); } -bool mozilla_sampler_is_sleeping() { +bool +profiler_is_sleeping() +{ if (sInitCount == 0) { return false; } @@ -1095,18 +1132,42 @@ bool mozilla_sampler_is_sleeping() { return stack->isSleeping(); } -double mozilla_sampler_time(const mozilla::TimeStamp& aTime) +void +profiler_js_operation_callback() +{ + PseudoStack *stack = tlsPseudoStack.get(); + if (!stack) { + return; + } + + stack->jsOperationCallback(); +} + +double +profiler_time(const mozilla::TimeStamp& aTime) { mozilla::TimeDuration delta = aTime - sStartTime; return delta.ToMilliseconds(); } -double mozilla_sampler_time() +double +profiler_time() { - return mozilla_sampler_time(mozilla::TimeStamp::Now()); + return profiler_time(mozilla::TimeStamp::Now()); } -UniqueProfilerBacktrace mozilla_sampler_get_backtrace() +bool +profiler_in_privacy_mode() +{ + PseudoStack *stack = tlsPseudoStack.get(); + if (!stack) { + return false; + } + return stack->mPrivacyMode; +} + +UniqueProfilerBacktrace +profiler_get_backtrace() { if (!stack_key_initialized) return nullptr; @@ -1138,7 +1199,8 @@ ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* aBacktrace) // Fill the output buffer with the following pattern: // "Lable 1" "\0" "Label 2" "\0" ... "Label N" "\0" "\0" // TODO: use the unwinder instead of pseudo stack. -void mozilla_sampler_get_backtrace_noalloc(char *output, size_t outputSize) +void +profiler_get_backtrace_noalloc(char *output, size_t outputSize) { MOZ_ASSERT(outputSize >= 2); char *bound = output + outputSize - 2; @@ -1162,21 +1224,35 @@ void mozilla_sampler_get_backtrace_noalloc(char *output, size_t outputSize) } } -void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, - TracingMetadata aMetaData) +void +profiler_tracing(const char* aCategory, const char* aInfo, + TracingMetadata aMetaData) { - mozilla_sampler_add_marker(aInfo, new ProfilerMarkerTracing(aCategory, aMetaData)); + // Don't insert a marker if we're not profiling, to avoid the heap copy + // (malloc). + if (!stack_key_initialized || !profiler_is_active()) { + return; + } + + profiler_add_marker(aInfo, new ProfilerMarkerTracing(aCategory, aMetaData)); } -void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, - UniqueProfilerBacktrace aCause, - TracingMetadata aMetaData) +void +profiler_tracing(const char* aCategory, const char* aInfo, + UniqueProfilerBacktrace aCause, TracingMetadata aMetaData) { - mozilla_sampler_add_marker(aInfo, new ProfilerMarkerTracing(aCategory, aMetaData, - mozilla::Move(aCause))); + // Don't insert a marker if we're not profiling, to avoid the heap copy + // (malloc). + if (!stack_key_initialized || !profiler_is_active()) { + return; + } + + profiler_add_marker(aInfo, new ProfilerMarkerTracing(aCategory, aMetaData, + mozilla::Move(aCause))); } -void mozilla_sampler_add_marker(const char *aMarker, ProfilerMarkerPayload *aPayload) +void +profiler_add_marker(const char *aMarker, ProfilerMarkerPayload *aPayload) { // Note that aPayload may be allocated by the caller, so we need to make sure // that we free it at some point. diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index 5dedfd2e6945..5a21ca637abc 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -90,6 +90,13 @@ using UniqueProfilerBacktrace = #if !defined(MOZ_ENABLE_PROFILER_SPS) +// Use these for functions below that must be visible whether the profiler is +// enabled or not. When the profiler is disabled they are static inline +// functions (with a simple return value if they are non-void) that should be +// optimized away during compilation. +#define PROFILER_FUNC(decl, rv) static inline decl { return rv; } +#define PROFILER_FUNC_VOID(decl) static inline void decl {} + // Insert a RAII in this scope to active a pseudo label. Any samples collected // in this scope will contain this annotation. For dynamic strings use // PROFILER_LABEL_PRINTF. Arguments must be string literals. @@ -112,21 +119,42 @@ using UniqueProfilerBacktrace = #define PROFILER_MARKER(info) do {} while (0) #define PROFILER_MARKER_PAYLOAD(info, payload) do { mozilla::UniquePtr payloadDeletor(payload); } while (0) -static inline void profiler_tracing(const char* aCategory, const char* aInfo, - TracingMetadata metaData = TRACING_DEFAULT) {} -static inline void profiler_tracing(const char* aCategory, const char* aInfo, +#else // defined(MOZ_ENABLE_PROFILER_SPS) + +#define PROFILER_FUNC(decl, rv) decl; +#define PROFILER_FUNC_VOID(decl) void decl; + +// we want the class and function name but can't easily get that using preprocessor macros +// __func__ doesn't have the class name and __PRETTY_FUNCTION__ has the parameters + +#define PROFILER_LABEL(name_space, info, category) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__) + +#define PROFILER_LABEL_FUNC(category) MOZ_PLATFORM_TRACING(SAMPLE_FUNCTION_NAME) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(SAMPLE_FUNCTION_NAME, category, __LINE__) + +#define PROFILER_LABEL_PRINTF(name_space, info, category, ...) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__, __VA_ARGS__) + +#define PROFILER_MARKER(info) profiler_add_marker(info) +#define PROFILER_MARKER_PAYLOAD(info, payload) profiler_add_marker(info, payload) + +#endif // defined(MOZ_ENABLE_PROFILER_SPS) + +// These functions are defined whether the profiler is enabled or not. + +PROFILER_FUNC_VOID(profiler_tracing(const char* aCategory, const char* aInfo, + TracingMetadata metaData = TRACING_DEFAULT)) +PROFILER_FUNC_VOID(profiler_tracing(const char* aCategory, const char* aInfo, UniqueProfilerBacktrace aCause, - TracingMetadata metaData = TRACING_DEFAULT) {} + TracingMetadata metaData = TRACING_DEFAULT)) // Initilize the profiler TLS, signal handlers on linux. If MOZ_PROFILER_STARTUP // is set the profiler will be started. This call must happen before any other // sampler calls. Particularly sampler_label/sampler_marker. -static inline void profiler_init(void* stackTop) {}; +PROFILER_FUNC_VOID(profiler_init(void* stackTop)) // Clean up the profiler module, stopping it if required. This function may // also save a shutdown profile if requested. No profiler calls should happen // after this point and all pseudo labels should have been popped. -static inline void profiler_shutdown() {}; +PROFILER_FUNC_VOID(profiler_shutdown()) // Start the profiler with the selected options. The samples will be // recorded in a circular buffer. @@ -136,69 +164,78 @@ static inline void profiler_shutdown() {}; // "aInterval" the sampling interval. The profiler will do its // best to sample at this interval. The profiler visualization // should represent the actual sampling accuracy. -static inline void profiler_start(int aProfileEntries, double aInterval, +PROFILER_FUNC_VOID(profiler_start(int aProfileEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, - const char** aThreadNameFilters, uint32_t aFilterCount) {} + const char** aThreadNameFilters, uint32_t aFilterCount)) // Stop the profiler and discard the profile. Call 'profiler_save' before this // to retrieve the profile. -static inline void profiler_stop() {} +PROFILER_FUNC_VOID(profiler_stop()) // These functions pause and resume the profiler. While paused the profile will not // take any samples and will not record any data into its buffers. The profiler // remains fully initialized in this state. Timeline markers will still be stored. // This feature will keep javascript profiling enabled, thus allowing toggling the // profiler without invalidating the JIT. -static inline bool profiler_is_paused() { return false; } -static inline void profiler_pause() {} -static inline void profiler_resume() {} - +PROFILER_FUNC(bool profiler_is_paused(), false) +PROFILER_FUNC_VOID(profiler_pause()) +PROFILER_FUNC_VOID(profiler_resume()) // Immediately capture the current thread's call stack and return it -static inline UniqueProfilerBacktrace profiler_get_backtrace() { return nullptr; } -static inline void profiler_get_backtrace_noalloc(char *output, size_t outputSize) { return; } +PROFILER_FUNC(UniqueProfilerBacktrace profiler_get_backtrace(), nullptr) +PROFILER_FUNC_VOID(profiler_get_backtrace_noalloc(char *output, + size_t outputSize)) // Free a ProfilerBacktrace returned by profiler_get_backtrace() +#if !defined(MOZ_ENABLE_PROFILER_SPS) inline void ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* aBacktrace) {} +#endif -static inline bool profiler_is_active() { return false; } +PROFILER_FUNC(bool profiler_is_active(), false) // Check if an external profiler feature is active. // Supported: // * gpu -static inline bool profiler_feature_active(const char*) { return false; } +PROFILER_FUNC(bool profiler_feature_active(const char*), false) // Internal-only. Used by the event tracer. -static inline void profiler_responsiveness(const mozilla::TimeStamp& aTime) {} +PROFILER_FUNC_VOID(profiler_responsiveness(const mozilla::TimeStamp& aTime)) // Internal-only. -static inline void profiler_set_frame_number(int frameNumber) {} +PROFILER_FUNC_VOID(profiler_set_frame_number(int frameNumber)) // Get the profile encoded as a JSON string. -static inline mozilla::UniquePtr profiler_get_profile(double aSinceTime = 0) { - return nullptr; -} +PROFILER_FUNC(mozilla::UniquePtr profiler_get_profile(double aSinceTime = 0), + nullptr) // Get the profile encoded as a JSON object. -static inline JSObject* profiler_get_profile_jsobject(JSContext* aCx, - double aSinceTime = 0) { - return nullptr; -} +PROFILER_FUNC(JSObject* profiler_get_profile_jsobject(JSContext* aCx, + double aSinceTime = 0), + nullptr) // Get the profile encoded as a JSON object. -static inline void profiler_get_profile_jsobject_async(double aSinceTime = 0, - mozilla::dom::Promise* = 0) {} -static inline void profiler_get_start_params(int* aEntrySize, +PROFILER_FUNC_VOID(profiler_get_profile_jsobject_async(double aSinceTime = 0, + mozilla::dom::Promise* = 0)) + +PROFILER_FUNC_VOID(profiler_get_start_params(int* aEntrySize, double* aInterval, mozilla::Vector* aFilters, - mozilla::Vector* aFeatures) {} + mozilla::Vector* aFeatures)) -// Get the profile and write it into a file -static inline void profiler_save_profile_to_file(char* aFilename) { } +// Get the profile and write it into a file. It is 'extern "C"' so that it is +// easily callable from a debugger in a build without debugging information +// (work around http://llvm.org/bugs/show_bug.cgi?id=22211). +extern "C" { +PROFILER_FUNC_VOID(profiler_save_profile_to_file(const char* aFilename)) +} // Get the features supported by the profiler that are accepted by profiler_init. // Returns a null terminated char* array. -static inline char** profiler_get_features() { return nullptr; } +PROFILER_FUNC(const char** profiler_get_features(), nullptr) + +PROFILER_FUNC_VOID(profiler_get_buffer_info_helper(uint32_t* aCurrentPosition, + uint32_t* aTotalSize, + uint32_t* aGeneration)) // Get information about the current buffer status. // Retursn (using outparams) the current write position in the buffer, @@ -207,46 +244,52 @@ static inline char** profiler_get_features() { return nullptr; } // current status of the profiler, allowing the user to get a sense // for how fast the buffer is being written to, and how much // data is visible. -static inline void profiler_get_buffer_info(uint32_t *aCurrentPosition, - uint32_t *aTotalSize, - uint32_t *aGeneration) +static inline void profiler_get_buffer_info(uint32_t* aCurrentPosition, + uint32_t* aTotalSize, + uint32_t* aGeneration) { *aCurrentPosition = 0; *aTotalSize = 0; *aGeneration = 0; + + profiler_get_buffer_info_helper(aCurrentPosition, aTotalSize, aGeneration); } -// Discard the profile, throw away the profile and notify 'profiler-locked'. -// This function is to be used when entering private browsing to prevent -// the profiler from collecting sensitive data. -static inline void profiler_lock() {} +// Lock the profiler. When locked the profiler is (1) stopped, +// (2) profile data is cleared, (3) 'profiler-locked' is fired. +// This is used to lock down the profiler during private browsing. +PROFILER_FUNC_VOID(profiler_lock()) -// Re-enable the profiler and notify 'profiler-unlocked'. -static inline void profiler_unlock() {} +// Unlock the profiler, leaving it stopped, and fire 'profiler-unlocked'. +PROFILER_FUNC_VOID(profiler_unlock()) -static inline void profiler_register_thread(const char* name, void* guessStackTop) {} -static inline void profiler_unregister_thread() {} +// Register/unregister threads with the profiler. +PROFILER_FUNC_VOID(profiler_register_thread(const char* name, + void* guessStackTop)) +PROFILER_FUNC_VOID(profiler_unregister_thread()) // These functions tell the profiler that a thread went to sleep so that we can avoid // sampling it while it's sleeping. Calling profiler_sleep_start() twice without // profiler_sleep_end() is an error. -static inline void profiler_sleep_start() {} -static inline void profiler_sleep_end() {} -static inline bool profiler_is_sleeping() { return false; } +PROFILER_FUNC_VOID(profiler_sleep_start()) +PROFILER_FUNC_VOID(profiler_sleep_end()) +PROFILER_FUNC(bool profiler_is_sleeping(), false) // Call by the JSRuntime's operation callback. This is used to enable // profiling on auxilerary threads. -static inline void profiler_js_operation_callback() {} +PROFILER_FUNC_VOID(profiler_js_operation_callback()) -static inline double profiler_time() { return 0; } -static inline double profiler_time(const mozilla::TimeStamp& aTime) { return 0; } +PROFILER_FUNC(double profiler_time(), 0) +PROFILER_FUNC(double profiler_time(const mozilla::TimeStamp& aTime), 0) -static inline bool profiler_in_privacy_mode() { return false; } +PROFILER_FUNC(bool profiler_in_privacy_mode(), false) -static inline void profiler_log(const char *str) {} -static inline void profiler_log(const char *fmt, va_list args) {} +PROFILER_FUNC_VOID(profiler_log(const char *str)) +PROFILER_FUNC_VOID(profiler_log(const char *fmt, va_list args)) -#else +// End of the functions defined whether the profiler is enabled or not. + +#if defined(MOZ_ENABLE_PROFILER_SPS) #include #include @@ -266,15 +309,6 @@ class GeckoSampler; class nsISupports; class ProfilerMarkerPayload; -namespace mozilla { -class TimeStamp; - -namespace dom { -class Promise; -} // namespace dom -} // namespace mozilla - - extern MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack; extern MOZ_THREAD_LOCAL(GeckoSampler *) tlsTicker; extern bool stack_key_initialized; @@ -291,10 +325,10 @@ extern bool stack_key_initialized; // Returns a handle to pass on exit. This can check that we are popping the // correct callstack. -inline void* -mozilla_sampler_call_enter(const char *aInfo, - js::ProfileEntry::Category aCategory, - void *aFrameAddress, bool aCopy, uint32_t line) +static inline void* +profiler_call_enter(const char* aInfo, + js::ProfileEntry::Category aCategory, + void *aFrameAddress, bool aCopy, uint32_t line) { // check if we've been initialized to avoid calling pthread_getspecific // with a null tlsStack which will return undefined results. @@ -319,8 +353,8 @@ mozilla_sampler_call_enter(const char *aInfo, return stack; } -inline void -mozilla_sampler_call_exit(void *aHandle) +static inline void +profiler_call_exit(void* aHandle) { if (!aHandle) return; @@ -329,322 +363,13 @@ mozilla_sampler_call_exit(void *aHandle) stack->popAndMaybeDelete(); } -void mozilla_sampler_add_marker(const char *aMarker, - ProfilerMarkerPayload *aPayload = nullptr); +void profiler_add_marker(const char *aMarker, + ProfilerMarkerPayload *aPayload = nullptr); -void mozilla_sampler_start(int aEntries, double aInterval, - const char** aFeatures, uint32_t aFeatureCount, - const char** aThreadNameFilters, uint32_t aFilterCount); - -void mozilla_sampler_stop(); - -bool mozilla_sampler_is_paused(); -void mozilla_sampler_pause(); -void mozilla_sampler_resume(); - -UniqueProfilerBacktrace mozilla_sampler_get_backtrace(); -void mozilla_sampler_get_backtrace_noalloc(char *output, size_t outputSize); - -bool mozilla_sampler_is_active(); - -bool mozilla_sampler_feature_active(const char* aName); - -void mozilla_sampler_responsiveness(const mozilla::TimeStamp& time); - -void mozilla_sampler_frame_number(int frameNumber); - -mozilla::UniquePtr mozilla_sampler_get_profile(double aSinceTime); - -JSObject *mozilla_sampler_get_profile_data(JSContext* aCx, double aSinceTime); -void mozilla_sampler_get_profile_data_async(double aSinceTime, - mozilla::dom::Promise* aPromise); -MOZ_EXPORT -void mozilla_sampler_save_profile_to_file_async(double aSinceTime, - const char* aFileName); -void mozilla_sampler_get_profiler_start_params(int* aEntrySize, - double* aInterval, - mozilla::Vector* aFilters, - mozilla::Vector* aFeatures); -void mozilla_sampler_get_gatherer(nsISupports** aRetVal); - -// Make this function easily callable from a debugger in a build without -// debugging information (work around http://llvm.org/bugs/show_bug.cgi?id=22211) -extern "C" { - void mozilla_sampler_save_profile_to_file(const char* aFilename); -} - -const char** mozilla_sampler_get_features(); - -void mozilla_sampler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, - uint32_t *aGeneration); - -void mozilla_sampler_init(void* stackTop); - -void mozilla_sampler_shutdown(); - -// Lock the profiler. When locked the profiler is (1) stopped, -// (2) profile data is cleared, (3) profiler-locked is fired. -// This is used to lock down the profiler during private browsing -void mozilla_sampler_lock(); - -// Unlock the profiler, leaving it stopped and fires profiler-unlocked. -void mozilla_sampler_unlock(); - -// Register/unregister threads with the profiler -bool mozilla_sampler_register_thread(const char* name, void* stackTop); -void mozilla_sampler_unregister_thread(); - -void mozilla_sampler_sleep_start(); -void mozilla_sampler_sleep_end(); -bool mozilla_sampler_is_sleeping(); - -double mozilla_sampler_time(); -double mozilla_sampler_time(const mozilla::TimeStamp& aTime); - -void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, - TracingMetadata aMetaData); - -void mozilla_sampler_tracing(const char* aCategory, const char* aInfo, - UniqueProfilerBacktrace aCause, - TracingMetadata aMetaData); - -void mozilla_sampler_log(const char *fmt, va_list args); - -static inline -void profiler_init(void* stackTop) -{ - mozilla_sampler_init(stackTop); -} - -static inline -void profiler_shutdown() -{ - mozilla_sampler_shutdown(); -} - -static inline -void profiler_start(int aProfileEntries, double aInterval, - const char** aFeatures, uint32_t aFeatureCount, - const char** aThreadNameFilters, uint32_t aFilterCount) -{ - mozilla_sampler_start(aProfileEntries, aInterval, aFeatures, aFeatureCount, aThreadNameFilters, aFilterCount); -} - -static inline -void profiler_stop() -{ - mozilla_sampler_stop(); -} - -static inline -bool profiler_is_paused() -{ - return mozilla_sampler_is_paused(); -} - -static inline -void profiler_pause() -{ - mozilla_sampler_pause(); -} - -static inline -void profiler_resume() -{ - mozilla_sampler_resume(); -} - -static inline -UniqueProfilerBacktrace profiler_get_backtrace() -{ - return mozilla_sampler_get_backtrace(); -} - -static inline -void profiler_get_backtrace_noalloc(char *output, size_t outputSize) -{ - return mozilla_sampler_get_backtrace_noalloc(output, outputSize); -} - -static inline -bool profiler_is_active() -{ - return mozilla_sampler_is_active(); -} - -static inline -bool profiler_feature_active(const char* aName) -{ - return mozilla_sampler_feature_active(aName); -} - -static inline -void profiler_responsiveness(const mozilla::TimeStamp& aTime) -{ - mozilla_sampler_responsiveness(aTime); -} - -static inline -void profiler_set_frame_number(int frameNumber) -{ - return mozilla_sampler_frame_number(frameNumber); -} - -static inline -mozilla::UniquePtr profiler_get_profile(double aSinceTime = 0) -{ - return mozilla_sampler_get_profile(aSinceTime); -} - -static inline -JSObject* profiler_get_profile_jsobject(JSContext* aCx, double aSinceTime = 0) -{ - return mozilla_sampler_get_profile_data(aCx, aSinceTime); -} - -static inline -void profiler_get_profile_jsobject_async(double aSinceTime = 0, - mozilla::dom::Promise* aPromise = 0) -{ - mozilla_sampler_get_profile_data_async(aSinceTime, aPromise); -} - -static inline -void profiler_get_start_params(int* aEntrySize, - double* aInterval, - mozilla::Vector* aFilters, - mozilla::Vector* aFeatures) -{ - mozilla_sampler_get_profiler_start_params(aEntrySize, aInterval, aFilters, aFeatures); -} - -static inline -void profiler_get_gatherer(nsISupports** aRetVal) -{ - mozilla_sampler_get_gatherer(aRetVal); -} - -static inline -void profiler_save_profile_to_file(const char* aFilename) -{ - return mozilla_sampler_save_profile_to_file(aFilename); -} - -static inline -const char** profiler_get_features() -{ - return mozilla_sampler_get_features(); -} - -static inline -void profiler_get_buffer_info(uint32_t *aCurrentPosition, uint32_t *aTotalSize, - uint32_t *aGeneration) -{ - return mozilla_sampler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration); -} - -static inline -void profiler_lock() -{ - return mozilla_sampler_lock(); -} - -static inline -void profiler_unlock() -{ - return mozilla_sampler_unlock(); -} - -static inline -void profiler_register_thread(const char* name, void* guessStackTop) -{ - mozilla_sampler_register_thread(name, guessStackTop); -} - -static inline -void profiler_unregister_thread() -{ - mozilla_sampler_unregister_thread(); -} - -static inline -void profiler_sleep_start() -{ - mozilla_sampler_sleep_start(); -} - -static inline -void profiler_sleep_end() -{ - mozilla_sampler_sleep_end(); -} - -static inline -bool profiler_is_sleeping() -{ - return mozilla_sampler_is_sleeping(); -} - -static inline -void profiler_js_operation_callback() -{ - PseudoStack *stack = tlsPseudoStack.get(); - if (!stack) { - return; - } - - stack->jsOperationCallback(); -} - -static inline -double profiler_time() -{ - return mozilla_sampler_time(); -} - -static inline -double profiler_time(const mozilla::TimeStamp& aTime) -{ - return mozilla_sampler_time(aTime); -} - -static inline -bool profiler_in_privacy_mode() -{ - PseudoStack *stack = tlsPseudoStack.get(); - if (!stack) { - return false; - } - return stack->mPrivacyMode; -} - -static inline void profiler_tracing(const char* aCategory, const char* aInfo, - UniqueProfilerBacktrace aCause, - TracingMetadata aMetaData = TRACING_DEFAULT) -{ - // Don't insert a marker if we're not profiling to avoid - // the heap copy (malloc). - if (!stack_key_initialized || !profiler_is_active()) { - return; - } - - mozilla_sampler_tracing(aCategory, aInfo, mozilla::Move(aCause), aMetaData); -} - -static inline void profiler_tracing(const char* aCategory, const char* aInfo, - TracingMetadata aMetaData = TRACING_DEFAULT) -{ - if (!stack_key_initialized) - return; - - // Don't insert a marker if we're not profiling to avoid - // the heap copy (malloc). - if (!profiler_is_active()) { - return; - } - - mozilla_sampler_tracing(aCategory, aInfo, aMetaData); -} +MOZ_EXPORT // XXX: should this be 'extern "C"' as well? +void profiler_save_profile_to_file_async(double aSinceTime, + const char* aFileName); +void profiler_get_gatherer(nsISupports** aRetVal); #define SAMPLER_APPEND_LINE_NUMBER_PASTE(id, line) id ## line #define SAMPLER_APPEND_LINE_NUMBER_EXPAND(id, line) SAMPLER_APPEND_LINE_NUMBER_PASTE(id, line) @@ -680,18 +405,6 @@ static inline void profiler_tracing(const char* aCategory, const char* aInfo, # define MOZ_PLATFORM_TRACING(name) #endif -// we want the class and function name but can't easily get that using preprocessor macros -// __func__ doesn't have the class name and __PRETTY_FUNCTION__ has the parameters - -#define PROFILER_LABEL(name_space, info, category) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__) - -#define PROFILER_LABEL_FUNC(category) MOZ_PLATFORM_TRACING(SAMPLE_FUNCTION_NAME) mozilla::SamplerStackFrameRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(SAMPLE_FUNCTION_NAME, category, __LINE__) - -#define PROFILER_LABEL_PRINTF(name_space, info, category, ...) MOZ_PLATFORM_TRACING(name_space "::" info) mozilla::SamplerStackFramePrintfRAII SAMPLER_APPEND_LINE_NUMBER(sampler_raii)(name_space "::" info, category, __LINE__, __VA_ARGS__) - -#define PROFILER_MARKER(info) mozilla_sampler_add_marker(info) -#define PROFILER_MARKER_PAYLOAD(info, payload) mozilla_sampler_add_marker(info, payload) - /* FIXME/bug 789667: memory constraints wouldn't much of a problem for * this small a sample buffer size, except that serializing the * profile data is extremely, unnecessarily memory intensive. */ @@ -743,10 +456,10 @@ public: MOZ_GUARD_OBJECT_NOTIFIER_PARAM) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - mHandle = mozilla_sampler_call_enter(aInfo, aCategory, this, false, line); + mHandle = profiler_call_enter(aInfo, aCategory, this, false, line); } ~SamplerStackFrameRAII() { - mozilla_sampler_call_exit(mHandle); + profiler_call_exit(mHandle); } private: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER @@ -771,14 +484,14 @@ public: VsprintfLiteral(buff, aFormat, args); SprintfLiteral(mDest, "%s %s", aInfo, buff); - mHandle = mozilla_sampler_call_enter(mDest, aCategory, this, true, line); + mHandle = profiler_call_enter(mDest, aCategory, this, true, line); va_end(args); } else { - mHandle = mozilla_sampler_call_enter(aInfo, aCategory, this, false, line); + mHandle = profiler_call_enter(aInfo, aCategory, this, false, line); } } ~SamplerStackFramePrintfRAII() { - mozilla_sampler_call_exit(mHandle); + profiler_call_exit(mHandle); } private: char mDest[SAMPLER_MAX_STRING]; @@ -795,19 +508,7 @@ profiler_get_pseudo_stack(void) return tlsPseudoStack.get(); } -static inline -void profiler_log(const char *str) -{ - profiler_tracing("log", str, TRACING_EVENT); -} - -static inline -void profiler_log(const char *fmt, va_list args) -{ - mozilla_sampler_log(fmt, args); -} - -#endif +#endif // defined(MOZ_ENABLE_PROFILER_SPS) namespace mozilla {