Bug 838014 - Rooting the JS debugger, r=jorendorff.

--HG--
extra : rebase_source : 32db3aba8742ec36cc7edfead57a278e1861b86d
This commit is contained in:
Steve Fink 2013-02-01 13:38:42 -08:00
parent b67c21c1dc
commit 03f8e6fb7b
6 changed files with 84 additions and 66 deletions

View File

@ -95,7 +95,7 @@ js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
}
RootedValue rval(cx);
JSTrapStatus status = Debugger::onEnterFrame(cx, rval.address());
JSTrapStatus status = Debugger::onEnterFrame(cx, &rval);
switch (status) {
case JSTRAP_CONTINUE:
break;
@ -142,12 +142,12 @@ js::DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc)
return JSTRAP_CONTINUE;
/* Call debugger throw hook if set. */
Value rval;
RootedValue rval(cx);
JSTrapStatus status = Debugger::onExceptionUnwind(cx, &rval);
if (status == JSTRAP_CONTINUE) {
if (JSThrowHook handler = cx->runtime->debugHooks.throwHook) {
RootedScript script(cx, frame.script());
status = handler(cx, script, pc, &rval, cx->runtime->debugHooks.throwHookData);
status = handler(cx, script, pc, rval.address(), cx->runtime->debugHooks.throwHookData);
}
}

View File

