mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1040390 - Replace ad hoc methods with JS::ProfilingFrameIterator::label() (r=dougc)
--HG-- extra : rebase_source : 396c7925edac39e39d16dea7a53da3ba34f68ddf
This commit is contained in:
parent
2875ab4eb5
commit
d082a048a2
@ -43,11 +43,10 @@ class JS_PUBLIC_API(ProfilingFrameIterator)
|
||||
public:
|
||||
struct RegisterState
|
||||
{
|
||||
RegisterState() : pc(nullptr), sp(nullptr), lr(nullptr) {}
|
||||
void *pc;
|
||||
void *sp;
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
void *lr;
|
||||
#endif
|
||||
};
|
||||
|
||||
ProfilingFrameIterator(JSRuntime *rt, const RegisterState &state);
|
||||
@ -62,19 +61,9 @@ class JS_PUBLIC_API(ProfilingFrameIterator)
|
||||
// and less than older native and psuedo-stack frame addresses
|
||||
void *stackAddress() const;
|
||||
|
||||
enum Kind {
|
||||
Function,
|
||||
AsmJSTrampoline,
|
||||
CppFunction
|
||||
};
|
||||
Kind kind() const;
|
||||
|
||||
// Methods available if kind() == Function:
|
||||
JSAtom *functionDisplayAtom() const;
|
||||
const char *functionFilename() const;
|
||||
|
||||
// Methods available if kind() != Function
|
||||
const char *nonFunctionDescription() const;
|
||||
// Return a label suitable for regexp-matching as performed by
|
||||
// browser/devtools/profiler/cleopatra/js/parserWorker.js
|
||||
const char *label() const;
|
||||
};
|
||||
|
||||
} // namespace JS
|
||||
|
@ -4,6 +4,17 @@ load(libdir + "asm.js");
|
||||
if (!getBuildConfiguration()["arm-simulator"])
|
||||
quit();
|
||||
|
||||
function assertEqualStacks(got, expect)
|
||||
{
|
||||
// Strip off the " (script/library info)"
|
||||
got = String(got).replace(/ \([^\)]*\)/g, "");
|
||||
|
||||
// Shorten FFI/entry trampolines
|
||||
got = got.replace(/FFI trampoline/g, "<").replace(/entry trampoline/g, ">");
|
||||
|
||||
assertEq(got, expect);
|
||||
}
|
||||
|
||||
// Test profiling enablement while asm.js is running.
|
||||
var stacks;
|
||||
var ffi = function(enable) {
|
||||
@ -16,15 +27,15 @@ var ffi = function(enable) {
|
||||
}
|
||||
var f = asmLink(asmCompile('global','ffis',USE_ASM + "var ffi=ffis.ffi; function g(i) { i=i|0; ffi(i|0) } function f(i) { i=i|0; g(i|0) } return f"), null, {ffi});
|
||||
f(0);
|
||||
assertEq(String(stacks), "");
|
||||
assertEqualStacks(stacks, "");
|
||||
f(+1);
|
||||
assertEq(String(stacks), "");
|
||||
assertEqualStacks(stacks, "");
|
||||
f(0);
|
||||
assertEq(String(stacks), "*gf*");
|
||||
assertEqualStacks(stacks, "<gf>");
|
||||
f(-1);
|
||||
assertEq(String(stacks), "*gf*");
|
||||
assertEqualStacks(stacks, "<gf>");
|
||||
f(0);
|
||||
assertEq(String(stacks), "");
|
||||
assertEqualStacks(stacks, "");
|
||||
|
||||
// Enable profiling for the rest of the tests.
|
||||
enableSPSProfiling();
|
||||
@ -33,27 +44,27 @@ var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f"));
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(), 42);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,>,");
|
||||
|
||||
var f = asmLink(asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f"));
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(), 43);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,gf*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,gf>,f>,>,");
|
||||
|
||||
var f = asmLink(asmCompile(USE_ASM + "function g1() { return 1 } function g2() { return 2 } function f(i) { i=i|0; return TBL[i&1]()|0 } var TBL=[g1,g2]; return f"));
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(0), 1);
|
||||
assertEq(f(1), 2);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,g1f*,f*,*,,*,f*,g2f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,g1f>,f>,>,,>,f>,g2f>,f>,>,");
|
||||
|
||||
function testBuiltinD2D(name) {
|
||||
var f = asmLink(asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d) { d=+d; return +fun(d) } return f"), this);
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(.1), eval("Math." + name + "(.1)"));
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,Math." + name + "f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,Math." + name + "f>,f>,>,");
|
||||
}
|
||||
for (name of ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'ceil', 'floor', 'exp', 'log'])
|
||||
testBuiltinD2D(name);
|
||||
@ -62,7 +73,7 @@ function testBuiltinF2F(name) {
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(.1), eval("Math.fround(Math." + name + "(Math.fround(.1)))"));
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,Math." + name + "f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,Math." + name + "f>,f>,>,");
|
||||
}
|
||||
for (name of ['ceil', 'floor'])
|
||||
testBuiltinF2F(name);
|
||||
@ -71,7 +82,7 @@ function testBuiltinDD2D(name) {
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(.1, .2), eval("Math." + name + "(.1, .2)"));
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,Math." + name + "f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,Math." + name + "f>,f>,>,");
|
||||
}
|
||||
for (name of ['atan2', 'pow'])
|
||||
testBuiltinDD2D(name);
|
||||
@ -88,14 +99,14 @@ var f = asmLink(asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(), 83);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,*f*,f*,*f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,<f>,f>,<f>,f>,>,");
|
||||
// Ion FFI exit
|
||||
for (var i = 0; i < 20; i++)
|
||||
assertEq(f(), 83);
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f(), 83);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f*,*f*,f*,*f*,f*,*,");
|
||||
assertEqualStacks(stacks, ",>,f>,<f>,f>,<f>,f>,>,");
|
||||
|
||||
var ffi1 = function() { return 15 }
|
||||
var ffi2 = function() { return f2() + 17 }
|
||||
@ -104,14 +115,14 @@ var {f1,f2} = asmLink(asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f1(), 32);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f1*,*f1*,**f1*,f2**f1*,*f2**f1*,f2**f1*,**f1*,*f1*,f1*,*,");
|
||||
assertEqualStacks(stacks, ",>,f1>,<f1>,><f1>,f2><f1>,<f2><f1>,f2><f1>,><f1>,<f1>,f1>,>,");
|
||||
// Ion FFI exit
|
||||
for (var i = 0; i < 20; i++)
|
||||
assertEq(f1(), 32);
|
||||
enableSingleStepProfiling();
|
||||
assertEq(f1(), 32);
|
||||
var stacks = disableSingleStepProfiling();
|
||||
assertEq(String(stacks), ",*,f1*,*f1*,**f1*,f2**f1*,*f2**f1*,f2**f1*,**f1*,*f1*,f1*,*,");
|
||||
assertEqualStacks(stacks, ",>,f1>,<f1>,><f1>,f2><f1>,<f2><f1>,f2><f1>,><f1>,<f1>,f1>,>,");
|
||||
|
||||
// This takes forever to run.
|
||||
// Stack-overflow exit test
|
||||
|
@ -1018,6 +1018,10 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
private:
|
||||
struct SlowFunction
|
||||
{
|
||||
SlowFunction(PropertyName *name, unsigned ms, unsigned line, unsigned column)
|
||||
: name(name), ms(ms), line(line), column(column)
|
||||
{}
|
||||
|
||||
PropertyName *name;
|
||||
unsigned ms;
|
||||
unsigned line;
|
||||
@ -1423,7 +1427,10 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
bool finishGeneratingFunction(Func &func, CodeGenerator &codegen,
|
||||
const AsmJSFunctionLabels &labels)
|
||||
{
|
||||
if (!module_->addFunctionCodeRange(func.name(), labels))
|
||||
uint32_t line, column;
|
||||
tokenStream().srcCoords.lineNumAndColumnIndex(func.srcBegin(), &line, &column);
|
||||
|
||||
if (!module_->addFunctionCodeRange(func.name(), line, labels))
|
||||
return false;
|
||||
|
||||
jit::IonScriptCounts *counts = codegen.extractScriptCounts();
|
||||
@ -1433,17 +1440,12 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
|
||||
if (func.compileTime() >= 250) {
|
||||
SlowFunction sf;
|
||||
sf.name = func.name();
|
||||
sf.ms = func.compileTime();
|
||||
tokenStream().srcCoords.lineNumAndColumnIndex(func.srcBegin(), &sf.line, &sf.column);
|
||||
SlowFunction sf(func.name(), func.compileTime(), line, column);
|
||||
if (!slowFunctions_.append(sf))
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
uint32_t line, column;
|
||||
tokenStream().srcCoords.lineNumAndColumnIndex(func.srcBegin(), &line, &column);
|
||||
unsigned begin = labels.begin.offset();
|
||||
unsigned end = labels.end.offset();
|
||||
if (!module_->addProfiledFunction(func.name(), begin, end, line, column))
|
||||
|
@ -599,90 +599,50 @@ AsmJSProfilingFrameIterator::operator++()
|
||||
JS_ASSERT(!done());
|
||||
}
|
||||
|
||||
AsmJSProfilingFrameIterator::Kind
|
||||
AsmJSProfilingFrameIterator::kind() const
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
|
||||
switch (AsmJSExit::ExtractReasonKind(exitReason_)) {
|
||||
case AsmJSExit::Reason_None:
|
||||
break;
|
||||
case AsmJSExit::Reason_Interrupt:
|
||||
case AsmJSExit::Reason_FFI:
|
||||
return JS::ProfilingFrameIterator::AsmJSTrampoline;
|
||||
case AsmJSExit::Reason_Builtin:
|
||||
return JS::ProfilingFrameIterator::CppFunction;
|
||||
}
|
||||
|
||||
auto codeRange = reinterpret_cast<const AsmJSModule::CodeRange*>(codeRange_);
|
||||
switch (codeRange->kind()) {
|
||||
case AsmJSModule::CodeRange::Function:
|
||||
return JS::ProfilingFrameIterator::Function;
|
||||
case AsmJSModule::CodeRange::Entry:
|
||||
case AsmJSModule::CodeRange::FFI:
|
||||
case AsmJSModule::CodeRange::Interrupt:
|
||||
case AsmJSModule::CodeRange::Inline:
|
||||
return JS::ProfilingFrameIterator::AsmJSTrampoline;
|
||||
case AsmJSModule::CodeRange::Thunk:
|
||||
return JS::ProfilingFrameIterator::CppFunction;
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Bad kind");
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
AsmJSProfilingFrameIterator::functionDisplayAtom() const
|
||||
{
|
||||
JS_ASSERT(kind() == JS::ProfilingFrameIterator::Function);
|
||||
return reinterpret_cast<const AsmJSModule::CodeRange*>(codeRange_)->functionName(*module_);
|
||||
}
|
||||
|
||||
const char *
|
||||
AsmJSProfilingFrameIterator::functionFilename() const
|
||||
{
|
||||
JS_ASSERT(kind() == JS::ProfilingFrameIterator::Function);
|
||||
return module_->scriptSource()->filename();
|
||||
}
|
||||
|
||||
static const char *
|
||||
BuiltinToName(AsmJSExit::BuiltinKind builtin)
|
||||
{
|
||||
// Note: this label is regexp-matched by
|
||||
// browser/devtools/profiler/cleopatra/js/parserWorker.js.
|
||||
|
||||
switch (builtin) {
|
||||
case AsmJSExit::Builtin_ToInt32: return "ToInt32";
|
||||
case AsmJSExit::Builtin_ToInt32: return "ToInt32 (in asm.js)";
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
case AsmJSExit::Builtin_IDivMod: return "software idivmod";
|
||||
case AsmJSExit::Builtin_UDivMod: return "software uidivmod";
|
||||
case AsmJSExit::Builtin_IDivMod: return "software idivmod (in asm.js)";
|
||||
case AsmJSExit::Builtin_UDivMod: return "software uidivmod (in asm.js)";
|
||||
#endif
|
||||
case AsmJSExit::Builtin_ModD: return "fmod";
|
||||
case AsmJSExit::Builtin_SinD: return "Math.sin";
|
||||
case AsmJSExit::Builtin_CosD: return "Math.cos";
|
||||
case AsmJSExit::Builtin_TanD: return "Math.tan";
|
||||
case AsmJSExit::Builtin_ASinD: return "Math.asin";
|
||||
case AsmJSExit::Builtin_ACosD: return "Math.acos";
|
||||
case AsmJSExit::Builtin_ATanD: return "Math.atan";
|
||||
case AsmJSExit::Builtin_ModD: return "fmod (in asm.js)";
|
||||
case AsmJSExit::Builtin_SinD: return "Math.sin (in asm.js)";
|
||||
case AsmJSExit::Builtin_CosD: return "Math.cos (in asm.js)";
|
||||
case AsmJSExit::Builtin_TanD: return "Math.tan (in asm.js)";
|
||||
case AsmJSExit::Builtin_ASinD: return "Math.asin (in asm.js)";
|
||||
case AsmJSExit::Builtin_ACosD: return "Math.acos (in asm.js)";
|
||||
case AsmJSExit::Builtin_ATanD: return "Math.atan (in asm.js)";
|
||||
case AsmJSExit::Builtin_CeilD:
|
||||
case AsmJSExit::Builtin_CeilF: return "Math.ceil";
|
||||
case AsmJSExit::Builtin_CeilF: return "Math.ceil (in asm.js)";
|
||||
case AsmJSExit::Builtin_FloorD:
|
||||
case AsmJSExit::Builtin_FloorF: return "Math.floor";
|
||||
case AsmJSExit::Builtin_ExpD: return "Math.exp";
|
||||
case AsmJSExit::Builtin_LogD: return "Math.log";
|
||||
case AsmJSExit::Builtin_PowD: return "Math.pow";
|
||||
case AsmJSExit::Builtin_ATan2D: return "Math.atan2";
|
||||
case AsmJSExit::Builtin_FloorF: return "Math.floor (in asm.js)";
|
||||
case AsmJSExit::Builtin_ExpD: return "Math.exp (in asm.js)";
|
||||
case AsmJSExit::Builtin_LogD: return "Math.log (in asm.js)";
|
||||
case AsmJSExit::Builtin_PowD: return "Math.pow (in asm.js)";
|
||||
case AsmJSExit::Builtin_ATan2D: return "Math.atan2 (in asm.js)";
|
||||
case AsmJSExit::Builtin_Limit: break;
|
||||
}
|
||||
MOZ_ASSUME_UNREACHABLE("Bad builtin kind");
|
||||
}
|
||||
|
||||
const char *
|
||||
AsmJSProfilingFrameIterator::nonFunctionDescription() const
|
||||
AsmJSProfilingFrameIterator::label() const
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
JS_ASSERT(kind() != JS::ProfilingFrameIterator::Function);
|
||||
|
||||
// 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 = "asm.js FFI trampoline";
|
||||
const char *interruptDescription = "asm.js slow script interrupt";
|
||||
const char *ffiDescription = "FFI trampoline (in asm.js)";
|
||||
const char *interruptDescription = "slow script interrupt trampoline (in asm.js)";
|
||||
|
||||
switch (AsmJSExit::ExtractReasonKind(exitReason_)) {
|
||||
case AsmJSExit::Reason_None:
|
||||
@ -697,11 +657,11 @@ AsmJSProfilingFrameIterator::nonFunctionDescription() const
|
||||
|
||||
auto codeRange = reinterpret_cast<const AsmJSModule::CodeRange*>(codeRange_);
|
||||
switch (codeRange->kind()) {
|
||||
case AsmJSModule::CodeRange::Function: MOZ_ASSUME_UNREACHABLE("non-functions only");
|
||||
case AsmJSModule::CodeRange::Entry: return "asm.js entry trampoline";
|
||||
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::Interrupt: return interruptDescription;
|
||||
case AsmJSModule::CodeRange::Inline: return "asm.js inline stub";
|
||||
case AsmJSModule::CodeRange::Inline: return "inline stub (in asm.js)";
|
||||
case AsmJSModule::CodeRange::Thunk: return BuiltinToName(codeRange->thunkTarget());
|
||||
}
|
||||
|
||||
|
@ -133,15 +133,7 @@ class AsmJSProfilingFrameIterator
|
||||
bool done() const { return !codeRange_; }
|
||||
|
||||
void *stackAddress() const { JS_ASSERT(!done()); return stackAddress_; }
|
||||
|
||||
typedef JS::ProfilingFrameIterator::Kind Kind;
|
||||
Kind kind() const;
|
||||
|
||||
JSAtom *functionDisplayAtom() const;
|
||||
const char *functionFilename() const;
|
||||
unsigned functionLine() const;
|
||||
|
||||
const char *nonFunctionDescription() const;
|
||||
const char *label() const;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -1173,8 +1173,10 @@ AsmJSModule::ExportedFunction::clone(ExclusiveContext *cx, ExportedFunction *out
|
||||
return true;
|
||||
}
|
||||
|
||||
AsmJSModule::CodeRange::CodeRange(uint32_t nameIndex, const AsmJSFunctionLabels &l)
|
||||
AsmJSModule::CodeRange::CodeRange(uint32_t nameIndex, uint32_t lineNumber,
|
||||
const AsmJSFunctionLabels &l)
|
||||
: nameIndex_(nameIndex),
|
||||
lineNumber_(lineNumber),
|
||||
begin_(l.begin.offset()),
|
||||
profilingReturn_(l.profilingReturn.offset()),
|
||||
end_(l.end.offset())
|
||||
@ -1535,6 +1537,29 @@ AsmJSModule::setProfilingEnabled(bool enabled, JSContext *cx)
|
||||
if (profilingEnabled_ == enabled)
|
||||
return;
|
||||
|
||||
// When enabled, generate profiling labels for every name in names_ that is
|
||||
// the name of some Function CodeRange. This involves malloc() so do it now
|
||||
// since, once we start sampling, we'll be in a signal-handing context where
|
||||
// we cannot malloc.
|
||||
if (enabled) {
|
||||
profilingLabels_.resize(names_.length());
|
||||
const char *filename = scriptSource_->filename();
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
for (size_t i = 0; i < codeRanges_.length(); i++) {
|
||||
CodeRange &cr = codeRanges_[i];
|
||||
if (!cr.isFunction())
|
||||
continue;
|
||||
unsigned lineno = cr.functionLineNumber();
|
||||
PropertyName *name = names_[cr.functionNameIndex()].name();
|
||||
profilingLabels_[cr.functionNameIndex()].reset(
|
||||
name->hasLatin1Chars()
|
||||
? JS_smprintf("%s (%s:%u)", name->latin1Chars(nogc), filename, lineno)
|
||||
: JS_smprintf("%hs (%s:%u)", name->twoByteChars(nogc), filename, lineno));
|
||||
}
|
||||
} else {
|
||||
profilingLabels_.clear();
|
||||
}
|
||||
|
||||
// Conservatively flush the icache for the entire module.
|
||||
AutoFlushICache afc("AsmJSModule::setProfilingEnabled");
|
||||
setAutoFlushICacheRange();
|
||||
|
@ -335,6 +335,7 @@ class AsmJSModule
|
||||
class CodeRange
|
||||
{
|
||||
uint32_t nameIndex_;
|
||||
uint32_t lineNumber_;
|
||||
uint32_t begin_;
|
||||
uint32_t profilingReturn_;
|
||||
uint32_t end_;
|
||||
@ -358,7 +359,7 @@ class AsmJSModule
|
||||
enum Kind { Function, Entry, FFI, Interrupt, Thunk, Inline };
|
||||
|
||||
CodeRange() {}
|
||||
CodeRange(uint32_t nameIndex, const AsmJSFunctionLabels &l);
|
||||
CodeRange(uint32_t nameIndex, uint32_t lineNumber, const AsmJSFunctionLabels &l);
|
||||
CodeRange(Kind kind, uint32_t begin, uint32_t end);
|
||||
CodeRange(Kind kind, uint32_t begin, uint32_t profilingReturn, uint32_t end);
|
||||
CodeRange(AsmJSExit::BuiltinKind builtin, uint32_t begin, uint32_t pret, uint32_t end);
|
||||
@ -393,10 +394,22 @@ class AsmJSModule
|
||||
JS_ASSERT(isFunction() || isFFI() || isInterrupt() || isThunk());
|
||||
return profilingReturn_;
|
||||
}
|
||||
uint32_t functionNameIndex() const {
|
||||
JS_ASSERT(isFunction());
|
||||
return nameIndex_;
|
||||
}
|
||||
PropertyName *functionName(const AsmJSModule &module) const {
|
||||
JS_ASSERT(isFunction());
|
||||
return module.names_[nameIndex_].name();
|
||||
}
|
||||
const char *functionProfilingLabel(const AsmJSModule &module) const {
|
||||
JS_ASSERT(isFunction());
|
||||
return module.profilingLabels_[nameIndex_].get();
|
||||
}
|
||||
uint32_t functionLineNumber() const {
|
||||
JS_ASSERT(isFunction());
|
||||
return lineNumber_;
|
||||
}
|
||||
AsmJSExit::BuiltinKind thunkTarget() const {
|
||||
JS_ASSERT(isThunk());
|
||||
return AsmJSExit::BuiltinKind(u.thunk.target_);
|
||||
@ -430,6 +443,8 @@ class AsmJSModule
|
||||
bool clone(ExclusiveContext *cx, Name *out) const;
|
||||
};
|
||||
|
||||
typedef mozilla::UniquePtr<char, JS::FreePolicy> ProfilingLabel;
|
||||
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
// Function information to add to the VTune JIT profiler following linking.
|
||||
struct ProfiledFunction
|
||||
@ -603,6 +618,7 @@ class AsmJSModule
|
||||
Vector<FuncPtrTable, 0, SystemAllocPolicy> funcPtrTables_;
|
||||
Vector<uint32_t, 0, SystemAllocPolicy> builtinThunkOffsets_;
|
||||
Vector<Name, 0, SystemAllocPolicy> names_;
|
||||
Vector<ProfilingLabel, 0, SystemAllocPolicy> profilingLabels_;
|
||||
Vector<jit::AsmJSHeapAccess, 0, SystemAllocPolicy> heapAccesses_;
|
||||
Vector<jit::IonScriptCounts*, 0, SystemAllocPolicy> functionCounts_;
|
||||
#if defined(MOZ_VTUNE) || defined(JS_ION_PERF)
|
||||
@ -801,13 +817,15 @@ class AsmJSModule
|
||||
if (len > pod.minHeapLength_)
|
||||
pod.minHeapLength_ = len;
|
||||
}
|
||||
bool addFunctionCodeRange(PropertyName *name, const AsmJSFunctionLabels &labels) {
|
||||
bool addFunctionCodeRange(PropertyName *name, uint32_t lineNumber,
|
||||
const AsmJSFunctionLabels &labels)
|
||||
{
|
||||
JS_ASSERT(!isFinished());
|
||||
JS_ASSERT(name->isTenured());
|
||||
if (names_.length() >= UINT32_MAX)
|
||||
return false;
|
||||
uint32_t nameIndex = names_.length();
|
||||
return names_.append(name) && codeRanges_.append(CodeRange(nameIndex, labels));
|
||||
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));
|
||||
|
@ -4273,26 +4273,8 @@ SingleStepCallback(void *arg, jit::Simulator *sim, void *pc)
|
||||
JS_ASSERT(i.stackAddress() != nullptr);
|
||||
JS_ASSERT(lastStackAddress <= i.stackAddress());
|
||||
lastStackAddress = i.stackAddress();
|
||||
switch (i.kind()) {
|
||||
case JS::ProfilingFrameIterator::Function: {
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
JSAtom *atom = i.functionDisplayAtom();
|
||||
if (atom->hasLatin1Chars())
|
||||
stack.append(atom->latin1Chars(nogc), atom->length());
|
||||
else
|
||||
stack.append(atom->twoByteChars(nogc), atom->length());
|
||||
break;
|
||||
}
|
||||
case JS::ProfilingFrameIterator::AsmJSTrampoline: {
|
||||
stack.append('*');
|
||||
break;
|
||||
}
|
||||
case JS::ProfilingFrameIterator::CppFunction: {
|
||||
const char *desc = i.nonFunctionDescription();
|
||||
stack.append(desc, strlen(desc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
const char *label = i.label();
|
||||
stack.append(label, strlen(label));
|
||||
}
|
||||
|
||||
// Only append the stack if it differs from the last stack.
|
||||
|
@ -1842,44 +1842,11 @@ JS::ProfilingFrameIterator::stackAddress() const
|
||||
#endif
|
||||
}
|
||||
|
||||
JS::ProfilingFrameIterator::Kind
|
||||
JS::ProfilingFrameIterator::kind() const
|
||||
{
|
||||
#ifdef JS_ION
|
||||
return iter().kind();
|
||||
#else
|
||||
MOZ_CRASH("Shouldn't have any frames");
|
||||
#endif
|
||||
}
|
||||
|
||||
JSAtom *
|
||||
JS::ProfilingFrameIterator::functionDisplayAtom() const
|
||||
{
|
||||
#ifdef JS_ION
|
||||
JS_ASSERT(kind() == Function);
|
||||
return iter().functionDisplayAtom();
|
||||
#else
|
||||
MOZ_CRASH("Shouldn't have any frames");
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
JS::ProfilingFrameIterator::functionFilename() const
|
||||
JS::ProfilingFrameIterator::label() const
|
||||
{
|
||||
#ifdef JS_ION
|
||||
JS_ASSERT(kind() == Function);
|
||||
return iter().functionFilename();
|
||||
#else
|
||||
MOZ_CRASH("Shouldn't have any frames");
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
JS::ProfilingFrameIterator::nonFunctionDescription() const
|
||||
{
|
||||
#ifdef JS_ION
|
||||
JS_ASSERT(kind() != Function);
|
||||
return iter().nonFunctionDescription();
|
||||
return iter().label();
|
||||
#else
|
||||
MOZ_CRASH("Shouldn't have any frames");
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user