зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1004726 - Clean up profiler pseudo-stack representation (relanded), r=djvj,jchen
This commit is contained in:
Родитель
ac61ea89ba
Коммит
07cede5f0b
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 999651 et al. apparently require a clobber, unclear why
|
||||
Bug 1004726 requires a clobber for B2G Emulator builds
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define js_ProfilingStack_h
|
||||
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
|
||||
#include "jsbytecode.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
|
@ -34,67 +34,97 @@ class ProfileEntry
|
|||
// If the size modification were somehow reordered before the stores, then
|
||||
// if a sample were taken it would be examining bogus information.
|
||||
//
|
||||
// A ProfileEntry represents both a C++ profile entry and a JS one. Both use
|
||||
// the string as a description, but JS uses the sp as nullptr or (void*)1 to
|
||||
// indicate that it is a JS entry. The script_ is then only ever examined for
|
||||
// a JS entry, and the idx is used by both, but with different meanings.
|
||||
//
|
||||
const char * volatile string; // Descriptive string of this entry
|
||||
void * volatile sp; // Relevant stack pointer for the entry,
|
||||
// less than or equal to SCRIPT_OPT_STACKPOINTER for js
|
||||
// script entries, greater for non-js entries.
|
||||
JSScript * volatile script_; // if js(), non-null script which is running - low bit
|
||||
// indicates if script is optimized or not.
|
||||
int32_t volatile idx; // if js(), idx of pc, otherwise line number
|
||||
// A ProfileEntry represents both a C++ profile entry and a JS one.
|
||||
|
||||
// Descriptive string of this entry.
|
||||
const char * volatile string;
|
||||
|
||||
// Stack pointer for non-JS entries, the script pointer otherwise.
|
||||
void * volatile spOrScript;
|
||||
|
||||
// Line number for non-JS entries, the bytecode offset otherwise.
|
||||
int32_t volatile lineOrPc;
|
||||
|
||||
// General purpose storage describing this frame.
|
||||
uint32_t volatile flags;
|
||||
|
||||
public:
|
||||
static const uintptr_t SCRIPT_OPT_STACKPOINTER = 0x1;
|
||||
ProfileEntry(void) : flags(0) {}
|
||||
|
||||
// These traits are bit masks. Make sure they're powers of 2.
|
||||
enum Flags {
|
||||
// Indicate whether a profile entry represents a CPP frame. If not set,
|
||||
// a JS frame is assumed by default. You're not allowed to publicly
|
||||
// change the frame type. Instead, call `setJsFrame` or `setCppFrame`.
|
||||
IS_CPP_ENTRY = 0x01,
|
||||
|
||||
// Indicate that copying the frame label is not necessary when taking a
|
||||
// sample of the pseudostack.
|
||||
FRAME_LABEL_COPY = 0x02
|
||||
};
|
||||
|
||||
// All of these methods are marked with the 'volatile' keyword because SPS's
|
||||
// representation of the stack is stored such that all ProfileEntry
|
||||
// instances are volatile. These methods would not be available unless they
|
||||
// were marked as volatile as well.
|
||||
|
||||
bool js() const volatile {
|
||||
MOZ_ASSERT_IF(uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER, script_ != nullptr);
|
||||
return uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER;
|
||||
}
|
||||
bool isCpp() const volatile { return hasFlag(IS_CPP_ENTRY); }
|
||||
bool isJs() const volatile { return !isCpp(); }
|
||||
|
||||
uint32_t line() const volatile { MOZ_ASSERT(!js()); return idx; }
|
||||
JSScript *script() const volatile { MOZ_ASSERT(js()); return script_; }
|
||||
bool scriptIsOptimized() const volatile {
|
||||
MOZ_ASSERT(js());
|
||||
return uintptr_t(sp) <= SCRIPT_OPT_STACKPOINTER;
|
||||
}
|
||||
void *stackAddress() const volatile {
|
||||
if (js())
|
||||
return nullptr;
|
||||
return sp;
|
||||
}
|
||||
bool isCopyLabel() const volatile { return hasFlag(FRAME_LABEL_COPY); };
|
||||
|
||||
void setLabel(const char *aString) volatile { string = aString; }
|
||||
const char *label() const volatile { return string; }
|
||||
|
||||
void setLine(uint32_t aLine) volatile { MOZ_ASSERT(!js()); idx = aLine; }
|
||||
void setLabel(const char *aString) volatile { string = aString; }
|
||||
void setStackAddress(void *aSp) volatile { sp = aSp; }
|
||||
void setScript(JSScript *aScript) volatile { script_ = aScript; }
|
||||
void setJsFrame(JSScript *aScript, jsbytecode *aPc) volatile {
|
||||
flags &= ~IS_CPP_ENTRY;
|
||||
spOrScript = aScript;
|
||||
setPC(aPc);
|
||||
}
|
||||
void setCppFrame(void *aSp, uint32_t aLine) volatile {
|
||||
flags |= IS_CPP_ENTRY;
|
||||
spOrScript = aSp;
|
||||
lineOrPc = aLine;
|
||||
}
|
||||
|
||||
void setFlag(Flags flag) volatile {
|
||||
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
||||
flags |= flag;
|
||||
}
|
||||
void unsetFlag(Flags flag) volatile {
|
||||
MOZ_ASSERT(flag != IS_CPP_ENTRY);
|
||||
flags &= ~flag;
|
||||
}
|
||||
bool hasFlag(Flags flag) const volatile {
|
||||
return bool(flags & uint32_t(flag));
|
||||
}
|
||||
|
||||
void *stackAddress() const volatile {
|
||||
MOZ_ASSERT(!isJs());
|
||||
return spOrScript;
|
||||
}
|
||||
JSScript *script() const volatile {
|
||||
MOZ_ASSERT(isJs());
|
||||
return (JSScript *)spOrScript;
|
||||
}
|
||||
uint32_t line() const volatile {
|
||||
MOZ_ASSERT(!isJs());
|
||||
return lineOrPc;
|
||||
}
|
||||
|
||||
// We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp.
|
||||
JS_FRIEND_API(jsbytecode *) pc() const volatile;
|
||||
JS_FRIEND_API(void) setPC(jsbytecode *pc) volatile;
|
||||
|
||||
static size_t offsetOfString() { return offsetof(ProfileEntry, string); }
|
||||
static size_t offsetOfStackAddress() { return offsetof(ProfileEntry, sp); }
|
||||
static size_t offsetOfPCIdx() { return offsetof(ProfileEntry, idx); }
|
||||
static size_t offsetOfScript() { return offsetof(ProfileEntry, script_); }
|
||||
// The offset of a pc into a script's code can actually be 0, so to
|
||||
// signify a nullptr pc, use a -1 index. This is checked against in
|
||||
// pc() and setPC() to set/get the right pc.
|
||||
static const int32_t NullPCOffset = -1;
|
||||
|
||||
// The index used in the entry can either be a line number or the offset of
|
||||
// a pc into a script's code. To signify a nullptr pc, use a -1 index. This
|
||||
// is checked against in pc() and setPC() to set/get the right pc.
|
||||
static const int32_t NullPCIndex = -1;
|
||||
|
||||
// This bit is added to the stack address to indicate that copying the
|
||||
// frame label is not necessary when taking a sample of the pseudostack.
|
||||
static const uintptr_t NoCopyBit = 1;
|
||||
static size_t offsetOfLabel() { return offsetof(ProfileEntry, string); }
|
||||
static size_t offsetOfSpOrScript() { return offsetof(ProfileEntry, spOrScript); }
|
||||
static size_t offsetOfLineOrPc() { return offsetof(ProfileEntry, lineOrPc); }
|
||||
static size_t offsetOfFlags() { return offsetof(ProfileEntry, flags); }
|
||||
};
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
|
|
|
@ -1942,10 +1942,10 @@ MacroAssembler::spsMarkJit(SPSProfiler *p, Register framePtr, Register temp)
|
|||
// and won't be regenerated when SPS state changes.
|
||||
spsProfileEntryAddressSafe(p, 0, temp, &stackFull);
|
||||
|
||||
storePtr(ImmPtr(enterJitLabel), Address(temp, ProfileEntry::offsetOfString()));
|
||||
storePtr(framePtr, Address(temp, ProfileEntry::offsetOfStackAddress()));
|
||||
storePtr(ImmWord(uintptr_t(0)), Address(temp, ProfileEntry::offsetOfScript()));
|
||||
store32(Imm32(ProfileEntry::NullPCIndex), Address(temp, ProfileEntry::offsetOfPCIdx()));
|
||||
storePtr(ImmPtr(enterJitLabel), Address(temp, ProfileEntry::offsetOfLabel()));
|
||||
storePtr(framePtr, Address(temp, ProfileEntry::offsetOfSpOrScript()));
|
||||
store32(Imm32(ProfileEntry::NullPCOffset), Address(temp, ProfileEntry::offsetOfLineOrPc()));
|
||||
store32(Imm32(ProfileEntry::IS_CPP_ENTRY), Address(temp, ProfileEntry::offsetOfFlags()));
|
||||
|
||||
/* Always increment the stack size, whether or not we actually pushed. */
|
||||
bind(&stackFull);
|
||||
|
|
|
@ -1016,9 +1016,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
add32(Imm32(offset), temp);
|
||||
branch32(Assembler::GreaterThanOrEqual, temp, Imm32(p->maxSize()), full);
|
||||
|
||||
// 4 * sizeof(void*) * idx = idx << (2 + log(sizeof(void*)))
|
||||
JS_STATIC_ASSERT(sizeof(ProfileEntry) == 4 * sizeof(void*));
|
||||
lshiftPtr(Imm32(2 + (sizeof(void*) == 4 ? 2 : 3)), temp);
|
||||
JS_STATIC_ASSERT(sizeof(ProfileEntry) == (2 * sizeof(void *)) + 8);
|
||||
if (sizeof(void *) == 4) {
|
||||
lshiftPtr(Imm32(4), temp);
|
||||
} else {
|
||||
lshiftPtr(Imm32(3), temp);
|
||||
mulBy3(temp, temp);
|
||||
}
|
||||
|
||||
addPtr(ImmPtr(p->stack()), temp);
|
||||
}
|
||||
|
||||
|
@ -1042,9 +1047,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
// Test against max size.
|
||||
branch32(Assembler::LessThanOrEqual, AbsoluteAddress(p->addressOfMaxSize()), temp, full);
|
||||
|
||||
// 4 * sizeof(void*) * idx = idx << (2 + log(sizeof(void*)))
|
||||
JS_STATIC_ASSERT(sizeof(ProfileEntry) == 4 * sizeof(void*));
|
||||
lshiftPtr(Imm32(2 + (sizeof(void*) == 4 ? 2 : 3)), temp);
|
||||
JS_STATIC_ASSERT(sizeof(ProfileEntry) == (2 * sizeof(void *)) + 8);
|
||||
if (sizeof(void *) == 4) {
|
||||
lshiftPtr(Imm32(4), temp);
|
||||
} else {
|
||||
lshiftPtr(Imm32(3), temp);
|
||||
mulBy3(temp, temp);
|
||||
}
|
||||
|
||||
push(temp);
|
||||
loadPtr(AbsoluteAddress(p->addressOfStack()), temp);
|
||||
addPtr(Address(StackPointer, 0), temp);
|
||||
|
@ -1059,14 +1069,14 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
void spsUpdatePCIdx(SPSProfiler *p, int32_t idx, Register temp) {
|
||||
Label stackFull;
|
||||
spsProfileEntryAddress(p, -1, temp, &stackFull);
|
||||
store32(Imm32(idx), Address(temp, ProfileEntry::offsetOfPCIdx()));
|
||||
store32(Imm32(idx), Address(temp, ProfileEntry::offsetOfLineOrPc()));
|
||||
bind(&stackFull);
|
||||
}
|
||||
|
||||
void spsUpdatePCIdx(SPSProfiler *p, Register idx, Register temp) {
|
||||
Label stackFull;
|
||||
spsProfileEntryAddressSafe(p, -1, temp, &stackFull);
|
||||
store32(idx, Address(temp, ProfileEntry::offsetOfPCIdx()));
|
||||
store32(idx, Address(temp, ProfileEntry::offsetOfLineOrPc()));
|
||||
bind(&stackFull);
|
||||
}
|
||||
|
||||
|
@ -1075,11 +1085,10 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
Label stackFull;
|
||||
spsProfileEntryAddress(p, 0, temp, &stackFull);
|
||||
|
||||
storePtr(ImmPtr(str), Address(temp, ProfileEntry::offsetOfString()));
|
||||
storePtr(ImmGCPtr(s), Address(temp, ProfileEntry::offsetOfScript()));
|
||||
storePtr(ImmPtr((void*) ProfileEntry::SCRIPT_OPT_STACKPOINTER),
|
||||
Address(temp, ProfileEntry::offsetOfStackAddress()));
|
||||
store32(Imm32(ProfileEntry::NullPCIndex), Address(temp, ProfileEntry::offsetOfPCIdx()));
|
||||
storePtr(ImmPtr(str), Address(temp, ProfileEntry::offsetOfLabel()));
|
||||
storePtr(ImmGCPtr(s), Address(temp, ProfileEntry::offsetOfSpOrScript()));
|
||||
store32(Imm32(ProfileEntry::NullPCOffset), Address(temp, ProfileEntry::offsetOfLineOrPc()));
|
||||
store32(Imm32(0), Address(temp, ProfileEntry::offsetOfFlags()));
|
||||
|
||||
/* Always increment the stack size, whether or not we actually pushed. */
|
||||
bind(&stackFull);
|
||||
|
@ -1095,17 +1104,16 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
spsProfileEntryAddressSafe(p, 0, temp, &stackFull);
|
||||
|
||||
loadPtr(str, temp2);
|
||||
storePtr(temp2, Address(temp, ProfileEntry::offsetOfString()));
|
||||
storePtr(temp2, Address(temp, ProfileEntry::offsetOfLabel()));
|
||||
|
||||
loadPtr(script, temp2);
|
||||
storePtr(temp2, Address(temp, ProfileEntry::offsetOfScript()));
|
||||
|
||||
storePtr(ImmPtr(nullptr), Address(temp, ProfileEntry::offsetOfStackAddress()));
|
||||
storePtr(temp2, Address(temp, ProfileEntry::offsetOfSpOrScript()));
|
||||
|
||||
// Store 0 for PCIdx because that's what interpreter does.
|
||||
// (See probes::EnterScript, which calls spsProfiler.enter, which pushes an entry
|
||||
// with 0 pcIdx).
|
||||
store32(Imm32(0), Address(temp, ProfileEntry::offsetOfPCIdx()));
|
||||
store32(Imm32(0), Address(temp, ProfileEntry::offsetOfLineOrPc()));
|
||||
store32(Imm32(0), Address(temp, ProfileEntry::offsetOfFlags()));
|
||||
|
||||
/* Always increment the stack size, whether or not we actually pushed. */
|
||||
bind(&stackFull);
|
||||
|
|
|
@ -1427,6 +1427,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
void addPtr(ImmPtr imm, const Register dest) {
|
||||
addPtr(ImmWord(uintptr_t(imm.value)), dest);
|
||||
}
|
||||
void mulBy3(const Register &src, const Register &dest) {
|
||||
as_add(dest, src, lsl(src, 1));
|
||||
}
|
||||
|
||||
void setStackArg(Register reg, uint32_t arg);
|
||||
|
||||
|
|
|
@ -572,6 +572,9 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||
void subPtr(Register src, const Address &dest) {
|
||||
subq(src, Operand(dest));
|
||||
}
|
||||
void mulBy3(const Register &src, const Register &dest) {
|
||||
lea(Operand(src, src, TimesTwo), dest);
|
||||
}
|
||||
|
||||
void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label *label) {
|
||||
if (JSC::X86Assembler::isAddressImmediate(lhs.addr)) {
|
||||
|
|
|
@ -581,6 +581,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
|||
void subPtr(Register src, const Address &dest) {
|
||||
subl(src, Operand(dest));
|
||||
}
|
||||
void mulBy3(const Register &src, const Register &dest) {
|
||||
lea(Operand(src, src, TimesTwo), dest);
|
||||
}
|
||||
|
||||
void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label *label) {
|
||||
cmpl(Operand(lhs), rhs);
|
||||
|
|
|
@ -162,11 +162,11 @@ SPSProfiler::enter(JSScript *script, JSFunction *maybeFun)
|
|||
if (*size_ > 0 && *size_ - 1 < max_) {
|
||||
size_t start = (*size_ > 4) ? *size_ - 4 : 0;
|
||||
for (size_t i = start; i < *size_ - 1; i++)
|
||||
MOZ_ASSERT_IF(stack_[i].js(), stack_[i].pc() != nullptr);
|
||||
MOZ_ASSERT_IF(stack_[i].isJs(), stack_[i].pc() != nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
push(str, nullptr, script, script->code());
|
||||
push(str, nullptr, script, script->code(), /* copy = */ true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -183,18 +183,18 @@ SPSProfiler::exit(JSScript *script, JSFunction *maybeFun)
|
|||
JS_ASSERT(str != nullptr);
|
||||
|
||||
// Bug 822041
|
||||
if (!stack_[*size_].js()) {
|
||||
if (!stack_[*size_].isJs()) {
|
||||
fprintf(stderr, "--- ABOUT TO FAIL ASSERTION ---\n");
|
||||
fprintf(stderr, " stack=%p size=%d/%d\n", (void*) stack_, *size_, max_);
|
||||
for (int32_t i = *size_; i >= 0; i--) {
|
||||
if (stack_[i].js())
|
||||
if (stack_[i].isJs())
|
||||
fprintf(stderr, " [%d] JS %s\n", i, stack_[i].label());
|
||||
else
|
||||
fprintf(stderr, " [%d] C line %d %s\n", i, stack_[i].line(), stack_[i].label());
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(stack_[*size_].js());
|
||||
JS_ASSERT(stack_[*size_].isJs());
|
||||
JS_ASSERT(stack_[*size_].script() == script);
|
||||
JS_ASSERT(strcmp((const char*) stack_[*size_].label(), str) == 0);
|
||||
stack_[*size_].setLabel(nullptr);
|
||||
|
@ -214,16 +214,17 @@ SPSProfiler::enterNative(const char *string, void *sp)
|
|||
JS_ASSERT(enabled());
|
||||
if (current < max_) {
|
||||
stack[current].setLabel(string);
|
||||
stack[current].setStackAddress(sp);
|
||||
stack[current].setScript(nullptr);
|
||||
stack[current].setLine(0);
|
||||
stack[current].setCppFrame(sp, 0);
|
||||
}
|
||||
*size = current + 1;
|
||||
}
|
||||
|
||||
void
|
||||
SPSProfiler::push(const char *string, void *sp, JSScript *script, jsbytecode *pc)
|
||||
SPSProfiler::push(const char *string, void *sp, JSScript *script, jsbytecode *pc, bool copy)
|
||||
{
|
||||
JS_ASSERT_IF(sp != nullptr, script == nullptr && pc == nullptr);
|
||||
JS_ASSERT_IF(sp == nullptr, script != nullptr && pc != nullptr);
|
||||
|
||||
/* these operations cannot be re-ordered, so volatile-ize operations */
|
||||
volatile ProfileEntry *stack = stack_;
|
||||
volatile uint32_t *size = size_;
|
||||
|
@ -231,10 +232,19 @@ SPSProfiler::push(const char *string, void *sp, JSScript *script, jsbytecode *pc
|
|||
|
||||
JS_ASSERT(installed());
|
||||
if (current < max_) {
|
||||
stack[current].setLabel(string);
|
||||
stack[current].setStackAddress(sp);
|
||||
stack[current].setScript(script);
|
||||
stack[current].setPC(pc);
|
||||
volatile ProfileEntry &entry = stack[current];
|
||||
entry.setLabel(string);
|
||||
|
||||
if (sp != nullptr)
|
||||
entry.setCppFrame(sp, 0);
|
||||
else
|
||||
entry.setJsFrame(script, pc);
|
||||
|
||||
// Track if mLabel needs a copy.
|
||||
if (copy)
|
||||
entry.setFlag(js::ProfileEntry::FRAME_LABEL_COPY);
|
||||
else
|
||||
entry.unsetFlag(js::ProfileEntry::FRAME_LABEL_COPY);
|
||||
}
|
||||
*size = current + 1;
|
||||
}
|
||||
|
@ -313,9 +323,8 @@ SPSEntryMarker::SPSEntryMarker(JSRuntime *rt
|
|||
return;
|
||||
}
|
||||
size_before = *profiler->size_;
|
||||
profiler->pushNoCopy("js::RunScript", this, nullptr, nullptr);
|
||||
profiler->push("js::RunScript", this, nullptr, nullptr, /* copy = */ false);
|
||||
}
|
||||
|
||||
SPSEntryMarker::~SPSEntryMarker()
|
||||
{
|
||||
if (profiler != nullptr) {
|
||||
|
@ -327,13 +336,15 @@ SPSEntryMarker::~SPSEntryMarker()
|
|||
JS_FRIEND_API(jsbytecode*)
|
||||
ProfileEntry::pc() const volatile
|
||||
{
|
||||
return idx == NullPCIndex ? nullptr : script()->offsetToPC(idx);
|
||||
MOZ_ASSERT(isJs());
|
||||
return lineOrPc == NullPCOffset ? nullptr : script()->offsetToPC(lineOrPc);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
ProfileEntry::setPC(jsbytecode *pc) volatile
|
||||
{
|
||||
idx = pc == nullptr ? NullPCIndex : script()->pcToOffset(pc);
|
||||
MOZ_ASSERT(isJs());
|
||||
lineOrPc = pc == nullptr ? NullPCOffset : script()->pcToOffset(pc);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
|
|
|
@ -128,13 +128,7 @@ class SPSProfiler
|
|||
void (*eventMarker_)(const char *);
|
||||
|
||||
const char *allocProfileString(JSScript *script, JSFunction *function);
|
||||
void push(const char *string, void *sp, JSScript *script, jsbytecode *pc);
|
||||
void pushNoCopy(const char *string, void *sp,
|
||||
JSScript *script, jsbytecode *pc) {
|
||||
push(string, reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(sp) | ProfileEntry::NoCopyBit),
|
||||
script, pc);
|
||||
}
|
||||
void push(const char *string, void *sp, JSScript *script, jsbytecode *pc, bool copy);
|
||||
void pop();
|
||||
|
||||
public:
|
||||
|
@ -437,7 +431,7 @@ class SPSInstrumentation
|
|||
return;
|
||||
|
||||
if (!inlinedFunction)
|
||||
masm.spsUpdatePCIdx(profiler_, ProfileEntry::NullPCIndex, scratch);
|
||||
masm.spsUpdatePCIdx(profiler_, ProfileEntry::NullPCOffset, scratch);
|
||||
|
||||
setPushed(script);
|
||||
}
|
||||
|
@ -478,8 +472,8 @@ class SPSInstrumentation
|
|||
if (frame->skipNext) {
|
||||
frame->skipNext = false;
|
||||
} else {
|
||||
if (!inlinedFunction)
|
||||
masm.spsUpdatePCIdx(profiler_, ProfileEntry::NullPCIndex, scratch);
|
||||
if (!inlinedFunction)
|
||||
masm.spsUpdatePCIdx(profiler_, ProfileEntry::NullPCOffset, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ void genProfileEntry(/*MODIFIED*/UnwinderThreadBuffer* utb,
|
|||
// Cast to *((void**) to pass the text data to a void*
|
||||
utb__addEntry( utb, ProfileEntry('d', *((void**)(&text[0]))) );
|
||||
}
|
||||
if (entry.js()) {
|
||||
if (entry.isJs()) {
|
||||
if (!entry.pc()) {
|
||||
// The JIT only allows the top-most entry to have a nullptr pc
|
||||
MOZ_ASSERT(&entry == &stack->mStack[stack->stackSize() - 1]);
|
||||
|
@ -227,7 +227,7 @@ void populateBuffer(UnwinderThreadBuffer* utb, TickSample* sample,
|
|||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
if (recordSample) {
|
||||
if (recordSample) {
|
||||
// add a "flush now" hint
|
||||
utb__addEntry( utb, ProfileEntry('h'/*hint*/, 'F'/*flush*/) );
|
||||
}
|
||||
|
|
|
@ -85,26 +85,6 @@ static inline uint32_t sMin(uint32_t l, uint32_t r) {
|
|||
// of the two representations are consistent.
|
||||
class StackEntry : public js::ProfileEntry
|
||||
{
|
||||
public:
|
||||
|
||||
bool isCopyLabel() const volatile {
|
||||
return !((uintptr_t)stackAddress() & 0x1);
|
||||
}
|
||||
|
||||
void setStackAddressCopy(void *sparg, bool copy) volatile {
|
||||
// Tagged pointer. Less significant bit used to track if mLabel needs a
|
||||
// copy. Note that we don't need the last bit of the stack address for
|
||||
// proper ordering. This is optimized for encoding within the JS engine's
|
||||
// instrumentation, so we do the extra work here of encoding a bit.
|
||||
// Last bit 1 = Don't copy, Last bit 0 = Copy.
|
||||
if (copy) {
|
||||
setStackAddress(reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(sparg) & ~NoCopyBit));
|
||||
} else {
|
||||
setStackAddress(reinterpret_cast<void*>(
|
||||
reinterpret_cast<uintptr_t>(sparg) | NoCopyBit));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ProfilerMarkerPayload;
|
||||
|
@ -375,11 +355,18 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
volatile StackEntry &entry = mStack[mStackPointer];
|
||||
|
||||
// Make sure we increment the pointer after the name has
|
||||
// been written such that mStack is always consistent.
|
||||
mStack[mStackPointer].setLabel(aName);
|
||||
mStack[mStackPointer].setStackAddressCopy(aStackAddress, aCopy);
|
||||
mStack[mStackPointer].setLine(line);
|
||||
entry.setLabel(aName);
|
||||
entry.setCppFrame(aStackAddress, line);
|
||||
|
||||
// Track if mLabel needs a copy.
|
||||
if (aCopy)
|
||||
entry.setFlag(js::ProfileEntry::FRAME_LABEL_COPY);
|
||||
else
|
||||
entry.unsetFlag(js::ProfileEntry::FRAME_LABEL_COPY);
|
||||
|
||||
// Prevent the optimizer from re-ordering these instructions
|
||||
STORE_SEQUENCER();
|
||||
|
|
|
@ -347,7 +347,7 @@ void addProfileEntry(volatile StackEntry &entry, ThreadProfile &aProfile,
|
|||
// that will happen to the preceding tag
|
||||
|
||||
addDynamicTag(aProfile, 'c', sampleLabel);
|
||||
if (entry.js()) {
|
||||
if (entry.isJs()) {
|
||||
if (!entry.pc()) {
|
||||
// The JIT only allows the top-most entry to have a nullptr pc
|
||||
MOZ_ASSERT(&entry == &stack->mStack[stack->stackSize() - 1]);
|
||||
|
@ -367,7 +367,12 @@ void addProfileEntry(volatile StackEntry &entry, ThreadProfile &aProfile,
|
|||
}
|
||||
} else {
|
||||
aProfile.addTag(ProfileEntry('c', sampleLabel));
|
||||
lineno = entry.line();
|
||||
|
||||
// XXX: Bug 1010578. Don't assume a CPP entry and try to get the
|
||||
// line for js entries as well.
|
||||
if (entry.isCpp()) {
|
||||
lineno = entry.line();
|
||||
}
|
||||
}
|
||||
if (lineno != -1) {
|
||||
aProfile.addTag(ProfileEntry('n', lineno));
|
||||
|
@ -507,7 +512,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample
|
|||
// The pseudostack grows towards higher indices, so we iterate
|
||||
// backwards (from callee to caller).
|
||||
volatile StackEntry &entry = pseudoStack->mStack[i - 1];
|
||||
if (!entry.js() && strcmp(entry.label(), "EnterJIT") == 0) {
|
||||
if (!entry.isJs() && strcmp(entry.label(), "EnterJIT") == 0) {
|
||||
// Found JIT entry frame. Unwind up to that point (i.e., force
|
||||
// the stack walk to stop before the block of saved registers;
|
||||
// note that it yields nondecreasing stack pointers), then restore
|
||||
|
|
Загрузка…
Ссылка в новой задаче