Bug 1499507 - Don't collect line numbers for profiling stack frames. r=njn

They were not displayed in the UI, and the instructions to initialize the line
field of a stack frame increased code size unnecessarily.

This change reduces the binary size on Linux x64 by around 100KB.

Here's a diff of the impact on the code generated for Attr_Binding::get_specified
in the Mac build:

@@ -20,17 +20,16 @@
    movq       0x8(%rbx), %rax
    movq       %r12, %rcx
    shlq       $0x5, %rcx
    leaq       aGetAttrspecifi, %rdx                       ; "get Attr.specified"
    movq       %rdx, (%rax,%rcx)
    movq       $0x0, 0x8(%rax,%rcx)
    leaq       -40(%rbp), %rdx
    movq       %rdx, 0x10(%rax,%rcx)
-   movl       $0x106, 0x18(%rax,%rcx)
    movl       $0x1c, 0x1c(%rax,%rcx)
    leal       0x1(%r12), %eax
    movl       %eax, 0x10(%rbx)

    movq       %r15, %rdi
    call       __ZNK7mozilla3dom4Attr9SpecifiedEv          ; mozilla::dom::Attr::Specified() const
    movzxl     %al, %eax
    movabsq    $0xfff9000000000000, %rcx

Depends on D9193

Differential Revision: https://phabricator.services.mozilla.com/D9195

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Markus Stange 2018-11-05 19:07:45 +00:00
parent 354b56c30c
commit 000dc83f31
14 changed files with 41 additions and 53 deletions

View File

@ -125,7 +125,7 @@ nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx,
:
#ifdef MOZ_GECKO_PROFILER
mAutoProfilerLabel("nsJSUtils::ExecutionContext", /* dynamicStr */ nullptr,
__LINE__, js::ProfilingStackFrame::Category::JS),
js::ProfilingStackFrame::Category::JS),
#endif
mCx(aCx)
, mRealm(aCx, aGlobal)

View File

