Bug 1284808 - Rename RuntimeOptions to ContextOptions and move it to the context. r=luke,baku
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 07 Jul 2016 08:15:15 +0200
changeset 385000 cc866385dd0124bde69f1d7fd50baee93c531ddf
parent 384999 c8700e65f41b9a7ead1047848e06d1eddd62564d
child 385001 1052561d1faf90af585c7b17909049d7bd960050
push id22385
push userbmo:wpan@mozilla.com
push dateThu, 07 Jul 2016 12:18:17 +0000
reviewersluke, baku
bugs1284808
milestone50.0a1
Bug 1284808 - Rename RuntimeOptions to ContextOptions and move it to the context. r=luke,baku
dom/bindings/CallbackObject.h
dom/workers/RuntimeService.cpp
dom/workers/RuntimeService.h
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/Workers.h
js/src/asmjs/AsmJS.cpp
js/src/asmjs/WasmCompile.cpp
js/src/asmjs/WasmJS.cpp
js/src/builtin/Promise.cpp
js/src/builtin/TestingFunctions.cpp
js/src/irregexp/RegExpEngine.cpp
js/src/jit/BaselineJIT.h
js/src/jit/Ion.h
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/jscntxt.cpp
js/src/jscntxt.h
js/src/jsexn.cpp
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/Runtime.h
js/src/vm/UnboxedObject.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCShellImpl.cpp
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -53,17 +53,17 @@ public:
   // the entry point computed from aCallback). If no override is required, the
   // caller should pass null.  |aCx| is used to capture the current
   // stack, which is later used as an async parent when the callback
   // is invoked.  aCx can be nullptr, in which case no stack is
   // captured.
   explicit CallbackObject(JSContext* aCx, JS::Handle<JSObject*> aCallback,
                           nsIGlobalObject* aIncumbentGlobal)
   {
-    if (aCx && JS::RuntimeOptionsRef(aCx).asyncStack()) {
+    if (aCx && JS::ContextOptionsRef(aCx).asyncStack()) {
       JS::RootedObject stack(aCx);
       if (!JS::CaptureCurrentStack(aCx, &stack)) {
         JS_ClearPendingException(aCx);
       }
       Init(aCallback, stack, aIncumbentGlobal);
     } else {
       Init(aCallback, nullptr, aIncumbentGlobal);
     }
@@ -225,17 +225,17 @@ protected:
 
   // Just like the public version without the FastCallbackConstructor argument,
   // except for not calling HoldJSObjects.  If you use this, you MUST ensure
   // that the object is traced until the HoldJSObjects happens!
   CallbackObject(JSContext* aCx, JS::Handle<JSObject*> aCallback,
                  nsIGlobalObject* aIncumbentGlobal,
                  const FastCallbackConstructor&)
   {
-    if (aCx && JS::RuntimeOptionsRef(aCx).asyncStack()) {
+    if (aCx && JS::ContextOptionsRef(aCx).asyncStack()) {
       JS::RootedObject stack(aCx);
       if (!JS::CaptureCurrentStack(aCx, &stack)) {
         JS_ClearPendingException(aCx);
       }
       InitNoHold(aCallback, stack, aIncumbentGlobal);
     } else {
       InitNoHold(aCallback, nullptr, aIncumbentGlobal);
     }
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -256,17 +256,17 @@ GenerateSharedWorkerKey(const nsACString
     }
   }
 
   aKey.Append('|');
   aKey.Append(aScriptSpec);
 }
 
 void
-LoadRuntimeOptions(const char* aPrefName, void* /* aClosure */)
+LoadContextOptions(const char* aPrefName, void* /* aClosure */)
 {
   AssertIsOnMainThread();
 
   RuntimeService* rts = RuntimeService::GetService();
   if (!rts) {
     // May be shutting down, just bail.
     return;
   }
@@ -286,33 +286,33 @@ LoadRuntimeOptions(const char* aPrefName
 
 #ifdef JS_GC_ZEAL
   if (prefName.EqualsLiteral(PREF_JS_OPTIONS_PREFIX PREF_GCZEAL) ||
       prefName.EqualsLiteral(PREF_WORKERS_OPTIONS_PREFIX PREF_GCZEAL)) {
     return;
   }
 #endif
 
-  // Runtime options.
-  JS::RuntimeOptions runtimeOptions;
-  runtimeOptions.setAsmJS(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs")))
+  // Context options.
+  JS::ContextOptions contextOptions;
+  contextOptions.setAsmJS(GetWorkerPref<bool>(NS_LITERAL_CSTRING("asmjs")))
                 .setWasm(GetWorkerPref<bool>(NS_LITERAL_CSTRING("wasm")))
                 .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")))
                 .setExtraWarnings(GetWorkerPref<bool>(NS_LITERAL_CSTRING("strict")));
 
-  RuntimeService::SetDefaultRuntimeOptions(runtimeOptions);
+  RuntimeService::SetDefaultContextOptions(contextOptions);
 
   if (rts) {
-    rts->UpdateAllWorkerRuntimeOptions();
+    rts->UpdateAllWorkerContextOptions();
   }
 }
 
 #ifdef JS_GC_ZEAL
 void
 LoadGCZealOptions(const char* /* aPrefName */, void* /* aClosure */)
 {
   AssertIsOnMainThread();
@@ -753,17 +753,17 @@ InitJSContextForWorker(WorkerPrivate* aW
   aWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(!aWorkerPrivate->GetJSContext(), "Already has a context!");
 
   JSSettings settings;
   aWorkerPrivate->CopyJSSettings(settings);
 
   JSContext* workerCx = JS_GetContext(aRuntime);
 
-  JS::RuntimeOptionsRef(aRuntime) = settings.runtimeOptions;
+  JS::ContextOptionsRef(workerCx) = settings.contextOptions;
 
   JSSettings::JSGCSettingsArray& gcSettings = settings.gcSettings;
 
   // This is the real place where we set the max memory for the runtime.
   for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
     const JSSettings::JSGCSetting& setting = gcSettings[index];
     if (setting.IsSet()) {
       NS_ASSERTION(setting.value, "Can't handle 0 values!");
@@ -1706,17 +1706,17 @@ RuntimeService::Init()
     RefPtr<BackgroundChildCallback> callback = new BackgroundChildCallback();
     if (!BackgroundChild::GetOrCreateForCurrentThread(callback)) {
       MOZ_CRASH("Unable to connect PBackground actor for the main thread!");
     }
   }
 
   // Initialize JSSettings.
   if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
-    sDefaultJSSettings.runtimeOptions = JS::RuntimeOptions();
+    sDefaultJSSettings.contextOptions = JS::ContextOptions();
     sDefaultJSSettings.chrome.maxScriptRuntime = -1;
     sDefaultJSSettings.chrome.compartmentOptions.behaviors().setVersion(JSVERSION_LATEST);
     sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
 #ifdef JS_GC_ZEAL
     sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
     sDefaultJSSettings.gcZeal = 0;
 #endif
     SetDefaultJSGCSettings(JSGC_MAX_BYTES, WORKER_DEFAULT_RUNTIME_HEAPSIZE);
@@ -1784,20 +1784,20 @@ RuntimeService::Init()
                   callback,                                                   \
                   name,                                                       \
                   nullptr)) ||
 #include "WorkerPrefs.h"
 #undef WORKER_SIMPLE_PREF
 #undef WORKER_PREF
 
       NS_FAILED(Preferences::RegisterCallbackAndCall(
-                                                   LoadRuntimeOptions,
+                                                   LoadContextOptions,
                                                    PREF_WORKERS_OPTIONS_PREFIX,
                                                    nullptr)) ||
-      NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
+      NS_FAILED(Preferences::RegisterCallback(LoadContextOptions,
                                               PREF_JS_OPTIONS_PREFIX,
                                               nullptr))) {
     NS_WARNING("Failed to register pref callbacks!");
   }
 
   MOZ_ASSERT(gRuntimeServiceDuringInit, "Should be true!");
   gRuntimeServiceDuringInit = false;
 
@@ -1926,20 +1926,20 @@ RuntimeService::Cleanup()
         }
       }
     }
   }
 
   NS_ASSERTION(!mWindowMap.Count(), "All windows should have been released!");
 
   if (mObserved) {
-    if (NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
+    if (NS_FAILED(Preferences::UnregisterCallback(LoadContextOptions,
                                                   PREF_JS_OPTIONS_PREFIX,
                                                   nullptr)) ||
-        NS_FAILED(Preferences::UnregisterCallback(LoadRuntimeOptions,
+        NS_FAILED(Preferences::UnregisterCallback(LoadContextOptions,
                                                   PREF_WORKERS_OPTIONS_PREFIX,
                                                   nullptr)) ||
 
 #define WORKER_SIMPLE_PREF(name, getter, NAME)                                \
       NS_FAILED(Preferences::UnregisterCallback(                              \
                   WorkerPrefChanged,                                          \
                   name,                                                       \
                   reinterpret_cast<void*>(WORKERPREF_##NAME))) ||
@@ -2282,19 +2282,19 @@ RuntimeService::NoteIdleThread(WorkerThr
       mIdleThreadTimer->InitWithFuncCallback(ShutdownIdleThreads,
                                              nullptr,
                                              IDLE_THREAD_TIMEOUT_SEC * 1000,
                                              nsITimer::TYPE_ONE_SHOT));
   }
 }
 
 void
-RuntimeService::UpdateAllWorkerRuntimeOptions()
+RuntimeService::UpdateAllWorkerContextOptions()
 {
-  BROADCAST_ALL_WORKERS(UpdateRuntimeOptions, sDefaultJSSettings.runtimeOptions);
+  BROADCAST_ALL_WORKERS(UpdateContextOptions, sDefaultJSSettings.contextOptions);
 }
 
 void
 RuntimeService::UpdateAppNameOverridePreference(const nsAString& aValue)
 {
   AssertIsOnMainThread();
   mNavigatorProperties.mAppNameOverridden = aValue;
 }
--- a/dom/workers/RuntimeService.h
+++ b/dom/workers/RuntimeService.h
@@ -163,33 +163,33 @@ public:
   static void
   GetDefaultPreferences(bool aPreferences[WORKERPREF_COUNT])
   {
     AssertIsOnMainThread();
     memcpy(aPreferences, sDefaultPreferences, WORKERPREF_COUNT * sizeof(bool));
   }
 
   static void
-  SetDefaultRuntimeOptions(const JS::RuntimeOptions& aRuntimeOptions)
+  SetDefaultContextOptions(const JS::ContextOptions& aContextOptions)
   {
     AssertIsOnMainThread();
-    sDefaultJSSettings.runtimeOptions = aRuntimeOptions;
+    sDefaultJSSettings.contextOptions = aContextOptions;
   }
 
   void
   UpdateAppNameOverridePreference(const nsAString& aValue);
 
   void
   UpdateAppVersionOverridePreference(const nsAString& aValue);
 
   void
   UpdatePlatformOverridePreference(const nsAString& aValue);
 
   void
-  UpdateAllWorkerRuntimeOptions();
+  UpdateAllWorkerContextOptions();
 
   void
   UpdateAllWorkerLanguages(const nsTArray<nsString>& aLanguages);
 
   void
   UpdateAllWorkerPreference(WorkerPreference aPref, bool aValue);
 
   static void
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1437,33 +1437,32 @@ private:
   nsresult Cancel() override
   {
     // We need to run regardless.
     Run();
     return WorkerRunnable::Cancel();
   }
 };
 
-class UpdateRuntimeOptionsRunnable final : public WorkerControlRunnable
-{
-  JS::RuntimeOptions mRuntimeOptions;
+class UpdateContextOptionsRunnable final : public WorkerControlRunnable
+{
+  JS::ContextOptions mContextOptions;
 
 public:
-  UpdateRuntimeOptionsRunnable(
-                                    WorkerPrivate* aWorkerPrivate,
-                                    const JS::RuntimeOptions& aRuntimeOptions)
+  UpdateContextOptionsRunnable(WorkerPrivate* aWorkerPrivate,
+                               const JS::ContextOptions& aContextOptions)
   : WorkerControlRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
-    mRuntimeOptions(aRuntimeOptions)
+    mContextOptions(aContextOptions)
   { }
 
 private:
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
-    aWorkerPrivate->UpdateRuntimeOptionsInternal(aCx, mRuntimeOptions);
+    aWorkerPrivate->UpdateContextOptionsInternal(aCx, mContextOptions);
     return true;
   }
 };
 
 class UpdatePreferenceRunnable final : public WorkerControlRunnable
 {
   WorkerPreference mPref;
   bool mValue;
@@ -3046,28 +3045,28 @@ WorkerPrivateParent<Derived>::PostMessag
 {
   AssertIsOnMainThread();
   PostMessageInternal(aCx, aMessage, aTransferable, Move(aClientInfo),
                       aKeepAliveToken, aRv);
 }
 
 template <class Derived>
 void
-WorkerPrivateParent<Derived>::UpdateRuntimeOptions(
-                                    const JS::RuntimeOptions& aRuntimeOptions)
+WorkerPrivateParent<Derived>::UpdateContextOptions(
+                                    const JS::ContextOptions& aContextOptions)
 {
   AssertIsOnParentThread();
 
   {
     MutexAutoLock lock(mMutex);
-    mJSSettings.runtimeOptions = aRuntimeOptions;
-  }
-
-  RefPtr<UpdateRuntimeOptionsRunnable> runnable =
-    new UpdateRuntimeOptionsRunnable(ParentAsWorkerPrivate(), aRuntimeOptions);
+    mJSSettings.contextOptions = aContextOptions;
+  }
+
+  RefPtr<UpdateContextOptionsRunnable> runnable =
+    new UpdateContextOptionsRunnable(ParentAsWorkerPrivate(), aContextOptions);
   if (!runnable->Dispatch()) {
     NS_WARNING("Failed to update worker context options!");
   }
 }
 
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::UpdatePreference(WorkerPreference aPref, bool aValue)
@@ -6304,26 +6303,26 @@ WorkerPrivate::RescheduleTimeoutTimer(JS
     JS_ReportError(aCx, "Failed to start timer!");
     return false;
   }
 
   return true;
 }
 
 void
-WorkerPrivate::UpdateRuntimeOptionsInternal(
+WorkerPrivate::UpdateContextOptionsInternal(
                                     JSContext* aCx,
-                                    const JS::RuntimeOptions& aRuntimeOptions)
+                                    const JS::ContextOptions& aContextOptions)
 {
   AssertIsOnWorkerThread();
 
-  JS::RuntimeOptionsRef(aCx) = aRuntimeOptions;
+  JS::ContextOptionsRef(aCx) = aContextOptions;
 
   for (uint32_t index = 0; index < mChildWorkers.Length(); index++) {
-    mChildWorkers[index]->UpdateRuntimeOptions(aRuntimeOptions);
+    mChildWorkers[index]->UpdateContextOptions(aContextOptions);
   }
 }
 
 void
 WorkerPrivate::UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages)
 {
   WorkerGlobalScope* globalScope = GlobalScope();
   if (globalScope) {
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -348,17 +348,17 @@ public:
   void
   PostMessageToServiceWorker(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                              const Optional<Sequence<JS::Value>>& aTransferable,
                              UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
                              const nsMainThreadPtrHandle<nsISupports>& aKeepAliveToken,
                              ErrorResult& aRv);
 
   void
-  UpdateRuntimeOptions(const JS::RuntimeOptions& aRuntimeOptions);
+  UpdateContextOptions(const JS::ContextOptions& aContextOptions);
 
   void
   UpdateLanguages(const nsTArray<nsString>& aLanguages);
 
   void
   UpdatePreference(WorkerPreference aPref, bool aValue);
 
   void
@@ -1163,17 +1163,17 @@ public:
   void
   CloseHandlerFinished()
   {
     AssertIsOnWorkerThread();
     mCloseHandlerFinished = true;
   }
 
   void
-  UpdateRuntimeOptionsInternal(JSContext* aCx, const JS::RuntimeOptions& aRuntimeOptions);
+  UpdateContextOptionsInternal(JSContext* aCx, const JS::ContextOptions& aContextOptions);
 
   void
   UpdateLanguagesInternal(const nsTArray<nsString>& aLanguages);
 
   void
   UpdatePreferenceInternal(WorkerPreference aPref, bool aValue);
 
   void
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -136,17 +136,17 @@ struct JSSettings
     JSContentChromeSettings()
     : compartmentOptions(), maxScriptRuntime(0)
     { }
   };
 
   JSContentChromeSettings chrome;
   JSContentChromeSettings content;
   JSGCSettingsArray gcSettings;
-  JS::RuntimeOptions runtimeOptions;
+  JS::ContextOptions contextOptions;
 
 #ifdef JS_GC_ZEAL
   uint8_t gcZeal;
   uint32_t gcZealFrequency;
 #endif
 
   JSSettings()
 #ifdef JS_GC_ZEAL
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -8595,17 +8595,17 @@ js::IsAsmJSStrictModeModuleOrFunction(JS
 }
 
 bool
 js::IsAsmJSCompilationAvailable(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // See EstablishPreconditions.
-    bool available = HasCompilerSupport(cx) && cx->runtime()->options().asmJS();
+    bool available = HasCompilerSupport(cx) && cx->options().asmJS();
 
     args.rval().set(BooleanValue(available));
     return true;
 }
 
 static JSFunction*
 MaybeWrappedNativeFunction(const Value& v)
 {
--- a/js/src/asmjs/WasmCompile.cpp
+++ b/js/src/asmjs/WasmCompile.cpp
@@ -1145,17 +1145,17 @@ DecodeUnknownSections(Decoder& d)
     }
 
     return true;
 }
 
 bool
 CompileArgs::init(ExclusiveContext* cx)
 {
-    alwaysBaseline = cx->compartment()->runtimeFromAnyThread()->options().wasmAlwaysBaseline();
+    alwaysBaseline = cx->options().wasmAlwaysBaseline();
     return assumptions.init(SignalUsage(cx), cx->buildIdOp());
 }
 
 UniqueModule
 wasm::Compile(Bytes&& bytecode, CompileArgs&& args, UniqueChars* error)
 {
     bool newFormat = args.assumptions.newFormat;
 
--- a/js/src/asmjs/WasmJS.cpp
+++ b/js/src/asmjs/WasmJS.cpp
@@ -152,17 +152,17 @@ wasm::Eval(JSContext* cx, Handle<TypedAr
         return false;
 
     return module->instantiate(cx, funcImports, nullptr, instanceObj);
 }
 
 static bool
 InstantiateModule(JSContext* cx, unsigned argc, Value* vp)
 {
-    MOZ_ASSERT(cx->runtime()->options().wasm());
+    MOZ_ASSERT(cx->options().wasm());
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!args.get(0).isObject() || !args.get(0).toObject().is<TypedArrayObject>()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_BUF_ARG);
         return false;
     }
 
     RootedObject importObj(cx);
@@ -204,17 +204,17 @@ static const JSFunctionSpec wasm_static_
 const Class js::WasmClass = {
     js_Wasm_str,
     JSCLASS_HAS_CACHED_PROTO(JSProto_Wasm)
 };
 
 JSObject*
 js::InitWasmClass(JSContext* cx, HandleObject global)
 {
-    MOZ_ASSERT(cx->runtime()->options().wasm());
+    MOZ_ASSERT(cx->options().wasm());
 
     RootedObject proto(cx, global->as<GlobalObject>().getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
 
     RootedObject Wasm(cx, NewObjectWithGivenProto(cx, &WasmClass, proto, SingletonObject));
     if (!Wasm)
         return nullptr;
@@ -644,17 +644,17 @@ InitConstructor(JSContext* cx, HandleObj
     RootedId id(cx, AtomToId(className));
     RootedValue ctorValue(cx, ObjectValue(*ctor));
     return DefineProperty(cx, wasm, id, ctorValue, nullptr, nullptr, 0);
 }
 
 JSObject*
 js::InitWebAssemblyClass(JSContext* cx, HandleObject global)
 {
-    MOZ_ASSERT(cx->runtime()->options().wasm());
+    MOZ_ASSERT(cx->options().wasm());
 
     RootedObject proto(cx, global->as<GlobalObject>().getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
 
     RootedObject wasm(cx, NewObjectWithGivenProto(cx, &WebAssemblyClass, proto, SingletonObject));
     if (!wasm)
         return nullptr;
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -129,17 +129,17 @@ PromiseObject::create(JSContext* cx, Han
         // Step 7.
         promise->setFixedSlot(PROMISE_IS_HANDLED_SLOT,
                               Int32Value(PROMISE_IS_HANDLED_STATE_UNHANDLED));
 
         // Store an allocation stack so we can later figure out what the
         // control flow was for some unexpected results. Frightfully expensive,
         // but oh well.
         RootedObject stack(cx);
-        if (cx->runtime()->options().asyncStack() || cx->compartment()->isDebuggee()) {
+        if (cx->options().asyncStack() || cx->compartment()->isDebuggee()) {
             if (!JS::CaptureCurrentStack(cx, &stack, 0))
                 return nullptr;
         }
         promise->setFixedSlot(PROMISE_ALLOCATION_SITE_SLOT, ObjectOrNullValue(stack));
         promise->setFixedSlot(PROMISE_ALLOCATION_TIME_SLOT,
                               DoubleValue(MillisecondsSinceStartup()));
     }
 
@@ -419,17 +419,17 @@ PromiseObject::reject(JSContext* cx, Han
     return Call(cx, funVal, UndefinedHandleValue, args, &dummy);
 }
 
 void
 PromiseObject::onSettled(JSContext* cx)
 {
     Rooted<PromiseObject*> promise(cx, this);
     RootedObject stack(cx);
-    if (cx->runtime()->options().asyncStack() || cx->compartment()->isDebuggee()) {
+    if (cx->options().asyncStack() || cx->compartment()->isDebuggee()) {
         if (!JS::CaptureCurrentStack(cx, &stack, 0)) {
             cx->clearPendingException();
             return;
         }
     }
     promise->setFixedSlot(PROMISE_RESOLUTION_SITE_SLOT, ObjectOrNullValue(stack));
     promise->setFixedSlot(PROMISE_RESOLUTION_TIME_SLOT, DoubleValue(MillisecondsSinceStartup()));
 
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -502,17 +502,17 @@ IsProxy(JSContext* cx, unsigned argc, Va
     args.rval().setBoolean(args[0].toObject().is<ProxyObject>());
     return true;
 }
 
 static bool
 WasmIsSupported(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(wasm::HasCompilerSupport(cx) && cx->runtime()->options().wasm());
+    args.rval().setBoolean(wasm::HasCompilerSupport(cx) && cx->options().wasm());
     return true;
 }
 
 static bool
 WasmTextToBinary(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject callee(cx, &args.callee());
@@ -564,17 +564,17 @@ WasmTextToBinary(JSContext* cx, unsigned
 
     args.rval().setObject(*obj);
     return true;
 }
 
 static bool
 WasmBinaryToText(JSContext* cx, unsigned argc, Value* vp)
 {
-    MOZ_ASSERT(cx->runtime()->options().wasm());
+    MOZ_ASSERT(cx->options().wasm());
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!args.get(0).isObject() || !args.get(0).toObject().is<TypedArrayObject>()) {
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_BUF_ARG);
         return false;
     }
 
     Rooted<TypedArrayObject*> code(cx, &args[0].toObject().as<TypedArrayObject>());
--- a/js/src/irregexp/RegExpEngine.cpp
+++ b/js/src/irregexp/RegExpEngine.cpp
@@ -1767,17 +1767,17 @@ SampleChars(FrequencyCollator* collator,
 }
 
 static bool
 IsNativeRegExpEnabled(JSContext* cx)
 {
 #ifdef JS_CODEGEN_NONE
     return false;
 #else
-    return cx->runtime()->options().nativeRegExp();
+    return cx->options().nativeRegExp();
 #endif
 }
 
 RegExpCode
 irregexp::CompilePattern(JSContext* cx, RegExpShared* shared, RegExpCompileData* data,
                          HandleLinearString sample, bool is_global, bool ignore_case,
                          bool is_ascii, bool match_only, bool force_bytecode, bool sticky,
                          bool unicode)
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -510,17 +510,17 @@ static_assert(sizeof(BaselineScript) % s
               "The data attached to the script must be aligned for fast JIT access.");
 
 inline bool
 IsBaselineEnabled(JSContext* cx)
 {
 #ifdef JS_CODEGEN_NONE
     return false;
 #else
-    return cx->runtime()->options().baseline();
+    return cx->options().baseline();
 #endif
 }
 
 MethodStatus
 CanEnterBaselineMethod(JSContext* cx, RunState& state);
 
 MethodStatus
 CanEnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, bool newType);
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -162,18 +162,18 @@ uint8_t* LazyLinkTopActivation(JSContext
 
 static inline bool
 IsIonEnabled(JSContext* cx)
 {
     // The ARM64 Ion engine is not yet implemented.
 #if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
     return false;
 #else
-    return cx->runtime()->options().ion() &&
-           cx->runtime()->options().baseline() &&
+    return cx->options().ion() &&
+           cx->options().baseline() &&
            cx->runtime()->jitSupportsFloatingPoint;
 #endif
 }
 
 inline bool
 IsIonInlinablePC(jsbytecode* pc) {
     // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites)
     // GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
--- a/js/src/jsapi-tests/testChromeBuffer.cpp
+++ b/js/src/jsapi-tests/testChromeBuffer.cpp
@@ -59,18 +59,18 @@ 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::RuntimeOptions oldOptions = JS::RuntimeOptionsRef(rt);
-        JS::RuntimeOptionsRef(rt).setIon(false).setBaseline(false);
+        JS::ContextOptions oldOptions = JS::ContextOptionsRef(cx);
+        JS::ContextOptionsRef(cx).setIon(false).setBaseline(false);
         {
             JSAutoCompartment ac(cx, trusted_glob);
             const char* paramName = "x";
             const char* bytes = "return x ? 1 + trusted(x-1) : 0";
             JS::CompileOptions options(cx);
             options.setFileAndLine("", 0);
             JS::AutoObjectVector emptyScopeChain(cx);
             CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "trusted",
@@ -97,17 +97,17 @@ BEGIN_TEST(testChromeBuffer)
         JS::AutoObjectVector emptyScopeChain(cx);
         CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "untrusted", 1,
                                   &paramName, bytes, strlen(bytes), &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::RuntimeOptionsRef(rt) = oldOptions;
+        JS::ContextOptionsRef(cx) = oldOptions;
     }
 
     /*
      * 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
@@ -30,18 +30,18 @@ countIonScripts(JSObject* global)
     unsigned count = 0;
     js::IterateScripts(rt, global->compartment(), &count, ScriptCallback);
     return count;
 }
 
 bool
 testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts)
 {
-    rt->options().setBaseline(true);
-    rt->options().setIon(true);
+    cx->options().setBaseline(true);
+    cx->options().setIon(true);
     rt->setOffthreadIonCompilationEnabled(false);
 
     RootedObject global(cx, createTestGlobal(preserveJitCode));
     CHECK(global);
     JSAutoCompartment ac(cx, global);
 
 #ifdef JS_CODEGEN_ARM64
     // The ARM64 Ion JIT is not yet enabled, so this test will fail with
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -140,17 +140,17 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWithInterpreter)
 
 BEGIN_TEST(testProfileStrings_isCalledWithJIT)
 {
     CHECK(initialize(cx));
-    JS::RuntimeOptionsRef(cx).setBaseline(true)
+    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(); }");
@@ -192,17 +192,17 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWithJIT)
 
 BEGIN_TEST(testProfileStrings_isCalledWhenError)
 {
     CHECK(initialize(cx));
-    JS::RuntimeOptionsRef(cx).setBaseline(true)
+    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 */
@@ -216,17 +216,17 @@ BEGIN_TEST(testProfileStrings_isCalledWh
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
 
 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
 {
     CHECK(initialize(cx));
-    JS::RuntimeOptionsRef(cx).setBaseline(true)
+    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::EnableRuntimeProfilingStack(cx->runtime(), false);
     {
         /* enable it in the middle of JS and make sure things check out */
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -609,26 +609,20 @@ JS_StringToVersion(const char* string)
     int i;
 
     for (i = 0; v2smap[i].string; i++)
         if (strcmp(v2smap[i].string, string) == 0)
             return v2smap[i].version;
     return JSVERSION_UNKNOWN;
 }
 
-JS_PUBLIC_API(JS::RuntimeOptions&)
-JS::RuntimeOptionsRef(JSRuntime* rt)
-{
-    return rt->options();
-}
-
-JS_PUBLIC_API(JS::RuntimeOptions&)
-JS::RuntimeOptionsRef(JSContext* cx)
-{
-    return cx->runtime()->options();
+JS_PUBLIC_API(JS::ContextOptions&)
+JS::ContextOptionsRef(JSContext* cx)
+{
+    return cx->options();
 }
 
 JS_PUBLIC_API(bool)
 JS::InitSelfHostedCode(JSContext* cx)
 {
     MOZ_RELEASE_ASSERT(!cx->runtime()->hasInitializedSelfHosting(),
                        "JS::InitSelfHostedCode() called more than once");
 
@@ -1744,19 +1738,19 @@ JS_GetConstructor(JSContext* cx, HandleO
         JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                              proto->getClass()->name);
         return nullptr;
     }
     return &cval.toObject();
 }
 
 bool
-JS::CompartmentBehaviors::extraWarnings(JSRuntime* rt) const
-{
-    return extraWarningsOverride_.get(rt->options().extraWarnings());
+JS::CompartmentBehaviors::extraWarnings(JSContext* cx) const
+{
+    return extraWarningsOverride_.get(cx->options().extraWarnings());
 }
 
 JS::CompartmentCreationOptions&
 JS::CompartmentCreationOptions::setZone(ZoneSpecifier spec)
 {
     zone_.spec = spec;
     return *this;
 }
@@ -3879,26 +3873,26 @@ JS::OwningCompileOptions::setIntroducerF
 }
 
 JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version)
     : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
       introductionScriptRoot(cx)
 {
     this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion();
 
-    strictOption = cx->runtime()->options().strictMode();
+    strictOption = cx->options().strictMode();
     extraWarningsOption = cx->compartment()->behaviors().extraWarnings(cx);
-    werrorOption = cx->runtime()->options().werror();
-    if (!cx->runtime()->options().asmJS())
+    werrorOption = cx->options().werror();
+    if (!cx->options().asmJS())
         asmJSOption = AsmJSOption::Disabled;
     else if (cx->compartment()->debuggerObservesAsmJS())
         asmJSOption = AsmJSOption::DisabledByDebugger;
     else
         asmJSOption = AsmJSOption::Enabled;
-    throwOnAsmJSValidationFailureOption = cx->runtime()->options().throwOnAsmJSValidationFailure();
+    throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure();
 }
 
 enum SyntacticScopeOption { HasSyntacticScope, HasNonSyntacticScope };
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, SyntacticScopeOption scopeOption,
         SourceBufferHolder& srcBuf, MutableHandleScript script)
 {
@@ -4898,17 +4892,17 @@ JS::AutoSetAsyncStackForNewCalls::AutoSe
     oldAsyncCause(cx->runtime()->asyncCauseForNewActivations),
     oldAsyncCallIsExplicit(cx->runtime()->asyncCallIsExplicit)
 {
     CHECK_REQUEST(cx);
 
     // The option determines whether we actually use the new values at this
     // point. It will not affect restoring the previous values when the object
     // is destroyed, so if the option changes it won't cause consistency issues.
-    if (!cx->runtime()->options().asyncStack())
+    if (!cx->options().asyncStack())
         return;
 
     SavedFrame* asyncStack = &stack->as<SavedFrame>();
 
     cx->runtime()->asyncStackForNewActivations = asyncStack;
     cx->runtime()->asyncCauseForNewActivations = asyncCause;
     cx->runtime()->asyncCallIsExplicit = kind == AsyncCallKind::EXPLICIT;
 }
@@ -6077,30 +6071,30 @@ JS_SetGlobalJitCompilerOption(JSContext*
             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable non-IC optimizations.");
         } else {
             jit::JitOptions.forceInlineCaches = true;
             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable non-IC optimizations.");
         }
         break;
       case JSJITCOMPILER_ION_ENABLE:
         if (value == 1) {
-            JS::RuntimeOptionsRef(rt).setIon(true);
+            JS::ContextOptionsRef(cx).setIon(true);
             JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
         } else if (value == 0) {
-            JS::RuntimeOptionsRef(rt).setIon(false);
+            JS::ContextOptionsRef(cx).setIon(false);
             JitSpew(js::jit::JitSpew_IonScripts, "Disable ion");
         }
         break;
       case JSJITCOMPILER_BASELINE_ENABLE:
         if (value == 1) {
-            JS::RuntimeOptionsRef(rt).setBaseline(true);
+            JS::ContextOptionsRef(cx).setBaseline(true);
             ReleaseAllJITCode(rt->defaultFreeOp());
             JitSpew(js::jit::JitSpew_BaselineScripts, "Enable baseline");
         } else if (value == 0) {
-            JS::RuntimeOptionsRef(rt).setBaseline(false);
+            JS::ContextOptionsRef(cx).setBaseline(false);
             ReleaseAllJITCode(rt->defaultFreeOp());
             JitSpew(js::jit::JitSpew_BaselineScripts, "Disable baseline");
         }
         break;
       case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
         if (value == 1) {
             rt->setOffthreadIonCompilationEnabled(true);
             JitSpew(js::jit::JitSpew_IonScripts, "Enable offthread compilation");
@@ -6143,19 +6137,19 @@ JS_GetGlobalJitCompilerOption(JSContext*
         return jit::JitOptions.baselineWarmUpThreshold;
       case JSJITCOMPILER_ION_WARMUP_TRIGGER:
         return jit::JitOptions.forcedDefaultIonWarmUpThreshold.isSome()
              ? jit::JitOptions.forcedDefaultIonWarmUpThreshold.ref()
              : jit::OptimizationInfo::CompilerWarmupThreshold;
       case JSJITCOMPILER_ION_FORCE_IC:
         return jit::JitOptions.forceInlineCaches;
       case JSJITCOMPILER_ION_ENABLE:
-        return JS::RuntimeOptionsRef(rt).ion();
+        return JS::ContextOptionsRef(cx).ion();
       case JSJITCOMPILER_BASELINE_ENABLE:
-        return JS::RuntimeOptionsRef(rt).baseline();
+        return JS::ContextOptionsRef(cx).baseline();
       case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
         return rt->canUseOffthreadIonCompilation();
       case JSJITCOMPILER_SIGNALS_ENABLE:
         return rt->canUseSignalHandlers();
       case JSJITCOMPILER_WASM_TEST_MODE:
         return jit::JitOptions.wasmTestMode ? 1 : 0;
       default:
         break;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1069,19 +1069,19 @@ JS_SetVersionForCompartment(JSCompartmen
 extern JS_PUBLIC_API(const char*)
 JS_VersionToString(JSVersion version);
 
 extern JS_PUBLIC_API(JSVersion)
 JS_StringToVersion(const char* string);
 
 namespace JS {
 
-class JS_PUBLIC_API(RuntimeOptions) {
+class JS_PUBLIC_API(ContextOptions) {
   public:
-    RuntimeOptions()
+    ContextOptions()
       : baseline_(true),
         ion_(true),
         asmJS_(true),
         wasm_(false),
         wasmAlwaysBaseline_(false),
         throwOnAsmJSValidationFailure_(false),
         nativeRegExp_(true),
         unboxedArrays_(false),
@@ -1090,131 +1090,131 @@ class JS_PUBLIC_API(RuntimeOptions) {
         dumpStackOnDebuggeeWouldRun_(false),
         werror_(false),
         strictMode_(false),
         extraWarnings_(false)
     {
     }
 
     bool baseline() const { return baseline_; }
-    RuntimeOptions& setBaseline(bool flag) {
+    ContextOptions& setBaseline(bool flag) {
         baseline_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleBaseline() {
+    ContextOptions& toggleBaseline() {
         baseline_ = !baseline_;
         return *this;
     }
 
     bool ion() const { return ion_; }
-    RuntimeOptions& setIon(bool flag) {
+    ContextOptions& setIon(bool flag) {
         ion_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleIon() {
+    ContextOptions& toggleIon() {
         ion_ = !ion_;
         return *this;
     }
 
     bool asmJS() const { return asmJS_; }
-    RuntimeOptions& setAsmJS(bool flag) {
+    ContextOptions& setAsmJS(bool flag) {
         asmJS_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleAsmJS() {
+    ContextOptions& toggleAsmJS() {
         asmJS_ = !asmJS_;
         return *this;
     }
 
     bool wasm() const { return wasm_; }
-    RuntimeOptions& setWasm(bool flag) {
+    ContextOptions& setWasm(bool flag) {
         wasm_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleWasm() {
+    ContextOptions& toggleWasm() {
         wasm_ = !wasm_;
         return *this;
     }
 
     bool wasmAlwaysBaseline() const { return wasmAlwaysBaseline_; }
-    RuntimeOptions& setWasmAlwaysBaseline(bool flag) {
+    ContextOptions& setWasmAlwaysBaseline(bool flag) {
         wasmAlwaysBaseline_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleWasmAlwaysBaseline() {
+    ContextOptions& toggleWasmAlwaysBaseline() {
         wasmAlwaysBaseline_ = !wasmAlwaysBaseline_;
         return *this;
     }
 
     bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
-    RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) {
+    ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
         throwOnAsmJSValidationFailure_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleThrowOnAsmJSValidationFailure() {
+    ContextOptions& toggleThrowOnAsmJSValidationFailure() {
         throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
         return *this;
     }
 
     bool nativeRegExp() const { return nativeRegExp_; }
-    RuntimeOptions& setNativeRegExp(bool flag) {
+    ContextOptions& setNativeRegExp(bool flag) {
         nativeRegExp_ = flag;
         return *this;
     }
 
     bool unboxedArrays() const { return unboxedArrays_; }
-    RuntimeOptions& setUnboxedArrays(bool flag) {
+    ContextOptions& setUnboxedArrays(bool flag) {
         unboxedArrays_ = flag;
         return *this;
     }
 
     bool asyncStack() const { return asyncStack_; }
-    RuntimeOptions& setAsyncStack(bool flag) {
+    ContextOptions& setAsyncStack(bool flag) {
         asyncStack_ = flag;
         return *this;
     }
 
     bool throwOnDebuggeeWouldRun() const { return throwOnDebuggeeWouldRun_; }
-    RuntimeOptions& setThrowOnDebuggeeWouldRun(bool flag) {
+    ContextOptions& setThrowOnDebuggeeWouldRun(bool flag) {
         throwOnDebuggeeWouldRun_ = flag;
         return *this;
     }
 
     bool dumpStackOnDebuggeeWouldRun() const { return dumpStackOnDebuggeeWouldRun_; }
-    RuntimeOptions& setDumpStackOnDebuggeeWouldRun(bool flag) {
+    ContextOptions& setDumpStackOnDebuggeeWouldRun(bool flag) {
         dumpStackOnDebuggeeWouldRun_ = flag;
         return *this;
     }
 
     bool werror() const { return werror_; }
-    RuntimeOptions& setWerror(bool flag) {
+    ContextOptions& setWerror(bool flag) {
         werror_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleWerror() {
+    ContextOptions& toggleWerror() {
         werror_ = !werror_;
         return *this;
     }
 
     bool strictMode() const { return strictMode_; }
-    RuntimeOptions& setStrictMode(bool flag) {
+    ContextOptions& setStrictMode(bool flag) {
         strictMode_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleStrictMode() {
+    ContextOptions& toggleStrictMode() {
         strictMode_ = !strictMode_;
         return *this;
     }
 
     bool extraWarnings() const { return extraWarnings_; }
-    RuntimeOptions& setExtraWarnings(bool flag) {
+    ContextOptions& setExtraWarnings(bool flag) {
         extraWarnings_ = flag;
         return *this;
     }
-    RuntimeOptions& toggleExtraWarnings() {
+    ContextOptions& toggleExtraWarnings() {
         extraWarnings_ = !extraWarnings_;
         return *this;
     }
 
   private:
     bool baseline_ : 1;
     bool ion_ : 1;
     bool asmJS_ : 1;
@@ -1226,21 +1226,18 @@ class JS_PUBLIC_API(RuntimeOptions) {
     bool asyncStack_ : 1;
     bool throwOnDebuggeeWouldRun_ : 1;
     bool dumpStackOnDebuggeeWouldRun_ : 1;
     bool werror_ : 1;
     bool strictMode_ : 1;
     bool extraWarnings_ : 1;
 };
 
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSRuntime* rt);
-
-JS_PUBLIC_API(RuntimeOptions&)
-RuntimeOptionsRef(JSContext* cx);
+JS_PUBLIC_API(ContextOptions&)
+ContextOptionsRef(JSContext* cx);
 
 /**
  * Initialize the runtime's self-hosted code. Embeddings should call this
  * exactly once per runtime/context, before the first JS_NewGlobalObject
  * call.
  */
 JS_PUBLIC_API(bool)
 InitSelfHostedCode(JSContext* cx);
@@ -2304,17 +2301,17 @@ class JS_PUBLIC_API(CompartmentBehaviors
     }
 
     bool disableLazyParsing() const { return disableLazyParsing_; }
     CompartmentBehaviors& setDisableLazyParsing(bool flag) {
         disableLazyParsing_ = flag;
         return *this;
     }
 
-    bool extraWarnings(JSRuntime* rt) const;
+    bool extraWarnings(JSContext* cx) const;
     Override& extraWarningsOverride() { return extraWarningsOverride_; }
 
     bool getSingletonsAsTemplates() const {
         return singletonsAsTemplates_;
     }
     CompartmentBehaviors& setSingletonsAsValues() {
         singletonsAsTemplates_ = false;
         return *this;
@@ -4125,17 +4122,17 @@ JS_DecompileFunction(JSContext* cx, JS::
  * the "this" keyword value and the variables object (ECMA parlance for where
  * 'var' and 'function' bind names) of the execution context for script.  In the
  * latter case, the first object in the provided list is used, unless the list
  * is empty, in which case the global is used.
  *
  * Why a runtime option?  The alternative is to add APIs duplicating those
  * for the other value of flags, and that doesn't seem worth the code bloat
  * cost.  Such new entry points would probably have less obvious names, too, so
- * would not tend to be used.  The RuntimeOptionsRef adjustment, OTOH, can be
+ * would not tend to be used.  The ContextOptionsRef adjustment, OTOH, can be
  * more easily hacked into existing code that does not depend on the bug; such
  * code can continue to use the familiar JS::Evaluate, etc., entry points.
  */
 
 /**
  * Evaluate a script in the scope of the current global of cx.
  */
 extern JS_PUBLIC_API(bool)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -319,17 +319,17 @@ checkReportFlags(JSContext* cx, unsigned
             return true;
     } else if (JSREPORT_IS_STRICT(*flags)) {
         /* Warning/error only when JSOPTION_STRICT is set. */
         if (!cx->compartment()->behaviors().extraWarnings(cx))
             return true;
     }
 
     /* Warnings become errors when JSOPTION_WERROR is set. */
-    if (JSREPORT_IS_WARNING(*flags) && cx->runtime()->options().werror())
+    if (JSREPORT_IS_WARNING(*flags) && cx->options().werror())
         *flags &= ~JSREPORT_WARNING;
 
     return false;
 }
 
 bool
 js::ReportErrorVA(JSContext* cx, unsigned flags, const char* format, va_list ap)
 {
@@ -840,20 +840,22 @@ const JSErrorFormatString js_ErrorFormat
 JS_FRIEND_API(const JSErrorFormatString*)
 js::GetErrorMessage(void* userRef, const unsigned errorNumber)
 {
     if (errorNumber > 0 && errorNumber < JSErr_Limit)
         return &js_ErrorFormatString[errorNumber];
     return nullptr;
 }
 
-ExclusiveContext::ExclusiveContext(JSRuntime* rt, PerThreadData* pt, ContextKind kind)
+ExclusiveContext::ExclusiveContext(JSRuntime* rt, PerThreadData* pt, ContextKind kind,
+                                   const JS::ContextOptions& options)
   : ContextFriendFields(rt),
     helperThread_(nullptr),
     contextKind_(kind),
+    options_(options),
     perThreadData(pt),
     arenas_(nullptr),
     enterCompartmentDepth_(0)
 {
 }
 
 void
 ExclusiveContext::recoverFromOutOfMemory()
@@ -866,17 +868,17 @@ ExclusiveContext::recoverFromOutOfMemory
         return;
     }
     // Keep in sync with addPendingOutOfMemory.
     if (ParseTask* task = helperThread()->parseTask())
         task->outOfMemory = false;
 }
 
 JSContext::JSContext(JSRuntime* parentRuntime)
-  : ExclusiveContext(this, &this->JSRuntime::mainThread, Context_JS),
+  : ExclusiveContext(this, &this->JSRuntime::mainThread, Context_JS, JS::ContextOptions()),
     JSRuntime(parentRuntime),
     throwing(false),
     unwrappedException_(this),
     overRecursed_(false),
     propagatingForcedReturn_(false),
     liveVolatileJitFrameIterators_(nullptr),
     reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     resolvingList(nullptr),
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -112,20 +112,26 @@ class ExclusiveContext : public ContextF
     enum ContextKind {
         Context_JS,
         Context_Exclusive
     };
 
   private:
     ContextKind contextKind_;
 
+  protected:
+    // Background threads get a read-only copy of the main thread's
+    // ContextOptions.
+    JS::ContextOptions options_;
+
   public:
     PerThreadData* perThreadData;
 
-    ExclusiveContext(JSRuntime* rt, PerThreadData* pt, ContextKind kind);
+    ExclusiveContext(JSRuntime* rt, PerThreadData* pt, ContextKind kind,
+                     const JS::ContextOptions& options);
 
     bool isJSContext() const {
         return contextKind_ == Context_JS;
     }
 
     JSContext* maybeJSContext() const {
         if (isJSContext())
             return (JSContext*) this;
@@ -148,16 +154,20 @@ class ExclusiveContext : public ContextF
     // asJSContext() and crashing afterwards, this method may be used to watch
     // for such cases and produce either a soft failure in release builds or
     // an assertion failure in debug builds.
     bool shouldBeJSContext() const {
         MOZ_ASSERT(isJSContext());
         return isJSContext();
     }
 
+    const JS::ContextOptions& options() const {
+        return options_;
+    }
+
   protected:
     js::gc::ArenaLists* arenas_;
 
   public:
     inline js::gc::ArenaLists* arenas() const { return arenas_; }
 
     template <typename T>
     bool isInsideCurrentZone(T thing) const {
@@ -380,16 +390,20 @@ struct JSContext : public js::ExclusiveC
      * - The newest scripted frame's version, if there is such a frame.
      * - The version from the compartment.
      * - The default version.
      *
      * Note: if this ever shows up in a profile, just add caching!
      */
     JSVersion findVersion() const;
 
+    JS::ContextOptions& options() {
+        return options_;
+    }
+
     js::LifoAlloc& tempLifoAlloc() { return runtime()->tempLifoAlloc; }
 
     unsigned            outstandingRequests;/* number of JS_BeginRequest calls
                                                without the corresponding
                                                JS_EndRequest. */
 
     bool jitIsBroken;
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -545,17 +545,17 @@ js::ErrorToException(JSContext* cx, cons
     if (!callback)
         callback = GetErrorMessage;
     const JSErrorFormatString* errorString = callback(userRef, errorNumber);
     JSExnType exnType = errorString ? static_cast<JSExnType>(errorString->exnType) : JSEXN_ERR;
     MOZ_ASSERT(exnType < JSEXN_LIMIT);
 
     if (exnType == JSEXN_WARN) {
         // werror must be enabled, so we use JSEXN_ERR.
-        MOZ_ASSERT(cx->runtime()->options().werror());
+        MOZ_ASSERT(cx->options().werror());
         exnType = JSEXN_ERR;
     }
 
     // Prevent infinite recursion.
     if (cx->generatingError)
         return;
     AutoScopedAssign<bool> asa(&cx->generatingError, true);
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1016,60 +1016,60 @@ AddPromiseReactions(JSContext* cx, unsig
     return JS::AddPromiseReactions(cx, promise, onResolve, onReject);
 }
 
 static bool
 Options(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    JS::RuntimeOptions oldRuntimeOptions = JS::RuntimeOptionsRef(cx);
+    JS::ContextOptions oldContextOptions = JS::ContextOptionsRef(cx);
     for (unsigned i = 0; i < args.length(); i++) {
         JSString* str = JS::ToString(cx, args[i]);
         if (!str)
             return false;
         args[i].setString(str);
 
         JSAutoByteString opt(cx, str);
         if (!opt)
             return false;
 
         if (strcmp(opt.ptr(), "strict") == 0)
-            JS::RuntimeOptionsRef(cx).toggleExtraWarnings();
+            JS::ContextOptionsRef(cx).toggleExtraWarnings();
         else if (strcmp(opt.ptr(), "werror") == 0)
-            JS::RuntimeOptionsRef(cx).toggleWerror();
+            JS::ContextOptionsRef(cx).toggleWerror();
         else if (strcmp(opt.ptr(), "throw_on_asmjs_validation_failure") == 0)
-            JS::RuntimeOptionsRef(cx).toggleThrowOnAsmJSValidationFailure();
+            JS::ContextOptionsRef(cx).toggleThrowOnAsmJSValidationFailure();
         else if (strcmp(opt.ptr(), "strict_mode") == 0)
-            JS::RuntimeOptionsRef(cx).toggleStrictMode();
+            JS::ContextOptionsRef(cx).toggleStrictMode();
         else {
             JS_ReportError(cx,
                            "unknown option name '%s'."
                            " The valid names are strict,"
                            " werror, and strict_mode.",
                            opt.ptr());
             return false;
         }
     }
 
     char* names = strdup("");
     bool found = false;
-    if (names && oldRuntimeOptions.extraWarnings()) {
+    if (names && oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict");
         found = true;
     }
-    if (names && oldRuntimeOptions.werror()) {
+    if (names && oldContextOptions.werror()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "werror");
         found = true;
     }
-    if (names && oldRuntimeOptions.throwOnAsmJSValidationFailure()) {
+    if (names && oldContextOptions.throwOnAsmJSValidationFailure()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "throw_on_asmjs_validation_failure");
         found = true;
     }
-    if (names && oldRuntimeOptions.strictMode()) {
+    if (names && oldContextOptions.strictMode()) {
         names = JS_sprintf_append(names, "%s%s", found ? "," : "", "strict_mode");
         found = true;
     }
     if (!names) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
 
@@ -2917,17 +2917,17 @@ struct WorkerInput
       : runtime(runtime), chars(chars), length(length)
     {}
 
     ~WorkerInput() {
         js_free(chars);
     }
 };
 
-static void SetWorkerRuntimeOptions(JSRuntime* rt);
+static void SetWorkerContextOptions(JSContext* cx);
 
 static void
 WorkerMain(void* arg)
 {
     WorkerInput* input = (WorkerInput*) arg;
 
     JSRuntime* rt = JS_NewRuntime(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->runtime);
     if (!rt) {
@@ -2944,17 +2944,17 @@ WorkerMain(void* arg)
 
     JSContext* cx = JS_GetContext(rt);
 
     sr->isWorker = true;
     JS_SetRuntimePrivate(rt, sr.get());
     JS_SetFutexCanWait(cx);
     JS::SetWarningReporter(cx, WarningReporter);
     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
-    SetWorkerRuntimeOptions(rt);
+    SetWorkerContextOptions(cx);
 
     if (!JS::InitSelfHostedCode(cx)) {
         JS_DestroyRuntime(rt);
         js_delete(input);
         return;
     }
 
 #ifdef SPIDERMONKEY_PROMISE
@@ -6642,17 +6642,17 @@ OptionFailure(const char* option, const 
 }
 
 static MOZ_MUST_USE bool
 ProcessArgs(JSContext* cx, OptionParser* op)
 {
     ShellRuntime* sr = GetShellRuntime(cx);
 
     if (op->getBoolOption('s'))
-        JS::RuntimeOptionsRef(cx).toggleExtraWarnings();
+        JS::ContextOptionsRef(cx).toggleExtraWarnings();
 
     /* |scriptArgs| gets bound on the global before any code is run. */
     if (!BindScriptArgs(cx, op))
         return false;
 
     MultiStringRange filePaths = op->getMultiStringOption('f');
     MultiStringRange codeChunks = op->getMultiStringOption('e');
     MultiStringRange modulePaths = op->getMultiStringOption('m');
@@ -6715,26 +6715,26 @@ ProcessArgs(JSContext* cx, OptionParser*
         if (!Process(cx, nullptr, true))
             return false;
     }
 
     return true;
 }
 
 static bool
-SetRuntimeOptions(JSRuntime* rt, const OptionParser& op)
+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");
     enableUnboxedArrays = op.getBoolOption("unboxed-arrays");
     enableWasmAlwaysBaseline = op.getBoolOption("wasm-always-baseline");
 
-    JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline)
+    JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
                              .setIon(enableIon)
                              .setAsmJS(enableAsmJS)
                              .setWasm(true)
                              .setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
                              .setNativeRegExp(enableNativeRegExp)
                              .setUnboxedArrays(enableUnboxedArrays);
 
     if (op.getBoolOption("no-unboxed-objects"))
@@ -6907,17 +6907,17 @@ SetRuntimeOptions(JSRuntime* rt, const O
 
     offthreadCompilation = true;
     if (const char* str = op.getStringOption("ion-offthread-compile")) {
         if (strcmp(str, "off") == 0)
             offthreadCompilation = false;
         else if (strcmp(str, "on") != 0)
             return OptionFailure("ion-offthread-compile", str);
     }
-    rt->setOffthreadIonCompilationEnabled(offthreadCompilation);
+    cx->setOffthreadIonCompilationEnabled(offthreadCompilation);
 
     if (op.getStringOption("ion-parallel-compile")) {
         fprintf(stderr, "--ion-parallel-compile is deprecated. Please use --ion-offthread-compile instead.\n");
         return false;
     }
 
 #ifdef ENABLE_SHARED_ARRAY_BUFFER
     if (const char* str = op.getStringOption("shared-memory")) {
@@ -6959,71 +6959,71 @@ SetRuntimeOptions(JSRuntime* rt, const O
         jit::Simulator::StopSimAt = stopAt;
 #endif
 
     reportWarnings = op.getBoolOption('w');
     compileOnly = op.getBoolOption('c');
     printTiming = op.getBoolOption('b');
     enableCodeCoverage = op.getBoolOption("code-coverage");
     enableDisassemblyDumps = op.getBoolOption('D');
-    rt->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
+    cx->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
     jsCacheDir = op.getStringOption("js-cache");
     if (jsCacheDir) {
         if (!op.getBoolOption("no-js-cache-per-process"))
             jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
         else
-            jsCacheDir = JS_strdup(rt, jsCacheDir);
+            jsCacheDir = JS_strdup(cx, jsCacheDir);
         if (!jsCacheDir)
             return false;
         jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
     }
 
 #ifdef DEBUG
     dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables");
 #endif
 
 #ifdef JS_GC_ZEAL
     const char* zealStr = op.getStringOption("gc-zeal");
     if (zealStr) {
-        if (!rt->gc.parseAndSetZeal(zealStr))
+        if (!cx->gc.parseAndSetZeal(zealStr))
             return false;
         uint32_t nextScheduled;
-        rt->gc.getZealBits(&gZealBits, &gZealFrequency, &nextScheduled);
+        cx->gc.getZealBits(&gZealBits, &gZealFrequency, &nextScheduled);
     }
 #endif
 
     return true;
 }
 
 static void
-SetWorkerRuntimeOptions(JSRuntime* rt)
+SetWorkerContextOptions(JSContext* cx)
 {
     // Copy option values from the main thread.
-    JS::RuntimeOptionsRef(rt).setBaseline(enableBaseline)
+    JS::ContextOptionsRef(cx).setBaseline(enableBaseline)
                              .setIon(enableIon)
                              .setAsmJS(enableAsmJS)
                              .setWasm(true)
                              .setWasmAlwaysBaseline(enableWasmAlwaysBaseline)
                              .setNativeRegExp(enableNativeRegExp)
                              .setUnboxedArrays(enableUnboxedArrays);
-    rt->setOffthreadIonCompilationEnabled(offthreadCompilation);
-    rt->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
+    cx->setOffthreadIonCompilationEnabled(offthreadCompilation);
+    cx->profilingScripts = enableCodeCoverage || enableDisassemblyDumps;
 
 #ifdef JS_GC_ZEAL
     if (gZealBits && gZealFrequency) {
 #define ZEAL_MODE(_, value)                        \
         if (gZealBits & (1 << value))              \
-            rt->gc.setZeal(value, gZealFrequency);
+            cx->gc.setZeal(value, gZealFrequency);
         JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
 #undef ZEAL_MODE
     }
 #endif
 
-    JS_SetNativeStackQuota(JS_GetContext(rt), gMaxStackSize);
+    JS_SetNativeStackQuota(cx, gMaxStackSize);
 }
 
 static int
 Shell(JSContext* cx, OptionParser* op, char** envp)
 {
     Maybe<JS::AutoDisableGenerationalGC> noggc;
     if (op->getBoolOption("no-ggc"))
         noggc.emplace(cx->runtime());
@@ -7381,17 +7381,17 @@ main(int argc, char** argv, char** envp)
         return 1;
 
     JSContext* cx = JS_GetContext(rt);
 
     JS_SetRuntimePrivate(rt, sr.get());
     // Waiting is allowed on the shell's main thread, for now.
     JS_SetFutexCanWait(cx);
     JS::SetWarningReporter(cx, WarningReporter);
-    if (!SetRuntimeOptions(rt, op))
+    if (!SetContextOptions(cx, op))
         return 1;
 
     JS_SetGCParameter(cx, JSGC_MAX_BYTES, 0xffffffff);
 
     size_t availMem = op.getIntOption("available-memory");
     if (availMem > 0)
         JS_SetGCParametersBasedOnAvailableMemory(cx, availMem);
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -332,21 +332,21 @@ class MOZ_RAII js::EnterDebuggeeNoExecut
         }
         return nullptr;
     }
 
     // Given a JSContext entered into a debuggee compartment, report a
     // warning or an error if there is a lock that locks it.
     static bool reportIfFoundInStack(JSContext* cx, HandleScript script) {
         if (EnterDebuggeeNoExecute* nx = findInStack(cx)) {
-            bool warning = !cx->runtime()->options().throwOnDebuggeeWouldRun();
+            bool warning = !cx->options().throwOnDebuggeeWouldRun();
             if (!warning || !nx->reported_) {
                 AutoCompartment ac(cx, nx->debugger().toJSObject());
                 nx->reported_ = true;
-                if (cx->runtime()->options().dumpStackOnDebuggeeWouldRun()) {
+                if (cx->options().dumpStackOnDebuggeeWouldRun()) {
                     fprintf(stdout, "Dumping stack for DebuggeeWouldRun:\n");
                     DumpBacktrace(cx);
                 }
                 const char* filename = script->filename() ? script->filename() : "(none)";
                 char linenoStr[15];
                 JS_snprintf(linenoStr, sizeof(linenoStr), "%" PRIuSIZE, script->lineno());
                 unsigned flags = warning ? JSREPORT_WARNING : JSREPORT_ERROR;
                 return JS_ReportErrorFlagsAndNumber(cx, flags, GetErrorMessage, nullptr,
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -96,17 +96,17 @@ js::GlobalObject::getTypedObjectModule()
     MOZ_ASSERT(v.isObject());
     return v.toObject().as<TypedObjectModuleObject>();
 }
 
 /* static */ bool
 GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key)
 {
     if (key == JSProto_Wasm || key == JSProto_WebAssembly)
-        return !cx->runtime()->options().wasm();
+        return !cx->options().wasm();
 
 #ifdef ENABLE_SHARED_ARRAY_BUFFER
     // Return true if the given constructor has been disabled at run-time.
     switch (key) {
       case JSProto_Atomics:
       case JSProto_SharedArrayBuffer:
         return !cx->compartment()->creationOptions().getSharedMemoryAndAtomicsEnabled();
       default:
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -479,17 +479,17 @@ js::StartOffThreadParseScript(JSContext*
     AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
 
     JSObject* global = CreateGlobalForOffThreadParse(cx, ParseTaskKind::Script, nogc);
     if (!global)
         return false;
 
     ScopedJSDeletePtr<ExclusiveContext> helpercx(
         cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData*) nullptr,
-                                   ExclusiveContext::Context_Exclusive));
+                                   ExclusiveContext::Context_Exclusive, cx->options()));
     if (!helpercx)
         return false;
 
     ScopedJSDeletePtr<ParseTask> task(
         cx->new_<ScriptParseTask>(helpercx.get(), global, cx, chars, length,
                                   callback, callbackData));
     if (!task)
         return false;
@@ -516,17 +516,17 @@ js::StartOffThreadParseModule(JSContext*
     AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
 
     JSObject* global = CreateGlobalForOffThreadParse(cx, ParseTaskKind::Module, nogc);
     if (!global)
         return false;
 
     ScopedJSDeletePtr<ExclusiveContext> helpercx(
         cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData*) nullptr,
-                                   ExclusiveContext::Context_Exclusive));
+                                   ExclusiveContext::Context_Exclusive, cx->options()));
     if (!helpercx)
         return false;
 
     ScopedJSDeletePtr<ParseTask> task(
         cx->new_<ModuleParseTask>(helpercx.get(), global, cx, chars, length,
                                   callback, callbackData));
     if (!task)
         return false;
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1466,17 +1466,17 @@ ObjectGroup::allocationSiteGroup(JSConte
                 res->setPreliminaryObjects(preliminaryObjects);
             else
                 cx->recoverFromOutOfMemory();
         }
     }
 
     if (kind == JSProto_Array &&
         (JSOp(*pc) == JSOP_NEWARRAY || IsCallPC(pc)) &&
-        cx->runtime()->options().unboxedArrays())
+        cx->options().unboxedArrays())
     {
         PreliminaryObjectArrayWithTemplate* preliminaryObjects =
             cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
         if (preliminaryObjects)
             res->setPreliminaryObjects(preliminaryObjects);
         else
             cx->recoverFromOutOfMemory();
     }
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1242,17 +1242,16 @@ struct JSRuntime : public JS::shadow::Ru
 
     /*  onOutOfMemory but can call the largeAllocationFailureCallback. */
     JS_FRIEND_API(void*) onOutOfMemoryCanGC(js::AllocFunction allocator, size_t nbytes,
                                             void* reallocPtr = nullptr);
 
     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* runtime);
 
   private:
-    JS::RuntimeOptions options_;
     const js::Class* windowProxyClass_;
 
     // Settings for how helper threads can be used.
     bool offthreadIonCompilationEnabled_;
     bool parallelParsingEnabled_;
 
     bool autoWritableJitCodeActive_;
 
@@ -1274,23 +1273,16 @@ struct JSRuntime : public JS::shadow::Ru
     }
 
     void toggleAutoWritableJitCodeActive(bool b) {
         MOZ_ASSERT(autoWritableJitCodeActive_ != b, "AutoWritableJitCode should not be nested.");
         MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
         autoWritableJitCodeActive_ = b;
     }
 
-    const JS::RuntimeOptions& options() const {
-        return options_;
-    }
-    JS::RuntimeOptions& options() {
-        return options_;
-    }
-
     const js::Class* maybeWindowProxyClass() const {
         return windowProxyClass_;
     }
     void setWindowProxyClass(const js::Class* clasp) {
         windowProxyClass_ = clasp;
     }
 
 #ifdef DEBUG
--- a/js/src/vm/UnboxedObject.cpp
+++ b/js/src/vm/UnboxedObject.cpp
@@ -1925,17 +1925,17 @@ js::TryConvertToUnboxedLayout(ExclusiveC
 {
     bool isArray = !templateShape;
 
     // Unboxed arrays are nightly only for now. The getenv() call will be
     // removed when they are on by default. See bug 1153266.
     if (isArray) {
 #ifdef NIGHTLY_BUILD
         if (!getenv("JS_OPTION_USE_UNBOXED_ARRAYS")) {
-            if (!group->runtimeFromAnyThread()->options().unboxedArrays())
+            if (!cx->options().unboxedArrays())
                 return true;
         }
 #else
         return true;
 #endif
     } else {
         if (jit::JitOptions.disableUnboxedObjects)
             return true;
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2995,37 +2995,22 @@ nsXPCComponents_Utils::Dispatch(HandleVa
     }                                                                   \
     NS_IMETHODIMP                                                       \
     nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
     {                                                                   \
         ContextOptionsRef(cx)._setter(aValue);                          \
         return NS_OK;                                                   \
     }
 
-#define GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(_attr, _getter, _setter) \
-    NS_IMETHODIMP                                                       \
-    nsXPCComponents_Utils::Get## _attr(JSContext* cx, bool* aValue)     \
-    {                                                                   \
-        *aValue = RuntimeOptionsRef(cx)._getter();                      \
-        return NS_OK;                                                   \
-    }                                                                   \
-    NS_IMETHODIMP                                                       \
-    nsXPCComponents_Utils::Set## _attr(JSContext* cx, bool aValue)      \
-    {                                                                   \
-        RuntimeOptionsRef(cx)._setter(aValue);                          \
-        return NS_OK;                                                   \
-    }
-
-GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Strict, extraWarnings, setExtraWarnings)
-GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Werror, werror, setWerror)
-GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Strict_mode, strictMode, setStrictMode)
-GENERATE_JSRUNTIMEOPTION_GETTER_SETTER(Ion, ion, setIon)
+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
-#undef GENERATE_JSRUNTIMEOPTION_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
     return NS_OK;
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1556,17 +1556,16 @@ void XPCJSRuntime::SystemIsBeingShutDown
 }
 
 #define JS_OPTIONS_DOT_STR "javascript.options."
 
 static void
 ReloadPrefsCallback(const char* pref, void* data)
 {
     XPCJSRuntime* runtime = reinterpret_cast<XPCJSRuntime*>(data);
-    JSRuntime* rt = runtime->Runtime();
     JSContext* cx = runtime->Context();
 
     bool safeMode = false;
     nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
     if (xr) {
         xr->GetInSafeMode(&safeMode);
     }
 
@@ -1611,17 +1610,17 @@ ReloadPrefsCallback(const char* pref, vo
     int32_t zeal_frequency =
         Preferences::GetInt(JS_OPTIONS_DOT_STR "gczeal.frequency",
                             JS_DEFAULT_ZEAL_FREQ);
     if (zeal >= 0) {
         JS_SetGCZeal(cx, (uint8_t)zeal, zeal_frequency);
     }
 #endif // JS_GC_ZEAL
 
-    JS::RuntimeOptionsRef(rt).setBaseline(useBaseline)
+    JS::ContextOptionsRef(cx).setBaseline(useBaseline)
                              .setIon(useIon)
                              .setAsmJS(useAsmJS)
                              .setWasm(useWasm)
                              .setWasmAlwaysBaseline(useWasmBaseline)
                              .setThrowOnAsmJSValidationFailure(throwOnAsmJSValidationFailure)
                              .setNativeRegExp(useNativeRegExp)
                              .setAsyncStack(useAsyncStack)
                              .setThrowOnDebuggeeWouldRun(throwOnDebuggeeWouldRun)
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -480,56 +480,56 @@ SendCommand(JSContext* cx, unsigned argc
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 Options(JSContext* cx, unsigned argc, Value* vp)
 {
     JS::CallArgs args = CallArgsFromVp(argc, vp);
-    RuntimeOptions oldRuntimeOptions = RuntimeOptionsRef(cx);
+    ContextOptions oldContextOptions = ContextOptionsRef(cx);
 
     for (unsigned i = 0; i < args.length(); ++i) {
         JSString* str = ToString(cx, args[i]);
         if (!str)
             return false;
 
         JSAutoByteString opt(cx, str);
         if (!opt)
             return false;
 
         if (strcmp(opt.ptr(), "strict") == 0)
-            RuntimeOptionsRef(cx).toggleExtraWarnings();
+            ContextOptionsRef(cx).toggleExtraWarnings();
         else if (strcmp(opt.ptr(), "werror") == 0)
-            RuntimeOptionsRef(cx).toggleWerror();
+            ContextOptionsRef(cx).toggleWerror();
         else if (strcmp(opt.ptr(), "strict_mode") == 0)
-            RuntimeOptionsRef(cx).toggleStrictMode();
+            ContextOptionsRef(cx).toggleStrictMode();
         else {
             JS_ReportError(cx, "unknown option name '%s'. The valid names are "
                            "strict, werror, and strict_mode.", opt.ptr());
             return false;
         }
     }
 
     char* names = nullptr;
-    if (oldRuntimeOptions.extraWarnings()) {
+    if (oldContextOptions.extraWarnings()) {
         names = JS_sprintf_append(names, "%s", "strict");
         if (!names) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
     }
-    if (oldRuntimeOptions.werror()) {
+    if (oldContextOptions.werror()) {
         names = JS_sprintf_append(names, "%s%s", names ? "," : "", "werror");
         if (!names) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
     }
-    if (names && oldRuntimeOptions.strictMode()) {
+    if (names && oldContextOptions.strictMode()) {
         names = JS_sprintf_append(names, "%s%s", names ? "," : "", "strict_mode");
         if (!names) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
     }
 
     JSString* str = JS_NewStringCopyZ(cx, names);
@@ -956,23 +956,23 @@ ProcessArgsForCompartment(JSContext* cx,
         switch (argv[i][1]) {
           case 'v':
           case 'f':
           case 'e':
             if (++i == argc)
                 return;
             break;
         case 'S':
-            RuntimeOptionsRef(cx).toggleWerror();
+            ContextOptionsRef(cx).toggleWerror();
             MOZ_FALLTHROUGH; // because -S implies -s
         case 's':
-            RuntimeOptionsRef(cx).toggleExtraWarnings();
+            ContextOptionsRef(cx).toggleExtraWarnings();
             break;
         case 'I':
-            RuntimeOptionsRef(cx).toggleIon()
+            ContextOptionsRef(cx).toggleIon()
                                  .toggleAsmJS()
                                  .toggleWasm();
             break;
         }
     }
 }
 
 static bool