@ -1261,10 +1261,10 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
if (hook || script->stepModeEnabled()) {
Value rval;
RootedValue rval(cx);
JSTrapStatus status = JSTRAP_CONTINUE;
if (hook)
status = hook(cx, script, regs.pc, &rval, cx->runtime->debugHooks.interruptHookData);
status = hook(cx, script, regs.pc, rval.address(), cx->runtime->debugHooks.interruptHookData);
if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
status = Debugger::onSingleStep(cx, &rval);
switch (status) {
@ -1288,7 +1288,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
moreInterrupts = true;
if (script->hasBreakpointsAt(regs.pc) && interpMode != JSINTERP_SKIP_TRAP) {
Value rval;
RootedValue rval(cx);
JSTrapStatus status = Debugger::onTrap(cx, &rval);
switch (status) {
case JSTRAP_ERROR:
@ -3100,9 +3100,9 @@ END_CASE(JSOP_INSTANCEOF)
BEGIN_CASE(JSOP_DEBUGGER)
{
JSTrapStatus st = JSTRAP_CONTINUE;
Value rval;
RootedValue rval(cx);
if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
st = handler(cx, script, regs.pc, rval.address(), cx->runtime->debugHooks.debuggerHandlerData);
if (st == JSTRAP_CONTINUE)
st = Debugger::onDebuggerStatement(cx, &rval);
switch (st) {

View File

@ -558,11 +558,11 @@ js_InternalThrow(VMFrame &f)
// Call the throw hook if necessary
JSThrowHook handler = cx->runtime->debugHooks.throwHook;
if (handler || !cx->compartment->getDebuggees().empty()) {
Value rval;
RootedValue rval(cx);
JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
if (st == JSTRAP_CONTINUE && handler) {
RootedScript fscript(cx, cx->fp()->script());
st = handler(cx, fscript, cx->regs().pc, &rval,
st = handler(cx, fscript, cx->regs().pc, rval.address(),
cx->runtime->debugHooks.throwHookData);
}

View File

@ -748,7 +748,7 @@ stubs::DebuggerStatement(VMFrame &f, jsbytecode *pc)
st = handler(f.cx, fscript, pc, rval.address(), f.cx->runtime->debugHooks.debuggerHandlerData);
}
if (st == JSTRAP_CONTINUE)
st = Debugger::onDebuggerStatement(f.cx, rval.address());
st = Debugger::onDebuggerStatement(f.cx, &rval);
switch (st) {
case JSTRAP_THROW:
@ -860,7 +860,7 @@ stubs::RecompileForInline(VMFrame &f)
void JS_FASTCALL
stubs::Trap(VMFrame &f, uint32_t trapTypes)
{
Value rval;
RootedValue rval(f.cx);
/*
* Trap may be called for a single-step interrupt trap and/or a
@ -876,7 +876,8 @@ stubs::Trap(VMFrame &f, uint32_t trapTypes)
JSInterruptHook hook = f.cx->runtime->debugHooks.interruptHook;
if (hook) {
RootedScript fscript(f.cx, f.script());
result = hook(f.cx, fscript, f.pc(), &rval, f.cx->runtime->debugHooks.interruptHookData);
result = hook(f.cx, fscript, f.pc(), rval.address(),
f.cx->runtime->debugHooks.interruptHookData);
}
if (result == JSTRAP_CONTINUE)

View File

@ -413,7 +413,7 @@ Debugger::fromChildJSObject(JSObject *obj)
}
bool
Debugger::getScriptFrame(JSContext *cx, const ScriptFrameIter &iter, Value *vp)
Debugger::getScriptFrame(JSContext *cx, const ScriptFrameIter &iter, MutableHandleValue vp)
{
FrameMap::AddPtr p = frames.lookupForAdd(iter.abstractFramePtr());
if (!p) {
@ -434,7 +434,7 @@ Debugger::getScriptFrame(JSContext *cx, const ScriptFrameIter &iter, Value *vp)
return false;
}
}
vp->setObject(*p->value);
vp.setObject(*p->value);
return true;
}
@ -477,7 +477,7 @@ Debugger::hasAnyLiveHooks() const
}
JSTrapStatus
Debugger::slowPathOnEnterFrame(JSContext *cx, Value *vp)
Debugger::slowPathOnEnterFrame(JSContext *cx, MutableHandleValue vp)
{
/* Build the list of recipients. */
AutoValueVector triggered(cx);
@ -557,11 +557,11 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx, bool frameOk)
}
/* Call the onPop handler. */
Value rval;
RootedValue rval(cx);
bool hookOk = Invoke(cx, ObjectValue(*frameobj), handler, 1, completion.address(),
&rval);
rval.address());
RootedValue nextValue(cx);
JSTrapStatus nextStatus = dbg->parseResumptionValue(ac, hookOk, rval, nextValue.address());
JSTrapStatus nextStatus = dbg->parseResumptionValue(ac, hookOk, rval, &nextValue);
/*
* At this point, we are back in the debuggee compartment, and any error has
@ -744,7 +744,8 @@ Debugger::unwrapDebuggeeValue(JSContext *cx, MutableHandleValue vp)
}
JSTrapStatus
Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, Value *vp, bool callHook)
Debugger::handleUncaughtExceptionHelper(Maybe<AutoCompartment> &ac,
MutableHandleValue *vp, bool callHook)
{
JSContext *cx = ac.ref().context();
if (cx->isExceptionPending()) {
@ -754,7 +755,7 @@ Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, Value *vp, bool ca
Value rv;
cx->clearPendingException();
if (Invoke(cx, ObjectValue(*object), fval, 1, &exc, &rv))
return vp ? parseResumptionValue(ac, true, rv, vp, false) : JSTRAP_CONTINUE;
return vp ? parseResumptionValue(ac, true, rv, *vp, false) : JSTRAP_CONTINUE;
}
if (cx->isExceptionPending()) {
@ -766,6 +767,18 @@ Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, Value *vp, bool ca
return JSTRAP_ERROR;
}
JSTrapStatus
Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, MutableHandleValue vp, bool callHook)
{
return handleUncaughtExceptionHelper(ac, &vp, callHook);
}
JSTrapStatus
Debugger::handleUncaughtException(Maybe<AutoCompartment> &ac, bool callHook)
{
return handleUncaughtExceptionHelper(ac, NULL, callHook);
}
void
Debugger::resultToCompletion(JSContext *cx, bool ok, const Value &rv,
JSTrapStatus *status, MutableHandleValue value)
@ -843,10 +856,10 @@ Debugger::receiveCompletionValue(Maybe<AutoCompartment> &ac, bool ok, Value val,
}
JSTrapStatus
Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value &rv, Value *vp,
Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value &rv, MutableHandleValue vp,
bool callHook)
{
vp->setUndefined();
vp.setUndefined();
if (!ok)
return handleUncaughtException(ac, vp, callHook);
if (rv.isUndefined()) {
@ -881,16 +894,16 @@ Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value
return handleUncaughtException(ac, vp, callHook);
}
RootedValue v(cx, *vp);
RootedValue v(cx, vp.get());
if (!js_NativeGet(cx, obj, obj, shape, 0, &v) || !unwrapDebuggeeValue(cx, &v))
return handleUncaughtException(ac, v.address(), callHook);
return handleUncaughtException(ac, &v, callHook);
ac.destroy();
if (!cx->compartment->wrap(cx, &v)) {
vp->setUndefined();
vp.setUndefined();
return JSTRAP_ERROR;
}
*vp = v;
vp.set(v);
return shape->propid() == returnId ? JSTRAP_RETURN : JSTRAP_THROW;
}
@ -911,7 +924,7 @@ CallMethodIfPresent(JSContext *cx, HandleObject obj, const char *name, int argc,
}
JSTrapStatus
Debugger::fireDebuggerStatement(JSContext *cx, Value *vp)
Debugger::fireDebuggerStatement(JSContext *cx, MutableHandleValue vp)
{
RootedObject hook(cx, getHook(OnDebuggerStatement));
JS_ASSERT(hook);
@ -922,17 +935,17 @@ Debugger::fireDebuggerStatement(JSContext *cx, Value *vp)
ScriptFrameIter iter(cx);
Value argv[1];
if (!getScriptFrame(cx, iter, argv))
RootedValue argv(cx);
if (!getScriptFrame(cx, iter, &argv))
return handleUncaughtException(ac, vp, false);
Value rv;
bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, argv, &rv);
bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, argv.address(), &rv);
return parseResumptionValue(ac, ok, rv, vp);
}
JSTrapStatus
Debugger::fireExceptionUnwind(JSContext *cx, Value *vp)
Debugger::fireExceptionUnwind(JSContext *cx, MutableHandleValue vp)
{
RootedObject hook(cx, getHook(OnExceptionUnwind));
JS_ASSERT(hook);
@ -950,7 +963,7 @@ Debugger::fireExceptionUnwind(JSContext *cx, Value *vp)
ScriptFrameIter iter(cx);
argv[1] = exc;
if (!getScriptFrame(cx, iter, &argv[0]) || !wrapDebuggeeValue(cx, avr.handleAt(1)))
if (!getScriptFrame(cx, iter, avr.handleAt(0)) || !wrapDebuggeeValue(cx, avr.handleAt(1)))
return handleUncaughtException(ac, vp, false);
Value rv;
@ -962,7 +975,7 @@ Debugger::fireExceptionUnwind(JSContext *cx, Value *vp)
}
JSTrapStatus
Debugger::fireEnterFrame(JSContext *cx, Value *vp)
Debugger::fireEnterFrame(JSContext *cx, MutableHandleValue vp)
{
RootedObject hook(cx, getHook(OnEnterFrame));
JS_ASSERT(hook);
@ -972,12 +985,12 @@ Debugger::fireEnterFrame(JSContext *cx, Value *vp)
Maybe<AutoCompartment> ac;
ac.construct(cx, object);
Value argv[1];
if (!getScriptFrame(cx, iter, &argv[0]))
RootedValue argv(cx);
if (!getScriptFrame(cx, iter, &argv))
return handleUncaughtException(ac, vp, false);
Value rv;
bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, argv, &rv);
bool ok = Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, argv.address(), &rv);
return parseResumptionValue(ac, ok, rv, vp);
}
@ -1005,7 +1018,7 @@ Debugger::fireNewScript(JSContext *cx, HandleScript script)
}
JSTrapStatus
Debugger::dispatchHook(JSContext *cx, Value *vp, Hook which)
Debugger::dispatchHook(JSContext *cx, MutableHandleValue vp, Hook which)
{
JS_ASSERT(which == OnDebuggerStatement || which == OnExceptionUnwind);
@ -1104,7 +1117,7 @@ Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *
}
JSTrapStatus
Debugger::onTrap(JSContext *cx, Value *vp)
Debugger::onTrap(JSContext *cx, MutableHandleValue vp)
{
ScriptFrameIter iter(cx);
RootedScript script(cx, iter.script());
@ -1146,7 +1159,7 @@ Debugger::onTrap(JSContext *cx, Value *vp)
Value argv[1];
AutoValueArray ava(cx, argv, 1);
if (!dbg->getScriptFrame(cx, iter, &argv[0]))
if (!dbg->getScriptFrame(cx, iter, ava.handleAt(0)))
return dbg->handleUncaughtException(ac, vp, false);
Value rv;
Rooted<JSObject*> handler(cx, bp->handler);
@ -1161,18 +1174,18 @@ Debugger::onTrap(JSContext *cx, Value *vp)
}
if (site && site->trapHandler) {
JSTrapStatus st = site->trapHandler(cx, script, pc, vp, site->trapClosure);
JSTrapStatus st = site->trapHandler(cx, script, pc, vp.address(), site->trapClosure);
if (st != JSTRAP_CONTINUE)
return st;
}
/* By convention, return the true op to the interpreter in vp. */
vp->setInt32(op);
vp.setInt32(op);
return JSTRAP_CONTINUE;
}
JSTrapStatus
Debugger::onSingleStep(JSContext *cx, Value *vp)
Debugger::onSingleStep(JSContext *cx, MutableHandleValue vp)
{
ScriptFrameIter iter(cx);
@ -1270,14 +1283,14 @@ Debugger::onSingleStep(JSContext *cx, Value *vp)
return st;
}
vp->setUndefined();
vp.setUndefined();
if (exceptionPending)
cx->setPendingException(exception);
return JSTRAP_CONTINUE;
}
JSTrapStatus
Debugger::fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, Value *vp)
Debugger::fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, MutableHandleValue vp)
{
RootedObject hook(cx, getHook(OnNewGlobalObject));
JS_ASSERT(hook);
@ -1326,7 +1339,7 @@ Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global
// One Debugger's onNewGlobalObject handler can disable another's, so we
// must test this in the loop.
if (dbg->observesNewGlobalObject()) {
status = dbg->fireNewGlobalObject(cx, global, &value.get());
status = dbg->fireNewGlobalObject(cx, global, &value);
if (status != JSTRAP_CONTINUE && status != JSTRAP_RETURN)
break;
}
@ -1983,7 +1996,7 @@ Debugger::getNewestFrame(JSContext *cx, unsigned argc, Value *vp)
ScriptFrameIter iter(i.seg()->cx(), StackIter::GO_THROUGH_SAVED);
while (iter.isIon() || iter.abstractFramePtr() != i.abstractFramePtr())
++iter;
return dbg->getScriptFrame(cx, iter, vp);
return dbg->getScriptFrame(cx, iter, args.rval());
}
}
args.rval().setNull();
@ -3409,7 +3422,7 @@ DebuggerFrame_getOlder(JSContext *cx, unsigned argc, Value *vp)
if (iter.isIon())
continue;
if (dbg->observesFrame(iter.abstractFramePtr()))
return dbg->getScriptFrame(cx, iter, vp);
return dbg->getScriptFrame(cx, iter, args.rval());
}
args.rval().setNull();
return true;