@ -645,7 +645,7 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
// ran.
, mCallerOverride(cx())
#ifdef MOZ_GECKO_PROFILER
, mAutoProfilerLabel("AutoEntryScript", aReason, __LINE__,
, mAutoProfilerLabel("AutoEntryScript", aReason,
js::ProfilingStackFrame::Category::JS)
#endif
{

View File

@ -145,9 +145,12 @@ class ProfilingStackFrame
mozilla::Atomic<void*, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve> spOrScript;
// Line number for non-JS stack frames, the bytecode offset otherwise.
// The bytecode offset for JS stack frames.
// Must not be used on non-JS frames; it'll contain either the default 0,
// or a leftover value from a previous JS stack frame that was using this
// ProfilingStackFrame object.
mozilla::Atomic<int32_t, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve> lineOrPcOffset;
mozilla::recordreplay::Behavior::DontPreserve> pcOffsetIfJS_;
// Bits 0...1 hold the Kind. Bits 2...31 hold the category.
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
@ -163,8 +166,8 @@ class ProfilingStackFrame
dynamicString_ = other.dynamicString();
void* spScript = other.spOrScript;
spOrScript = spScript;
int32_t offset = other.lineOrPcOffset;
lineOrPcOffset = offset;
int32_t offsetIfJS = other.pcOffsetIfJS_;
pcOffsetIfJS_ = offsetIfJS;
uint32_t kindAndCategory = other.kindAndCategory_;
kindAndCategory_ = kindAndCategory;
return *this;
@ -233,12 +236,12 @@ class ProfilingStackFrame
const char* dynamicString() const { return dynamicString_; }
void initLabelFrame(const char* aLabel, const char* aDynamicString, void* sp,
uint32_t aLine, Category aCategory)
Category aCategory)
{
label_ = aLabel;
dynamicString_ = aDynamicString;
spOrScript = sp;
lineOrPcOffset = static_cast<int32_t>(aLine);
// pcOffsetIfJS_ is not set and must not be used on label frames.
kindAndCategory_ = uint32_t(Kind::LABEL) | (uint32_t(aCategory) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isLabelFrame());
}
@ -248,7 +251,7 @@ class ProfilingStackFrame
label_ = "";
dynamicString_ = nullptr;
spOrScript = sp;
lineOrPcOffset = 0;
// pcOffsetIfJS_ is not set and must not be used on sp marker frames.
kindAndCategory_ = uint32_t(Kind::SP_MARKER) | (uint32_t(Category::OTHER) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isSpMarkerFrame());
}
@ -259,7 +262,7 @@ class ProfilingStackFrame
label_ = aLabel;
dynamicString_ = aDynamicString;
spOrScript = aScript;
lineOrPcOffset = pcToOffset(aScript, aPc);
pcOffsetIfJS_ = pcToOffset(aScript, aPc);
kindAndCategory_ = uint32_t(Kind::JS_NORMAL) | (uint32_t(Category::JS) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isJsFrame());
}
@ -283,11 +286,6 @@ class ProfilingStackFrame
JS_PUBLIC_API(JSScript*) script() const;
uint32_t line() const {
MOZ_ASSERT(!isJsFrame());
return static_cast<uint32_t>(lineOrPcOffset);
}
// Note that the pointer returned might be invalid.
JSScript* rawScript() const {
MOZ_ASSERT(isJsFrame());
@ -363,13 +361,13 @@ class ProfilingStack final
~ProfilingStack();
void pushLabelFrame(const char* label, const char* dynamicString, void* sp,
uint32_t line, js::ProfilingStackFrame::Category category) {
js::ProfilingStackFrame::Category category) {
uint32_t oldStackPointer = stackPointer;
if (MOZ_UNLIKELY(oldStackPointer >= capacity)) {
ensureCapacitySlow();
}
frames[oldStackPointer].initLabelFrame(label, dynamicString, sp, line, category);
frames[oldStackPointer].initLabelFrame(label, dynamicString, sp, category);
// This must happen at the end! The compiler will not reorder this
// update because stackPointer is Atomic<..., ReleaseAcquire>, so any

View File

@ -98,7 +98,6 @@ AutoGeckoProfilerEntry::AutoGeckoProfilerEntry(JSContext* cx, const char* label,
profiler_->profilingStack_->pushLabelFrame(label,
/* dynamicString = */ nullptr,
/* sp = */ this,
/* line = */ 0,
category);
}

View File

@ -256,7 +256,7 @@ GeckoProfilerThread::exit(JSScript* script, JSFunction* maybeFun)
if (frame.isJsFrame()) {
fprintf(stderr, " [%d] JS %s\n", i, frame.dynamicString());
} else {
fprintf(stderr, " [%d] C line %d %s\n", i, frame.line(), frame.dynamicString());
fprintf(stderr, " [%d] Label %s\n", i, frame.dynamicString());
}
}
}
@ -449,12 +449,12 @@ JS_FRIEND_API(jsbytecode*)
ProfilingStackFrame::pc() const
{
MOZ_ASSERT(isJsFrame());
if (lineOrPcOffset == NullPCOffset) {
if (pcOffsetIfJS_ == NullPCOffset) {
return nullptr;
}
JSScript* script = this->script();
return script ? script->offsetToPC(lineOrPcOffset) : nullptr;
return script ? script->offsetToPC(pcOffsetIfJS_) : nullptr;
}
/* static */ int32_t
@ -468,7 +468,7 @@ ProfilingStackFrame::setPC(jsbytecode* pc)
MOZ_ASSERT(isJsFrame());
JSScript* script = this->script();
MOZ_ASSERT(script); // This should not be called while profiling is suppressed.
lineOrPcOffset = pcToOffset(script, pc);
pcOffsetIfJS_ = pcToOffset(script, pc);
}
JS_FRIEND_API(void)

View File

