Bug 1007383 - Include asm.js frames in JS::DescribeStack (r=jandem,robcee)

This commit is contained in:
Luke Wagner 2014-05-15 12:30:45 -05:00
parent 686a50e920
commit cca3db9fa5
3 changed files with 105 additions and 18 deletions

View File

@ -24,7 +24,8 @@ class JSFreeOp;
namespace js {
class InterpreterFrame;
class ScriptFrameIter;
class FrameIter;
class ScriptSource;
}
// Raw JSScript* because this needs to be callable from a signal handler.
@ -39,18 +40,20 @@ namespace JS {
class FrameDescription
{
public:
explicit FrameDescription(const js::ScriptFrameIter& iter);
explicit FrameDescription(const js::FrameIter& iter);
FrameDescription(const FrameDescription &rhs);
~FrameDescription();
unsigned lineno() {
if (!linenoComputed) {
if (!linenoComputed_) {
lineno_ = JS_PCToLineNumber(nullptr, script_, pc_);
linenoComputed = true;
linenoComputed_ = true;
}
return lineno_;
}
const char *filename() const {
return JS_GetScriptFilename(script_);
return filename_;
}
JSFlatString *funDisplayName() const {
@ -67,11 +70,22 @@ class FrameDescription
}
private:
Heap<JSScript*> script_;
void operator=(const FrameDescription &) MOZ_DELETE;
// These fields are always initialized:
Heap<JSString*> funDisplayName_;
jsbytecode *pc_;
const char *filename_;
// One of script_ xor scriptSource_ is non-null.
Heap<JSScript*> script_;
js::ScriptSource *scriptSource_;
// For script_-having frames, lineno_ is lazily computed as an optimization.
bool linenoComputed_;
unsigned lineno_;
bool linenoComputed;
// pc_ is non-null iff script_ is non-null. If !pc_, linenoComputed_ = true.
jsbytecode *pc_;
};
struct StackDescription

View File

@ -897,14 +897,45 @@ js_CallContextDebugHandler(JSContext *cx)
* constructing a FrameDescription on the stack just to append it to a vector.
* FrameDescription contains Heap<T> fields that should not live on the stack.
*/
JS::FrameDescription::FrameDescription(const ScriptFrameIter& iter)
: script_(iter.script()),
funDisplayName_(nullptr),
pc_(iter.pc()),
linenoComputed(false)
JS::FrameDescription::FrameDescription(const FrameIter& iter)
: scriptSource_(nullptr),
linenoComputed_(false),
pc_(nullptr)
{
if (JSFunction *fun = iter.maybeCallee())
funDisplayName_ = fun->displayAtom();
if (iter.isNonEvalFunctionFrame())
funDisplayName_ = iter.functionDisplayAtom();
if (iter.hasScript()) {
script_ = iter.script();
pc_ = iter.pc();
filename_ = script_->filename();
} else {
scriptSource_ = iter.scriptSource();
scriptSource_->incref();
filename_ = scriptSource_->filename();
lineno_ = iter.computeLine();
linenoComputed_ = true;
}
}
JS::FrameDescription::FrameDescription(const FrameDescription &rhs)
: funDisplayName_(rhs.funDisplayName_),
filename_(rhs.filename_),
script_(rhs.script_),
scriptSource_(rhs.scriptSource_),
linenoComputed_(rhs.linenoComputed_),
lineno_(rhs.lineno_),
pc_(rhs.pc_)
{
if (scriptSource_)
scriptSource_->incref();
}
JS::FrameDescription::~FrameDescription()
{
if (scriptSource_)
scriptSource_->decref();
}
JS_PUBLIC_API(JS::StackDescription *)
@ -912,9 +943,9 @@ JS::DescribeStack(JSContext *cx, unsigned maxFrames)
{
Vector<FrameDescription> frames(cx);
NonBuiltinScriptFrameIter i(cx, ScriptFrameIter::ALL_CONTEXTS,
ScriptFrameIter::GO_THROUGH_SAVED,
cx->compartment()->principals);
NonBuiltinFrameIter i(cx, FrameIter::ALL_CONTEXTS,
FrameIter::GO_THROUGH_SAVED,
cx->compartment()->principals);
for ( ; !i.done(); ++i) {
if (!frames.append(i))
return nullptr;

View File

@ -28,6 +28,18 @@ function doConsoleCalls(aState)
top.console.dir(top.document, top.location);
top.console.log("foo", longString);
function fromAsmJS() {
top.console.error("foobarBaz-asmjs-error", undefined);
}
(function(global, foreign) {
"use asm";
var fromAsmJS = foreign.fromAsmJS;
function inAsmJS2() { fromAsmJS() }
function inAsmJS1() { inAsmJS2() }
return inAsmJS1
})(null, { fromAsmJS:fromAsmJS })();
expectedConsoleCalls = [
{
level: "log",
@ -107,6 +119,36 @@ function doConsoleCalls(aState)
},
],
},
{
level: "error",
filename: /test_consoleapi/,
functionName: "fromAsmJS",
timeStamp: /^\d+$/,
arguments: ["foobarBaz-asmjs-error", { type: "undefined" }],
stacktrace: [
{
filename: /test_consoleapi/,
functionName: "fromAsmJS",
},
{
filename: /test_consoleapi/,
functionName: "inAsmJS2",
},
{
filename: /test_consoleapi/,
functionName: "inAsmJS1",
},
{
filename: /test_consoleapi/,
functionName: "doConsoleCalls",
},
{
filename: /test_consoleapi/,
functionName: "onAttach",
},
],
},
];
}