Bug 934419 - Split CompartmentOptions off from ContextOptions; r=bholley

This commit is contained in:
Eddy Bruel 2013-11-11 21:44:33 +01:00
parent cd758b567d
commit 5c1c83ae2f
9 changed files with 128 additions and 39 deletions

View File

@ -1666,9 +1666,9 @@ jsdContext::GetOptions(uint32_t *_rval)
| (JS::ContextOptionsRef(mJSCx).dontReportUncaught() ? JSOPTION_DONT_REPORT_UNCAUGHT : 0)
| (JS::ContextOptionsRef(mJSCx).noDefaultCompartmentObject() ? JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT : 0)
| (JS::ContextOptionsRef(mJSCx).noScriptRval() ? JSOPTION_NO_SCRIPT_RVAL : 0)
| (JS::ContextOptionsRef(mJSCx).strictMode() ? JSOPTION_STRICT_MODE : 0)
| (JS::ContextOptionsRef(mJSCx).baseline() ? JSOPTION_BASELINE : 0)
| (JS::ContextOptionsRef(mJSCx).typeInference() ? JSOPTION_TYPE_INFERENCE : 0)
| (JS::ContextOptionsRef(mJSCx).strictMode() ? JSOPTION_STRICT_MODE : 0)
| (JS::ContextOptionsRef(mJSCx).ion() ? JSOPTION_ION : 0)
| (JS::ContextOptionsRef(mJSCx).asmJS() ? JSOPTION_ASMJS : 0);
return NS_OK;
@ -1692,9 +1692,9 @@ jsdContext::SetOptions(uint32_t options)
.setDontReportUncaught(options & JSOPTION_DONT_REPORT_UNCAUGHT)
.setNoDefaultCompartmentObject(options & JSOPTION_NO_DEFAULT_COMPARTMENT_OBJECT)
.setNoScriptRval(options & JSOPTION_NO_SCRIPT_RVAL)
.setStrictMode(options & JSOPTION_STRICT_MODE)
.setBaseline(options & JSOPTION_BASELINE)
.setTypeInference(options & JSOPTION_TYPE_INFERENCE)
.setStrictMode(options & JSOPTION_STRICT_MODE)
.setIon(options & JSOPTION_ION)
.setAsmJS(options & JSOPTION_ASMJS);
return NS_OK;

View File

@ -6537,7 +6537,7 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
bool available = JSC::MacroAssembler::supportsFloatingPoint() &&
cx->gcSystemPageSize() == AsmJSPageSize &&
!cx->compartment()->debugMode() &&
cx->options().asmJS();
cx->compartment()->options().asmJS(cx);
args.rval().set(BooleanValue(available));
return true;

View File

@ -296,7 +296,7 @@ struct BaselineScript
inline bool
IsBaselineEnabled(JSContext *cx)
{
return cx->options().baseline();
return cx->compartment()->options().baseline(cx);
}
MethodStatus

View File

@ -371,8 +371,8 @@ void FinishOffThreadBuilder(IonBuilder *builder);
static inline bool
IsIonEnabled(JSContext *cx)
{
return cx->options().ion() &&
cx->options().baseline() &&
return cx->compartment()->options().ion(cx) &&
cx->compartment()->options().baseline(cx) &&
cx->typeInferenceEnabled();
}

View File