@ -56,7 +56,7 @@ GlobalHelperThreadState* gHelperThreadState = nullptr;
#define PROFILER_RAII_EXPAND(id, line) PROFILER_RAII_PASTE(id, line)
#define PROFILER_RAII PROFILER_RAII_EXPAND(raiiObject, __LINE__)
#define AUTO_PROFILER_LABEL(label, category) \
HelperThread::AutoProfilerLabel PROFILER_RAII(this, label, __LINE__, \
HelperThread::AutoProfilerLabel PROFILER_RAII(this, label, \
js::ProfilingStackFrame::Category::category)
bool
@ -2583,12 +2583,11 @@ const HelperThread::TaskSpec HelperThread::taskSpecs[] = {
HelperThread::AutoProfilerLabel::AutoProfilerLabel(HelperThread* helperThread,
const char* label,
uint32_t line,
ProfilingStackFrame::Category category)
: profilingStack(helperThread->profilingStack)
{
if (profilingStack) {
profilingStack->pushLabelFrame(label, nullptr, this, line, category);
profilingStack->pushLabelFrame(label, nullptr, this, category);
}
}

View File

@ -421,7 +421,6 @@ struct HelperThread
struct AutoProfilerLabel
{
AutoProfilerLabel(HelperThread* helperThread, const char* label,
uint32_t line,
ProfilingStackFrame::Category category);
~AutoProfilerLabel();

View File

@ -669,8 +669,7 @@ continue_loading:
// A few DLLs such as xul.dll and nss3.dll get loaded before mozglue's
// AutoProfilerLabel is initialized, and this is a no-op in those cases. But
// the vast majority of DLLs do get labelled here.
AutoProfilerLabel label("WindowsDllBlocklist::patched_LdrLoadDll", dllName,
__LINE__);
AutoProfilerLabel label("WindowsDllBlocklist::patched_LdrLoadDll", dllName);
#ifdef _M_AMD64
// Prevent the stack walker from suspending this thread when LdrLoadDll

View File

@ -20,13 +20,12 @@ RegisterProfilerLabelEnterExit(ProfilerLabelEnter aEnter,
}
AutoProfilerLabel::AutoProfilerLabel(const char* aLabel,
const char* aDynamicString,
uint32_t aLine
const char* aDynamicString
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
mProfilingStack = sEnter ? sEnter(aLabel, aDynamicString, this, aLine) : nullptr;
mProfilingStack = sEnter ? sEnter(aLabel, aDynamicString, this) : nullptr;
}
AutoProfilerLabel::~AutoProfilerLabel()

View File

@ -29,8 +29,7 @@ class ProfilingStack;
namespace mozilla {
typedef ProfilingStack* (*ProfilerLabelEnter)(const char*, const char*, void*,
uint32_t);
typedef ProfilingStack* (*ProfilerLabelEnter)(const char*, const char*, void*);
typedef void (*ProfilerLabelExit)(ProfilingStack*);
// Register callbacks that do the entry/exit work involving sProfilingStack.
@ -44,8 +43,7 @@ MFBT_API void RegisterProfilerLabelEnterExit(ProfilerLabelEnter aEnter,
class MOZ_RAII AutoProfilerLabel
{
public:
AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
uint32_t aLine
AutoProfilerLabel(const char* aLabel, const char* aDynamicString
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoProfilerLabel();

View File

@ -198,7 +198,6 @@ ProfileBufferCollector::CollectProfilingStackFrame(const js::ProfilingStackFrame
}
} else {
MOZ_ASSERT(aFrame.isLabelFrame());
line = Some(aFrame.line());
}
if (dynamicString) {

View File

@ -2493,12 +2493,11 @@ locked_profiler_start(PSLockRef aLock, uint32_t aCapacity, double aInterval,
// This basically duplicates AutoProfilerLabel's constructor.
ProfilingStack*
MozGlueLabelEnter(const char* aLabel, const char* aDynamicString, void* aSp,
uint32_t aLine)
MozGlueLabelEnter(const char* aLabel, const char* aDynamicString, void* aSp)
{
ProfilingStack* profilingStack = AutoProfilerLabel::sProfilingStack.get();
if (profilingStack) {
profilingStack->pushLabelFrame(aLabel, aDynamicString, aSp, aLine,
profilingStack->pushLabelFrame(aLabel, aDynamicString, aSp,
js::ProfilingStackFrame::Category::OTHER);
}
return profilingStack;

View File

@ -473,7 +473,7 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
// Use AUTO_PROFILER_LABEL_DYNAMIC_* if you want to add additional / dynamic
// information to the label stack frame.
#define AUTO_PROFILER_LABEL(label, category) \
mozilla::AutoProfilerLabel PROFILER_RAII(label, nullptr, __LINE__, \
mozilla::AutoProfilerLabel PROFILER_RAII(label, nullptr, \
js::ProfilingStackFrame::Category::category)
// Similar to AUTO_PROFILER_LABEL, but with an additional string. The inserted
@ -497,7 +497,7 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
// the profile buffer than AUTO_PROFILER_LABEL_DYNAMIC_* frames.
#define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, category, cStr) \
mozilla::AutoProfilerLabel \
PROFILER_RAII(label, cStr, __LINE__, js::ProfilingStackFrame::Category::category)
PROFILER_RAII(label, cStr, js::ProfilingStackFrame::Category::category)
// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an nsACString.
//
@ -511,7 +511,7 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
mozilla::Maybe<AutoProfilerLabel> raiiObjectNsCString; \
if (profiler_is_active()) { \
autoCStr.emplace(nsCStr); \
raiiObjectNsCString.emplace(label, autoCStr->get(), __LINE__, \
raiiObjectNsCString.emplace(label, autoCStr->get(), \
js::ProfilingStackFrame::Category::category); \
}
@ -528,7 +528,7 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
mozilla::Maybe<AutoProfilerLabel> raiiObjectLossyNsString; \
if (profiler_is_active()) { \
asciiStr.emplace(nsStr); \
raiiObjectLossyNsString.emplace(label, asciiStr->get(), __LINE__, \
raiiObjectLossyNsString.emplace(label, asciiStr->get(), \
js::ProfilingStackFrame::Category::category); \
}
@ -539,7 +539,7 @@ mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
// ProfilingStack 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__, \
mozilla::AutoProfilerLabel PROFILER_RAII(ctx, label, nullptr, \
js::ProfilingStackFrame::Category::category)
// Insert a marker in the profile timeline. This is useful to delimit something
@ -719,37 +719,36 @@ 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::ProfilingStackFrame::Category aCategory
js::ProfilingStackFrame::Category aCategory
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
// Get the ProfilingStack from TLS.
Push(sProfilingStack.get(), aLabel, aDynamicString, aLine, aCategory);
Push(sProfilingStack.get(), aLabel, aDynamicString, aCategory);
}
// This is the AUTO_PROFILER_LABEL_FAST variant. It retrieves the ProfilingStack
// from the JSContext and does nothing if the profiler is inactive.
AutoProfilerLabel(JSContext* aJSContext,
const char* aLabel, const char* aDynamicString,
uint32_t aLine, js::ProfilingStackFrame::Category aCategory
js::ProfilingStackFrame::Category aCategory
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
Push(js::GetContextProfilingStackIfEnabled(aJSContext),
aLabel, aDynamicString, aLine, aCategory);
aLabel, aDynamicString, aCategory);
}
void Push(ProfilingStack* aProfilingStack,
const char* aLabel, const char* aDynamicString,
uint32_t aLine, js::ProfilingStackFrame::Category aCategory)
js::ProfilingStackFrame::Category aCategory)
{
// This function runs both on and off the main thread.
mProfilingStack = aProfilingStack;
if (mProfilingStack) {
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this, aLine,
aCategory);
mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this, aCategory);
}
}

View File

@ -748,9 +748,9 @@ TEST(GeckoProfiler, ProfilingStack)
ASSERT_TRUE(profiler_get_backtrace());
}
AutoProfilerLabel label1("A", nullptr, 888,
AutoProfilerLabel label1("A", nullptr,
js::ProfilingStackFrame::Category::DOM);
AutoProfilerLabel label2("A", dynamic.get(), 888,
AutoProfilerLabel label2("A", dynamic.get(),
js::ProfilingStackFrame::Category::NETWORK);
ASSERT_TRUE(profiler_get_backtrace());