View File

@ -239,7 +239,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
* Cope with an error or exception in a debugger hook.
*
* If callHook is true, then call the uncaughtExceptionHook, if any. If, in
* addition, vp is non-null, then parse the value returned by
* addition, vp is given, then parse the value returned by
* uncaughtExceptionHook as a resumption value.
*
* If there is no uncaughtExceptionHook, or if it fails, report and clear
@ -249,7 +249,11 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
* do some things in the debugger compartment and some things in the
* debuggee compartment.
*/
JSTrapStatus handleUncaughtException(mozilla::Maybe<AutoCompartment> &ac, Value *vp, bool callHook);
JSTrapStatus handleUncaughtException(mozilla::Maybe<AutoCompartment> &ac, bool callHook);
JSTrapStatus handleUncaughtException(mozilla::Maybe<AutoCompartment> &ac, MutableHandleValue vp, bool callHook);
JSTrapStatus handleUncaughtExceptionHelper(mozilla::Maybe<AutoCompartment> &ac,
MutableHandleValue *vp, bool callHook);
/*
* Handle the result of a hook that is expected to return a resumption
@ -277,7 +281,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
* return handleUncaughtException(ac, vp, callHook).
*/
JSTrapStatus parseResumptionValue(mozilla::Maybe<AutoCompartment> &ac, bool ok, const Value &rv,
Value *vp, bool callHook = true);
MutableHandleValue vp, bool callHook = true);
GlobalObject *unwrapDebuggeeArgument(JSContext *cx, const Value &v);
@ -323,17 +327,17 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
JSObject *getHook(Hook hook) const;
bool hasAnyLiveHooks() const;
static JSTrapStatus slowPathOnEnterFrame(JSContext *cx, Value *vp);
static JSTrapStatus slowPathOnEnterFrame(JSContext *cx, MutableHandleValue vp);
static bool slowPathOnLeaveFrame(JSContext *cx, bool ok);
static void slowPathOnNewScript(JSContext *cx, HandleScript script,
GlobalObject *compileAndGoGlobal);
static bool slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
static JSTrapStatus dispatchHook(JSContext *cx, Value *vp, Hook which);
static JSTrapStatus dispatchHook(JSContext *cx, MutableHandleValue vp, Hook which);
JSTrapStatus fireDebuggerStatement(JSContext *cx, Value *vp);
JSTrapStatus fireExceptionUnwind(JSContext *cx, Value *vp);
JSTrapStatus fireEnterFrame(JSContext *cx, Value *vp);
JSTrapStatus fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, Value *vp);
JSTrapStatus fireDebuggerStatement(JSContext *cx, MutableHandleValue vp);
JSTrapStatus fireExceptionUnwind(JSContext *cx, MutableHandleValue vp);
JSTrapStatus fireEnterFrame(JSContext *cx, MutableHandleValue vp);
JSTrapStatus fireNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global, MutableHandleValue vp);
/*
* Allocate and initialize a Debugger.Script instance whose referent is
@ -386,15 +390,15 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static bool isDebugWrapper(RawObject o);
static void findCompartmentEdges(JS::Zone *v, gc::ComponentFinder<JS::Zone> &finder);
static inline JSTrapStatus onEnterFrame(JSContext *cx, Value *vp);
static inline JSTrapStatus onEnterFrame(JSContext *cx, MutableHandleValue vp);
static inline bool onLeaveFrame(JSContext *cx, bool ok);
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, Value *vp);
static inline JSTrapStatus onExceptionUnwind(JSContext *cx, Value *vp);
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, MutableHandleValue vp);
static inline JSTrapStatus onExceptionUnwind(JSContext *cx, MutableHandleValue vp);
static inline void onNewScript(JSContext *cx, HandleScript script,
GlobalObject *compileAndGoGlobal);
static inline bool onNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global);
static JSTrapStatus onTrap(JSContext *cx, Value *vp);
static JSTrapStatus onSingleStep(JSContext *cx, Value *vp);
static JSTrapStatus onTrap(JSContext *cx, MutableHandleValue vp);
static JSTrapStatus onSingleStep(JSContext *cx, MutableHandleValue vp);
/************************************* Functions for use by Debugger.cpp. */
@ -453,7 +457,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
bool unwrapDebuggeeValue(JSContext *cx, MutableHandleValue vp);
/* Store the Debugger.Frame object for iter in *vp. */
bool getScriptFrame(JSContext *cx, const ScriptFrameIter &iter, Value *vp);
bool getScriptFrame(JSContext *cx, const ScriptFrameIter &iter, MutableHandleValue vp);
/*
* Set |*status| and |*value| to a (JSTrapStatus, Value) pair reflecting a
@ -638,7 +642,7 @@ Debugger::observesFrame(AbstractFramePtr frame) const
}
JSTrapStatus
Debugger::onEnterFrame(JSContext *cx, Value *vp)
Debugger::onEnterFrame(JSContext *cx, MutableHandleValue vp)
{
if (cx->compartment->getDebuggees().empty())
return JSTRAP_CONTINUE;
@ -657,7 +661,7 @@ Debugger::onLeaveFrame(JSContext *cx, bool ok)
}
JSTrapStatus
Debugger::onDebuggerStatement(JSContext *cx, Value *vp)
Debugger::onDebuggerStatement(JSContext *cx, MutableHandleValue vp)
{
return cx->compartment->getDebuggees().empty()
? JSTRAP_CONTINUE
@ -665,7 +669,7 @@ Debugger::onDebuggerStatement(JSContext *cx, Value *vp)
}
JSTrapStatus
Debugger::onExceptionUnwind(JSContext *cx, Value *vp)
Debugger::onExceptionUnwind(JSContext *cx, MutableHandleValue vp)
{
return cx->compartment->getDebuggees().empty()
? JSTRAP_CONTINUE