@ -2506,6 +2506,36 @@ class AutoHoldZone
} /* anonymous namespace */
bool
JS::CompartmentOptions::baseline(JSContext *cx) const
{
return baselineOverride_.get(cx->options().baseline());
}
bool
JS::CompartmentOptions::typeInference(const ExclusiveContext *cx) const
{
/* Unlike the other options that can be overriden on a per compartment
* basis, the default value for the typeInference option is stored on the
* compartment's type zone, rather than the current JSContext. Type zones
* copy this default value over from the current JSContext when they are
* created.
*/
return typeInferenceOverride_.get(cx->compartment()->zone()->types.inferenceEnabled);
}
bool
JS::CompartmentOptions::ion(JSContext *cx) const
{
return ionOverride_.get(cx->options().ion());
}
bool
JS::CompartmentOptions::asmJS(JSContext *cx) const
{
return asmJSOverride_.get(cx->options().asmJS());
}
JS::CompartmentOptions &
JS::CompartmentOptions::setZone(ZoneSpecifier spec)
{
@ -2520,6 +2550,18 @@ JS::CompartmentOptions::setSameZoneAs(JSObject *obj)
return *this;
}
JS::CompartmentOptions &
JS::CompartmentOptionsRef(JSCompartment *compartment)
{
return compartment->options();
}
JS::CompartmentOptions &
JS::CompartmentOptionsRef(JSContext *cx)
{
return cx->compartment()->options();
}
JS_PUBLIC_API(JSObject *)
JS_NewGlobalObject(JSContext *cx, const JSClass *clasp, JSPrincipals *principals,
JS::OnNewGlobalHookOption hookOption,

View File

@ -1440,9 +1440,9 @@ class JS_PUBLIC_API(ContextOptions) {
dontReportUncaught_(false),
noDefaultCompartmentObject_(false),
noScriptRval_(false),
strictMode_(false),
baseline_(false),
typeInference_(false),
strictMode_(false),
ion_(false),
asmJS_(false)
{
@ -1528,6 +1528,16 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
bool strictMode() const { return strictMode_; }
ContextOptions &setStrictMode(bool flag) {
strictMode_ = flag;
return *this;
}
ContextOptions &toggleStrictMode() {
strictMode_ = !strictMode_;
return *this;
}
bool baseline() const { return baseline_; }
ContextOptions &setBaseline(bool flag) {
baseline_ = flag;
@ -1548,16 +1558,6 @@ class JS_PUBLIC_API(ContextOptions) {
return *this;
}
bool strictMode() const { return strictMode_; }
ContextOptions &setStrictMode(bool flag) {
strictMode_ = flag;
return *this;
}
ContextOptions &toggleStrictMode() {
strictMode_ = !strictMode_;
return *this;
}
bool ion() const { return ion_; }
ContextOptions &setIon(bool flag) {
ion_ = flag;
@ -1587,9 +1587,9 @@ class JS_PUBLIC_API(ContextOptions) {
bool dontReportUncaught_ : 1;
bool noDefaultCompartmentObject_ : 1;
bool noScriptRval_ : 1;
bool strictMode_ : 1;
bool baseline_ : 1;
bool typeInference_ : 1;
bool strictMode_ : 1;
bool ion_ : 1;
bool asmJS_ : 1;
};
@ -2546,26 +2546,43 @@ enum ZoneSpecifier {
class JS_PUBLIC_API(CompartmentOptions)
{
union {
ZoneSpecifier spec;
void *pointer; // js::Zone* is not exposed in the API.
} zone_;
JSVersion version_;
public:
bool invisibleToDebugger;
class Override {
public:
Override() : mode_(Default) {}
bool get(bool defaultValue) const {
if (mode_ == Default)
return defaultValue;
return mode_ == ForceTrue;
};
void set(bool overrideValue) {
mode_ = overrideValue ? ForceTrue : ForceFalse;
};
void reset() {
mode_ = Default;
}
private:
enum Mode {
Default,
ForceTrue,
ForceFalse
};
Mode mode_;
};
explicit CompartmentOptions()
: version_(JSVERSION_UNKNOWN)
, invisibleToDebugger(false)
, invisibleToDebugger_(false)
{
zone_.spec = JS::FreshZone;
}
CompartmentOptions &setZone(ZoneSpecifier spec);
CompartmentOptions &setSameZoneAs(JSObject *obj);
JSVersion version() const { return version_; }
CompartmentOptions &setVersion(JSVersion aVersion) {
MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
version_ = aVersion;
@ -2576,21 +2593,51 @@ class JS_PUBLIC_API(CompartmentOptions)
// of the embedding, and references to them should never leak out to script.
// This flag causes the this compartment to skip firing onNewGlobalObject
// and makes addDebuggee a no-op for this global.
CompartmentOptions &setInvisibleToDebugger(bool invisible) {
invisibleToDebugger = invisible;
bool invisibleToDebugger() { return invisibleToDebugger_; }
CompartmentOptions &setInvisibleToDebugger(bool flag) {
invisibleToDebugger_ = flag;
return *this;
}
ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
bool baseline(JSContext *cx) const;
Override &baselineOverride() { return baselineOverride_; }
JSVersion version() const { return version_; }
bool typeInference(const js::ExclusiveContext *cx) const;
Override &typeInferenceOverride() { return typeInferenceOverride_; }
bool ion(JSContext *cx) const;
Override &ionOverride() { return ionOverride_; }
bool asmJS(JSContext *cx) const;
Override &asmJSOverride() { return asmJSOverride_; }
void *zonePointer() const {
JS_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
return zone_.pointer;
}
ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
CompartmentOptions &setZone(ZoneSpecifier spec);
CompartmentOptions &setSameZoneAs(JSObject *obj);
private:
JSVersion version_;
bool invisibleToDebugger_;
Override baselineOverride_;
Override typeInferenceOverride_;
Override ionOverride_;
Override asmJSOverride_;
union {
ZoneSpecifier spec;
void *pointer; // js::Zone* is not exposed in the API.
} zone_;
};
JS_PUBLIC_API(CompartmentOptions &)
CompartmentOptionsRef(JSCompartment *compartment);
JS_PUBLIC_API(CompartmentOptions &)
CompartmentOptionsRef(JSContext *cx);
// During global creation, we fire notifications to callbacks registered
// via the Debugger API. These callbacks are arbitrary script, and can touch
// the global in arbitrary ways. When that happens, the global should not be

View File

@ -453,7 +453,7 @@ namespace js {
inline bool
ExclusiveContext::typeInferenceEnabled() const
{
return compartment_->zone()->types.inferenceEnabled;
return compartment_->options().typeInference(this);
}
inline js::Handle<js::GlobalObject*>

View File

@ -1333,7 +1333,7 @@ void
Debugger::slowPathOnNewGlobalObject(JSContext *cx, Handle<GlobalObject *> global)
{
JS_ASSERT(!JS_CLIST_IS_EMPTY(&cx->runtime()->onNewGlobalObjectWatchers));
if (global->compartment()->options().invisibleToDebugger)
if (global->compartment()->options().invisibleToDebugger())
return;
/*
@ -1951,7 +1951,7 @@ Debugger::addAllGlobalsAsDebuggees(JSContext *cx, unsigned argc, Value *vp)
THIS_DEBUGGER(cx, argc, vp, "addAllGlobalsAsDebuggees", args, dbg);
AutoDebugModeGC dmgc(cx->runtime());
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
if (c == dbg->object->compartment() || c->options().invisibleToDebugger)
if (c == dbg->object->compartment() || c->options().invisibleToDebugger())
continue;
c->zone()->scheduledForDestruction = false;
GlobalObject *global = c->maybeGlobal();
@ -2134,7 +2134,7 @@ Debugger::addDebuggeeGlobal(JSContext *cx,
// with certain testing aides we expose in the shell, so just make addDebuggee
// throw in that case.
JSCompartment *debuggeeCompartment = global->compartment();
if (debuggeeCompartment->options().invisibleToDebugger) {
if (debuggeeCompartment->options().invisibleToDebugger()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
JSMSG_DEBUG_CANT_DEBUG_GLOBAL);
return false;

View File

@ -701,7 +701,7 @@ Debugger::onNewScript(JSContext *cx, HandleScript script, GlobalObject *compileA
JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal == &script->uninlinedGlobal());
// We early return in slowPathOnNewScript for self-hosted scripts, so we can
// ignore those in our assertion here.
JS_ASSERT_IF(!script->compartment()->options().invisibleToDebugger &&
JS_ASSERT_IF(!script->compartment()->options().invisibleToDebugger() &&
!script->selfHosted,
script->compartment()->firedOnNewGlobalObject);
JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);