mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-14 22:13:31 +00:00
Backed out 7 changesets (bug 935228, bug 936143, bug 935470, bug 933882, bug 934799) for breaking ASAN browser-chrome tests on a CLOSED TREE
Backed out changeset ae6f2151610f (bug 934799) Backed out changeset 82495f0c5da2 (bug 934799) Backed out changeset 77be849d81e7 (bug 935228) Backed out changeset 555e5759fe5f (bug 935470) Backed out changeset ce4011f33422 (bug 933882) Backed out changeset e13e98eab890 (bug 936143) Backed out changeset fb230c191a88 (bug 936143)
This commit is contained in:
parent
cf2c6961bf
commit
d034f915c0
@ -25,6 +25,7 @@ namespace JS {
|
||||
D(TOO_MUCH_MALLOC) \
|
||||
D(ALLOC_TRIGGER) \
|
||||
D(DEBUG_GC) \
|
||||
D(DEBUG_MODE_GC) \
|
||||
D(TRANSPLANT) \
|
||||
D(RESET) \
|
||||
D(OUT_OF_NURSERY) \
|
||||
|
@ -142,8 +142,7 @@ CanLazilyParse(ExclusiveContext *cx, const ReadOnlyCompileOptions &options)
|
||||
return options.canLazilyParse &&
|
||||
options.compileAndGo &&
|
||||
options.sourcePolicy == CompileOptions::SAVE_SOURCE &&
|
||||
!(cx->compartment()->debugMode() &&
|
||||
cx->compartment()->runtimeFromAnyThread()->debugHooks.newScriptHook);
|
||||
!cx->compartment()->debugMode();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1757,9 +1757,7 @@ BytecodeEmitter::tellDebuggerAboutCompiledScript(ExclusiveContext *cx)
|
||||
|
||||
RootedFunction function(cx, script->function());
|
||||
CallNewScriptHook(cx->asJSContext(), script, function);
|
||||
// Lazy scripts are never top level (despite always being invoked with a
|
||||
// nullptr parent), and so the hook should never be fired.
|
||||
if (emitterMode != LazyFunction && !parent) {
|
||||
if (!parent) {
|
||||
GlobalObject *compileAndGoGlobal = nullptr;
|
||||
if (script->compileAndGo)
|
||||
compileAndGoGlobal = &script->global();
|
||||
|
@ -2121,9 +2121,6 @@ Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
|
||||
// Advance this parser over tokens processed by the syntax parser.
|
||||
parser->tokenStream.tell(&position);
|
||||
tokenStream.seek(position, parser->tokenStream);
|
||||
|
||||
// Update the end position of the parse node.
|
||||
pn->pn_pos.end = tokenStream.currentToken().pos.end;
|
||||
}
|
||||
|
||||
if (!addFreeVariablesFromLazyFunction(fun, pc))
|
||||
|
@ -1,22 +0,0 @@
|
||||
// Lazy scripts should correctly report line offsets
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger();
|
||||
|
||||
g.eval("// Header comment\n" + // <- line 6 in this file
|
||||
"\n" +
|
||||
"\n" +
|
||||
"function f(n) {\n" + // <- line 9 in this file
|
||||
" var foo = '!';\n" +
|
||||
"}");
|
||||
|
||||
dbg.addDebuggee(g);
|
||||
var scripts = dbg.findScripts();
|
||||
var found = false;
|
||||
for (var i = 0; i < scripts.length; i++) {
|
||||
found = found || scripts[i].startLine == 6;
|
||||
// Nothing should have offsets for the deffun on line 9 if lazy scripts
|
||||
// correctly update the position.
|
||||
assertEq(scripts[i].getLineOffsets(9).length, 0);
|
||||
}
|
||||
assertEq(found, true);
|
@ -8,11 +8,9 @@ dbg.onDebuggerStatement = function (frame) {
|
||||
assertEq(typeof frame.script.url, 'string');
|
||||
};
|
||||
|
||||
function test(f, manualCount) {
|
||||
function test(f) {
|
||||
start = count = g.first = g.last = undefined;
|
||||
f();
|
||||
if (manualCount)
|
||||
g.last = g.first + manualCount - 1;
|
||||
assertEq(start, g.first);
|
||||
assertEq(count, g.last + 1 - g.first);
|
||||
print(start, count);
|
||||
@ -43,19 +41,3 @@ g.eval("function f2() {\n" +
|
||||
"}\n");
|
||||
test(g.f2);
|
||||
test(g.f2);
|
||||
|
||||
// Having a last = Error().lineNumber forces a setline srcnote, so test a
|
||||
// function that ends with newline srcnotes.
|
||||
g.eval("/* Any copyright is dedicated to the Public Domain.\n" +
|
||||
" http://creativecommons.org/publicdomain/zero/1.0/ */\n" +
|
||||
"\n" +
|
||||
"function secondCall() { first = Error().lineNumber;\n" +
|
||||
" debugger;\n" +
|
||||
" // Comment\n" +
|
||||
" eval(\"42;\");\n" +
|
||||
" function foo() {}\n" +
|
||||
" if (true) {\n" +
|
||||
" foo();\n" + // <- this is +6 and must be within the extent
|
||||
" }\n" +
|
||||
"}");
|
||||
test(g.secondCall, 7);
|
||||
|
@ -251,9 +251,6 @@ BaselineCompiler::compile()
|
||||
bytecodeMap[script->nTypeSets] = 0;
|
||||
}
|
||||
|
||||
if (script->compartment()->debugMode())
|
||||
baselineScript->setDebugMode();
|
||||
|
||||
return Method_Compiled;
|
||||
}
|
||||
|
||||
|
@ -746,10 +746,6 @@ BaselineScript::toggleDebugTraps(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(script->baselineScript() == this);
|
||||
|
||||
// Only scripts compiled for debug mode have toggled calls.
|
||||
if (!debugMode())
|
||||
return;
|
||||
|
||||
SrcNoteLineScanner scanner(script->notes(), script->lineno);
|
||||
|
||||
JSRuntime *rt = script->runtimeFromMainThread();
|
||||
|
@ -132,11 +132,7 @@ struct BaselineScript
|
||||
|
||||
// Flag set when the script contains any writes to its on-stack
|
||||
// (rather than call object stored) arguments.
|
||||
MODIFIES_ARGUMENTS = 1 << 2,
|
||||
|
||||
// Flag set when compiled for use for debug mode. Handles various
|
||||
// Debugger hooks and compiles toggled calls for traps.
|
||||
DEBUG_MODE = 1 << 3
|
||||
MODIFIES_ARGUMENTS = 1 << 2
|
||||
};
|
||||
|
||||
private:
|
||||
@ -205,13 +201,6 @@ struct BaselineScript
|
||||
return flags_ & MODIFIES_ARGUMENTS;
|
||||
}
|
||||
|
||||
void setDebugMode() {
|
||||
flags_ |= DEBUG_MODE;
|
||||
}
|
||||
bool debugMode() const {
|
||||
return flags_ & DEBUG_MODE;
|
||||
}
|
||||
|
||||
uint32_t prologueOffset() const {
|
||||
return prologueOffset_;
|
||||
}
|
||||
|
@ -2354,20 +2354,15 @@ InvalidateActivation(FreeOp *fop, uint8_t *ionTop, bool invalidateAll)
|
||||
IonSpew(IonSpew_Invalidate, "END invalidating activation");
|
||||
}
|
||||
|
||||
static inline void
|
||||
StopOffThreadCompilation(JSCompartment *comp)
|
||||
{
|
||||
if (comp->jitCompartment()) {
|
||||
CancelOffThreadIonCompile(comp, nullptr);
|
||||
FinishAllOffThreadCompilations(comp->jitCompartment());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
jit::InvalidateAll(FreeOp *fop, Zone *zone)
|
||||
{
|
||||
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
|
||||
StopOffThreadCompilation(comp);
|
||||
for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
|
||||
if (!comp->jitCompartment())
|
||||
continue;
|
||||
CancelOffThreadIonCompile(comp, nullptr);
|
||||
FinishAllOffThreadCompilations(comp->jitCompartment());
|
||||
}
|
||||
|
||||
for (JitActivationIterator iter(fop->runtime()); !iter.done(); ++iter) {
|
||||
if (iter.activation()->compartment()->zone() == zone) {
|
||||
@ -2714,56 +2709,3 @@ jit::TraceIonScripts(JSTracer* trc, JSScript *script)
|
||||
if (script->hasBaselineScript())
|
||||
jit::BaselineScript::Trace(trc, script->baselineScript());
|
||||
}
|
||||
|
||||
AutoDebugModeInvalidation::~AutoDebugModeInvalidation()
|
||||
{
|
||||
MOZ_ASSERT(!!comp_ != !!zone_);
|
||||
|
||||
if (needInvalidation_ == NoNeed)
|
||||
return;
|
||||
|
||||
// Invalidate the stack if any compartments toggled from on->off, because
|
||||
// we allow scripts to be on stack when turning off debug mode.
|
||||
bool invalidateStack = needInvalidation_ == ToggledOff;
|
||||
Zone *zone = zone_ ? zone_ : comp_->zone();
|
||||
JSRuntime *rt = zone->runtimeFromMainThread();
|
||||
FreeOp *fop = rt->defaultFreeOp();
|
||||
|
||||
if (comp_) {
|
||||
StopOffThreadCompilation(comp_);
|
||||
} else {
|
||||
for (CompartmentsInZoneIter comp(zone_); !comp.done(); comp.next())
|
||||
StopOffThreadCompilation(comp);
|
||||
}
|
||||
|
||||
if (invalidateStack) {
|
||||
jit::MarkActiveBaselineScripts(zone);
|
||||
|
||||
for (JitActivationIterator iter(rt); !iter.done(); ++iter) {
|
||||
JSCompartment *comp = iter.activation()->compartment();
|
||||
if ((comp_ && comp_ == comp) ||
|
||||
(zone_ && zone_ == comp->zone() && comp->principals))
|
||||
{
|
||||
IonContext ictx(rt);
|
||||
AutoFlushCache afc("AutoDebugModeInvalidation", rt->jitRuntime());
|
||||
IonSpew(IonSpew_Invalidate, "Invalidating frames for debug mode toggle");
|
||||
InvalidateActivation(fop, iter.jitTop(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (gc::CellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
if ((comp_ && script->compartment() == comp_) ||
|
||||
(zone_ && script->compartment()->principals))
|
||||
{
|
||||
FinishInvalidation(fop, script);
|
||||
FinishDiscardBaselineScript(fop, script);
|
||||
script->clearAnalysis();
|
||||
script->resetUseCount();
|
||||
} else {
|
||||
if (script->hasBaselineScript())
|
||||
script->baselineScript()->resetActive();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,20 +673,20 @@ CreateLazyScriptsForCompartment(JSContext *cx)
|
||||
{
|
||||
AutoObjectVector lazyFunctions(cx);
|
||||
|
||||
// Find all live lazy scripts in the compartment, and via them all root
|
||||
// lazy functions in the compartment: those which have not been compiled
|
||||
// and which have a source object, indicating that their parent has been
|
||||
// compiled.
|
||||
for (gc::CellIter i(cx->zone(), gc::FINALIZE_LAZY_SCRIPT); !i.done(); i.next()) {
|
||||
LazyScript *lazy = i.get<LazyScript>();
|
||||
JSFunction *fun = lazy->function();
|
||||
if (fun->compartment() == cx->compartment() &&
|
||||
lazy->sourceObject() && !lazy->maybeScript())
|
||||
{
|
||||
MOZ_ASSERT(fun->isInterpretedLazy());
|
||||
MOZ_ASSERT(lazy == fun->lazyScriptOrNull());
|
||||
if (!lazyFunctions.append(fun))
|
||||
return false;
|
||||
// Find all root lazy functions in the compartment: those which have not been
|
||||
// compiled and which have a source object, indicating that their parent has
|
||||
// been compiled.
|
||||
for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
|
||||
JSObject *obj = i.get<JSObject>();
|
||||
if (obj->compartment() == cx->compartment() && obj->is<JSFunction>()) {
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
if (fun->isInterpretedLazy()) {
|
||||
LazyScript *lazy = fun->lazyScriptOrNull();
|
||||
if (lazy && lazy->sourceObject() && !lazy->maybeScript()) {
|
||||
if (!lazyFunctions.append(fun))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,24 +708,27 @@ CreateLazyScriptsForCompartment(JSContext *cx)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Repoint any clones of the original functions to their new script.
|
||||
for (gc::CellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
|
||||
JSObject *obj = i.get<JSObject>();
|
||||
if (obj->compartment() == cx->compartment() && obj->is<JSFunction>()) {
|
||||
JSFunction *fun = &obj->as<JSFunction>();
|
||||
if (fun->isInterpretedLazy()) {
|
||||
LazyScript *lazy = fun->lazyScriptOrNull();
|
||||
if (lazy && lazy->maybeScript())
|
||||
fun->existingScript();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::ensureDelazifyScriptsForDebugMode(JSContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(cx->compartment() == this);
|
||||
if ((debugModeBits & DebugNeedDelazification) && !CreateLazyScriptsForCompartment(cx))
|
||||
return false;
|
||||
debugModeBits &= ~DebugNeedDelazification;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeInvalidation &invalidate)
|
||||
JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeGC &dmgc)
|
||||
{
|
||||
bool enabledBefore = debugMode();
|
||||
bool enabledAfter = (debugModeBits & DebugModeFromMask & ~DebugFromC) || b;
|
||||
bool enabledAfter = (debugModeBits & ~unsigned(DebugFromC)) || b;
|
||||
|
||||
// Debug mode can be enabled only when no scripts from the target
|
||||
// compartment are on the stack. It would even be incorrect to discard just
|
||||
@ -744,12 +747,14 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeInvalidatio
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_IDLE);
|
||||
return false;
|
||||
}
|
||||
if (enabledAfter && !CreateLazyScriptsForCompartment(cx))
|
||||
return false;
|
||||
}
|
||||
|
||||
debugModeBits = (debugModeBits & ~DebugFromC) | (b ? DebugFromC : 0);
|
||||
debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0);
|
||||
JS_ASSERT(debugMode() == enabledAfter);
|
||||
if (enabledBefore != enabledAfter) {
|
||||
updateForDebugMode(cx->runtime()->defaultFreeOp(), invalidate);
|
||||
updateForDebugMode(cx->runtime()->defaultFreeOp(), dmgc);
|
||||
if (!enabledAfter)
|
||||
DebugScopes::onCompartmentLeaveDebugMode(this);
|
||||
}
|
||||
@ -757,7 +762,7 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeInvalidatio
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeInvalidation &invalidate)
|
||||
JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeGC &dmgc)
|
||||
{
|
||||
JSRuntime *rt = runtimeFromMainThread();
|
||||
|
||||
@ -767,42 +772,52 @@ JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeInvalidation &invali
|
||||
}
|
||||
|
||||
#ifdef JS_ION
|
||||
MOZ_ASSERT(invalidate.isFor(this));
|
||||
JS_ASSERT_IF(debugMode(), !hasScriptsOnStack());
|
||||
|
||||
// Invalidate all JIT code since debug mode invalidates assumptions made
|
||||
// by the JIT.
|
||||
// When we change a compartment's debug mode, whether we're turning it
|
||||
// on or off, we must always throw away all analyses: debug mode
|
||||
// affects various aspects of the analysis, which then get baked into
|
||||
// SSA results, which affects code generation in complicated ways. We
|
||||
// must also throw away all JIT code, as its soundness depends on the
|
||||
// analyses.
|
||||
//
|
||||
// The AutoDebugModeInvalidation argument makes sure we can't forget to
|
||||
// invalidate, but it is also important not to run any scripts in this
|
||||
// compartment until the invalidate is destroyed. That is the caller's
|
||||
// responsibility.
|
||||
invalidate.scheduleInvalidation(debugMode());
|
||||
// It suffices to do a garbage collection cycle or to finish the
|
||||
// ongoing GC cycle. The necessary cleanup happens in
|
||||
// JSCompartment::sweep.
|
||||
//
|
||||
// dmgc makes sure we can't forget to GC, but it is also important not
|
||||
// to run any scripts in this compartment until the dmgc is destroyed.
|
||||
// That is the caller's responsibility.
|
||||
if (!rt->isHeapBusy())
|
||||
dmgc.scheduleGC(zone());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(this);
|
||||
return addDebuggee(cx, global, invalidate);
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
return addDebuggee(cx, global, dmgc);
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::addDebuggee(JSContext *cx,
|
||||
GlobalObject *globalArg,
|
||||
AutoDebugModeInvalidation &invalidate)
|
||||
AutoDebugModeGC &dmgc)
|
||||
{
|
||||
Rooted<GlobalObject*> global(cx, globalArg);
|
||||
|
||||
bool wasEnabled = debugMode();
|
||||
if (!wasEnabled && !CreateLazyScriptsForCompartment(cx))
|
||||
return false;
|
||||
if (!debuggees.put(global)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
debugModeBits |= DebugFromJS;
|
||||
if (!wasEnabled)
|
||||
updateForDebugMode(cx->runtime()->defaultFreeOp(), invalidate);
|
||||
if (!wasEnabled) {
|
||||
updateForDebugMode(cx->runtime()->defaultFreeOp(), dmgc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -811,14 +826,14 @@ JSCompartment::removeDebuggee(FreeOp *fop,
|
||||
js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(this);
|
||||
return removeDebuggee(fop, global, invalidate, debuggeesEnum);
|
||||
AutoDebugModeGC dmgc(fop->runtime());
|
||||
return removeDebuggee(fop, global, dmgc, debuggeesEnum);
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::removeDebuggee(FreeOp *fop,
|
||||
js::GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
AutoDebugModeGC &dmgc,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
{
|
||||
bool wasEnabled = debugMode();
|
||||
@ -832,7 +847,7 @@ JSCompartment::removeDebuggee(FreeOp *fop,
|
||||
debugModeBits &= ~DebugFromJS;
|
||||
if (wasEnabled && !debugMode()) {
|
||||
DebugScopes::onCompartmentLeaveDebugMode(this);
|
||||
updateForDebugMode(fop, invalidate);
|
||||
updateForDebugMode(fop, dmgc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ struct TypeInferenceSizes;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
class AutoDebugModeInvalidation;
|
||||
class AutoDebugModeGC;
|
||||
class ArrayBufferObject;
|
||||
class DebugScopes;
|
||||
class WeakMapBase;
|
||||
@ -278,13 +278,7 @@ struct JSCompartment
|
||||
js::WeakMapBase *gcWeakMapList;
|
||||
|
||||
private:
|
||||
enum {
|
||||
DebugFromC = 1 << 0,
|
||||
DebugFromJS = 1 << 1,
|
||||
DebugNeedDelazification = 1 << 2
|
||||
};
|
||||
|
||||
static const unsigned DebugModeFromMask = DebugFromC | DebugFromJS;
|
||||
enum { DebugFromC = 1, DebugFromJS = 2 };
|
||||
|
||||
unsigned debugModeBits; // see debugMode() below
|
||||
|
||||
@ -362,49 +356,27 @@ struct JSCompartment
|
||||
* by Debugger objects. Therefore debugModeBits has the DebugFromC bit set
|
||||
* if the C API wants debug mode and the DebugFromJS bit set if debuggees
|
||||
* is non-empty.
|
||||
*
|
||||
* When toggling on, DebugNeedDelazification is set to signal that
|
||||
* Debugger methods which depend on seeing all scripts (like findScripts)
|
||||
* need to delazify the scripts in the compartment first.
|
||||
*/
|
||||
bool debugMode() const {
|
||||
return !!(debugModeBits & DebugModeFromMask);
|
||||
}
|
||||
bool debugMode() const { return !!debugModeBits; }
|
||||
|
||||
/* True if any scripts from this compartment are on the JS stack. */
|
||||
bool hasScriptsOnStack();
|
||||
|
||||
/*
|
||||
* Schedule the compartment to be delazified. Called from
|
||||
* LazyScript::Create.
|
||||
*/
|
||||
void scheduleDelazificationForDebugMode() {
|
||||
debugModeBits |= DebugNeedDelazification;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we scheduled delazification for turning on debug mode, delazify all
|
||||
* scripts.
|
||||
*/
|
||||
bool ensureDelazifyScriptsForDebugMode(JSContext *cx);
|
||||
|
||||
private:
|
||||
|
||||
/* This is called only when debugMode() has just toggled. */
|
||||
void updateForDebugMode(js::FreeOp *fop, js::AutoDebugModeInvalidation &invalidate);
|
||||
void updateForDebugMode(js::FreeOp *fop, js::AutoDebugModeGC &dmgc);
|
||||
|
||||
public:
|
||||
js::GlobalObjectSet &getDebuggees() { return debuggees; }
|
||||
bool addDebuggee(JSContext *cx, js::GlobalObject *global);
|
||||
bool addDebuggee(JSContext *cx, js::GlobalObject *global,
|
||||
js::AutoDebugModeInvalidation &invalidate);
|
||||
js::AutoDebugModeGC &dmgc);
|
||||
void removeDebuggee(js::FreeOp *fop, js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
void removeDebuggee(js::FreeOp *fop, js::GlobalObject *global,
|
||||
js::AutoDebugModeInvalidation &invalidate,
|
||||
js::AutoDebugModeGC &dmgc,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
bool setDebugModeFromC(JSContext *cx, bool b,
|
||||
js::AutoDebugModeInvalidation &invalidate);
|
||||
bool setDebugModeFromC(JSContext *cx, bool b, js::AutoDebugModeGC &dmgc);
|
||||
|
||||
void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JSObject *handler);
|
||||
void clearTraps(js::FreeOp *fop);
|
||||
@ -450,56 +422,29 @@ JSRuntime::isAtomsZone(JS::Zone *zone)
|
||||
}
|
||||
|
||||
// For use when changing the debug mode flag on one or more compartments.
|
||||
// Invalidate and discard JIT code since debug mode breaks JIT assumptions.
|
||||
// Do not run scripts in any compartment that is scheduled for GC using this
|
||||
// object. See comment in updateForDebugMode.
|
||||
//
|
||||
// AutoDebugModeInvalidation has two modes: compartment or zone
|
||||
// invalidation. While it is correct to always use compartment invalidation,
|
||||
// if you know ahead of time you need to invalidate a whole zone, it is faster
|
||||
// to invalidate the zone.
|
||||
//
|
||||
// Compartment invalidation only invalidates scripts belonging to that
|
||||
// compartment.
|
||||
//
|
||||
// Zone invalidation invalidates all scripts belonging to non-special
|
||||
// (i.e. those with principals) compartments of the zone.
|
||||
//
|
||||
// FIXME: Remove entirely once bug 716647 lands.
|
||||
//
|
||||
class js::AutoDebugModeInvalidation
|
||||
class js::AutoDebugModeGC
|
||||
{
|
||||
JSCompartment *comp_;
|
||||
JS::Zone *zone_;
|
||||
|
||||
enum {
|
||||
NoNeed = 0,
|
||||
ToggledOn = 1,
|
||||
ToggledOff = 2
|
||||
} needInvalidation_;
|
||||
|
||||
JSRuntime *rt;
|
||||
bool needGC;
|
||||
public:
|
||||
explicit AutoDebugModeInvalidation(JSCompartment *comp)
|
||||
: comp_(comp), zone_(nullptr), needInvalidation_(NoNeed)
|
||||
{ }
|
||||
explicit AutoDebugModeGC(JSRuntime *rt) : rt(rt), needGC(false) {}
|
||||
|
||||
explicit AutoDebugModeInvalidation(JS::Zone *zone)
|
||||
: comp_(nullptr), zone_(zone), needInvalidation_(NoNeed)
|
||||
{ }
|
||||
|
||||
~AutoDebugModeInvalidation();
|
||||
|
||||
bool isFor(JSCompartment *comp) {
|
||||
if (comp_)
|
||||
return comp == comp_;
|
||||
return comp->zone() == zone_;
|
||||
~AutoDebugModeGC() {
|
||||
// Under some circumstances (say, in the midst of an animation),
|
||||
// the garbage collector may try to retain JIT code and analyses.
|
||||
// The DEBUG_MODE_GC reason forces the collector to always throw
|
||||
// everything away, as required for debug mode transitions.
|
||||
if (needGC)
|
||||
GC(rt, GC_NORMAL, JS::gcreason::DEBUG_MODE_GC);
|
||||
}
|
||||
|
||||
void scheduleInvalidation(bool debugMode) {
|
||||
// If we are scheduling invalidation for multiple compartments, they
|
||||
// must all agree on the toggle. This is so we can decide if we need
|
||||
// to invalidate on-stack scripts.
|
||||
MOZ_ASSERT_IF(needInvalidation_ != NoNeed,
|
||||
needInvalidation_ == debugMode ? ToggledOn : ToggledOff);
|
||||
needInvalidation_ = debugMode ? ToggledOn : ToggledOff;
|
||||
void scheduleGC(Zone *zone) {
|
||||
JS_ASSERT(!rt->isHeapBusy());
|
||||
PrepareZoneForGC(zone);
|
||||
needGC = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4620,8 +4620,13 @@ ShouldCleanUpEverything(JSRuntime *rt, JS::gcreason::Reason reason, JSGCInvocati
|
||||
// During shutdown, we must clean everything up, for the sake of leak
|
||||
// detection. When a runtime has no contexts, or we're doing a GC before a
|
||||
// shutdown CC, those are strong indications that we're shutting down.
|
||||
//
|
||||
// DEBUG_MODE_GC indicates we're discarding code because the debug mode
|
||||
// has changed; debug mode affects the results of bytecode analysis, so
|
||||
// we need to clear everything away.
|
||||
return reason == JS::gcreason::DESTROY_RUNTIME ||
|
||||
reason == JS::gcreason::SHUTDOWN_CC ||
|
||||
reason == JS::gcreason::DEBUG_MODE_GC ||
|
||||
gckind == GC_SHRINK;
|
||||
}
|
||||
|
||||
|
@ -2204,19 +2204,29 @@ JS_FRIEND_API(unsigned)
|
||||
js_GetScriptLineExtent(JSScript *script)
|
||||
{
|
||||
unsigned lineno = script->lineno;
|
||||
unsigned maxLineNo = lineno;
|
||||
unsigned maxLineNo = 0;
|
||||
bool counting = true;
|
||||
for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
|
||||
SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
|
||||
if (type == SRC_SETLINE)
|
||||
if (type == SRC_SETLINE) {
|
||||
if (maxLineNo < lineno)
|
||||
maxLineNo = lineno;
|
||||
lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
|
||||
else if (type == SRC_NEWLINE)
|
||||
lineno++;
|
||||
|
||||
if (maxLineNo < lineno)
|
||||
maxLineNo = lineno;
|
||||
counting = true;
|
||||
if (maxLineNo < lineno)
|
||||
maxLineNo = lineno;
|
||||
else
|
||||
counting = false;
|
||||
} else if (type == SRC_NEWLINE) {
|
||||
if (counting)
|
||||
lineno++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1 + maxLineNo - script->lineno;
|
||||
if (maxLineNo > lineno)
|
||||
lineno = maxLineNo;
|
||||
|
||||
return 1 + lineno - script->lineno;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2994,8 +3004,6 @@ LazyScript::Create(ExclusiveContext *cx, HandleFunction fun,
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
cx->compartment()->scheduleDelazificationForDebugMode();
|
||||
|
||||
return new (res) LazyScript(fun, table, numFreeVariables, numInnerFunctions, version,
|
||||
begin, end, lineno, column);
|
||||
}
|
||||
|
@ -97,25 +97,6 @@ ReportMoreArgsNeeded(JSContext *cx, const char *name, unsigned required)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
EnsureFunctionHasScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
if (fun->isInterpretedLazy()) {
|
||||
AutoCompartment ac(cx, fun);
|
||||
return !!fun->getOrCreateScript(cx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline JSScript *
|
||||
GetOrCreateFunctionScript(JSContext *cx, JSFunction *fun)
|
||||
{
|
||||
MOZ_ASSERT(fun->isInterpreted());
|
||||
if (!EnsureFunctionHasScript(cx, fun))
|
||||
return nullptr;
|
||||
return fun->nonLazyScript();
|
||||
}
|
||||
|
||||
#define REQUIRE_ARGC(name, n) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (argc < (n)) \
|
||||
@ -705,9 +686,6 @@ Debugger::wrapDebuggeeValue(JSContext *cx, MutableHandleValue vp)
|
||||
if (vp.isObject()) {
|
||||
RootedObject obj(cx, &vp.toObject());
|
||||
|
||||
if (obj->is<JSFunction>() && !EnsureFunctionHasScript(cx, &obj->as<JSFunction>()))
|
||||
return false;
|
||||
|
||||
ObjectWeakMap::AddPtr p = objects.lookupForAdd(obj);
|
||||
if (p) {
|
||||
vp.setObject(*p->value);
|
||||
@ -1145,8 +1123,6 @@ Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *
|
||||
JSTrapStatus
|
||||
Debugger::onTrap(JSContext *cx, MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(cx->compartment()->debugMode());
|
||||
|
||||
ScriptFrameIter iter(cx);
|
||||
RootedScript script(cx, iter.script());
|
||||
Rooted<GlobalObject*> scriptGlobal(cx, &script->global());
|
||||
@ -1973,20 +1949,16 @@ bool
|
||||
Debugger::addAllGlobalsAsDebuggees(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_DEBUGGER(cx, argc, vp, "addAllGlobalsAsDebuggees", args, dbg);
|
||||
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
// Invalidate a zone at a time to avoid doing a zone-wide CellIter
|
||||
// per compartment.
|
||||
AutoDebugModeInvalidation invalidate(zone);
|
||||
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
|
||||
if (c == dbg->object->compartment() || c->options().invisibleToDebugger())
|
||||
continue;
|
||||
c->zone()->scheduledForDestruction = false;
|
||||
GlobalObject *global = c->maybeGlobal();
|
||||
if (global) {
|
||||
Rooted<GlobalObject*> rg(cx, global);
|
||||
if (!dbg->addDebuggeeGlobal(cx, rg, invalidate))
|
||||
return false;
|
||||
}
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
|
||||
if (c == dbg->object->compartment() || c->options().invisibleToDebugger())
|
||||
continue;
|
||||
c->zone()->scheduledForDestruction = false;
|
||||
GlobalObject *global = c->maybeGlobal();
|
||||
if (global) {
|
||||
Rooted<GlobalObject*> rg(cx, global);
|
||||
if (!dbg->addDebuggeeGlobal(cx, rg, dmgc))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2012,9 +1984,9 @@ bool
|
||||
Debugger::removeAllDebuggees(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
THIS_DEBUGGER(cx, argc, vp, "removeAllDebuggees", args, dbg);
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront())
|
||||
dbg->removeDebuggeeGlobal(cx->runtime()->defaultFreeOp(), e.front(), nullptr, &e);
|
||||
|
||||
dbg->removeDebuggeeGlobal(cx->runtime()->defaultFreeOp(), e.front(), dmgc, nullptr, &e);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
@ -2145,14 +2117,14 @@ Debugger::construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
bool
|
||||
Debugger::addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> global)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(global->compartment());
|
||||
return addDebuggeeGlobal(cx, global, invalidate);
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
return addDebuggeeGlobal(cx, global, dmgc);
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::addDebuggeeGlobal(JSContext *cx,
|
||||
Handle<GlobalObject*> global,
|
||||
AutoDebugModeInvalidation &invalidate)
|
||||
AutoDebugModeGC &dmgc)
|
||||
{
|
||||
if (debuggees.has(global))
|
||||
return true;
|
||||
@ -2218,7 +2190,7 @@ Debugger::addDebuggeeGlobal(JSContext *cx,
|
||||
} else {
|
||||
if (global->getDebuggers()->length() > 1)
|
||||
return true;
|
||||
if (debuggeeCompartment->addDebuggee(cx, global, invalidate))
|
||||
if (debuggeeCompartment->addDebuggee(cx, global, dmgc))
|
||||
return true;
|
||||
|
||||
/* Maintain consistency on error. */
|
||||
@ -2235,13 +2207,13 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(global->compartment());
|
||||
return removeDebuggeeGlobal(fop, global, invalidate, compartmentEnum, debugEnum);
|
||||
AutoDebugModeGC dmgc(fop->runtime());
|
||||
return removeDebuggeeGlobal(fop, global, dmgc, compartmentEnum, debugEnum);
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
AutoDebugModeGC &dmgc,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
@ -2297,7 +2269,7 @@ Debugger::removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
* global cannot be rooted on the stack without a cx.
|
||||
*/
|
||||
if (v->empty())
|
||||
global->compartment()->removeDebuggee(fop, global, invalidate, compartmentEnum);
|
||||
global->compartment()->removeDebuggee(fop, global, dmgc, compartmentEnum);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2425,14 +2397,10 @@ class Debugger::ScriptQuery {
|
||||
if (!prepareQuery())
|
||||
return false;
|
||||
|
||||
JSCompartment *singletonComp = nullptr;
|
||||
if (compartments.count() == 1)
|
||||
singletonComp = compartments.all().front();
|
||||
|
||||
/* Search each compartment for debuggee scripts. */
|
||||
vector = v;
|
||||
oom = false;
|
||||
IterateScripts(cx->runtime(), singletonComp, this, considerScript);
|
||||
IterateScripts(cx->runtime(), nullptr, this, considerScript);
|
||||
if (oom) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -2502,21 +2470,10 @@ class Debugger::ScriptQuery {
|
||||
/* Indicates whether OOM has occurred while matching. */
|
||||
bool oom;
|
||||
|
||||
bool addCompartment(JSCompartment *comp) {
|
||||
{
|
||||
// All scripts in the debuggee compartment must be visible, so
|
||||
// delazify everything.
|
||||
AutoCompartment ac(cx, comp);
|
||||
if (!comp->ensureDelazifyScriptsForDebugMode(cx))
|
||||
return false;
|
||||
}
|
||||
return compartments.put(comp);
|
||||
}
|
||||
|
||||
/* Arrange for this ScriptQuery to match only scripts that run in |global|. */
|
||||
bool matchSingleGlobal(GlobalObject *global) {
|
||||
JS_ASSERT(compartments.count() == 0);
|
||||
if (!addCompartment(global->compartment())) {
|
||||
if (!compartments.put(global->compartment())) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
@ -2531,7 +2488,7 @@ class Debugger::ScriptQuery {
|
||||
JS_ASSERT(compartments.count() == 0);
|
||||
/* Build our compartment set from the debugger's set of debuggee globals. */
|
||||
for (GlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
|
||||
if (!addCompartment(r.front()->compartment())) {
|
||||
if (!compartments.put(r.front()->compartment())) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
@ -2974,10 +2931,8 @@ DebuggerScript_getChildScripts(JSContext *cx, unsigned argc, Value *vp)
|
||||
for (uint32_t i = script->innerObjectsStart(); i < objects->length; i++) {
|
||||
obj = objects->vector[i];
|
||||
if (obj->is<JSFunction>()) {
|
||||
fun = &obj->as<JSFunction>();
|
||||
funScript = GetOrCreateFunctionScript(cx, fun);
|
||||
if (!funScript)
|
||||
return false;
|
||||
fun = static_cast<JSFunction *>(obj.get());
|
||||
funScript = fun->nonLazyScript();
|
||||
s = dbg->wrapScript(cx, funScript);
|
||||
if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
|
||||
return false;
|
||||
@ -4698,9 +4653,14 @@ DebuggerObject_getParameterNames(JSContext *cx, unsigned argc, Value *vp)
|
||||
result->ensureDenseInitializedLength(cx, 0, fun->nargs);
|
||||
|
||||
if (fun->isInterpreted()) {
|
||||
RootedScript script(cx, GetOrCreateFunctionScript(cx, fun));
|
||||
if (!script)
|
||||
return false;
|
||||
RootedScript script(cx);
|
||||
|
||||
{
|
||||
AutoCompartment ac(cx, fun);
|
||||
script = fun->getOrCreateScript(cx);
|
||||
if (!script)
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(fun->nargs == script->bindings.numArgs());
|
||||
|
||||
@ -4742,9 +4702,15 @@ DebuggerObject_getScript(JSContext *cx, unsigned argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedScript script(cx, GetOrCreateFunctionScript(cx, fun));
|
||||
if (!script)
|
||||
return false;
|
||||
RootedScript script(cx);
|
||||
|
||||
{
|
||||
AutoCompartment ac(cx, obj);
|
||||
|
||||
script = fun->getOrCreateScript(cx);
|
||||
if (!script)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Only hand out debuggee scripts. */
|
||||
if (!dbg->observesScript(script)) {
|
||||
|
@ -230,12 +230,12 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
|
||||
bool addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> obj);
|
||||
bool addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> obj,
|
||||
AutoDebugModeInvalidation &invalidate);
|
||||
AutoDebugModeGC &dmgc);
|
||||
void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
AutoDebugModeGC &dmgc,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
|
||||
|
@ -1412,55 +1412,52 @@ CASE(EnableInterruptsPseudoOpcode)
|
||||
moreInterrupts = true;
|
||||
}
|
||||
|
||||
if (cx->compartment()->debugMode()) {
|
||||
JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook;
|
||||
if (hook || script->stepModeEnabled()) {
|
||||
RootedValue rval(cx);
|
||||
JSTrapStatus status = JSTRAP_CONTINUE;
|
||||
if (hook)
|
||||
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) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
break;
|
||||
case JSTRAP_RETURN:
|
||||
REGS.fp()->setReturnValue(rval);
|
||||
interpReturnOK = true;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->setPendingException(rval);
|
||||
goto error;
|
||||
default:;
|
||||
}
|
||||
moreInterrupts = true;
|
||||
JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook;
|
||||
if (hook || script->stepModeEnabled()) {
|
||||
RootedValue rval(cx);
|
||||
JSTrapStatus status = JSTRAP_CONTINUE;
|
||||
if (hook)
|
||||
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) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_CONTINUE:
|
||||
break;
|
||||
case JSTRAP_RETURN:
|
||||
REGS.fp()->setReturnValue(rval);
|
||||
interpReturnOK = true;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->setPendingException(rval);
|
||||
goto error;
|
||||
default:;
|
||||
}
|
||||
moreInterrupts = true;
|
||||
}
|
||||
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
moreInterrupts = true;
|
||||
if (script->hasAnyBreakpointsOrStepMode())
|
||||
moreInterrupts = true;
|
||||
|
||||
if (script->hasBreakpointsAt(REGS.pc)) {
|
||||
RootedValue rval(cx);
|
||||
JSTrapStatus status = Debugger::onTrap(cx, &rval);
|
||||
switch (status) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_RETURN:
|
||||
REGS.fp()->setReturnValue(rval);
|
||||
interpReturnOK = true;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->setPendingException(rval);
|
||||
goto error;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
JS_ASSERT(status == JSTRAP_CONTINUE);
|
||||
JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
|
||||
if (script->hasBreakpointsAt(REGS.pc)) {
|
||||
RootedValue rval(cx);
|
||||
JSTrapStatus status = Debugger::onTrap(cx, &rval);
|
||||
switch (status) {
|
||||
case JSTRAP_ERROR:
|
||||
goto error;
|
||||
case JSTRAP_RETURN:
|
||||
REGS.fp()->setReturnValue(rval);
|
||||
interpReturnOK = true;
|
||||
goto forced_return;
|
||||
case JSTRAP_THROW:
|
||||
cx->setPendingException(rval);
|
||||
goto error;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
JS_ASSERT(status == JSTRAP_CONTINUE);
|
||||
JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
|
||||
}
|
||||
|
||||
JS_ASSERT(activation.opMask() == EnableInterruptsPseudoOpcode);
|
||||
|
@ -170,16 +170,13 @@ js::DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc)
|
||||
JS_FRIEND_API(bool)
|
||||
JS_SetDebugModeForAllCompartments(JSContext *cx, bool debug)
|
||||
{
|
||||
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
// Invalidate a zone at a time to avoid doing a zone-wide CellIter
|
||||
// per compartment.
|
||||
AutoDebugModeInvalidation invalidate(zone);
|
||||
for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
|
||||
// Ignore special compartments (atoms, JSD compartments)
|
||||
if (c->principals) {
|
||||
if (!c->setDebugModeFromC(cx, !!debug, invalidate))
|
||||
return false;
|
||||
}
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
|
||||
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
|
||||
// Ignore special compartments (atoms, JSD compartments)
|
||||
if (c->principals) {
|
||||
if (!c->setDebugModeFromC(cx, !!debug, dmgc))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -188,8 +185,8 @@ JS_SetDebugModeForAllCompartments(JSContext *cx, bool debug)
|
||||
JS_FRIEND_API(bool)
|
||||
JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, bool debug)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(comp);
|
||||
return comp->setDebugModeFromC(cx, !!debug, invalidate);
|
||||
AutoDebugModeGC dmgc(cx->runtime());
|
||||
return comp->setDebugModeFromC(cx, !!debug, dmgc);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
Loading…
x
Reference in New Issue
Block a user