Skip to content

Commit

Permalink
Bug 1915169 - Record WebIDL calls when tracing r=profiler-reviewers,aabh
Browse files Browse the repository at this point in the history
Fairly straightforward - this patch adds instrumentation into the profiling
RAII helper which is inserted into all WebIDL calls in order to include them
when running with JS Execution Tracing enabled.

Locally times on the attribute.specified getter microbenchmark were at ~5.6ns
without this patch and ~5.9 with the patch. Assuming that is real, is that an
acceptable perf hit here? The feature seems to be quite useful.

Differential Revision: https://phabricator.services.mozilla.com/D221690
  • Loading branch information
squarewave committed Oct 22, 2024
1 parent 68a589c commit 2d8e7a5
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
2 changes: 2 additions & 0 deletions js/public/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ extern JS_PUBLIC_API void JS_TracerEnterLabelLatin1(JSContext* cx,
extern JS_PUBLIC_API void JS_TracerEnterLabelTwoByte(JSContext* cx,
const char16_t* label);

extern JS_PUBLIC_API bool JS_TracerIsTracing(JSContext* cx);

// If the JS execution tracer is running, this will generate a
// ENTRY_KIND_LABEL_LEAVE entry with the specified label.
// It is up to the consumer to decide what to do with a ENTRY_KIND_LABEL_LEAVE
Expand Down
2 changes: 2 additions & 0 deletions js/src/debugger/ExecutionTracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ void JS_TracerLeaveLabelLatin1(JSContext* cx, const char* label) {
}
}

bool JS_TracerIsTracing(JSContext* cx) { return cx->hasExecutionTracer(); }

bool JS_TracerBeginTracing(JSContext* cx) {
CHECK_THREAD(cx);
return cx->enableExecutionTracing();
Expand Down
35 changes: 35 additions & 0 deletions tools/profiler/public/ProfilerLabels.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "mozilla/ProfilerState.h"
#include "mozilla/ProfilerThreadState.h"

#include "js/Debug.h"
#include "js/ProfilingCategory.h"
#include "js/ProfilingStack.h"
#include "js/RootingAPI.h"
Expand Down Expand Up @@ -289,6 +290,11 @@ class MOZ_RAII AutoProfilerLabelHot {
if (mProfilingStack) {
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this,
aCategoryPair, aFlags);

# ifdef MOZ_EXECUTION_TRACING
// We don't have a JSContext in this case, so we don't trace it.
mCx = nullptr;
# endif
}
}

Expand All @@ -303,20 +309,49 @@ class MOZ_RAII AutoProfilerLabelHot {
if (MOZ_UNLIKELY(mProfilingStack)) {
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this,
aCategoryPair, aFlags);
# ifdef MOZ_EXECUTION_TRACING
if (MOZ_UNLIKELY(JS_TracerIsTracing(aJSContext))) {
mCx = aJSContext;
TraceLabel(aLabel, aDynamicString);
} else {
mCx = nullptr;
}
# endif
}
}

~AutoProfilerLabelHot() {
// This function runs both on and off the main thread.
if (MOZ_UNLIKELY(mProfilingStack)) {
mProfilingStack->pop();
# ifdef MOZ_EXECUTION_TRACING
if (MOZ_UNLIKELY(mCx)) {
// We do not bother to produce a detailed label here, and just use an
// empty string. The label will be lost if we wrap over the ring
// buffer, but that's fine.
JS_TracerLeaveLabelLatin1(mCx, "");
}
# endif
}
}

private:
# ifdef MOZ_EXECUTION_TRACING
MOZ_NEVER_INLINE void TraceLabel(const char* aLabel,
const char* aDynamicString) {
char buffer[1024];
SprintfLiteral(buffer, "(DOM) %s.%s", aLabel, aDynamicString);
JS_TracerEnterLabelLatin1(mCx, buffer);
}
# endif

// We save a ProfilingStack pointer in the ctor so we don't have to redo the
// TLS lookup in the dtor.
ProfilingStack* mProfilingStack;

# ifdef MOZ_EXECUTION_TRACING
JSContext* mCx;
# endif
};

#endif // !MOZ_GECKO_PROFILER
Expand Down

0 comments on commit 2d8e7a5

Please sign in to comment.