Bug 1461938 part 23 - Move debugModeBits from JSCompartment to JS::Realm. r=luke

This commit is contained in:
Jan de Mooij 2018-05-23 15:26:00 +02:00
parent eea98b6d64
commit 4975a53b6d
19 changed files with 277 additions and 285 deletions

View File

@ -164,7 +164,7 @@ mozilla::Atomic<uint64_t> gIDGenerator(0);
static MOZ_ALWAYS_INLINE bool
ShouldCaptureDebugInfo(JSContext* cx)
{
return cx->options().asyncStack() || cx->compartment()->isDebuggee();
return cx->options().asyncStack() || cx->realm()->isDebuggee();
}
class PromiseDebugInfo : public NativeObject
@ -3067,8 +3067,8 @@ IsPromiseThenOrCatchRetValImplicitlyUsed(JSContext* cx)
if (!cx->options().asyncStack())
return false;
// If devtools is opened, the current compartment will become debuggee.
if (cx->compartment()->isDebuggee())
// If devtools is opened, the current realm will become debuggee.
if (cx->realm()->isDebuggee())
return true;
// There are 2 profilers, and they can be independently enabled.

View File

@ -8014,13 +8014,13 @@ GCRuntime::mergeCompartments(JSCompartment* source, JSCompartment* target)
sourceRealm->clearTables();
source->zone()->clearTables();
source->unsetIsDebuggee();
sourceRealm->unsetIsDebuggee();
// The delazification flag indicates the presence of LazyScripts in a
// compartment for the Debugger API, so if the source compartment created
// LazyScripts, the flag must be propagated to the target compartment.
if (source->needsDelazificationForDebugger())
target->scheduleDelazificationForDebugger();
// realm for the Debugger API, so if the source realm created LazyScripts,
// the flag must be propagated to the target realm.
if (sourceRealm->needsDelazificationForDebugger())
targetRealm->scheduleDelazificationForDebugger();
// Release any relocated arenas which we may be holding on to as they might
// be in the source zone

View File

