Bug 956324 - Remove all breakpoints from a debugger when the last debuggee is removed r=billm

This commit is contained in:
Jon Coppeard 2014-01-11 13:52:35 +00:00
parent e41fdd7947
commit e509557b22
4 changed files with 50 additions and 1 deletions

View File

@ -154,6 +154,9 @@ CheckMarkedThing(JSTracer *trc, T *thing)
JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc) && AsGCMarker(trc)->getMarkColor() == GRAY,
!thing->zone()->isGCMarkingBlack() || rt->isAtomsZone(thing->zone()));
JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc),
!(thing->zone()->isGCSweeping() || thing->zone()->isGCFinished()));
/*
* Try to assert that the thing is allocated. This is complicated by the
* fact that allocated things may still contain the poison pattern if that

View File

@ -137,20 +137,28 @@ Zone::sweepBreakpoints(FreeOp *fop)
gcstats::AutoPhase ap1(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_TABLES);
gcstats::AutoPhase ap2(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT);
JS_ASSERT(isGCSweeping());
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
JS_ASSERT(script->zone()->isGCSweeping());
if (!script->hasAnyBreakpointsOrStepMode())
continue;
bool scriptGone = IsScriptAboutToBeFinalized(&script);
JS_ASSERT(script == i.get<JSScript>());
for (unsigned i = 0; i < script->length(); i++) {
BreakpointSite *site = script->getBreakpointSite(script->offsetToPC(i));
if (!site)
continue;
Breakpoint *nextbp;
for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
nextbp = bp->nextInSite();
if (scriptGone || IsObjectAboutToBeFinalized(&bp->debugger->toJSObjectRef()))
HeapPtrObject& dbgobj = bp->debugger->toJSObjectRef();
JS_ASSERT(dbgobj->zone()->isGCSweeping());
bool dying = scriptGone || IsObjectAboutToBeFinalized(&dbgobj);
JS_ASSERT_IF(!dying, bp->getHandler()->isMarked());
if (dying)
bp->destroy(fop);
}
}

View File

@ -0,0 +1,28 @@
var g = newGlobal();
g.eval("function f() {\n" +
" debugger;\n" +
"}\n")
var dbg = new Debugger(g);
var handler = {};
dbg.onDebuggerStatement = function (frame) {
frame.script.setBreakpoint(0, {});
};
// create breakpoint
g.f()
// drop our references to things
handler = undefined;
dbg.onDebuggerStatement = undefined;
dbg.removeAllDebuggees();
gc();
//create garbage to trigger a minor GC
var x;
for (var i = 0; i < 100; ++i)
x = {};
gc();

View File

@ -342,6 +342,7 @@ BreakpointSite::hasBreakpoint(Breakpoint *bp)
Breakpoint::Breakpoint(Debugger *debugger, BreakpointSite *site, JSObject *handler)
: debugger(debugger), site(site), handler(handler)
{
JS_ASSERT(handler->compartment() == debugger->object->compartment());
JS_APPEND_LINK(&debuggerLinks, &debugger->breakpoints);
JS_APPEND_LINK(&siteLinks, &site->breakpoints);
}
@ -2304,6 +2305,15 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
else
debuggees.remove(global);
/* Remove all breakpoints for the debuggee. */
Breakpoint *nextbp;
for (Breakpoint *bp = firstBreakpoint(); bp; bp = nextbp) {
nextbp = bp->nextInDebugger();
if (bp->site->script->compartment() == global->compartment())
bp->destroy(fop);
}
JS_ASSERT_IF(debuggees.empty(), !firstBreakpoint());
/*
* The debuggee needs to be removed from the compartment last, as this can
* trigger GCs if the compartment's debug mode is being changed, and the