--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -57,18 +57,19 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/Maybe.h"
#include "mozilla/Sprintf.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/UniquePtr.h"
+#include "js/ProfilingStack.h"
+#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
-#include "js/ProfilingStack.h"
#include "nscore.h"
// Make sure that we can use std::min here without the Windows headers messing
// with us.
#ifdef min
# undef min
#endif
@@ -500,16 +501,26 @@ PseudoStack* profiler_get_pseudo_stack()
mozilla::Maybe<NS_LossyConvertUTF16toASCII> asciiStr; \
mozilla::Maybe<AutoProfilerLabel> raiiObjectLossyNsString; \
if (profiler_is_active()) { \
asciiStr.emplace(nsStr); \
raiiObjectLossyNsString.emplace(label, asciiStr->get(), __LINE__, \
js::ProfileEntry::Category::category); \
}
+// Similar to AUTO_PROFILER_LABEL, but accepting a JSContext* parameter, and a
+// no-op if the profiler is disabled.
+// Used to annotate functions for which overhead in the range of nanoseconds is
+// noticeable. It avoids overhead from the TLS lookup because it can get the
+// PseudoStack from the JS context, and avoids almost all overhead in the case
+// where the profiler is disabled.
+#define AUTO_PROFILER_LABEL_FAST(label, category, ctx) \
+ mozilla::AutoProfilerLabel PROFILER_RAII(ctx, label, nullptr, __LINE__, \
+ js::ProfileEntry::Category::category)
+
// Insert a marker in the profile timeline. This is useful to delimit something
// important happening such as the first paint. Unlike labels, which are only
// recorded in the profile buffer if a sample is collected while the label is
// on the pseudostack, markers will always be recorded in the profile buffer.
// aMarkerName is copied, so the caller does not need to ensure it lives for a
// certain length of time. A no-op if the profiler is inactive or in privacy
// mode.
#define PROFILER_ADD_MARKER(markerName) \
@@ -655,25 +666,50 @@ private:
// This class creates a non-owning PseudoStack reference. Objects of this class
// are stack-allocated, and so exist within a thread, and are thus bounded by
// the lifetime of the thread, which ensures that the references held can't be
// used after the PseudoStack is destroyed.
class MOZ_RAII AutoProfilerLabel
{
public:
+ // This is the AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC variant.
AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
uint32_t aLine, js::ProfileEntry::Category aCategory
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ // Get the PseudoStack from TLS.
+ Push(sPseudoStack.get(), aLabel, aDynamicString, aLine, aCategory);
+ }
+
+ // This is the AUTO_PROFILER_LABEL_FAST variant. It's guarded on
+ // profiler_is_active() and retrieves the PseudoStack from the JSContext.
+ AutoProfilerLabel(JSContext* aJSContext,
+ const char* aLabel, const char* aDynamicString,
+ uint32_t aLine, js::ProfileEntry::Category aCategory
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ if (profiler_is_active()) {
+ Push(js::GetContextProfilingStack(aJSContext),
+ aLabel, aDynamicString, aLine, aCategory);
+ } else {
+ mPseudoStack = nullptr;
+ }
+ }
+
+ void Push(PseudoStack* aPseudoStack,
+ const char* aLabel, const char* aDynamicString,
+ uint32_t aLine, js::ProfileEntry::Category aCategory)
+ {
// This function runs both on and off the main thread.
- mPseudoStack = sPseudoStack.get();
+ mPseudoStack = aPseudoStack;
if (mPseudoStack) {
mPseudoStack->pushCppFrame(aLabel, aDynamicString, this, aLine,
js::ProfileEntry::Kind::CPP_NORMAL, aCategory);
}
}
~AutoProfilerLabel()
{