@ -986,7 +986,7 @@ InitFromBailout(JSContext* cx, size_t frameNo,
// possible nothing was pushed before we threw. We can't drop
// iterators, however, so read them out. They will be closed by
// HandleExceptionBaseline.
MOZ_ASSERT(cx->compartment()->isDebuggee());
MOZ_ASSERT(cx->realm()->isDebuggee());
if (iter.moreFrames() || HasLiveStackValueAtDepth(script, pc, i + 1)) {
v = iter.read();
} else {

View File

@ -104,7 +104,7 @@ BaselineCompiler::compile()
// When code coverage is only enabled for optimizations, or when a Debugger
// set the collectCoverageInfo flag, we have to create the ScriptCounts if
// they do not exist.
if (!script->hasScriptCounts() && cx->compartment()->collectCoverage()) {
if (!script->hasScriptCounts() && cx->realm()->collectCoverage()) {
if (!script->initScriptCounts(cx))
return Method_Error;
}

View File

@ -174,7 +174,7 @@ static void
HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromException* rfe,
bool* overrecursed)
{
if (cx->compartment()->isDebuggee()) {
if (cx->realm()->isDebuggee()) {
// We need to bail when there is a catchable exception, and we are the
// debuggee of a Debugger with a live onExceptionUnwind hook, or if a
// Debugger has observed this frame (e.g., for onPop).
@ -652,7 +652,7 @@ HandleException(ResumeFromException* rfe)
bool invalidated = frame.checkInvalidation(&ionScript);
#ifdef JS_TRACE_LOGGING
if (logger && cx->compartment()->isDebuggee() && logger->enabled()) {
if (logger && cx->realm()->isDebuggee() && logger->enabled()) {
logger->disable(/* force = */ true,
"Forcefully disabled tracelogger, due to "
"throwing an exception with an active Debugger "

View File

@ -1136,7 +1136,7 @@ bool
GlobalHasLiveOnDebuggerStatement(JSContext* cx)
{
AutoUnsafeCallWithABI unsafe;
return cx->compartment()->isDebuggee() &&
return cx->realm()->isDebuggee() &&
Debugger::hasLiveHook(cx->global(), Debugger::OnDebuggerStatement);
}
@ -1191,7 +1191,7 @@ bool
DebugLeaveLexicalEnv(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
{
MOZ_ASSERT(frame->script()->baselineScript()->hasDebugInstrumentation());
if (cx->compartment()->isDebuggee())
if (cx->realm()->isDebuggee())
DebugEnvironments::onPopLexical(cx, frame, pc);
return true;
}

View File

@ -4069,7 +4069,7 @@ JS::CompileOptions::CompileOptions(JSContext* cx)
werrorOption = cx->options().werror();
if (!cx->options().asmJS())
asmJSOption = AsmJSOption::Disabled;
else if (cx->compartment()->debuggerObservesAsmJS())
else if (cx->realm()->debuggerObservesAsmJS())
asmJSOption = AsmJSOption::DisabledByDebugger;
else
asmJSOption = AsmJSOption::Enabled;

View File

@ -36,7 +36,7 @@ js::Debugger::fromJSObject(const JSObject* obj)
/* static */ inline bool
js::Debugger::checkNoExecute(JSContext* cx, HandleScript script)
{
if (!cx->compartment()->isDebuggee() || !cx->noExecuteDebuggerTop)
if (!cx->realm()->isDebuggee() || !cx->noExecuteDebuggerTop)
return true;
return slowPathCheckNoExecute(cx, script);
}
@ -53,7 +53,7 @@ js::Debugger::onEnterFrame(JSContext* cx, AbstractFramePtr frame)
/* static */ js::ResumeMode
js::Debugger::onDebuggerStatement(JSContext* cx, AbstractFramePtr frame)
{
if (!cx->compartment()->isDebuggee())
if (!cx->realm()->isDebuggee())
return ResumeMode::Continue;
return slowPathOnDebuggerStatement(cx, frame);
}
@ -61,7 +61,7 @@ js::Debugger::onDebuggerStatement(JSContext* cx, AbstractFramePtr frame)
/* static */ js::ResumeMode
js::Debugger::onExceptionUnwind(JSContext* cx, AbstractFramePtr frame)
{
if (!cx->compartment()->isDebuggee())
if (!cx->realm()->isDebuggee())
return ResumeMode::Continue;
return slowPathOnExceptionUnwind(cx, frame);
}
@ -69,21 +69,21 @@ js::Debugger::onExceptionUnwind(JSContext* cx, AbstractFramePtr frame)
/* static */ void
js::Debugger::onNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance)
{
if (cx->compartment()->isDebuggee())
if (cx->realm()->isDebuggee())
slowPathOnNewWasmInstance(cx, wasmInstance);
}
/* static */ void
js::Debugger::onNewPromise(JSContext* cx, Handle<PromiseObject*> promise)
{
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
slowPathPromiseHook(cx, Debugger::OnNewPromise, promise);
}
/* static */ void
js::Debugger::onPromiseSettled(JSContext* cx, Handle<PromiseObject*> promise)
{
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
slowPathPromiseHook(cx, Debugger::OnPromiseSettled, promise);
}

View File

@ -278,25 +278,25 @@ ValueToIdentifier(JSContext* cx, HandleValue v, MutableHandleId id)
return true;
}
class AutoRestoreCompartmentDebugMode
class js::AutoRestoreRealmDebugMode
{
JSCompartment* comp_;
Realm* realm_;
unsigned bits_;
public:
explicit AutoRestoreCompartmentDebugMode(JSCompartment* comp)
: comp_(comp), bits_(comp->debugModeBits)
explicit AutoRestoreRealmDebugMode(Realm* realm)
: realm_(realm), bits_(realm->debugModeBits_)
{
MOZ_ASSERT(comp_);
MOZ_ASSERT(realm_);
}
~AutoRestoreCompartmentDebugMode() {
if (comp_)
comp_->debugModeBits = bits_;
~AutoRestoreRealmDebugMode() {
if (realm_)
realm_->debugModeBits_ = bits_;
}
void release() {
comp_ = nullptr;
realm_ = nullptr;
}
};
@ -418,7 +418,7 @@ class MOZ_RAII js::LeaveDebuggeeNoExecute
/* static */ bool
Debugger::slowPathCheckNoExecute(JSContext* cx, HandleScript script)
{
MOZ_ASSERT(cx->compartment()->isDebuggee());
MOZ_ASSERT(cx->realm()->isDebuggee());
MOZ_ASSERT(cx->noExecuteDebuggerTop);
return EnterDebuggeeNoExecute::reportIfFoundInStack(cx, script);
}
@ -2367,35 +2367,36 @@ Debugger::slowPathPromiseHook(JSContext* cx, Hook hook, Handle<PromiseObject*> p
/*** Debugger code invalidation for observing execution ******************************************/
class MOZ_RAII ExecutionObservableCompartments : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableRealms : public Debugger::ExecutionObservableSet
{
HashSet<JSCompartment*> compartments_;
HashSet<Realm*> realms_;
HashSet<Zone*> zones_;
public:
explicit ExecutionObservableCompartments(JSContext* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: compartments_(cx),
explicit ExecutionObservableRealms(JSContext* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: realms_(cx),
zones_(cx)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
bool init() { return compartments_.init() && zones_.init(); }
bool add(JSCompartment* comp) { return compartments_.put(comp) && zones_.put(comp->zone()); }
bool init() { return realms_.init() && zones_.init(); }
bool add(Realm* realm) { return realms_.put(realm) && zones_.put(realm->zone()); }
typedef HashSet<JSCompartment*>::Range CompartmentRange;
const HashSet<JSCompartment*>* compartments() const { return &compartments_; }
using RealmRange = HashSet<Realm*>::Range;
const HashSet<Realm*>* realms() const { return &realms_; }
const HashSet<Zone*>* zones() const override { return &zones_; }
bool shouldRecompileOrInvalidate(JSScript* script) const override {
return script->hasBaselineScript() && compartments_.has(script->compartment());
return script->hasBaselineScript() && realms_.has(script->realm());
}
bool shouldMarkAsDebuggee(FrameIter& iter) const override {
// AbstractFramePtr can't refer to non-remateralized Ion frames or
// non-debuggee wasm frames, so if iter refers to one such, we know we
// don't match.
return iter.hasUsableAbstractFramePtr() && compartments_.has(iter.compartment());
return iter.hasUsableAbstractFramePtr() &&
realms_.has(JS::GetRealmForCompartment(iter.compartment()));
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@ -2743,12 +2744,13 @@ Debugger::ensureExecutionObservabilityOfFrame(JSContext* cx, AbstractFramePtr fr
/* static */ bool
Debugger::ensureExecutionObservabilityOfCompartment(JSContext* cx, JSCompartment* comp)
{
if (comp->debuggerObservesAllExecution())
Realm* realm = JS::GetRealmForCompartment(comp);
if (realm->debuggerObservesAllExecution())
return true;
ExecutionObservableCompartments obs(cx);
if (!obs.init() || !obs.add(comp))
ExecutionObservableRealms obs(cx);
if (!obs.init() || !obs.add(realm))
return false;
comp->updateDebuggerObservesAllExecution();
realm->updateDebuggerObservesAllExecution();
return updateExecutionObservability(cx, obs, Observing);
}
@ -2796,28 +2798,28 @@ Debugger::observesCoverage() const
bool
Debugger::updateObservesAllExecutionOnDebuggees(JSContext* cx, IsObserving observing)
{
ExecutionObservableCompartments obs(cx);
ExecutionObservableRealms obs(cx);
if (!obs.init())
return false;
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
JS::Realm* realm = global->realm();
if (comp->debuggerObservesAllExecution() == observing)
if (realm->debuggerObservesAllExecution() == observing)
continue;
// It's expensive to eagerly invalidate and recompile a compartment,
// so add the compartment to the set only if we are observing.
if (observing && !obs.add(comp))
// It's expensive to eagerly invalidate and recompile a realm,
// so add the realm to the set only if we are observing.
if (observing && !obs.add(realm))
return false;
}
if (!updateExecutionObservability(cx, obs, observing))
return false;
typedef ExecutionObservableCompartments::CompartmentRange CompartmentRange;
for (CompartmentRange r = obs.compartments()->all(); !r.empty(); r.popFront())
using RealmRange = ExecutionObservableRealms::RealmRange;
for (RealmRange r = obs.realms()->all(); !r.empty(); r.popFront())
r.front()->updateDebuggerObservesAllExecution();
return true;
@ -2826,21 +2828,21 @@ Debugger::updateObservesAllExecutionOnDebuggees(JSContext* cx, IsObserving obser
bool
Debugger::updateObservesCoverageOnDebuggees(JSContext* cx, IsObserving observing)
{
ExecutionObservableCompartments obs(cx);
ExecutionObservableRealms obs(cx);
if (!obs.init())
return false;
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
Realm* realm = global->realm();
if (comp->debuggerObservesCoverage() == observing)
if (realm->debuggerObservesCoverage() == observing)
continue;
// Invalidate and recompile a compartment to add or remove PCCounts
// Invalidate and recompile a realm to add or remove PCCounts
// increments. We have to eagerly invalidate, as otherwise we might have
// dangling pointers to freed PCCounts.
if (!obs.add(comp))
if (!obs.add(realm))
return false;
}
@ -2860,10 +2862,10 @@ Debugger::updateObservesCoverageOnDebuggees(JSContext* cx, IsObserving observing
if (!updateExecutionObservability(cx, obs, observing))
return false;
// All compartments can safely be toggled, and all scripts will be
// recompiled. Thus we can update each compartment accordingly.
typedef ExecutionObservableCompartments::CompartmentRange CompartmentRange;
for (CompartmentRange r = obs.compartments()->all(); !r.empty(); r.popFront())
// All realms can safely be toggled, and all scripts will be recompiled.
// Thus we can update each realm accordingly.
using RealmRange = ExecutionObservableRealms::RealmRange;
for (RealmRange r = obs.realms()->all(); !r.empty(); r.popFront())
r.front()->updateDebuggerObservesCoverage();
return true;
@ -2874,12 +2876,12 @@ Debugger::updateObservesAsmJSOnDebuggees(IsObserving observing)
{
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
Realm* realm = global->realm();
if (comp->debuggerObservesAsmJS() == observing)
if (realm->debuggerObservesAsmJS() == observing)
continue;
comp->updateDebuggerObservesAsmJS();
realm->updateDebuggerObservesAsmJS();
}
}
@ -2888,12 +2890,12 @@ Debugger::updateObservesBinarySourceDebuggees(IsObserving observing)
{
for (WeakGlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
Realm* realm = global->realm();
if (comp->debuggerObservesBinarySource() == observing)
if (realm->debuggerObservesBinarySource() == observing)
continue;
comp->updateDebuggerObservesBinarySource();
realm->updateDebuggerObservesBinarySource();
}
}
@ -3594,8 +3596,8 @@ Debugger::setAllowUnobservedAsmJS(JSContext* cx, unsigned argc, Value* vp)
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
comp->updateDebuggerObservesAsmJS();
Realm* realm = global->realm();
realm->updateDebuggerObservesAsmJS();
}
args.rval().setUndefined();
@ -3620,8 +3622,8 @@ Debugger::setAllowWasmBinarySource(JSContext* cx, unsigned argc, Value* vp)
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront()) {
GlobalObject* global = r.front();
JSCompartment* comp = global->compartment();
comp->updateDebuggerObservesBinarySource();
Realm* realm = global->realm();
realm->updateDebuggerObservesBinarySource();
}
args.rval().setUndefined();
@ -3769,17 +3771,17 @@ Debugger::removeDebuggee(JSContext* cx, unsigned argc, Value* vp)
if (!global)
return false;
ExecutionObservableCompartments obs(cx);
ExecutionObservableRealms obs(cx);
if (!obs.init())
return false;
if (dbg->debuggees.has(global)) {
dbg->removeDebuggeeGlobal(cx->runtime()->defaultFreeOp(), global, nullptr);
// Only update the compartment if there are no Debuggers left, as it's
// expensive to check if no other Debugger has a live script or frame hook
// on any of the current on-stack debuggee frames.
if (global->getDebuggers()->empty() && !obs.add(global->compartment()))
// Only update the realm if there are no Debuggers left, as it's
// expensive to check if no other Debugger has a live script or frame
// hook on any of the current on-stack debuggee frames.
if (global->getDebuggers()->empty() && !obs.add(global->realm()))
return false;
if (!updateExecutionObservability(cx, obs, NotObserving))
return false;
@ -3794,7 +3796,7 @@ Debugger::removeAllDebuggees(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGGER(cx, argc, vp, "removeAllDebuggees", args, dbg);
ExecutionObservableCompartments obs(cx);
ExecutionObservableRealms obs(cx);
if (!obs.init())
return false;
@ -3803,7 +3805,7 @@ Debugger::removeAllDebuggees(JSContext* cx, unsigned argc, Value* vp)
dbg->removeDebuggeeGlobal(cx->runtime()->defaultFreeOp(), global, &e);
// See note about adding to the observable set in removeDebuggee.
if (global->getDebuggers()->empty() && !obs.add(global->compartment()))
if (global->getDebuggers()->empty() && !obs.add(global->realm()))
return false;
}
@ -3888,8 +3890,7 @@ Debugger::clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGGER(cx, argc, vp, "clearAllBreakpoints", args, dbg);
for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
r.front()->compartment()->clearBreakpointsIn(cx->runtime()->defaultFreeOp(),
dbg, nullptr);
r.front()->realm()->clearBreakpointsIn(cx->runtime()->defaultFreeOp(), dbg, nullptr);
return true;
}
@ -3975,25 +3976,24 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
* then adding global would create a cycle. (Typically nobody is debugging
* the debugger, in which case we zip through this code without looping.)
*/
Vector<JSCompartment*> visited(cx);
if (!visited.append(object->compartment()))
Vector<Realm*> visited(cx);
if (!visited.append(object->realm()))
return false;
for (size_t i = 0; i < visited.length(); i++) {
JSCompartment* c = visited[i];
if (c == debuggeeRealm) {
Realm* realm = visited[i];
if (realm == debuggeeRealm) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_LOOP);
return false;
}
/*
* Find all compartments containing debuggers debugging c's global
* object. Add those compartments to visited.
* Find all realms containing debuggers debugging realm's global object.
* Add those realms to visited.
*/
if (c->isDebuggee()) {
Realm* realm = JS::GetRealmForCompartment(c);
if (realm->isDebuggee()) {
GlobalObject::DebuggerVector* v = realm->maybeGlobal()->getDebuggers();
for (auto p = v->begin(); p != v->end(); p++) {
JSCompartment* next = (*p)->object->compartment();
Realm* next = (*p)->object->realm();
if (Find(visited, next) == visited.end() && !visited.append(next))
return false;
}
@ -4008,8 +4008,8 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
* 3. it must be in zone->getDebuggers(),
* 4. the debuggee's zone must be in this->debuggeeZones,
* 5. if we are tracking allocations, the SavedStacksMetadataBuilder must be
* installed for this compartment, and
* 6. JSCompartment::isDebuggee()'s bit must be set.
* installed for this realm, and
* 6. Realm::isDebuggee()'s bit must be set.
*
* All six indications must be kept consistent.
*/
@ -4073,7 +4073,7 @@ Debugger::addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> global)
});
// (6)
AutoRestoreCompartmentDebugMode debugModeGuard(debuggeeRealm);
AutoRestoreRealmDebugMode debugModeGuard(debuggeeRealm);
debuggeeRealm->setIsDebuggee();
debuggeeRealm->updateDebuggerObservesAsmJS();
debuggeeRealm->updateDebuggerObservesBinarySource();
@ -4178,11 +4178,11 @@ Debugger::removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
nextbp = bp->nextInDebugger();
switch (bp->site->type()) {
case BreakpointSite::Type::JS:
if (bp->site->asJS()->script->compartment() == global->compartment())
if (bp->site->asJS()->script->realm() == global->realm())
bp->destroy(fop);
break;
case BreakpointSite::Type::Wasm:
if (bp->asWasm()->wasmInstance->compartment() == global->compartment())
if (bp->asWasm()->wasmInstance->realm() == global->realm())
bp->destroy(fop);
break;
}
@ -4191,18 +4191,18 @@ Debugger::removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
/*
* If we are tracking allocation sites, we need to remove the object
* metadata callback from this global's compartment.
* metadata callback from this global's realm.
*/
if (trackingAllocationSites)
Debugger::removeAllocationsTracking(*global);
if (global->getDebuggers()->empty()) {
global->compartment()->unsetIsDebuggee();
global->realm()->unsetIsDebuggee();
} else {
global->compartment()->updateDebuggerObservesAllExecution();
global->compartment()->updateDebuggerObservesAsmJS();
global->compartment()->updateDebuggerObservesBinarySource();
global->compartment()->updateDebuggerObservesCoverage();
global->realm()->updateDebuggerObservesAllExecution();
global->realm()->updateDebuggerObservesAsmJS();
global->realm()->updateDebuggerObservesBinarySource();
global->realm()->updateDebuggerObservesCoverage();
}
}
@ -4584,7 +4584,8 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery
// everything.
for (auto r = compartments.all(); !r.empty(); r.popFront()) {
JSCompartment* comp = r.front();
if (!comp->ensureDelazifyScriptsForDebugger(cx))
Realm* realm = JS::GetRealmForCompartment(comp);
if (!realm->ensureDelazifyScriptsForDebugger(cx))
return false;
}
return true;

View File

@ -1806,7 +1806,7 @@ Debugger::onNewScript(JSContext* cx, HandleScript script)
if (script->hideScriptFromDebugger())
return;
if (script->compartment()->isDebuggee())
if (script->realm()->isDebuggee())
slowPathOnNewScript(cx, script);
}

View File

@ -2510,7 +2510,7 @@ DebugEnvironments::checkHashTablesAfterMovingGC()
static bool
CanUseDebugEnvironmentMaps(JSContext* cx)
{
return cx->compartment()->isDebuggee();
return cx->realm()->isDebuggee();
}
DebugEnvironments*
@ -2893,7 +2893,7 @@ DebugEnvironments::updateLiveEnvironments(JSContext* cx)
if (frame.prevUpToDate())
return true;
MOZ_ASSERT(frame.environmentChain()->compartment()->isDebuggee());
MOZ_ASSERT(frame.environmentChain()->realm()->isDebuggee());
frame.setPrevUpToDate();
}

View File

@ -1045,18 +1045,18 @@ PopEnvironment(JSContext* cx, EnvironmentIter& ei)
case ScopeKind::Catch:
case ScopeKind::NamedLambda:
case ScopeKind::StrictNamedLambda:
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopLexical(cx, ei);
if (ei.scope().hasEnvironment())
ei.initialFrame().popOffEnvironmentChain<LexicalEnvironmentObject>();
break;
case ScopeKind::With:
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopWith(ei.initialFrame());
ei.initialFrame().popOffEnvironmentChain<WithEnvironmentObject>();
break;
case ScopeKind::Function:
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopCall(cx, ei.initialFrame());
if (ei.scope().hasEnvironment())
ei.initialFrame().popOffEnvironmentChain<CallObject>();
@ -1064,7 +1064,7 @@ PopEnvironment(JSContext* cx, EnvironmentIter& ei)
case ScopeKind::FunctionBodyVar:
case ScopeKind::ParameterExpressionVar:
case ScopeKind::StrictEval:
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopVar(cx, ei);
if (ei.scope().hasEnvironment())
ei.initialFrame().popOffEnvironmentChain<VarEnvironmentObject>();
@ -1815,7 +1815,7 @@ Interpret(JSContext* cx, RunState& state)
#define INIT_COVERAGE() \
JS_BEGIN_MACRO \
if (!script->hasScriptCounts()) { \
if (cx->compartment()->collectCoverageForDebug()) { \
if (cx->realm()->collectCoverageForDebug()) { \
if (!script->initScriptCounts(cx)) \
goto error; \
} \
@ -1935,7 +1935,7 @@ CASE(EnableInterruptsPseudoOpcode)
bool moreInterrupts = false;
jsbytecode op = *REGS.pc;
if (!script->hasScriptCounts() && cx->compartment()->collectCoverageForDebug()) {
if (!script->hasScriptCounts() && cx->realm()->collectCoverageForDebug()) {
if (!script->initScriptCounts(cx))
goto error;
}
@ -3980,7 +3980,7 @@ CASE(JSOP_POPLEXICALENV)
MOZ_ASSERT(scope->as<LexicalScope>().hasEnvironment());
#endif
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
// Pop block from scope chain.
@ -3997,14 +3997,14 @@ CASE(JSOP_DEBUGLEAVELEXICALENV)
// FIXME: This opcode should not be necessary. The debugger shouldn't need
// help from bytecode to do its job. See bug 927782.
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
}
END_CASE(JSOP_DEBUGLEAVELEXICALENV)
CASE(JSOP_FRESHENLEXICALENV)
{
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
if (!REGS.fp()->freshenLexicalEnvironment(cx))
@ -4014,7 +4014,7 @@ END_CASE(JSOP_FRESHENLEXICALENV)
CASE(JSOP_RECREATELEXICALENV)
{
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopLexical(cx, REGS.fp(), REGS.pc);
if (!REGS.fp()->recreateLexicalEnvironment(cx))
@ -4040,7 +4040,7 @@ CASE(JSOP_POPVARENV)
MOZ_ASSERT(scope->as<VarScope>().hasEnvironment());
#endif
if (MOZ_UNLIKELY(cx->compartment()->isDebuggee()))
if (MOZ_UNLIKELY(cx->realm()->isDebuggee()))
DebugEnvironments::onPopVar(cx, REGS.fp(), REGS.pc);
REGS.fp()->popOffEnvironmentChain<VarEnvironmentObject>();

View File

@ -54,7 +54,6 @@ JSCompartment::JSCompartment(Zone* zone)
lazyArrayBuffers(nullptr),
nonSyntacticLexicalEnvironments_(nullptr),
gcIncomingGrayPointers(nullptr),
debugModeBits(0),
validAccessPtr(nullptr),
randomKeyGenerator_(runtime_->forkRandomKeyGenerator()),
debugEnvs(nullptr),
@ -1071,9 +1070,9 @@ AddInnerLazyFunctionsFromScript(JSScript* script, AutoObjectVector& lazyFunction
}
static bool
AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind)
AddLazyFunctionsForRealm(JSContext* cx, AutoObjectVector& lazyFunctions, AllocKind kind)
{
// Find all live root lazy functions in the compartment: those which have a
// Find all live root lazy functions in the realm: those which have a
// non-lazy enclosing script, and which do not have an uncompiled enclosing
// script. The last condition is so that we don't compile lazy scripts
// whose enclosing scripts failed to compile, indicating that the lazy
@ -1090,7 +1089,7 @@ AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, A
// are about to be finalized. GC things referenced by objects that are
// about to be finalized (e.g., in slots) may already be freed.
if (gc::IsAboutToBeFinalizedUnbarriered(&fun) ||
fun->compartment() != cx->compartment())
fun->realm() != cx->realm())
{
continue;
}
@ -1108,16 +1107,16 @@ AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, A
}
static bool
CreateLazyScriptsForCompartment(JSContext* cx)
CreateLazyScriptsForRealm(JSContext* cx)
{
AutoObjectVector lazyFunctions(cx);
if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION))
if (!AddLazyFunctionsForRealm(cx, lazyFunctions, AllocKind::FUNCTION))
return false;
// Methods, for instance {get method() {}}, are extended functions that can
// be relazified, so we need to handle those as well.
if (!AddLazyFunctionsForCompartment(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED))
if (!AddLazyFunctionsForRealm(cx, lazyFunctions, AllocKind::FUNCTION_EXTENDED))
return false;
// Create scripts for each lazy function, updating the list of functions to
@ -1145,17 +1144,17 @@ CreateLazyScriptsForCompartment(JSContext* cx)
}
bool
JSCompartment::ensureDelazifyScriptsForDebugger(JSContext* cx)
Realm::ensureDelazifyScriptsForDebugger(JSContext* cx)
{
AutoRealmUnchecked ar(cx, this);
if (needsDelazificationForDebugger() && !CreateLazyScriptsForCompartment(cx))
if (needsDelazificationForDebugger() && !CreateLazyScriptsForRealm(cx))
return false;
debugModeBits &= ~DebuggerNeedsDelazification;
debugModeBits_ &= ~DebuggerNeedsDelazification;
return true;
}
void
JSCompartment::updateDebuggerObservesFlag(unsigned flag)
Realm::updateDebuggerObservesFlag(unsigned flag)
{
MOZ_ASSERT(isDebuggee());
MOZ_ASSERT(flag == DebuggerObservesAllExecution ||
@ -1163,10 +1162,9 @@ JSCompartment::updateDebuggerObservesFlag(unsigned flag)
flag == DebuggerObservesAsmJS ||
flag == DebuggerObservesBinarySource);
Realm* realm = JS::GetRealmForCompartment(this);
GlobalObject* global = zone()->runtimeFromMainThread()->gc.isForegroundSweeping()
? realm->unsafeUnbarrieredMaybeGlobal()
: realm->maybeGlobal();
? unsafeUnbarrieredMaybeGlobal()
: maybeGlobal();
const GlobalObject::DebuggerVector* v = global->getDebuggers();
for (auto p = v->begin(); p != v->end(); p++) {
Debugger* dbg = *p;
@ -1175,25 +1173,25 @@ JSCompartment::updateDebuggerObservesFlag(unsigned flag)
flag == DebuggerObservesAsmJS ? dbg->observesAsmJS() :
dbg->observesBinarySource())
{
debugModeBits |= flag;
debugModeBits_ |= flag;
return;
}
}
debugModeBits &= ~flag;
debugModeBits_ &= ~flag;
}
void
JSCompartment::unsetIsDebuggee()
Realm::unsetIsDebuggee()
{
if (isDebuggee()) {
debugModeBits &= ~DebuggerObservesMask;
debugModeBits_ &= ~DebuggerObservesMask;
DebugEnvironments::onCompartmentUnsetIsDebuggee(this);
}
}
void
JSCompartment::updateDebuggerObservesCoverage()
Realm::updateDebuggerObservesCoverage()
{
bool previousState = debuggerObservesCoverage();
updateDebuggerObservesFlag(DebuggerObservesCoverage);
@ -1215,26 +1213,25 @@ JSCompartment::updateDebuggerObservesCoverage()
if (collectCoverage())
return;
Realm* realm = JS::GetRealmForCompartment(this);
realm->clearScriptCounts();
realm->clearScriptNames();
clearScriptCounts();
clearScriptNames();
}
bool
JSCompartment::collectCoverage() const
Realm::collectCoverage() const
{
return collectCoverageForPGO() ||
collectCoverageForDebug();
}
bool
JSCompartment::collectCoverageForPGO() const
Realm::collectCoverageForPGO() const
{
return !JitOptions.disablePgo;
}
bool
JSCompartment::collectCoverageForDebug() const
Realm::collectCoverageForDebug() const
{
return debuggerObservesCoverage() ||
runtimeFromAnyThread()->profilingScripts ||
@ -1262,10 +1259,10 @@ Realm::clearScriptNames()
}
void
JSCompartment::clearBreakpointsIn(FreeOp* fop, js::Debugger* dbg, HandleObject handler)
Realm::clearBreakpointsIn(FreeOp* fop, js::Debugger* dbg, HandleObject handler)
{
for (auto script = zone()->cellIter<JSScript>(); !script.done(); script.next()) {
if (script->compartment() == this && script->hasAnyBreakpointsOrStepMode())
if (script->realm() == this && script->hasAnyBreakpointsOrStepMode())
script->clearBreakpointsIn(fop, dbg, handler);
}
}

View File

@ -38,6 +38,7 @@ namespace gc {
template <typename Node, typename Derived> class ComponentFinder;
} // namespace gc
class AutoRestoreRealmDebugMode;
class GlobalObject;
class LexicalEnvironmentObject;
class MapObject;
@ -660,26 +661,6 @@ struct JSCompartment
JSObject* gcIncomingGrayPointers;
private:
enum {
IsDebuggee = 1 << 0,
DebuggerObservesAllExecution = 1 << 1,
DebuggerObservesAsmJS = 1 << 2,
DebuggerObservesCoverage = 1 << 3,
DebuggerObservesBinarySource = 1 << 4,
DebuggerNeedsDelazification = 1 << 5
};
unsigned debugModeBits;
friend class AutoRestoreCompartmentDebugMode;
static const unsigned DebuggerObservesMask = IsDebuggee |
DebuggerObservesAllExecution |
DebuggerObservesCoverage |
DebuggerObservesAsmJS |
DebuggerObservesBinarySource;
void updateDebuggerObservesFlag(unsigned flag);
bool getNonWrapperObjectForCurrentCompartment(JSContext* cx, js::MutableHandleObject obj);
bool getOrCreateWrapper(JSContext* cx, js::HandleObject existing, js::MutableHandleObject obj);
@ -788,118 +769,6 @@ struct JSCompartment
return offsetof(JSCompartment, regExps);
}
//
// The Debugger observes execution on a frame-by-frame basis. The
// invariants of JSCompartment's debug mode bits, JSScript::isDebuggee,
// InterpreterFrame::isDebuggee, and BaselineFrame::isDebuggee are
// enumerated below.
//
// 1. When a compartment's isDebuggee() == true, relazification and lazy
// parsing are disabled.
//
// Whether AOT wasm is disabled is togglable by the Debugger API. By
// default it is disabled. See debuggerObservesAsmJS below.
//
// 2. When a compartment's debuggerObservesAllExecution() == true, all of
// the compartment's scripts are considered debuggee scripts.
//
// 3. A script is considered a debuggee script either when, per above, its
// compartment is observing all execution, or if it has breakpoints set.
//
// 4. A debuggee script always pushes a debuggee frame.
//
// 5. A debuggee frame calls all slow path Debugger hooks in the
// Interpreter and Baseline. A debuggee frame implies that its script's
// BaselineScript, if extant, has been compiled with debug hook calls.
//
// 6. A debuggee script or a debuggee frame (i.e., during OSR) ensures
// that the compiled BaselineScript is compiled with debug hook calls
// when attempting to enter Baseline.
//
// 7. A debuggee script or a debuggee frame (i.e., during OSR) does not
// attempt to enter Ion.
//
// Note that a debuggee frame may exist without its script being a
// debuggee script. e.g., Debugger.Frame.prototype.eval only marks the
// frame in which it is evaluating as a debuggee frame.
//
// True if this compartment's global is a debuggee of some Debugger
// object.
bool isDebuggee() const { return !!(debugModeBits & IsDebuggee); }
void setIsDebuggee() { debugModeBits |= IsDebuggee; }
void unsetIsDebuggee();
// True if this compartment's global is a debuggee of some Debugger
// object with a live hook that observes all execution; e.g.,
// onEnterFrame.
bool debuggerObservesAllExecution() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesAllExecution;
return (debugModeBits & Mask) == Mask;
}
void updateDebuggerObservesAllExecution() {
updateDebuggerObservesFlag(DebuggerObservesAllExecution);
}
// True if this compartment's global is a debuggee of some Debugger object
// whose allowUnobservedAsmJS flag is false.
//
// Note that since AOT wasm functions cannot bail out, this flag really
// means "observe wasm from this point forward". We cannot make
// already-compiled wasm code observable to Debugger.
bool debuggerObservesAsmJS() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesAsmJS;
return (debugModeBits & Mask) == Mask;
}
void updateDebuggerObservesAsmJS() {
updateDebuggerObservesFlag(DebuggerObservesAsmJS);
}
bool debuggerObservesBinarySource() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesBinarySource;
return (debugModeBits & Mask) == Mask;
}
void updateDebuggerObservesBinarySource() {
updateDebuggerObservesFlag(DebuggerObservesBinarySource);
}
// True if this compartment's global is a debuggee of some Debugger object
// whose collectCoverageInfo flag is true.
bool debuggerObservesCoverage() const {
static const unsigned Mask = DebuggerObservesCoverage;
return (debugModeBits & Mask) == Mask;
}
void updateDebuggerObservesCoverage();
// The code coverage can be enabled either for each compartment, with the
// Debugger API, or for the entire runtime.
bool collectCoverage() const;
bool collectCoverageForDebug() const;
bool collectCoverageForPGO() const;
bool needsDelazificationForDebugger() const {
return debugModeBits & DebuggerNeedsDelazification;
}
/*
* Schedule the compartment to be delazified. Called from
* LazyScript::Create.
*/
void scheduleDelazificationForDebugger() { debugModeBits |= DebuggerNeedsDelazification; }
/*
* If we scheduled delazification for turning on debug mode, delazify all
* scripts.
*/
bool ensureDelazifyScriptsForDebugger(JSContext* cx);
void clearBreakpointsIn(js::FreeOp* fop, js::Debugger* dbg, JS::HandleObject handler);
private:
void sweepBreakpoints(js::FreeOp* fop);
public:
/* Bookkeeping information for debug scope objects. */
js::DebugEnvironments* debugEnvs;
@ -967,6 +836,22 @@ class JS::Realm : public JSCompartment
unsigned enterRealmDepth_ = 0;
enum {
IsDebuggee = 1 << 0,
DebuggerObservesAllExecution = 1 << 1,
DebuggerObservesAsmJS = 1 << 2,
DebuggerObservesCoverage = 1 << 3,
DebuggerObservesBinarySource = 1 << 4,
DebuggerNeedsDelazification = 1 << 5
};
static const unsigned DebuggerObservesMask = IsDebuggee |
DebuggerObservesAllExecution |
DebuggerObservesCoverage |
DebuggerObservesAsmJS |
DebuggerObservesBinarySource;
unsigned debugModeBits_ = 0;
friend class js::AutoRestoreRealmDebugMode;
bool isAtomsRealm_ = false;
bool isSelfHostingRealm_ = false;
bool marked_ = true;
@ -998,6 +883,10 @@ class JS::Realm : public JSCompartment
bool firedOnNewGlobalObject = false;
#endif
private:
void updateDebuggerObservesFlag(unsigned flag);
public:
Realm(JS::Zone* zone, const JS::RealmOptions& options);
~Realm();
@ -1230,6 +1119,111 @@ class JS::Realm : public JSCompartment
js::ArgumentsObject* getOrCreateArgumentsTemplateObject(JSContext* cx, bool mapped);
js::ArgumentsObject* maybeArgumentsTemplateObject(bool mapped) const;
//
// The Debugger observes execution on a frame-by-frame basis. The
// invariants of Realm's debug mode bits, JSScript::isDebuggee,
// InterpreterFrame::isDebuggee, and BaselineFrame::isDebuggee are
// enumerated below.
//
// 1. When a realm's isDebuggee() == true, relazification and lazy
// parsing are disabled.
//
// Whether AOT wasm is disabled is togglable by the Debugger API. By
// default it is disabled. See debuggerObservesAsmJS below.
//
// 2. When a realm's debuggerObservesAllExecution() == true, all of
// the realm's scripts are considered debuggee scripts.
//
// 3. A script is considered a debuggee script either when, per above, its
// realm is observing all execution, or if it has breakpoints set.
//
// 4. A debuggee script always pushes a debuggee frame.
//
// 5. A debuggee frame calls all slow path Debugger hooks in the
// Interpreter and Baseline. A debuggee frame implies that its script's
// BaselineScript, if extant, has been compiled with debug hook calls.
//
// 6. A debuggee script or a debuggee frame (i.e., during OSR) ensures
// that the compiled BaselineScript is compiled with debug hook calls
// when attempting to enter Baseline.
//
// 7. A debuggee script or a debuggee frame (i.e., during OSR) does not
// attempt to enter Ion.
//
// Note that a debuggee frame may exist without its script being a
// debuggee script. e.g., Debugger.Frame.prototype.eval only marks the
// frame in which it is evaluating as a debuggee frame.
//
// True if this realm's global is a debuggee of some Debugger
// object.
bool isDebuggee() const { return !!(debugModeBits_ & IsDebuggee); }
void setIsDebuggee() { debugModeBits_ |= IsDebuggee; }
void unsetIsDebuggee();
// True if this compartment's global is a debuggee of some Debugger
// object with a live hook that observes all execution; e.g.,
// onEnterFrame.
bool debuggerObservesAllExecution() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesAllExecution;
return (debugModeBits_ & Mask) == Mask;
}
void updateDebuggerObservesAllExecution() {
updateDebuggerObservesFlag(DebuggerObservesAllExecution);
}
// True if this realm's global is a debuggee of some Debugger object
// whose allowUnobservedAsmJS flag is false.
//
// Note that since AOT wasm functions cannot bail out, this flag really
// means "observe wasm from this point forward". We cannot make
// already-compiled wasm code observable to Debugger.
bool debuggerObservesAsmJS() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesAsmJS;
return (debugModeBits_ & Mask) == Mask;
}
void updateDebuggerObservesAsmJS() {
updateDebuggerObservesFlag(DebuggerObservesAsmJS);
}
bool debuggerObservesBinarySource() const {
static const unsigned Mask = IsDebuggee | DebuggerObservesBinarySource;
return (debugModeBits_ & Mask) == Mask;
}
void updateDebuggerObservesBinarySource() {
updateDebuggerObservesFlag(DebuggerObservesBinarySource);
}
// True if this realm's global is a debuggee of some Debugger object
// whose collectCoverageInfo flag is true.
bool debuggerObservesCoverage() const {
static const unsigned Mask = DebuggerObservesCoverage;
return (debugModeBits_ & Mask) == Mask;
}
void updateDebuggerObservesCoverage();
// The code coverage can be enabled either for each realm, with the
// Debugger API, or for the entire runtime.
bool collectCoverage() const;
bool collectCoverageForDebug() const;
bool collectCoverageForPGO() const;
bool needsDelazificationForDebugger() const {
return debugModeBits_ & DebuggerNeedsDelazification;
}
// Schedule the realm to be delazified. Called from LazyScript::Create.
void scheduleDelazificationForDebugger() {
debugModeBits_ |= DebuggerNeedsDelazification;
}
// If we scheduled delazification for turning on debug mode, delazify all
// scripts.
bool ensureDelazifyScriptsForDebugger(JSContext* cx);
void clearBreakpointsIn(js::FreeOp* fop, js::Debugger* dbg, JS::HandleObject handler);
};
namespace js {

View File

@ -3798,7 +3798,7 @@ bool
JSScript::incrementStepModeCount(JSContext* cx)
{
assertSameCompartment(cx, this);
MOZ_ASSERT(cx->compartment()->isDebuggee());
MOZ_ASSERT(cx->realm()->isDebuggee());
if (!ensureHasDebugScript(cx))
return false;
@ -4259,7 +4259,7 @@ LazyScript::CreateRaw(JSContext* cx, HandleFunction fun,
if (!res)
return nullptr;
cx->compartment()->scheduleDelazificationForDebugger();
cx->realm()->scheduleDelazificationForDebugger();
return new (res) LazyScript(fun, *sourceObject, table.forget(), packed, sourceStart, sourceEnd,
toStringStart, lineno, column);

View File

@ -460,7 +460,7 @@ HandleInterrupt(JSContext* cx, bool invokeCallback)
if (!stop) {
// Debugger treats invoking the interrupt callback as a "step", so
// invoke the onStep handler.
if (cx->compartment()->isDebuggee()) {
if (cx->realm()->isDebuggee()) {
ScriptFrameIter iter(cx);
if (!iter.done() &&
cx->compartment() == iter.compartment() &&

View File

@ -1657,7 +1657,7 @@ jit::JitActivation::removeRematerializedFramesFromDebugger(JSContext* cx, uint8_
// Ion bailout can fail due to overrecursion and OOM. In such cases we
// cannot honor any further Debugger hooks on the frame, and need to
// ensure that its Debugger.Frame entry is cleaned up.
if (!cx->compartment()->isDebuggee() || !rematerializedFrames_)
if (!cx->realm()->isDebuggee() || !rematerializedFrames_)
return;
if (RematerializedFrameTable::Ptr p = rematerializedFrames_->lookup(top)) {
for (uint32_t i = 0; i < p->value().length(); i++)

View File

@ -103,7 +103,7 @@ CompileArgs::initFromContext(JSContext* cx, ScriptedCaller&& scriptedCaller)
// additional memory and permanently stay in baseline code, so we try to
// only enable it when a developer actually cares: when the debugger tab
// is open.
debugEnabled = cx->compartment()->debuggerObservesAsmJS();
debugEnabled = cx->realm()->debuggerObservesAsmJS();
this->scriptedCaller = Move(scriptedCaller);
return assumptions.initBuildIdFromContext(cx);

View File

@ -1281,13 +1281,13 @@ Module::instantiate(JSContext* cx,
// To support viewing the source of an instance (Instance::createText), the
// instance must hold onto a ref of the bytecode (keeping it alive). This
// wastes memory for most users, so we try to only save the source when a
// developer actually cares: when the compartment is debuggable (which is
// true when the web console is open), has code compiled with debug flag
// developer actually cares: when the realm is debuggable (which is true
// when the web console is open), has code compiled with debug flag
// enabled or a names section is present (since this going to be stripped
// for non-developer builds).
const ShareableBytes* maybeBytecode = nullptr;
if (cx->compartment()->isDebuggee() || metadata().debugEnabled ||
if (cx->realm()->isDebuggee() || metadata().debugEnabled ||
!metadata().funcNames.empty())
{
maybeBytecode = bytecode_.get();
@ -1297,7 +1297,7 @@ Module::instantiate(JSContext* cx,
// provides the lazily created source text for the program, even if that
// text is a placeholder message when debugging is not enabled.
bool binarySource = cx->compartment()->debuggerObservesBinarySource();
bool binarySource = cx->realm()->debuggerObservesBinarySource();
auto debug = cx->make_unique<DebugState>(code, maybeBytecode, binarySource);
if (!debug)
return false;