mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 986767 - Fix adjusting stepModeCount when removing a debuggee global from inside the onStep handler. (r=jimb)
This commit is contained in:
parent
168e132278
commit
2232bbdf1c
@ -3158,32 +3158,21 @@ JSScript::ensureHasDebugScript(JSContext *cx)
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::recompileForStepMode(FreeOp *fop)
|
||||
JSScript::setNewStepMode(FreeOp *fop, uint32_t newValue)
|
||||
{
|
||||
#ifdef JS_ION
|
||||
if (hasBaselineScript())
|
||||
baseline->toggleDebugTraps(this, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::tryNewStepMode(JSContext *cx, uint32_t newValue)
|
||||
{
|
||||
JS_ASSERT(hasDebugScript_);
|
||||
|
||||
DebugScript *debug = debugScript();
|
||||
uint32_t prior = debug->stepMode;
|
||||
debug->stepMode = newValue;
|
||||
|
||||
if (!prior != !newValue) {
|
||||
/* Step mode has been enabled or disabled. Alert the methodjit. */
|
||||
recompileForStepMode(cx->runtime()->defaultFreeOp());
|
||||
#ifdef JS_ION
|
||||
if (hasBaselineScript())
|
||||
baseline->toggleDebugTraps(this, nullptr);
|
||||
#endif
|
||||
|
||||
if (!stepModeEnabled() && !debug->numSites)
|
||||
js_free(releaseDebugScript());
|
||||
fop->free_(releaseDebugScript());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -3192,25 +3181,40 @@ JSScript::setStepModeFlag(JSContext *cx, bool step)
|
||||
if (!ensureHasDebugScript(cx))
|
||||
return false;
|
||||
|
||||
return tryNewStepMode(cx, (debugScript()->stepMode & stepCountMask) |
|
||||
(step ? stepFlagMask : 0));
|
||||
setNewStepMode(cx->runtime()->defaultFreeOp(),
|
||||
(debugScript()->stepMode & stepCountMask) |
|
||||
(step ? stepFlagMask : 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::changeStepModeCount(JSContext *cx, int delta)
|
||||
JSScript::incrementStepModeCount(JSContext *cx)
|
||||
{
|
||||
assertSameCompartment(cx, this);
|
||||
MOZ_ASSERT(cx->compartment()->debugMode());
|
||||
|
||||
if (!ensureHasDebugScript(cx))
|
||||
return false;
|
||||
|
||||
assertSameCompartment(cx, this);
|
||||
JS_ASSERT_IF(delta > 0, cx->compartment()->debugMode());
|
||||
|
||||
DebugScript *debug = debugScript();
|
||||
uint32_t count = debug->stepMode & stepCountMask;
|
||||
JS_ASSERT(((count + delta) & stepCountMask) == count + delta);
|
||||
return tryNewStepMode(cx,
|
||||
(debug->stepMode & stepFlagMask) |
|
||||
((count + delta) & stepCountMask));
|
||||
MOZ_ASSERT(((count + 1) & stepCountMask) == count + 1);
|
||||
|
||||
setNewStepMode(cx->runtime()->defaultFreeOp(),
|
||||
(debug->stepMode & stepFlagMask) |
|
||||
((count + 1) & stepCountMask));
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::decrementStepModeCount(FreeOp *fop)
|
||||
{
|
||||
DebugScript *debug = debugScript();
|
||||
uint32_t count = debug->stepMode & stepCountMask;
|
||||
|
||||
setNewStepMode(fop,
|
||||
(debug->stepMode & stepFlagMask) |
|
||||
((count - 1) & stepCountMask));
|
||||
}
|
||||
|
||||
BreakpointSite *
|
||||
|
@ -1504,14 +1504,8 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
bool formalLivesInArgumentsObject(unsigned argSlot);
|
||||
|
||||
private:
|
||||
/*
|
||||
* Recompile with or without single-stepping support, as directed
|
||||
* by stepModeEnabled().
|
||||
*/
|
||||
void recompileForStepMode(js::FreeOp *fop);
|
||||
|
||||
/* Attempt to change this->stepMode to |newValue|. */
|
||||
bool tryNewStepMode(JSContext *cx, uint32_t newValue);
|
||||
/* Change this->stepMode to |newValue|. */
|
||||
void setNewStepMode(js::FreeOp *fop, uint32_t newValue);
|
||||
|
||||
bool ensureHasDebugScript(JSContext *cx);
|
||||
js::DebugScript *debugScript();
|
||||
@ -1549,8 +1543,11 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
* the flag (set by setStepModeFlag) is set, then the script is in
|
||||
* single-step mode. (JSD uses an on/off-style interface; Debugger uses a
|
||||
* count-style interface.)
|
||||
*
|
||||
* Only incrementing is fallible, as it could allocate a DebugScript.
|
||||
*/
|
||||
bool changeStepModeCount(JSContext *cx, int delta);
|
||||
bool incrementStepModeCount(JSContext *cx);
|
||||
void decrementStepModeCount(js::FreeOp *fop);
|
||||
|
||||
bool stepModeEnabled() { return hasDebugScript_ && !!debugScript()->stepMode; }
|
||||
|
||||
|
@ -147,8 +147,8 @@ ValueToIdentifier(JSContext *cx, HandleValue v, MutableHandleId id)
|
||||
* A range of all the Debugger.Frame objects for a particular AbstractFramePtr.
|
||||
*
|
||||
* FIXME This checks only current debuggers, so it relies on a hack in
|
||||
* Debugger::removeDebuggeeGlobal to make sure only current debuggers have Frame
|
||||
* objects with .live === true.
|
||||
* Debugger::removeDebuggeeGlobal to make sure only current debuggers
|
||||
* have Frame objects with .live === true.
|
||||
*/
|
||||
class Debugger::FrameRange
|
||||
{
|
||||
@ -553,6 +553,10 @@ Debugger::slowPathOnEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHan
|
||||
return JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
DebuggerFrame_maybeDecrementFrameScriptStepModeCount(FreeOp *fop, AbstractFramePtr frame,
|
||||
JSObject *frameobj);
|
||||
|
||||
static void
|
||||
DebuggerFrame_freeScriptFrameIterData(FreeOp *fop, JSObject *obj);
|
||||
|
||||
@ -630,15 +634,9 @@ Debugger::slowPathOnLeaveFrame(JSContext *cx, AbstractFramePtr frame, bool frame
|
||||
Debugger *dbg = r.frontDebugger();
|
||||
JS_ASSERT(dbg == Debugger::fromChildJSObject(frameobj));
|
||||
|
||||
DebuggerFrame_freeScriptFrameIterData(cx->runtime()->defaultFreeOp(), frameobj);
|
||||
|
||||
/* If this frame had an onStep handler, adjust the script's count. */
|
||||
if (!frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER).isUndefined() &&
|
||||
!frame.script()->changeStepModeCount(cx, -1))
|
||||
{
|
||||
status = JSTRAP_ERROR;
|
||||
/* Don't exit the loop; we must mark all frames as dead. */
|
||||
}
|
||||
FreeOp *fop = cx->runtime()->defaultFreeOp();
|
||||
DebuggerFrame_freeScriptFrameIterData(fop, frameobj);
|
||||
DebuggerFrame_maybeDecrementFrameScriptStepModeCount(fop, frame, frameobj);
|
||||
|
||||
dbg->frames.remove(frame);
|
||||
}
|
||||
@ -2288,7 +2286,7 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(global->compartment());
|
||||
return removeDebuggeeGlobal(fop, global, invalidate, compartmentEnum, debugEnum);
|
||||
removeDebuggeeGlobal(fop, global, invalidate, compartmentEnum, debugEnum);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2319,8 +2317,10 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
*/
|
||||
for (FrameMap::Enum e(frames); !e.empty(); e.popFront()) {
|
||||
AbstractFramePtr frame = e.front().key();
|
||||
JSObject *frameobj = e.front().value();
|
||||
if (&frame.script()->global() == global) {
|
||||
DebuggerFrame_freeScriptFrameIterData(fop, e.front().value());
|
||||
DebuggerFrame_freeScriptFrameIterData(fop, frameobj);
|
||||
DebuggerFrame_maybeDecrementFrameScriptStepModeCount(fop, frame, frameobj);
|
||||
e.removeFront();
|
||||
}
|
||||
}
|
||||
@ -4042,6 +4042,15 @@ DebuggerFrame_freeScriptFrameIterData(FreeOp *fop, JSObject *obj)
|
||||
obj->setPrivate(nullptr);
|
||||
}
|
||||
|
||||
static void
|
||||
DebuggerFrame_maybeDecrementFrameScriptStepModeCount(FreeOp *fop, AbstractFramePtr frame,
|
||||
JSObject *frameobj)
|
||||
{
|
||||
/* If this frame has an onStep handler, decrement the script's count. */
|
||||
if (!frameobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER).isUndefined())
|
||||
frame.script()->decrementStepModeCount(fop);
|
||||
}
|
||||
|
||||
static void
|
||||
DebuggerFrame_finalize(FreeOp *fop, JSObject *obj)
|
||||
{
|
||||
@ -4446,12 +4455,14 @@ DebuggerFrame_setOnStep(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
Value prior = thisobj->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER);
|
||||
int delta = !args[0].isUndefined() - !prior.isUndefined();
|
||||
if (delta != 0) {
|
||||
/* Try to adjust this frame's script single-step mode count. */
|
||||
if (!args[0].isUndefined() && prior.isUndefined()) {
|
||||
// Single stepping toggled off->on.
|
||||
AutoCompartment ac(cx, frame.scopeChain());
|
||||
if (!frame.script()->changeStepModeCount(cx, delta))
|
||||
if (!frame.script()->incrementStepModeCount(cx))
|
||||
return false;
|
||||
} else if (args[0].isUndefined() && !prior.isUndefined()) {
|
||||
// Single stepping toggled on->off.
|
||||
frame.script()->decrementStepModeCount(cx->runtime()->defaultFreeOp());
|
||||
}
|
||||
|
||||
/* Now that the step mode switch has succeeded, we can install the handler. */
|
||||
|
Loading…
Reference in New Issue
Block a user