Bug 1564349 part 1 - Convert Baseline/Ion/NativeRegExp prefs from ContextOptions to JitOptions. r=nbp,smaug
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 10 Jul 2019 09:43:39 +0000
changeset 482137 4f267c2d1a7c13de18ab06beb4b224838950d889
parent 482136 07df7588275399c0008f811069f23f2c97c9b084
child 482138 be4f68034abd0676dd48a572722258ffba09731d
push id89592
push userjdemooij@mozilla.com
push dateWed, 10 Jul 2019 10:32:07 +0000
treeherderautoland@be4f68034abd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp, smaug
bugs1564349
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1564349 part 1 - Convert Baseline/Ion/NativeRegExp prefs from ContextOptions to JitOptions. r=nbp,smaug Using process-wide prefs is consistent with the other JIT options and is simpler to work with (one place to initialize for all runtimes). Differential Revision: https://phabricator.services.mozilla.com/D37385
dom/workers/RuntimeService.cpp
js/public/ContextOptions.h
js/rust/src/rust.rs
js/src/builtin/TestingFunctions.cpp
js/src/irregexp/RegExpEngine.cpp
js/src/jit/Bailouts.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineJIT.cpp
js/src/jit/BaselineJIT.h
js/src/jit/CacheIR.cpp
js/src/jit/Ion.cpp
js/src/jit/Ion.h
js/src/jit/IonAnalysis.cpp
js/src/jit/Jit.cpp
js/src/jit/JitOptions.cpp
js/src/jit/JitOptions.h
js/src/jit/VMFunctions.cpp
js/src/jsapi-tests/testChromeBuffer.cpp
js/src/jsapi-tests/testPreserveJitCode.cpp
js/src/jsapi-tests/testProfileStrings.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/src/vm/Interpreter.cpp
js/xpconnect/idl/xpccomponents.idl
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSContext.cpp
js/xpconnect/src/XPCShellImpl.cpp
modules/libpref/init/all.js
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -295,19 +295,16 @@ void LoadContextOptions(const char* aPre
           GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_cranelift")))
 #endif
 #ifdef ENABLE_WASM_REFTYPES
       .setWasmGc(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_gc")))
 #endif
       .setWasmVerbose(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm_verbose")))
       .setThrowOnAsmJSValidationFailure(GetWorkerPref<bool>(
           NS_LITERAL_CSTRING("throw_on_asmjs_validation_failure")))
-      .setBaseline(GetWorkerPref<bool>(NS_LITERAL_CSTRING("baselinejit")))
-      .setIon(GetWorkerPref<bool>(NS_LITERAL_CSTRING("ion")))
-      .setNativeRegExp(GetWorkerPref<bool>(NS_LITERAL_CSTRING("native_regexp")))
       .setAsyncStack(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asyncstack")))
       .setWerror(GetWorkerPref<bool>(NS_LITERAL_CSTRING("werror")))
 #ifdef FUZZING
       .setFuzzing(GetWorkerPref<bool>(NS_LITERAL_CSTRING("fuzzing.enabled")))
 #endif
       .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")));
 
   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
--- a/js/public/ContextOptions.h
+++ b/js/public/ContextOptions.h
@@ -13,65 +13,42 @@
 
 struct JSContext;
 
 namespace JS {
 
 class JS_PUBLIC_API ContextOptions {
  public:
   ContextOptions()
-      : baseline_(true),
-        ion_(true),
-        asmJS_(true),
+      : asmJS_(true),
         wasm_(true),
         wasmVerbose_(false),
         wasmBaseline_(true),
         wasmIon_(true),
 #ifdef ENABLE_WASM_CRANELIFT
         wasmCranelift_(false),
 #endif
 #ifdef ENABLE_WASM_GC
         wasmGc_(false),
 #endif
         testWasmAwaitTier2_(false),
         throwOnAsmJSValidationFailure_(false),
-        nativeRegExp_(true),
         asyncStack_(true),
         throwOnDebuggeeWouldRun_(true),
         dumpStackOnDebuggeeWouldRun_(false),
         werror_(false),
         strictMode_(false),
         extraWarnings_(false)
 #ifdef FUZZING
         ,
         fuzzing_(false)
 #endif
   {
   }
 
-  bool baseline() const { return baseline_; }
-  ContextOptions& setBaseline(bool flag) {
-    baseline_ = flag;
-    return *this;
-  }
-  ContextOptions& toggleBaseline() {
-    baseline_ = !baseline_;
-    return *this;
-  }
-
-  bool ion() const { return ion_; }
-  ContextOptions& setIon(bool flag) {
-    ion_ = flag;
-    return *this;
-  }
-  ContextOptions& toggleIon() {
-    ion_ = !ion_;
-    return *this;
-  }
-
   bool asmJS() const { return asmJS_; }
   ContextOptions& setAsmJS(bool flag) {
     asmJS_ = flag;
     return *this;
   }
   ContextOptions& toggleAsmJS() {
     asmJS_ = !asmJS_;
     return *this;
@@ -134,22 +111,16 @@ class JS_PUBLIC_API ContextOptions {
     throwOnAsmJSValidationFailure_ = flag;
     return *this;
   }
   ContextOptions& toggleThrowOnAsmJSValidationFailure() {
     throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
     return *this;
   }
 
-  bool nativeRegExp() const { return nativeRegExp_; }
-  ContextOptions& setNativeRegExp(bool flag) {
-    nativeRegExp_ = flag;
-    return *this;
-  }
-
   bool asyncStack() const { return asyncStack_; }
   ContextOptions& setAsyncStack(bool flag) {
     asyncStack_ = flag;
     return *this;
   }
 
   bool throwOnDebuggeeWouldRun() const { return throwOnDebuggeeWouldRun_; }
   ContextOptions& setThrowOnDebuggeeWouldRun(bool flag) {
@@ -199,45 +170,39 @@ class JS_PUBLIC_API ContextOptions {
   bool fuzzing() const { return fuzzing_; }
   ContextOptions& setFuzzing(bool flag) {
     fuzzing_ = flag;
     return *this;
   }
 #endif
 
   void disableOptionsForSafeMode() {
-    setBaseline(false);
-    setIon(false);
     setAsmJS(false);
     setWasm(false);
     setWasmBaseline(false);
     setWasmIon(false);
 #ifdef ENABLE_WASM_GC
     setWasmGc(false);
 #endif
-    setNativeRegExp(false);
   }
 
  private:
-  bool baseline_ : 1;
-  bool ion_ : 1;
   bool asmJS_ : 1;
   bool wasm_ : 1;
   bool wasmVerbose_ : 1;
   bool wasmBaseline_ : 1;
   bool wasmIon_ : 1;
 #ifdef ENABLE_WASM_CRANELIFT
   bool wasmCranelift_ : 1;
 #endif
 #ifdef ENABLE_WASM_GC
   bool wasmGc_ : 1;
 #endif
   bool testWasmAwaitTier2_ : 1;
   bool throwOnAsmJSValidationFailure_ : 1;
-  bool nativeRegExp_ : 1;
   bool asyncStack_ : 1;
   bool throwOnDebuggeeWouldRun_ : 1;
   bool dumpStackOnDebuggeeWouldRun_ : 1;
   bool werror_ : 1;
   bool strictMode_ : 1;
   bool extraWarnings_ : 1;
 #ifdef FUZZING
   bool fuzzing_ : 1;
--- a/js/rust/src/rust.rs
+++ b/js/rust/src/rust.rs
@@ -173,21 +173,16 @@ impl Runtime {
                 js_context, JSGCParamKey::JSGC_MAX_BYTES, u32::MAX);
 
             JS_SetNativeStackQuota(
                 js_context,
                 STACK_QUOTA,
                 STACK_QUOTA - SYSTEM_CODE_BUFFER,
                 STACK_QUOTA - SYSTEM_CODE_BUFFER - TRUSTED_SCRIPT_BUFFER);
 
-            let opts = JS::ContextOptionsRef(js_context);
-            (*opts).set_baseline_(true);
-            (*opts).set_ion_(true);
-            (*opts).set_nativeRegExp_(true);
-
             CONTEXT.with(|context| {
                 assert!(context.get().is_null());
                 context.set(js_context);
             });
 
             if use_internal_job_queue {
                 assert!(js::UseInternalJobQueues(js_context));
             }
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2807,17 +2807,17 @@ static bool testingFunc_bailAfter(JSCont
 static constexpr unsigned JitWarmupResetLimit = 20;
 static_assert(JitWarmupResetLimit <=
                   unsigned(JSScript::MutableFlags::WarmupResets_MASK),
               "JitWarmupResetLimit exceeds max value");
 
 static bool testingFunc_inJit(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  if (!jit::IsBaselineEnabled(cx)) {
+  if (!jit::IsBaselineJitEnabled()) {
     return ReturnStringCopy(cx, args, "Baseline is disabled.");
   }
 
   // Use frame iterator to inspect caller.
   FrameIter iter(cx);
   MOZ_ASSERT(!iter.done());
 
   if (iter.hasScript()) {
@@ -2835,17 +2835,17 @@ static bool testingFunc_inJit(JSContext*
   MOZ_ASSERT_IF(iter.isJSJit(), cx->currentlyRunningInJit());
   args.rval().setBoolean(cx->currentlyRunningInJit());
   return true;
 }
 
 static bool testingFunc_inIon(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  if (!jit::IsIonEnabled(cx)) {
+  if (!jit::IsIonEnabled()) {
     return ReturnStringCopy(cx, args, "Ion is disabled.");
   }
 
   // Use frame iterator to inspect caller.
   FrameIter iter(cx);
   MOZ_ASSERT(!iter.done());
 
   if (iter.hasScript()) {
@@ -5705,17 +5705,17 @@ static bool BaselineCompile(JSContext* c
             cx, callee, "unsupported case: recompiling script for debug mode");
         return false;
       }
 
       args.rval().setUndefined();
       return true;
     }
 
-    if (!jit::IsBaselineEnabled(cx)) {
+    if (!jit::IsBaselineJitEnabled()) {
       returnedStr = "baseline disabled";
       break;
     }
     if (!script->canBaselineCompile()) {
       returnedStr = "can't compile";
       break;
     }
     if (!cx->realm()->ensureJitRealmExists(cx)) {
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -33,16 +33,17 @@
 #include <utility>
 
 #include "gc/GC.h"
 #include "irregexp/NativeRegExpMacroAssembler.h"
 #include "irregexp/RegExpCharacters.h"
 #include "irregexp/RegExpMacroAssembler.h"
 #include "jit/ExecutableAllocator.h"
 #include "jit/JitCommon.h"
+#include "jit/JitOptions.h"
 
 #include "irregexp/RegExpCharacters-inl.h"
 
 using namespace js;
 using namespace js::irregexp;
 
 using mozilla::ArrayLength;
 using mozilla::DebugOnly;
@@ -1720,22 +1721,22 @@ SampleChars(FrequencyCollator* collator,
          i < length && chars_sampled < kSampleSize;
          i++, chars_sampled++)
     {
         collator->CountCharacter(chars[i]);
     }
 }
 
 static bool
-IsNativeRegExpEnabled(JSContext* cx)
+IsNativeRegExpEnabled()
 {
 #ifdef JS_CODEGEN_NONE
     return false;
 #else
-    return cx->options().nativeRegExp();
+    return jit::JitOptions.nativeRegExp;
 #endif
 }
 
 RegExpCode
 irregexp::CompilePattern(JSContext* cx, LifoAlloc& alloc, HandleRegExpShared shared,
                          RegExpCompileData* data, HandleLinearString sample, bool is_global,
                          bool ignore_case, bool is_latin1, bool match_only, bool force_bytecode,
                          bool sticky, bool unicode, RegExpShared::JitCodeTables& tables)
@@ -1822,17 +1823,17 @@ irregexp::CompilePattern(JSContext* cx, 
     // Maybe<NativeRegExpMacroAssembler> below.
     JS::AutoCheckCannotGC nogc(cx);
 
     Maybe<jit::JitContext> ctx;
     Maybe<NativeRegExpMacroAssembler> native_assembler;
     Maybe<InterpretedRegExpMacroAssembler> interpreted_assembler;
 
     RegExpMacroAssembler* assembler;
-    if (IsNativeRegExpEnabled(cx) &&
+    if (IsNativeRegExpEnabled() &&
         !force_bytecode &&
         jit::CanLikelyAllocateMoreExecutableMemory() &&
         shared->getSource()->length() < 32 * 1024)
     {
         NativeRegExpMacroAssembler::Mode mode =
             is_latin1 ? NativeRegExpMacroAssembler::LATIN1
                       : NativeRegExpMacroAssembler::CHAR16;
 
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -44,17 +44,17 @@ bool jit::Bailout(BailoutStack* sp, Base
   CommonFrameLayout* currentFramePtr = frame.current();
 
   TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
   TraceLogTimestamp(logger, TraceLogger_Bailout);
 
   JitSpew(JitSpew_IonBailouts, "Took bailout! Snapshot offset: %d",
           frame.snapshotOffset());
 
-  MOZ_ASSERT(IsBaselineEnabled(cx));
+  MOZ_ASSERT(IsBaselineJitEnabled());
 
   *bailoutInfo = nullptr;
   bool success = BailoutIonToBaseline(cx, bailoutData.activation(), frame,
                                       false, bailoutInfo,
                                       /* excInfo = */ nullptr);
   MOZ_ASSERT_IF(success, *bailoutInfo != nullptr);
 
   if (!success) {
@@ -121,17 +121,17 @@ bool jit::InvalidationBailout(Invalidati
   TraceLogTimestamp(logger, TraceLogger_Invalidation);
 
   JitSpew(JitSpew_IonBailouts, "Took invalidation bailout! Snapshot offset: %d",
           frame.snapshotOffset());
 
   // Note: the frame size must be computed before we return from this function.
   *frameSizeOut = frame.frameSize();
 
-  MOZ_ASSERT(IsBaselineEnabled(cx));
+  MOZ_ASSERT(IsBaselineJitEnabled());
 
   *bailoutInfo = nullptr;
   bool success = BailoutIonToBaseline(cx, bailoutData.activation(), frame, true,
                                       bailoutInfo,
                                       /* excInfo = */ nullptr);
   MOZ_ASSERT_IF(success, *bailoutInfo != nullptr);
 
   if (!success) {
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -55,18 +55,17 @@ BaselineCompilerHandler::BaselineCompile
                                                  JSScript* script)
     : frame_(script, masm),
       alloc_(alloc),
       analysis_(alloc, script),
       script_(script),
       pc_(script->code()),
       icEntryIndex_(0),
       compileDebugInstrumentation_(script->isDebuggee()),
-      ionCompileable_(jit::IsIonEnabled(cx) &&
-                      CanIonCompileScript(cx, script)) {}
+      ionCompileable_(jit::IsIonEnabled() && CanIonCompileScript(cx, script)) {}
 
 BaselineInterpreterHandler::BaselineInterpreterHandler(JSContext* cx,
                                                        MacroAssembler& masm)
     : frame_(masm) {}
 
 template <typename Handler>
 template <typename... HandlerArgs>
 BaselineCodeGen<Handler>::BaselineCodeGen(JSContext* cx, HandlerArgs&&... args)
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -154,17 +154,17 @@ class MOZ_RAII FallbackStubAllocator {
     return ICStub::NewFallback<T>(cx_, &stubSpace_, addr,
                                   std::forward<Args>(args)...);
   }
 };
 
 bool JitScript::initICEntriesAndBytecodeTypeMap(JSContext* cx,
                                                 JSScript* script) {
   MOZ_ASSERT(cx->realm()->jitRealm());
-  MOZ_ASSERT(jit::IsBaselineInterpreterOrJitEnabled(cx));
+  MOZ_ASSERT(jit::IsBaselineInterpreterOrJitEnabled());
 
   MOZ_ASSERT(numICEntries() == script->numICEntries());
 
   FallbackStubAllocator alloc(cx, fallbackStubSpace_);
 
   // Index of the next ICEntry to initialize.
   uint32_t icEntryIndex = 0;
 
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -80,17 +80,17 @@ static JitExecStatus EnterBaseline(JSCon
   // Assert we don't GC before entering JIT code. A GC could discard JIT code
   // or move the function stored in the CalleeToken (it won't be traced at
   // this point). We use Maybe<> here so we can call reset() to call the
   // AutoAssertNoGC destructor before we enter JIT code.
   mozilla::Maybe<JS::AutoAssertNoGC> nogc;
   nogc.emplace(cx);
 #endif
 
-  MOZ_ASSERT(IsBaselineInterpreterOrJitEnabled(cx));
+  MOZ_ASSERT(IsBaselineInterpreterOrJitEnabled());
   MOZ_ASSERT(CheckFrame(data.osrFrame));
 
   EnterJitCode enter = cx->runtime()->jitRuntime()->enterJit();
 
   // Caller must construct |this| before invoking the function.
   MOZ_ASSERT_IF(data.constructing,
                 data.maxArgv[0].isObject() ||
                     data.maxArgv[0].isMagic(JS_UNINITIALIZED_LEXICAL));
@@ -201,17 +201,17 @@ JitExecStatus jit::EnterBaselineAtBranch
   return JitExec_Ok;
 }
 
 MethodStatus jit::BaselineCompile(JSContext* cx, JSScript* script,
                                   bool forceDebugInstrumentation) {
   cx->check(script);
   MOZ_ASSERT(!script->hasBaselineScript());
   MOZ_ASSERT(script->canBaselineCompile());
-  MOZ_ASSERT(IsBaselineEnabled(cx));
+  MOZ_ASSERT(IsBaselineJitEnabled());
   AutoGeckoProfilerEntry pseudoFrame(
       cx, "Baseline script compilation",
       JS::ProfilingCategoryPair::JS_BaselineCompilation);
 
   script->ensureNonLazyCanonicalFunction();
 
   TempAllocator temp(&cx->tempLifoAlloc());
   JitContext jctx(cx, nullptr);
@@ -240,17 +240,17 @@ MethodStatus jit::BaselineCompile(JSCont
 
 static MethodStatus CanEnterBaselineJIT(JSContext* cx, HandleScript script,
                                         AbstractFramePtr osrSourceFrame) {
   // Skip if the script has been disabled.
   if (!script->canBaselineCompile()) {
     return Method_Skipped;
   }
 
-  if (!IsBaselineEnabled(cx)) {
+  if (!IsBaselineJitEnabled()) {
     script->setBaselineScript(cx->runtime(), BASELINE_DISABLED_SCRIPT);
     return Method_CantCompile;
   }
 
   // This check is needed in the following corner case. Consider a function h,
   //
   //   function h(x) {
   //      if (!x)
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -527,34 +527,34 @@ struct BaselineScript final {
   }
 
   size_t allocBytes() const { return allocBytes_; }
 };
 static_assert(
     sizeof(BaselineScript) % sizeof(uintptr_t) == 0,
     "The data attached to the script must be aligned for fast JIT access.");
 
-inline bool IsBaselineEnabled(JSContext* cx) {
+inline bool IsBaselineJitEnabled() {
 #ifdef JS_CODEGEN_NONE
   return false;
 #else
-  return cx->options().baseline() && JitOptions.supportsFloatingPoint;
+  return JitOptions.baselineJit && JitOptions.supportsFloatingPoint;
 #endif
 }
 
 inline bool IsBaselineInterpreterEnabled() {
 #ifdef JS_CODEGEN_NONE
   return false;
 #else
   return JitOptions.baselineInterpreter && JitOptions.supportsFloatingPoint;
 #endif
 }
 
-inline bool IsBaselineInterpreterOrJitEnabled(JSContext* cx) {
-  return IsBaselineInterpreterEnabled() || IsBaselineEnabled(cx);
+inline bool IsBaselineInterpreterOrJitEnabled() {
+  return IsBaselineInterpreterEnabled() || IsBaselineJitEnabled();
 }
 
 enum class BaselineTier { Interpreter, Compiler };
 
 template <BaselineTier Tier>
 MethodStatus CanEnterBaselineMethod(JSContext* cx, RunState& state);
 
 template <BaselineTier Tier>
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1826,17 +1826,17 @@ AttachDecision GetPropIRGenerator::tryAt
     return AttachDecision::NoAction;
   }
 
   // Don't emit a stub until the target binding has been initialized.
   if (env->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL)) {
     return AttachDecision::NoAction;
   }
 
-  if (IsIonEnabled(cx_)) {
+  if (IsIonEnabled()) {
     EnsureTrackPropertyTypes(cx_, env, shape->propid());
   }
 
   // Check for the specific namespace object.
   maybeEmitIdGuard(id);
   writer.guardSpecificObject(objId, ns);
 
   ObjOperandId envId = writer.loadObject(env);
@@ -1892,17 +1892,17 @@ AttachDecision GetPropIRGenerator::tryAt
   switch (type) {
     case CanAttachNone:
       return AttachDecision::NoAction;
     case CanAttachTemporarilyUnoptimizable:
       return AttachDecision::TemporarilyUnoptimizable;
     case CanAttachReadSlot: {
       if (holder) {
         // Instantiate this property, for use during Ion compilation.
-        if (IsIonEnabled(cx_)) {
+        if (IsIonEnabled()) {
           EnsureTrackPropertyTypes(cx_, holder, id);
         }
       }
 
       if (val_.isNumber()) {
         writer.guardIsNumber(valId);
       } else {
         writer.guardType(valId, val_.type());
@@ -2472,17 +2472,17 @@ AttachDecision GetNameIRGenerator::tryAt
   }
 
   // This might still be an uninitialized lexical.
   if (holder->getSlot(shape->slot()).isMagic()) {
     return AttachDecision::NoAction;
   }
 
   // Instantiate this global property, for use during Ion compilation.
-  if (IsIonEnabled(cx_)) {
+  if (IsIonEnabled()) {
     EnsureTrackPropertyTypes(cx_, holder, id);
   }
 
   if (holder == globalLexical) {
     // There is no need to guard on the shape. Lexical bindings are
     // non-configurable, and this stub cannot be shared across globals.
     size_t dynamicSlotOffset =
         holder->dynamicSlotIndex(shape->slot()) * sizeof(Value);
@@ -2540,17 +2540,17 @@ AttachDecision GetNameIRGenerator::tryAt
     return AttachDecision::NoAction;
   }
 
   if (IsCacheableGetPropCall(&globalLexical->global(), holder, shape) !=
       CanAttachNativeGetter) {
     return AttachDecision::NoAction;
   }
 
-  if (IsIonEnabled(cx_)) {
+  if (IsIonEnabled()) {
     EnsureTrackPropertyTypes(cx_, holder, id);
   }
 
   // Shape guard for global lexical.
   writer.guardShape(objId, globalLexical->lastProperty());
 
   // Guard on the shape of the GlobalObject.
   ObjOperandId globalId = writer.loadEnclosingEnvironment(objId);
@@ -5059,17 +5059,17 @@ AttachDecision CallIRGenerator::tryAttac
     // If we're constructing, require the callee to have a JitScript. This isn't
     // required for correctness but avoids allocating a template object below
     // for constructors that aren't hot. See bug 1419758.
     return AttachDecision::TemporarilyUnoptimizable;
   }
 
   // Keep track of the function's |prototype| property in type
   // information, for use during Ion compilation.
-  if (IsIonEnabled(cx_)) {
+  if (IsIonEnabled()) {
     EnsureTrackPropertyTypes(cx_, calleeFunc, NameToId(cx_->names().prototype));
   }
 
   RootedObject templateObj(cx_);
   bool skipAttach = false;
   if (isConstructing && isSpecialized &&
       !getTemplateObjectForScripted(calleeFunc, &templateObj, &skipAttach)) {
     cx_->clearPendingException();
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2102,18 +2102,18 @@ bool CanIonInlineScript(JSScript* script
 static OptimizationLevel GetOptimizationLevel(HandleScript script,
                                               jsbytecode* pc) {
   return IonOptimizations.levelForScript(script, pc);
 }
 
 static MethodStatus Compile(JSContext* cx, HandleScript script,
                             BaselineFrame* osrFrame, jsbytecode* osrPc,
                             bool forceRecompile = false) {
-  MOZ_ASSERT(jit::IsIonEnabled(cx));
-  MOZ_ASSERT(jit::IsBaselineEnabled(cx));
+  MOZ_ASSERT(jit::IsIonEnabled());
+  MOZ_ASSERT(jit::IsBaselineJitEnabled());
   MOZ_ASSERT_IF(osrPc != nullptr, LoopEntryCanIonOsr(osrPc));
   AutoGeckoProfilerEntry pseudoFrame(
       cx, "Ion script compilation",
       JS::ProfilingCategoryPair::JS_IonCompilation);
 
   if (!script->hasBaselineScript()) {
     return Method_Skipped;
   }
@@ -2202,17 +2202,17 @@ bool jit::OffThreadCompilationAvailable(
   //
   // Require cpuCount > 1 so that Ion compilation jobs and active-thread
   // execution are not competing for the same resources.
   return cx->runtime()->canUseOffthreadIonCompilation() &&
          HelperThreadState().cpuCount > 1 && CanUseExtraThreads();
 }
 
 MethodStatus jit::CanEnterIon(JSContext* cx, RunState& state) {
-  MOZ_ASSERT(jit::IsIonEnabled(cx));
+  MOZ_ASSERT(jit::IsIonEnabled());
 
   HandleScript script = state.script();
 
   // Skip if the script has been disabled.
   if (!script->canIonCompile()) {
     return Method_Skipped;
   }
 
@@ -2275,17 +2275,17 @@ MethodStatus jit::CanEnterIon(JSContext*
     }
   }
 
   return Method_Compiled;
 }
 
 static MethodStatus BaselineCanEnterAtEntry(JSContext* cx, HandleScript script,
                                             BaselineFrame* frame) {
-  MOZ_ASSERT(jit::IsIonEnabled(cx));
+  MOZ_ASSERT(jit::IsIonEnabled());
   MOZ_ASSERT(frame->callee()->nonLazyScript()->canIonCompile());
   MOZ_ASSERT(!frame->callee()->nonLazyScript()->isIonCompilingOffThread());
   MOZ_ASSERT(!frame->callee()->nonLazyScript()->hasIonScript());
   MOZ_ASSERT(frame->isFunctionFrame());
 
   // Mark as forbidden if frame can't be handled.
   if (!CheckFrame(cx, frame)) {
     ForbidCompilation(cx, script);
@@ -2304,17 +2304,17 @@ static MethodStatus BaselineCanEnterAtEn
   return Method_Compiled;
 }
 
 // Decide if a transition from baseline execution to Ion code should occur.
 // May compile or recompile the target JSScript.
 static MethodStatus BaselineCanEnterAtBranch(JSContext* cx, HandleScript script,
                                              BaselineFrame* osrFrame,
                                              jsbytecode* pc) {
-  MOZ_ASSERT(jit::IsIonEnabled(cx));
+  MOZ_ASSERT(jit::IsIonEnabled());
   MOZ_ASSERT((JSOp)*pc == JSOP_LOOPENTRY);
   MOZ_ASSERT(LoopEntryCanIonOsr(pc));
 
   // Skip if the script has been disabled.
   if (!script->canIonCompile()) {
     return Method_Skipped;
   }
 
@@ -2379,17 +2379,17 @@ static MethodStatus BaselineCanEnterAtBr
   }
 
   return Method_Compiled;
 }
 
 bool jit::IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame,
                                       jsbytecode* pc) {
   // A TI OOM will disable TI and Ion.
-  if (!jit::IsIonEnabled(cx)) {
+  if (!jit::IsIonEnabled()) {
     return true;
   }
 
   RootedScript script(cx, frame->script());
   bool isLoopEntry = JSOp(*pc) == JSOP_LOOPENTRY;
 
   MOZ_ASSERT(!isLoopEntry || LoopEntryCanIonOsr(pc));
 
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -158,21 +158,21 @@ CodeGenerator* CompileBackEnd(MIRGenerat
 void AttachFinishedCompilations(JSContext* cx);
 void FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
                             const AutoLockHelperThreadState& lock);
 void FreeIonBuilder(IonBuilder* builder);
 
 void LinkIonScript(JSContext* cx, HandleScript calleescript);
 uint8_t* LazyLinkTopActivation(JSContext* cx, LazyLinkExitFrameLayout* frame);
 
-static inline bool IsIonEnabled(JSContext* cx) {
+static inline bool IsIonEnabled() {
 #if defined(JS_CODEGEN_NONE)
   return false;
 #else
-  return cx->options().ion() && cx->options().baseline() &&
+  return JitOptions.ion && JitOptions.baselineJit &&
          JitOptions.supportsFloatingPoint;
 #endif
 }
 
 inline bool IsIonInlinableGetterOrSetterPC(jsbytecode* pc) {
   // GETPROP, CALLPROP, LENGTH, GETELEM, and JSOP_CALLELEM. (Inlined Getters)
   // SETPROP, SETNAME, SETGNAME (Inlined Setters)
   return IsGetPropPC(pc) || IsGetElemPC(pc) || IsSetPropPC(pc);
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -4514,17 +4514,17 @@ bool jit::AnalyzeNewScriptDefiniteProper
   // which will definitely be added to the created object before it has a
   // chance to escape and be accessed elsewhere.
 
   RootedScript script(cx, JSFunction::getOrCreateScript(cx, fun));
   if (!script) {
     return false;
   }
 
-  if (!jit::IsIonEnabled(cx) || !jit::IsBaselineEnabled(cx) ||
+  if (!jit::IsIonEnabled() || !jit::IsBaselineJitEnabled() ||
       !script->canBaselineCompile()) {
     return true;
   }
 
   static const uint32_t MAX_SCRIPT_SIZE = 2000;
   if (script->length() > MAX_SCRIPT_SIZE) {
     return true;
   }
@@ -4780,17 +4780,17 @@ bool jit::AnalyzeArgumentsUsage(JSContex
   // direct eval is present.
   //
   // FIXME: Don't build arguments for ES6 generator expressions.
   if (scriptArg->isDebuggee() || script->isGenerator() || script->isAsync() ||
       script->bindingsAccessedDynamically()) {
     return true;
   }
 
-  if (!jit::IsIonEnabled(cx)) {
+  if (!jit::IsIonEnabled()) {
     return true;
   }
 
   static const uint32_t MAX_SCRIPT_SIZE = 10000;
   if (script->length() > MAX_SCRIPT_SIZE) {
     return true;
   }
 
--- a/js/src/jit/Jit.cpp
+++ b/js/src/jit/Jit.cpp
@@ -20,17 +20,17 @@ using namespace js::jit;
 static EnterJitStatus JS_HAZ_JSNATIVE_CALLER EnterJit(JSContext* cx,
                                                       RunState& state,
                                                       uint8_t* code) {
   // We don't want to call the interpreter stub here (because
   // C++ -> interpreterStub -> C++ is slower than staying in C++).
   MOZ_ASSERT(code);
   MOZ_ASSERT(code != cx->runtime()->jitRuntime()->interpreterStub().value);
 
-  MOZ_ASSERT(IsBaselineInterpreterOrJitEnabled(cx));
+  MOZ_ASSERT(IsBaselineInterpreterOrJitEnabled());
 
   if (!CheckRecursionLimit(cx)) {
     return EnterJitStatus::Error;
   }
 
 #ifdef DEBUG
   // Assert we don't GC before entering JIT code. A GC could discard JIT code
   // or move the function stored in the CalleeToken (it won't be traced at
@@ -148,29 +148,29 @@ EnterJitStatus js::jit::MaybeEnterJit(JS
       if (script->hasBaselineScript()) {
         break;
       }
     }
 
     script->incWarmUpCounter();
 
     // Try to Ion-compile.
-    if (jit::IsIonEnabled(cx)) {
+    if (jit::IsIonEnabled()) {
       jit::MethodStatus status = jit::CanEnterIon(cx, state);
       if (status == jit::Method_Error) {
         return EnterJitStatus::Error;
       }
       if (status == jit::Method_Compiled) {
         code = script->jitCodeRaw();
         break;
       }
     }
 
     // Try to Baseline-compile.
-    if (jit::IsBaselineEnabled(cx)) {
+    if (jit::IsBaselineJitEnabled()) {
       jit::MethodStatus status =
           jit::CanEnterBaselineMethod<BaselineTier::Compiler>(cx, state);
       if (status == jit::Method_Error) {
         return EnterJitStatus::Error;
       }
       if (status == jit::Method_Compiled) {
         code = script->jitCodeRaw();
         break;
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -127,16 +127,25 @@ DefaultJitOptions::DefaultJitOptions() {
 
   // Toggles whether the use of multiple Ion optimization levels is globally
   // disabled.
   SET_DEFAULT(disableOptimizationLevels, false);
 
   // Whether the Baseline Interpreter is enabled.
   SET_DEFAULT(baselineInterpreter, false);
 
+  // Whether the Baseline JIT is enabled.
+  SET_DEFAULT(baselineJit, true);
+
+  // Whether the IonMonkey JIT is enabled.
+  SET_DEFAULT(ion, true);
+
+  // Whether the RegExp JIT is enabled.
+  SET_DEFAULT(nativeRegExp, true);
+
   // Whether IonBuilder should prefer IC generation above specialized MIR.
   SET_DEFAULT(forceInlineCaches, false);
 
   // Toggles whether large scripts are rejected.
   SET_DEFAULT(limitScriptSize, true);
 
   // Toggles whether functions may be entered at loop headers.
   SET_DEFAULT(osr, true);
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -55,16 +55,19 @@ struct DefaultJitOptions {
   bool disableInstructionReordering;
   bool disableRangeAnalysis;
   bool disableRecoverIns;
   bool disableScalarReplacement;
   bool disableCacheIR;
   bool disableSink;
   bool disableOptimizationLevels;
   bool baselineInterpreter;
+  bool baselineJit;
+  bool ion;
+  bool nativeRegExp;
   bool forceInlineCaches;
   bool fullDebugChecks;
   bool limitScriptSize;
   bool osr;
   bool wasmFoldOffsets;
   bool wasmDelayTier2;
 #ifdef JS_TRACE_LOGGING
   bool enableTraceLogger;
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1320,17 +1320,17 @@ bool RecompileImpl(JSContext* cx, bool f
   JSJitFrameIter frame(activations->asJit());
 
   MOZ_ASSERT(frame.type() == FrameType::Exit);
   ++frame;
 
   RootedScript script(cx, frame.script());
   MOZ_ASSERT(script->hasIonScript());
 
-  if (!IsIonEnabled(cx)) {
+  if (!IsIonEnabled()) {
     return true;
   }
 
   MethodStatus status = Recompile(cx, script, nullptr, nullptr, force);
   if (status == Method_Error) {
     return false;
   }
 
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -46,24 +46,26 @@ BEGIN_TEST(testChromeBuffer) {
 
   /*
    * Check that, even after untrusted content has exhausted the stack, code
    * compiled with "trusted principals" can run using reserved trusted-only
    * buffer space.
    */
   {
     // Disable the JIT because if we don't this test fails.  See bug 1160414.
-    JS::ContextOptions oldOptions = JS::ContextOptionsRef(cx);
     uint32_t oldBaselineInterpreterEnabled;
     CHECK(JS_GetGlobalJitCompilerOption(
         cx, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE,
         &oldBaselineInterpreterEnabled));
     JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE,
                                   0);
-    JS::ContextOptionsRef(cx).setIon(false).setBaseline(false);
+    uint32_t oldBaselineJitEnabled;
+    CHECK(JS_GetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_ENABLE,
+                                        &oldBaselineJitEnabled));
+    JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_ENABLE, 0);
     {
       JSAutoRealm ar(cx, trusted_glob);
       const char* paramName = "x";
       static const char bytes[] = "return x ? 1 + trusted(x-1) : 0";
 
       JS::SourceText<mozilla::Utf8Unit> srcBuf;
       CHECK(srcBuf.init(cx, bytes, mozilla::ArrayLength(bytes) - 1,
                         JS::SourceOwnership::Borrowed));
@@ -106,19 +108,20 @@ BEGIN_TEST(testChromeBuffer) {
     fun = JS::CompileFunction(cx, emptyScopeChain, options, "untrusted", 1,
                               &paramName, srcBuf);
     CHECK(fun);
     CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
 
     JS::RootedValue rval(cx);
     CHECK(JS_CallFunction(cx, nullptr, fun, JS::HandleValueArray(v), &rval));
     CHECK(rval.toInt32() == 100);
-    JS::ContextOptionsRef(cx) = oldOptions;
     JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE,
                                   oldBaselineInterpreterEnabled);
+    JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_ENABLE,
+                                  oldBaselineJitEnabled);
   }
 
   /*
    * Check that content called from chrome in the reserved-buffer space
    * immediately ooms.
    */
   {
     {
--- a/js/src/jsapi-tests/testPreserveJitCode.cpp
+++ b/js/src/jsapi-tests/testPreserveJitCode.cpp
@@ -29,27 +29,25 @@ BEGIN_TEST(test_PreserveJitCode) {
 
 unsigned countIonScripts(JSObject* global) {
   unsigned count = 0;
   js::IterateScripts(cx, global->nonCCWRealm(), &count, ScriptCallback);
   return count;
 }
 
 bool testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts) {
-  cx->options().setBaseline(true);
-  cx->options().setIon(true);
   cx->runtime()->setOffthreadIonCompilationEnabled(false);
 
   RootedObject global(cx, createTestGlobal(preserveJitCode));
   CHECK(global);
   JSAutoRealm ar(cx, global);
 
   // The Ion JIT may be unavailable due to --disable-ion or lack of support
   // for this platform.
-  if (!js::jit::IsIonEnabled(cx)) {
+  if (!js::jit::IsIonEnabled()) {
     knownFail = true;
   }
 
   CHECK_EQUAL(countIonScripts(global), 0u);
 
   static const char source[] =
       "var i = 0;\n"
       "var sum = 0;\n"
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -109,17 +109,16 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     CHECK(profilingStack.stackPointer == 0);
   }
   return true;
 }
 END_TEST(testProfileStrings_isCalledWithInterpreter)
 
 BEGIN_TEST(testProfileStrings_isCalledWithJIT) {
   CHECK(initialize(cx));
-  JS::ContextOptionsRef(cx).setBaseline(true).setIon(true);
 
   EXEC("function g() { var p = new Prof(); p.test_fn(); }");
   EXEC("function f() { g(); }");
   EXEC("function e() { f(); }");
   EXEC("function d() { e(); }");
   EXEC("function c() { d(); }");
   EXEC("function b() { c(); }");
   EXEC("function a() { b(); }");
@@ -146,17 +145,16 @@ BEGIN_TEST(testProfileStrings_isCalledWi
   }
 
   return true;
 }
 END_TEST(testProfileStrings_isCalledWithJIT)
 
 BEGIN_TEST(testProfileStrings_isCalledWhenError) {
   CHECK(initialize(cx));
-  JS::ContextOptionsRef(cx).setBaseline(true).setIon(true);
 
   EXEC("function check2() { throw 'a'; }");
 
   reset(cx);
   {
     JS::RootedValue rval(cx);
     /* Make sure the stack resets and we have an entry for each stack */
     bool ok = JS_CallFunctionName(cx, global, "check2",
@@ -169,17 +167,16 @@ BEGIN_TEST(testProfileStrings_isCalledWh
   }
 
   return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
 
 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly) {
   CHECK(initialize(cx));
-  JS::ContextOptionsRef(cx).setBaseline(true).setIon(true);
 
   EXEC("function b(p) { p.test_fn(); }");
   EXEC("function a() { var p = new Prof(); p.enable(); b(p); }");
   reset(cx);
   js::EnableContextProfilingStack(cx, false);
   {
     /* enable it in the middle of JS and make sure things check out */
     JS::RootedValue rval(cx);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -5299,20 +5299,20 @@ JS_PUBLIC_API void JS_SetGlobalJitCompil
       } else {
         jit::JitOptions.checkRangeAnalysis = true;
         JitSpew(js::jit::JitSpew_IonScripts,
                 "IonBuilder: Disable range analysis checks.");
       }
       break;
     case JSJITCOMPILER_ION_ENABLE:
       if (value == 1) {
-        JS::ContextOptionsRef(cx).setIon(true);
+        jit::JitOptions.ion = true;
         JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
       } else if (value == 0) {
-        JS::ContextOptionsRef(cx).setIon(false);
+        jit::JitOptions.ion = false;
         JitSpew(js::jit::JitSpew_IonScripts, "Disable ion");
       }
       break;
     case JSJITCOMPILER_ION_FREQUENT_BAILOUT_THRESHOLD:
       if (value == uint32_t(-1)) {
         jit::DefaultJitOptions defaultValues;
         value = defaultValues.frequentBailoutThreshold;
       }
@@ -5323,25 +5323,28 @@ JS_PUBLIC_API void JS_SetGlobalJitCompil
         jit::JitOptions.baselineInterpreter = true;
       } else if (value == 0) {
         ReleaseAllJITCode(rt->defaultFreeOp());
         jit::JitOptions.baselineInterpreter = false;
       }
       break;
     case JSJITCOMPILER_BASELINE_ENABLE:
       if (value == 1) {
-        JS::ContextOptionsRef(cx).setBaseline(true);
+        jit::JitOptions.baselineJit = true;
         ReleaseAllJITCode(rt->defaultFreeOp());
         JitSpew(js::jit::JitSpew_BaselineScripts, "Enable baseline");
       } else if (value == 0) {
-        JS::ContextOptionsRef(cx).setBaseline(false);
+        jit::JitOptions.baselineJit = false;
         ReleaseAllJITCode(rt->defaultFreeOp());
         JitSpew(js::jit::JitSpew_BaselineScripts, "Disable baseline");
       }
       break;
+    case JSJITCOMPILER_NATIVE_REGEXP_ENABLE:
+      jit::JitOptions.nativeRegExp = !!value;
+      break;
     case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
       if (value == 1) {
         rt->setOffthreadIonCompilationEnabled(true);
         JitSpew(js::jit::JitSpew_IonScripts, "Enable offthread compilation");
       } else if (value == 0) {
         rt->setOffthreadIonCompilationEnabled(false);
         JitSpew(js::jit::JitSpew_IonScripts, "Disable offthread compilation");
       }
@@ -5411,26 +5414,29 @@ JS_PUBLIC_API bool JS_GetGlobalJitCompil
       break;
     case JSJITCOMPILER_ION_FORCE_IC:
       *valueOut = jit::JitOptions.forceInlineCaches;
       break;
     case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
       *valueOut = jit::JitOptions.checkRangeAnalysis;
       break;
     case JSJITCOMPILER_ION_ENABLE:
-      *valueOut = JS::ContextOptionsRef(cx).ion();
+      *valueOut = jit::JitOptions.ion;
       break;
     case JSJITCOMPILER_ION_FREQUENT_BAILOUT_THRESHOLD:
       *valueOut = jit::JitOptions.frequentBailoutThreshold;
       break;
     case JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE:
       *valueOut = jit::JitOptions.baselineInterpreter;
       break;
     case JSJITCOMPILER_BASELINE_ENABLE:
-      *valueOut = JS::ContextOptionsRef(cx).baseline();
+      *valueOut = jit::JitOptions.baselineJit;
+      break;
+    case JSJITCOMPILER_NATIVE_REGEXP_ENABLE:
+      *valueOut = jit::JitOptions.nativeRegExp;
       break;
     case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
       *valueOut = rt->canUseOffthreadIonCompilation();
       break;
     case JSJITCOMPILER_WASM_FOLD_OFFSETS:
       *valueOut = jit::JitOptions.wasmFoldOffsets ? 1 : 0;
       break;
 #  ifdef DEBUG
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2858,22 +2858,22 @@ extern JS_PUBLIC_API void JS_SetOffthrea
   Register(ION_FULL_WARMUP_TRIGGER, "ion.full.warmup.trigger") \
   Register(ION_GVN_ENABLE, "ion.gvn.enable") \
   Register(ION_FORCE_IC, "ion.forceinlineCaches") \
   Register(ION_ENABLE, "ion.enable") \
   Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \
   Register(ION_FREQUENT_BAILOUT_THRESHOLD, "ion.frequent-bailout-threshold") \
   Register(BASELINE_INTERPRETER_ENABLE, "blinterp.enable") \
   Register(BASELINE_ENABLE, "baseline.enable") \
-  Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
+  Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable")  \
   Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks") \
   Register(JUMP_THRESHOLD, "jump-threshold") \
-  Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations")\
-  Register(UNBOXED_OBJECTS, "unboxed_objects") \
-  Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt") \
+  Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations") \
+  Register(NATIVE_REGEXP_ENABLE, "native_regexp.enable") \
+  Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt")      \
   Register(SPECTRE_INDEX_MASKING, "spectre.index-masking") \
   Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
   Register(SPECTRE_OBJECT_MITIGATIONS_MISC, "spectre.object-mitigations.misc") \
   Register(SPECTRE_STRING_MITIGATIONS, "spectre.string-mitigations") \
   Register(SPECTRE_VALUE_MASKING, "spectre.value-masking") \
   Register(SPECTRE_JIT_TO_CXX_CALLS, "spectre.jit-to-C++-calls") \
   Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets") \
   Register(WASM_DELAY_TIER2, "wasm.delay-tier2")
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -461,21 +461,18 @@ struct MOZ_STACK_CLASS EnvironmentPrepar
   }
   void invoke(JS::HandleObject global, Closure& closure) override;
 };
 
 // Shell state set once at startup.
 static bool enableCodeCoverage = false;
 static bool enableDisassemblyDumps = false;
 static bool offthreadCompilation = false;
-static bool enableBaseline = false;
-static bool enableIon = false;
 static bool enableAsmJS = false;
 static bool enableWasm = false;
-static bool enableNativeRegExp = false;
 static bool enableSharedMemory = SHARED_MEMORY_DEFAULT;
 static bool enableWasmBaseline = false;
 static bool enableWasmIon = false;
 static bool enableWasmCranelift = false;
 #ifdef ENABLE_WASM_GC
 static bool enableWasmGc = false;
 #endif
 static bool enableWasmVerbose = false;
@@ -10171,20 +10168,17 @@ static MOZ_MUST_USE bool ProcessArgs(JSC
       return false;
     }
   }
 
   return true;
 }
 
 static bool SetContextOptions(JSContext* cx, const OptionParser& op) {
-  enableBaseline = !op.getBoolOption("no-baseline");
-  enableIon = !op.getBoolOption("no-ion");
   enableAsmJS = !op.getBoolOption("no-asmjs");
-  enableNativeRegExp = !op.getBoolOption("no-native-regexp");
 
   // Default values for wasm.
   enableWasm = true;
   enableWasmBaseline = true;
   enableWasmIon = true;
   if (const char* str = op.getStringOption("wasm-compiler")) {
     if (strcmp(str, "none") == 0) {
       enableWasm = false;
@@ -10216,31 +10210,28 @@ static bool SetContextOptions(JSContext*
   enableTestWasmAwaitTier2 = op.getBoolOption("test-wasm-await-tier2");
   enableAsyncStacks = !op.getBoolOption("no-async-stacks");
   enableStreams = !op.getBoolOption("no-streams");
   enableBigInt = !op.getBoolOption("no-bigint");
   enableFields = !op.getBoolOption("disable-experimental-fields");
   enableAwaitFix = op.getBoolOption("enable-experimental-await-fix");
 
   JS::ContextOptionsRef(cx)
-      .setBaseline(enableBaseline)
-      .setIon(enableIon)
       .setAsmJS(enableAsmJS)
       .setWasm(enableWasm)
       .setWasmBaseline(enableWasmBaseline)
       .setWasmIon(enableWasmIon)
 #ifdef ENABLE_WASM_CRANELIFT
       .setWasmCranelift(enableWasmCranelift)
 #endif
 #ifdef ENABLE_WASM_GC
       .setWasmGc(enableWasmGc)
 #endif
       .setWasmVerbose(enableWasmVerbose)
       .setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
-      .setNativeRegExp(enableNativeRegExp)
       .setAsyncStack(enableAsyncStacks);
 
   if (const char* str = op.getStringOption("cache-ir-stubs")) {
     if (strcmp(str, "on") == 0) {
       jit::JitOptions.disableCacheIR = false;
     } else if (strcmp(str, "off") == 0) {
       jit::JitOptions.disableCacheIR = true;
     } else {
@@ -10433,16 +10424,28 @@ static bool SetContextOptions(JSContext*
   if (warmUpThreshold >= 0) {
     jit::JitOptions.baselineInterpreterWarmUpThreshold = warmUpThreshold;
   }
 
   if (op.getBoolOption("blinterp-eager")) {
     jit::JitOptions.baselineInterpreterWarmUpThreshold = 0;
   }
 
+  if (op.getBoolOption("no-baseline")) {
+    jit::JitOptions.baselineJit = false;
+  }
+
+  if (op.getBoolOption("no-ion")) {
+    jit::JitOptions.ion = false;
+  }
+
+  if (op.getBoolOption("no-native-regexp")) {
+    jit::JitOptions.nativeRegExp = false;
+  }
+
   if (const char* str = op.getStringOption("ion-regalloc")) {
     jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str);
     if (!jit::JitOptions.forcedRegisterAllocator.isSome()) {
       return OptionFailure("ion-regalloc", str);
     }
   }
 
   if (op.getBoolOption("ion-eager")) {
@@ -10535,31 +10538,28 @@ static bool SetContextOptions(JSContext*
 #endif
 
   return true;
 }
 
 static void SetWorkerContextOptions(JSContext* cx) {
   // Copy option values from the main thread.
   JS::ContextOptionsRef(cx)
-      .setBaseline(enableBaseline)
-      .setIon(enableIon)
       .setAsmJS(enableAsmJS)
       .setWasm(enableWasm)
       .setWasmBaseline(enableWasmBaseline)
       .setWasmIon(enableWasmIon)
 #ifdef ENABLE_WASM_CRANELIFT
       .setWasmCranelift(enableWasmCranelift)
 #endif
 #ifdef ENABLE_WASM_GC
       .setWasmGc(enableWasmGc)
 #endif
       .setWasmVerbose(enableWasmVerbose)
-      .setTestWasmAwaitTier2(enableTestWasmAwaitTier2)
-      .setNativeRegExp(enableNativeRegExp);
+      .setTestWasmAwaitTier2(enableTestWasmAwaitTier2);
 
   cx->runtime()->setOffthreadIonCompilationEnabled(offthreadCompilation);
   cx->runtime()->profilingScripts =
       enableCodeCoverage || enableDisassemblyDumps;
 
 #ifdef JS_GC_ZEAL
   if (gZealBits && gZealFrequency) {
     for (size_t i = 0; i < size_t(gc::ZealMode::Count); i++) {
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1967,17 +1967,17 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
     }
 
     CASE(JSOP_LABEL)
     END_CASE(JSOP_LABEL)
 
     CASE(JSOP_LOOPENTRY) {
       COUNT_COVERAGE();
       // Attempt on-stack replacement with Baseline code.
-      if (jit::IsBaselineInterpreterOrJitEnabled(cx)) {
+      if (jit::IsBaselineInterpreterOrJitEnabled()) {
         script->incWarmUpCounter();
 
         using Tier = jit::BaselineTier;
         bool tryBaselineInterpreter = (jit::IsBaselineInterpreterEnabled() &&
                                        !script->hasBaselineScript());
         jit::MethodStatus status =
             tryBaselineInterpreter
                 ? jit::CanEnterBaselineAtBranch<Tier::Interpreter>(cx,
--- a/js/xpconnect/idl/xpccomponents.idl
+++ b/js/xpconnect/idl/xpccomponents.idl
@@ -492,19 +492,16 @@ interface nsIXPCComponents_Utils : nsISu
     attribute boolean strict;
 
     [implicit_jscontext]
     attribute boolean werror;
 
     [implicit_jscontext]
     attribute boolean strict_mode;
 
-    [implicit_jscontext]
-    attribute boolean ion;
-
     // Returns true if we're running in automation and certain security
     // restrictions can be eased.
     readonly attribute boolean isInAutomation;
 
     void crashIfNotInAutomation();
 
     [implicit_jscontext]
     void setGCZeal(in long zeal);
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2044,17 +2044,16 @@ nsXPCComponents_Utils::Dispatch(HandleVa
   nsXPCComponents_Utils::Set##_attr(JSContext* cx, bool aValue) {       \
     ContextOptionsRef(cx)._setter(aValue);                              \
     return NS_OK;                                                       \
   }
 
 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Werror, werror, setWerror)
 GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
-GENERATE_JSCONTEXTOPTION_GETTER_SETTER(Ion, ion, setIon)
 
 #undef GENERATE_JSCONTEXTOPTION_GETTER_SETTER
 
 NS_IMETHODIMP
 nsXPCComponents_Utils::SetGCZeal(int32_t aValue, JSContext* cx) {
 #ifdef JS_GC_ZEAL
   JS_SetGCZeal(cx, uint8_t(aValue), JS_DEFAULT_ZEAL_FREQ);
 #endif
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -774,17 +774,17 @@ void xpc::SetPrefableRealmOptions(JS::Re
       .setFieldsEnabled(sFieldsEnabled)
       .setAwaitFixEnabled(sAwaitFixEnabled);
 }
 
 static void ReloadPrefsCallback(const char* pref, XPCJSContext* xpccx) {
   JSContext* cx = xpccx->Context();
 
   bool useBaselineInterp = Preferences::GetBool(JS_OPTIONS_DOT_STR "blinterp");
-  bool useBaseline = Preferences::GetBool(JS_OPTIONS_DOT_STR "baselinejit");
+  bool useBaselineJit = Preferences::GetBool(JS_OPTIONS_DOT_STR "baselinejit");
   bool useIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "ion");
   bool useAsmJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "asmjs");
   bool useWasm = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm");
   bool useWasmIon = Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_ionjit");
   bool useWasmBaseline =
       Preferences::GetBool(JS_OPTIONS_DOT_STR "wasm_baselinejit");
 #ifdef ENABLE_WASM_CRANELIFT
   bool useWasmCranelift =
@@ -875,58 +875,64 @@ static void ReloadPrefsCallback(const ch
   }
 #endif  // JS_GC_ZEAL
 
 #ifdef FUZZING
   bool fuzzingEnabled = StaticPrefs::fuzzing_enabled();
 #endif
 
   JS::ContextOptionsRef(cx)
-      .setBaseline(useBaseline)
-      .setIon(useIon)
       .setAsmJS(useAsmJS)
       .setWasm(useWasm)
       .setWasmIon(useWasmIon)
       .setWasmBaseline(useWasmBaseline)
 #ifdef ENABLE_WASM_CRANELIFT
       .setWasmCranelift(useWasmCranelift)
 #endif
 #ifdef ENABLE_WASM_GC
       .setWasmGc(useWasmGc)
 #endif
       .setWasmVerbose(useWasmVerbose)
       .setThrowOnAsmJSValidationFailure(throwOnAsmJSValidationFailure)
-      .setNativeRegExp(useNativeRegExp)
       .setAsyncStack(useAsyncStack)
       .setThrowOnDebuggeeWouldRun(throwOnDebuggeeWouldRun)
       .setDumpStackOnDebuggeeWouldRun(dumpStackOnDebuggeeWouldRun)
       .setWerror(werror)
 #ifdef FUZZING
       .setFuzzing(fuzzingEnabled)
 #endif
       .setExtraWarnings(extraWarnings);
 
   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   if (xr) {
     bool safeMode = false;
     xr->GetInSafeMode(&safeMode);
     if (safeMode) {
       JS::ContextOptionsRef(cx).disableOptionsForSafeMode();
       useBaselineInterp = false;
+      useBaselineJit = false;
+      useIon = false;
+      useNativeRegExp = false;
     }
   }
 
   JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_INTERPRETER_ENABLE,
                                 useBaselineInterp);
+  JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_ENABLE,
+                                useBaselineJit);
+  JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_ENABLE, useIon);
+  JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_NATIVE_REGEXP_ENABLE,
+                                useNativeRegExp);
+
+  JS_SetParallelParsingEnabled(cx, parallelParsing);
+  JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation);
+
   JS_SetGlobalJitCompilerOption(
       cx, JSJITCOMPILER_BASELINE_INTERPRETER_WARMUP_TRIGGER,
       baselineInterpThreshold);
-
-  JS_SetParallelParsingEnabled(cx, parallelParsing);
-  JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation);
   JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_WARMUP_TRIGGER,
                                 useBaselineEager ? 0 : baselineThreshold);
   JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_NORMAL_WARMUP_TRIGGER,
                                 useIonEager ? 0 : normalIonThreshold);
   JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_FULL_WARMUP_TRIGGER,
                                 useIonEager ? 0 : fullIonThreshold);
   JS_SetGlobalJitCompilerOption(cx,
                                 JSJITCOMPILER_ION_FREQUENT_BAILOUT_THRESHOLD,
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -866,19 +866,16 @@ static void ProcessArgsForCompartment(JS
         }
         break;
       case 'S':
         ContextOptionsRef(cx).toggleWerror();
         MOZ_FALLTHROUGH;  // because -S implies -s
       case 's':
         ContextOptionsRef(cx).toggleExtraWarnings();
         break;
-      case 'I':
-        ContextOptionsRef(cx).toggleIon().toggleAsmJS().toggleWasm();
-        break;
     }
   }
 }
 
 static bool ProcessArgs(AutoJSAPI& jsapi, char** argv, int argc,
                         XPCShellDirProvider* aDirProvider) {
   JSContext* cx = jsapi.cx();
   const char rcfilename[] = "xpcshell.js";
@@ -1001,17 +998,16 @@ static bool ProcessArgs(AutoJSAPI& jsapi
         break;
       }
       case 'C':
         compileOnly = true;
         isInteractive = false;
         break;
       case 'S':
       case 's':
-      case 'I':
         // These options are processed in ProcessArgsForCompartment.
         break;
       case 'p': {
         // plugins path
         char* pluginPath = argv[++i];
         nsCOMPtr<nsIFile> pluginsDir;
         if (NS_FAILED(
                 XRE_GetFileFromPath(pluginPath, getter_AddRefs(pluginsDir)))) {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1262,17 +1262,16 @@ pref("privacy.resistFingerprinting.reduc
 pref("dom.event.contextmenu.enabled",       true);
 pref("dom.event.coalesce_mouse_move",       true);
 
 pref("javascript.enabled",                  true);
 pref("javascript.options.strict",           false);
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     false);
 #endif
-pref("javascript.options.unboxed_objects",  false);
 pref("javascript.options.blinterp",         false);
 // Duplicated in JitOptions - ensure both match.
 pref("javascript.options.blinterp.threshold", 10);
 pref("javascript.options.baselinejit",      true);
 // Duplicated in JitOptions - ensure both match.
 pref("javascript.options.baselinejit.threshold", 10);
 pref("javascript.options.ion",              true);
 // Duplicated in JitOptions - ensure both match.