Bug 1047010 - OdinMonkey: provide better profiling info for FFI calls (r=dougc)

--HG--
extra : rebase_source : 9ab49294fc688bec90a9d211ad0ad03ab4c6a2e0
This commit is contained in:
Luke Wagner 2014-08-04 12:59:08 -05:00
parent f605107f86
commit 103cade597
6 changed files with 52 additions and 44 deletions

View File

@ -79,7 +79,8 @@ AsmJSFrameIterator::settle()
fp_ = nullptr;
JS_ASSERT(done());
break;
case AsmJSModule::CodeRange::FFI:
case AsmJSModule::CodeRange::IonFFI:
case AsmJSModule::CodeRange::SlowFFI:
case AsmJSModule::CodeRange::Interrupt:
case AsmJSModule::CodeRange::Inline:
case AsmJSModule::CodeRange::Thunk:
@ -462,7 +463,8 @@ AsmJSProfilingFrameIterator::initFromFP(const AsmJSActivation &activation)
callerFP_ = CallerFPFromFP(fp);
AssertMatchesCallSite(*module_, codeRange, callerPC_, callerFP_, fp);
break;
case AsmJSModule::CodeRange::FFI:
case AsmJSModule::CodeRange::IonFFI:
case AsmJSModule::CodeRange::SlowFFI:
case AsmJSModule::CodeRange::Interrupt:
case AsmJSModule::CodeRange::Inline:
case AsmJSModule::CodeRange::Thunk:
@ -505,7 +507,8 @@ AsmJSProfilingFrameIterator::AsmJSProfilingFrameIterator(const AsmJSActivation &
const AsmJSModule::CodeRange *codeRange = module_->lookupCodeRange(state.pc);
switch (codeRange->kind()) {
case AsmJSModule::CodeRange::Function:
case AsmJSModule::CodeRange::FFI:
case AsmJSModule::CodeRange::IonFFI:
case AsmJSModule::CodeRange::SlowFFI:
case AsmJSModule::CodeRange::Interrupt:
case AsmJSModule::CodeRange::Thunk: {
// While codeRange describes the *current* frame, the fp/pc state stored in
@ -606,7 +609,8 @@ AsmJSProfilingFrameIterator::operator++()
callerPC_ = nullptr;
break;
case AsmJSModule::CodeRange::Function:
case AsmJSModule::CodeRange::FFI:
case AsmJSModule::CodeRange::IonFFI:
case AsmJSModule::CodeRange::SlowFFI:
case AsmJSModule::CodeRange::Interrupt:
case AsmJSModule::CodeRange::Inline:
case AsmJSModule::CodeRange::Thunk:
@ -657,19 +661,22 @@ AsmJSProfilingFrameIterator::label() const
{
JS_ASSERT(!done());
// Note: this label is regexp-matched by
// browser/devtools/profiler/cleopatra/js/parserWorker.js.
// Use the same string for both time inside and under so that the two
// entries will be coalesced by the profiler.
const char *ffiDescription = "FFI trampoline (in asm.js)";
//
// NB: these labels are regexp-matched by
// browser/devtools/profiler/cleopatra/js/parserWorker.js.
const char *ionFFIDescription = "fast FFI trampoline (in asm.js)";
const char *slowFFIDescription = "slow FFI trampoline (in asm.js)";
const char *interruptDescription = "slow script interrupt trampoline (in asm.js)";
switch (AsmJSExit::ExtractReasonKind(exitReason_)) {
case AsmJSExit::Reason_None:
break;
case AsmJSExit::Reason_FFI:
return ffiDescription;
case AsmJSExit::Reason_IonFFI:
return ionFFIDescription;
case AsmJSExit::Reason_SlowFFI:
return slowFFIDescription;
case AsmJSExit::Reason_Interrupt:
return interruptDescription;
case AsmJSExit::Reason_Builtin:
@ -680,7 +687,8 @@ AsmJSProfilingFrameIterator::label() const
switch (codeRange->kind()) {
case AsmJSModule::CodeRange::Function: return codeRange->functionProfilingLabel(*module_);
case AsmJSModule::CodeRange::Entry: return "entry trampoline (in asm.js)";
case AsmJSModule::CodeRange::FFI: return ffiDescription;
case AsmJSModule::CodeRange::IonFFI: return ionFFIDescription;
case AsmJSModule::CodeRange::SlowFFI: return slowFFIDescription;
case AsmJSModule::CodeRange::Interrupt: return interruptDescription;
case AsmJSModule::CodeRange::Inline: return "inline stub (in asm.js)";
case AsmJSModule::CodeRange::Thunk: return BuiltinToName(codeRange->thunkTarget());

View File

@ -69,7 +69,8 @@ namespace AsmJSExit
// handler).
enum ReasonKind {
Reason_None,
Reason_FFI,
Reason_IonFFI,
Reason_SlowFFI,
Reason_Interrupt,
Reason_Builtin
};
@ -105,7 +106,8 @@ namespace AsmJSExit
typedef uint32_t Reason;
static const uint32_t None = Reason_None;
static const uint32_t FFI = Reason_FFI;
static const uint32_t IonFFI = Reason_IonFFI;
static const uint32_t SlowFFI = Reason_SlowFFI;
static const uint32_t Interrupt = Reason_Interrupt;
static inline Reason Builtin(BuiltinKind builtin) {
return uint16_t(Reason_Builtin) | (uint16_t(builtin) << 16);

View File

@ -1235,6 +1235,7 @@ AsmJSModule::CodeRange::CodeRange(Kind kind, uint32_t begin, uint32_t profilingR
JS_ASSERT(begin_ < profilingReturn_);
JS_ASSERT(profilingReturn_ < end_);
JS_ASSERT(u.kind_ == IonFFI || u.kind_ == SlowFFI || u.kind_ == Interrupt);
}
AsmJSModule::CodeRange::CodeRange(AsmJSExit::BuiltinKind builtin, uint32_t begin,

View File

@ -366,7 +366,7 @@ class AsmJSModule
void setDeltas(uint32_t entry, uint32_t profilingJump, uint32_t profilingEpilogue);
public:
enum Kind { Function, Entry, FFI, Interrupt, Thunk, Inline };
enum Kind { Function, Entry, IonFFI, SlowFFI, Interrupt, Thunk, Inline };
CodeRange() {}
CodeRange(uint32_t nameIndex, uint32_t lineNumber, const AsmJSFunctionLabels &l);
@ -378,7 +378,7 @@ class AsmJSModule
Kind kind() const { return Kind(u.kind_); }
bool isFunction() const { return kind() == Function; }
bool isEntry() const { return kind() == Entry; }
bool isFFI() const { return kind() == FFI; }
bool isFFI() const { return kind() == IonFFI || kind() == SlowFFI; }
bool isInterrupt() const { return kind() == Interrupt; }
bool isThunk() const { return kind() == Thunk; }
@ -827,6 +827,12 @@ class AsmJSModule
if (len > pod.minHeapLength_)
pod.minHeapLength_ = len;
}
bool addCodeRange(CodeRange::Kind kind, uint32_t begin, uint32_t end) {
return codeRanges_.append(CodeRange(kind, begin, end));
}
bool addCodeRange(CodeRange::Kind kind, uint32_t begin, uint32_t pret, uint32_t end) {
return codeRanges_.append(CodeRange(kind, begin, pret, end));
}
bool addFunctionCodeRange(PropertyName *name, uint32_t lineNumber,
const AsmJSFunctionLabels &labels)
{
@ -837,24 +843,12 @@ class AsmJSModule
uint32_t nameIndex = names_.length();
return names_.append(name) && codeRanges_.append(CodeRange(nameIndex, lineNumber, labels));
}
bool addEntryCodeRange(uint32_t begin, uint32_t end) {
return codeRanges_.append(CodeRange(CodeRange::Entry, begin, end));
}
bool addFFICodeRange(uint32_t begin, uint32_t pret, uint32_t end) {
return codeRanges_.append(CodeRange(CodeRange::FFI, begin, pret, end));
}
bool addInterruptCodeRange(uint32_t begin, uint32_t pret, uint32_t end) {
return codeRanges_.append(CodeRange(CodeRange::Interrupt, begin, pret, end));
}
bool addBuiltinThunkCodeRange(AsmJSExit::BuiltinKind builtin, uint32_t begin,
uint32_t profilingReturn, uint32_t end)
{
return builtinThunkOffsets_.append(begin) &&
codeRanges_.append(CodeRange(builtin, begin, profilingReturn, end));
}
bool addInlineCodeRange(uint32_t begin, uint32_t end) {
return codeRanges_.append(CodeRange(CodeRange::Inline, begin, end));
}
bool addExit(unsigned ffiIndex, unsigned *exitIndex) {
JS_ASSERT(isFinishedWithModulePrologue() && !isFinishedWithFunctionBodies());
if (SIZE_MAX - pod.funcPtrTableAndExitBytes_ < sizeof(ExitDatum))

View File

@ -1491,32 +1491,35 @@ class MOZ_STACK_CLASS ModuleCompiler
JS_ASSERT(finishedFunctionBodies_);
module_->exportedFunction(exportIndex).initCodeOffset(begin->offset());
uint32_t end = masm_.currentOffset();
return module_->addEntryCodeRange(begin->offset(), end);
}
bool finishGeneratingFFI(Label *begin, Label *profilingReturn) {
JS_ASSERT(finishedFunctionBodies_);
uint32_t end = masm_.currentOffset();
return module_->addFFICodeRange(begin->offset(), profilingReturn->offset(), end);
return module_->addCodeRange(AsmJSModule::CodeRange::Entry, begin->offset(), end);
}
bool finishGeneratingInterpExit(unsigned exitIndex, Label *begin, Label *profilingReturn) {
JS_ASSERT(finishedFunctionBodies_);
module_->exit(exitIndex).initInterpOffset(begin->offset());
return finishGeneratingFFI(begin, profilingReturn);
uint32_t beg = begin->offset();
module_->exit(exitIndex).initInterpOffset(beg);
uint32_t pret = profilingReturn->offset();
uint32_t end = masm_.currentOffset();
return module_->addCodeRange(AsmJSModule::CodeRange::SlowFFI, beg, pret, end);
}
bool finishGeneratingIonExit(unsigned exitIndex, Label *begin, Label *profilingReturn) {
JS_ASSERT(finishedFunctionBodies_);
module_->exit(exitIndex).initIonOffset(begin->offset());
return finishGeneratingFFI(begin, profilingReturn);
uint32_t beg = begin->offset();
module_->exit(exitIndex).initIonOffset(beg);
uint32_t pret = profilingReturn->offset();
uint32_t end = masm_.currentOffset();
return module_->addCodeRange(AsmJSModule::CodeRange::IonFFI, beg, pret, end);
}
bool finishGeneratingInterrupt(Label *begin, Label *profilingReturn) {
JS_ASSERT(finishedFunctionBodies_);
uint32_t beg = begin->offset();
uint32_t pret = profilingReturn->offset();
uint32_t end = masm_.currentOffset();
return module_->addInterruptCodeRange(begin->offset(), profilingReturn->offset(), end);
return module_->addCodeRange(AsmJSModule::CodeRange::Interrupt, beg, pret, end);
}
bool finishGeneratingInlineStub(Label *begin) {
JS_ASSERT(finishedFunctionBodies_);
uint32_t end = masm_.currentOffset();
return module_->addInlineCodeRange(begin->offset(), end);
return module_->addCodeRange(AsmJSModule::CodeRange::Inline, begin->offset(), end);
}
bool finishGeneratingBuiltinThunk(AsmJSExit::BuiltinKind builtin, Label *begin, Label *pret) {
JS_ASSERT(finishedFunctionBodies_);
@ -6141,7 +6144,7 @@ GenerateFFIInterpExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &e
unsigned framePushed = StackDecrementForCall(masm, offsetToArgv + argvBytes);
Label begin;
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::FFI, &begin);
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::SlowFFI, &begin);
// Fill the argument array.
unsigned offsetToCallerStackArgs = sizeof(AsmJSFrame) + masm.framePushed();
@ -6200,7 +6203,7 @@ GenerateFFIInterpExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &e
}
Label profilingReturn;
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::FFI, &profilingReturn);
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::SlowFFI, &profilingReturn);
return m.finishGeneratingInterpExit(exitIndex, &begin, &profilingReturn) && !masm.oom();
}
@ -6255,7 +6258,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
unsigned framePushed = Max(ionFrameSize, coerceFrameSize);
Label begin;
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::FFI, &begin);
GenerateAsmJSExitPrologue(masm, framePushed, AsmJSExit::IonFFI, &begin);
// 1. Descriptor
size_t argOffset = offsetToIonArgs;
@ -6415,7 +6418,7 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
masm.bind(&done);
Label profilingReturn;
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::FFI, &profilingReturn);
GenerateAsmJSExitEpilogue(masm, framePushed, AsmJSExit::IonFFI, &profilingReturn);
if (oolConvert.used()) {
masm.bind(&oolConvert);

View File

@ -10,7 +10,7 @@ function assertEqualStacks(got, expect)
got = String(got).replace(/ \([^\)]*\)/g, "");
// Shorten FFI/entry trampolines
got = got.replace(/FFI trampoline/g, "<").replace(/entry trampoline/g, ">");
got = got.replace(/(fast|slow) FFI trampoline/g, "<").replace(/entry trampoline/g, ">");
assertEq(got, expect);
}