void JSCompartment::sweepBreakpoints(FreeOp *fop) { gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_TABLES_BREAKPOINT); if (rt->debuggerList.isEmpty()) return; for (CellIterUnderGC i(zone(), FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); if (script->compartment() != this || !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->code + i); if (!site) continue; // nextbp is necessary here to avoid possibly reading *bp after // destroying it. Breakpoint *nextbp; for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); if (scriptGone || IsObjectAboutToBeFinalized(&bp->debugger->toJSObjectRef())) bp->destroy(fop); } } } }
void JSCompartment::sweepBreakpoints(JSContext *cx) { if (JS_CLIST_IS_EMPTY(&cx->runtime->debuggerList)) return; for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) { JSScript *script = i.get<JSScript>(); if (!script->hasAnyBreakpointsOrStepMode()) continue; bool scriptGone = IsAboutToBeFinalized(cx, script); for (unsigned i = 0; i < script->length; i++) { BreakpointSite *site = script->getBreakpointSite(script->code + i); if (!site) continue; // nextbp is necessary here to avoid possibly reading *bp after // destroying it. Breakpoint *nextbp; for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); if (scriptGone || IsAboutToBeFinalized(cx, bp->debugger->toJSObject())) bp->destroy(cx); } } } }
void JSCompartment::clearTraps(JSContext *cx, JSScript *script) { for (BreakpointSiteMap::Enum e(breakpointSites); !e.empty(); e.popFront()) { BreakpointSite *site = e.front().value; if (!script || site->script == script) site->clearTrap(cx, &e); } }
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JSTrapHandler handler, jsval closure) { assertSameCompartment(cx, script, closure); if (!CheckDebugMode(cx)) return false; BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc); if (!site) return false; site->setTrap(cx->runtime->defaultFreeOp(), handler, closure); return true; }
void JSCompartment::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSScript *script, JSObject *handler) { JS_ASSERT_IF(script, script->compartment() == this); for (BreakpointSiteMap::Enum e(breakpointSites); !e.empty(); e.popFront()) { BreakpointSite *site = e.front().value; if (!script || site->script == script) { Breakpoint *nextbp; for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); if ((!dbg || bp->debugger == dbg) && (!handler || bp->getHandler() == handler)) bp->destroy(cx, &e); } } } }
void JSCompartment::sweepBreakpoints(JSContext *cx) { for (BreakpointSiteMap::Enum e(breakpointSites); !e.empty(); e.popFront()) { BreakpointSite *site = e.front().value; // clearTrap and nextbp are necessary here to avoid possibly // reading *site or *bp after destroying it. bool scriptGone = IsAboutToBeFinalized(cx, site->script); bool clearTrap = scriptGone && site->hasTrap(); Breakpoint *nextbp; for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) { nextbp = bp->nextInSite(); if (scriptGone || IsAboutToBeFinalized(cx, bp->debugger->toJSObject())) bp->destroy(cx, &e); } if (clearTrap) site->clearTrap(cx, &e); } }
void JSCompartment::checkScriptMapsAfterMovingGC() { if (scriptCountsMap) { for (auto r = scriptCountsMap->all(); !r.empty(); r.popFront()) { JSScript* script = r.front().key(); CheckGCThingAfterMovingGC(script); auto ptr = scriptCountsMap->lookup(script); MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front()); } } if (scriptNameMap) { for (auto r = scriptNameMap->all(); !r.empty(); r.popFront()) { JSScript* script = r.front().key(); CheckGCThingAfterMovingGC(script); auto ptr = scriptNameMap->lookup(script); MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front()); } } if (debugScriptMap) { for (auto r = debugScriptMap->all(); !r.empty(); r.popFront()) { JSScript* script = r.front().key(); CheckGCThingAfterMovingGC(script); DebugScript* ds = r.front().value(); for (uint32_t i = 0; i < ds->numSites; i++) { BreakpointSite* site = ds->breakpoints[i]; if (site && site->type() == BreakpointSite::Type::JS) CheckGCThingAfterMovingGC(site->asJS()->script); } auto ptr = debugScriptMap->lookup(script); MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front()); } } }