Bug 881333 - Use accessor methods for cx->compartment and cx->runtime, r=luke.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 10 Jun 2013 15:22:18 -0600
changeset 134566 21e3c26108143c727b9304eacf8b916de62f9f44
parent 134565 8024f115507c49b7557634750674084d0598248a
child 134567 4a854c013d42478b46362a5b4d110016fe53264f
push id29272
push userbhackett@mozilla.com
push dateMon, 10 Jun 2013 21:22:27 +0000
treeherdermozilla-inbound@21e3c2610814 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs881333
milestone24.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 881333 - Use accessor methods for cx->compartment and cx->runtime, r=luke.
js/src/builtin/Eval.cpp
js/src/builtin/Intl.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/RegExp.cpp
js/src/builtin/TestingFunctions.cpp
js/src/ctypes/CTypes.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/ParseMaps-inl.h
js/src/frontend/Parser.cpp
js/src/frontend/TokenStream.cpp
js/src/gc/Verifier.cpp
js/src/ion/AsmJS.cpp
js/src/ion/AsmJSLink.cpp
js/src/ion/Bailouts.cpp
js/src/ion/BaselineBailouts.cpp
js/src/ion/BaselineCompiler.cpp
js/src/ion/BaselineFrame-inl.h
js/src/ion/BaselineFrame.cpp
js/src/ion/BaselineIC.cpp
js/src/ion/BaselineJIT.cpp
js/src/ion/CodeGenerator.cpp
js/src/ion/Ion.cpp
js/src/ion/IonBuilder.cpp
js/src/ion/IonFrames.cpp
js/src/ion/IonLinker.h
js/src/ion/MCallOptimize.cpp
js/src/ion/VMFunctions.cpp
js/src/ion/VMFunctions.h
js/src/ion/arm/Trampoline-arm.cpp
js/src/ion/shared/BaselineCompiler-shared.cpp
js/src/ion/x64/Trampoline-x64.cpp
js/src/ion/x86/Trampoline-x86.cpp
js/src/jsalloc.cpp
js/src/jsanalyze.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi-tests/testIndexToString.cpp
js/src/jsapi-tests/testProfileStrings.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsatom.cpp
js/src/jsatominlines.h
js/src/jsbool.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jscompartmentinlines.h
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsgcinlines.h
js/src/jsinfer.cpp
js/src/jsinferinlines.h
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsonparser.cpp
js/src/jsopcode.cpp
js/src/jspropertycache.cpp
js/src/jspropertytree.cpp
js/src/jsproxy.cpp
js/src/jspubtd.h
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jsstrinlines.h
js/src/jstypedarray.cpp
js/src/jswatchpoint.cpp
js/src/jsweakmap.cpp
js/src/jsweakmap.h
js/src/jsworkers.cpp
js/src/jsworkers.h
js/src/jswrapper.cpp
js/src/shell/js.cpp
js/src/shell/jsheaptools.cpp
js/src/vm/Debugger-inl.h
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
js/src/vm/ForkJoin.cpp
js/src/vm/GlobalObject-inl.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/ObjectImpl.cpp
js/src/vm/Probes-inl.h
js/src/vm/Probes.cpp
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpStatics-inl.h
js/src/vm/RegExpStatics.cpp
js/src/vm/SPSProfiler.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/Shape.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/String-inl.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -91,37 +91,37 @@ class EvalScriptGuard
     Rooted<JSLinearString*> lookupStr_;
 
   public:
     EvalScriptGuard(JSContext *cx)
         : cx_(cx), script_(cx), lookup_(cx), lookupStr_(cx) {}
 
     ~EvalScriptGuard() {
         if (script_) {
-            CallDestroyScriptHook(cx_->runtime->defaultFreeOp(), script_);
+            CallDestroyScriptHook(cx_->runtime()->defaultFreeOp(), script_);
             script_->isActiveEval = false;
             script_->isCachedEval = true;
             EvalCacheEntry cacheEntry = {script_, lookup_.callerScript, lookup_.pc};
             lookup_.str = lookupStr_;
             if (lookup_.str && IsEvalCacheCandidate(script_))
-                cx_->runtime->evalCache.relookupOrAdd(p_, lookup_, cacheEntry);
+                cx_->runtime()->evalCache.relookupOrAdd(p_, lookup_, cacheEntry);
         }
     }
 
     void lookupInEvalCache(JSLinearString *str, JSScript *callerScript, jsbytecode *pc)
     {
         lookupStr_ = str;
         lookup_.str = str;
         lookup_.callerScript = callerScript;
         lookup_.version = cx_->findVersion();
         lookup_.pc = pc;
-        p_ = cx_->runtime->evalCache.lookupForAdd(lookup_);
+        p_ = cx_->runtime()->evalCache.lookupForAdd(lookup_);
         if (p_) {
             script_ = p_->script;
-            cx_->runtime->evalCache.remove(p_);
+            cx_->runtime()->evalCache.remove(p_);
             CallNewScriptHook(cx_, script_, NullPtr());
             script_->isCachedEval = false;
             script_->isActiveEval = true;
         }
     }
 
     void setNewScript(JSScript *script) {
         // JSScript::initFromEmitter has already called js_CallNewScriptHook.
@@ -355,17 +355,17 @@ js::DirectEvalFromIon(JSContext *cx,
 
     EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, vp);
     if (ejr != EvalJSON_NotJSON)
         return ejr == EvalJSON_Success;
 
     EvalScriptGuard esg(cx);
 
     // Ion will not perform cross compartment direct eval calls.
-    JSPrincipals *principals = cx->compartment->principals;
+    JSPrincipals *principals = cx->compartment()->principals;
 
     esg.lookupInEvalCache(stableStr, callerScript, pc);
 
     if (!esg.foundScript()) {
         unsigned lineno;
         const char *filename;
         JSPrincipals *originPrincipals;
         CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals,
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -2044,17 +2044,17 @@ js_InitIntlClass(JSContext *cx, HandleOb
     }
 
     if (!JS_DefineFunctions(cx, Intl, intl_static_methods))
         return NULL;
 
     // Skip initialization of the Intl constructors during initialization of the
     // self-hosting global as we may get here before self-hosted code is compiled,
     // and no core code refers to the Intl classes.
-    if (!cx->runtime->isSelfHostingGlobal(cx->global())) {
+    if (!cx->runtime()->isSelfHostingGlobal(cx->global())) {
         if (!InitCollatorClass(cx, Intl, global))
             return NULL;
         if (!InitNumberFormatClass(cx, Intl, global))
             return NULL;
         if (!InitDateTimeFormatClass(cx, Intl, global))
             return NULL;
     }
 
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1169,17 +1169,17 @@ MapObject::finalize(FreeOp *fop, JSObjec
 
 JSBool
 MapObject::construct(JSContext *cx, unsigned argc, Value *vp)
 {
     Rooted<JSObject*> obj(cx, NewBuiltinClassInstance(cx, &class_));
     if (!obj)
         return false;
 
-    ValueMap *map = cx->new_<ValueMap>(cx->runtime);
+    ValueMap *map = cx->new_<ValueMap>(cx->runtime());
     if (!map)
         return false;
     if (!map->init()) {
         js_ReportOutOfMemory(cx);
         return false;
     }
     obj->setPrivate(map);
 
@@ -1203,17 +1203,17 @@ MapObject::construct(JSContext *cx, unsi
             if (!JSObject::getElement(cx, pairobj, pairobj, 1, &val))
                 return false;
 
             RelocatableValue rval(val);
             if (!map->put(hkey, rval)) {
                 js_ReportOutOfMemory(cx);
                 return false;
             }
-            WriteBarrierPost(cx->runtime, map, hkey);
+            WriteBarrierPost(cx->runtime(), map, hkey);
         }
         if (!iter.close())
             return false;
     }
 
     args.rval().setObject(*obj);
     return true;
 }
@@ -1302,17 +1302,17 @@ MapObject::set_impl(JSContext *cx, CallA
 
     ValueMap &map = extract(args);
     ARG0_KEY(cx, args, key);
     RelocatableValue rval(args.get(1));
     if (!map.put(key, rval)) {
         js_ReportOutOfMemory(cx);
         return false;
     }
-    WriteBarrierPost(cx->runtime, &map, key);
+    WriteBarrierPost(cx->runtime(), &map, key);
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 MapObject::set(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1665,17 +1665,17 @@ SetObject::finalize(FreeOp *fop, JSObjec
 
 JSBool
 SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
 {
     Rooted<JSObject*> obj(cx, NewBuiltinClassInstance(cx, &class_));
     if (!obj)
         return false;
 
-    ValueSet *set = cx->new_<ValueSet>(cx->runtime);
+    ValueSet *set = cx->new_<ValueSet>(cx->runtime());
     if (!set)
         return false;
     if (!set->init()) {
         js_ReportOutOfMemory(cx);
         return false;
     }
     obj->setPrivate(set);
 
@@ -1685,17 +1685,17 @@ SetObject::construct(JSContext *cx, unsi
         while (iter.next()) {
             AutoHashableValueRooter key(cx);
             if (!key.setValue(cx, iter.value()))
                 return false;
             if (!set->put(key)) {
                 js_ReportOutOfMemory(cx);
                 return false;
             }
-            WriteBarrierPost(cx->runtime, set, key);
+            WriteBarrierPost(cx->runtime(), set, key);
         }
         if (!iter.close())
             return false;
     }
 
     args.rval().setObject(*obj);
     return true;
 }
@@ -1756,17 +1756,17 @@ SetObject::add_impl(JSContext *cx, CallA
     JS_ASSERT(is(args.thisv()));
 
     ValueSet &set = extract(args);
     ARG0_KEY(cx, args, key);
     if (!set.put(key)) {
         js_ReportOutOfMemory(cx);
         return false;
     }
-    WriteBarrierPost(cx->runtime, &set, key);
+    WriteBarrierPost(cx->runtime(), &set, key);
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 SetObject::add(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -199,17 +199,17 @@ EscapeNakedForwardSlashes(JSContext *cx,
  *  _ => pattern := ToString(pattern) if defined(pattern) else ''
  *       flags := ToString(flags) if defined(flags) else ''
  */
 static bool
 CompileRegExpObject(JSContext *cx, RegExpObjectBuilder &builder, CallArgs args)
 {
     if (args.length() == 0) {
         RegExpStatics *res = cx->regExpStatics();
-        Rooted<JSAtom*> empty(cx, cx->runtime->emptyString);
+        Rooted<JSAtom*> empty(cx, cx->runtime()->emptyString);
         RegExpObject *reobj = builder.build(empty, res->getFlags());
         if (!reobj)
             return false;
         args.rval().setObject(*reobj);
         return true;
     }
 
     RootedValue sourceValue(cx, args[0]);
@@ -258,17 +258,17 @@ CompileRegExpObject(JSContext *cx, RegEx
             return false;
 
         args.rval().setObject(*reobj);
         return true;
     }
 
     RootedAtom source(cx);
     if (sourceValue.isUndefined()) {
-        source = cx->runtime->emptyString;
+        source = cx->runtime()->emptyString;
     } else {
         /* Coerce to string and compile. */
         JSString *str = ToString<CanGC>(cx, sourceValue);
         if (!str)
             return false;
 
         source = AtomizeString<CanGC>(cx, str);
         if (!source)
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -198,29 +198,29 @@ GC(JSContext *cx, unsigned argc, jsval *
                 return false;
         } else if (arg.isObject()) {
             PrepareZoneForGC(UncheckedUnwrap(&arg.toObject())->zone());
             compartment = true;
         }
     }
 
 #ifndef JS_MORE_DETERMINISTIC
-    size_t preBytes = cx->runtime->gcBytes;
+    size_t preBytes = cx->runtime()->gcBytes;
 #endif
 
     if (compartment)
-        PrepareForDebugGC(cx->runtime);
+        PrepareForDebugGC(cx->runtime());
     else
-        PrepareForFullGC(cx->runtime);
-    GCForReason(cx->runtime, gcreason::API);
+        PrepareForFullGC(cx->runtime());
+    GCForReason(cx->runtime(), gcreason::API);
 
     char buf[256] = { '\0' };
 #ifndef JS_MORE_DETERMINISTIC
     JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
-                (unsigned long)preBytes, (unsigned long)cx->runtime->gcBytes);
+                (unsigned long)preBytes, (unsigned long)cx->runtime()->gcBytes);
 #endif
     JSString *str = JS_NewStringCopyZ(cx, buf);
     if (!str)
         return false;
     *vp = STRING_TO_JSVAL(str);
     return true;
 }
 
@@ -263,17 +263,17 @@ GCParameter(JSContext *cx, unsigned argc
             return false;
         }
         if (JS_FlatStringEqualsAscii(flatStr, paramMap[paramIndex].name))
             break;
     }
     JSGCParamKey param = paramMap[paramIndex].param;
 
     if (argc == 1) {
-        uint32_t value = JS_GetGCParameter(cx->runtime, param);
+        uint32_t value = JS_GetGCParameter(cx->runtime(), param);
         vp[0] = JS_NumberValue(value);
         return true;
     }
 
     if (param == JSGC_NUMBER ||
         param == JSGC_BYTES) {
         JS_ReportError(cx, "Attempt to change read-only parameter %s",
                        paramMap[paramIndex].name);
@@ -284,27 +284,27 @@ GCParameter(JSContext *cx, unsigned argc
     if (!JS_ValueToECMAUint32(cx, vp[3], &value)) {
         JS_ReportError(cx,
                        "the second argument must be convertable to uint32_t "
                        "with non-zero value");
         return false;
     }
 
     if (param == JSGC_MAX_BYTES) {
-        uint32_t gcBytes = JS_GetGCParameter(cx->runtime, JSGC_BYTES);
+        uint32_t gcBytes = JS_GetGCParameter(cx->runtime(), JSGC_BYTES);
         if (value < gcBytes) {
             JS_ReportError(cx,
                            "attempt to set maxBytes to the value less than the current "
                            "gcBytes (%u)",
                            gcBytes);
             return false;
         }
     }
 
-    JS_SetGCParameter(cx->runtime, param, value);
+    JS_SetGCParameter(cx->runtime(), param, value);
     *vp = JSVAL_VOID;
     return true;
 }
 
 static JSBool
 IsProxy(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -350,17 +350,17 @@ GCPreserveCode(JSContext *cx, unsigned a
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (argc != 0) {
         RootedObject callee(cx, &args.callee());
         ReportUsageError(cx, callee, "Wrong number of arguments");
         return JS_FALSE;
     }
 
-    cx->runtime->alwaysPreserveCode = true;
+    cx->runtime()->alwaysPreserveCode = true;
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 #ifdef JS_GC_ZEAL
 static JSBool
 GCZeal(JSContext *cx, unsigned argc, jsval *vp)
@@ -409,17 +409,17 @@ ScheduleGC(JSContext *cx, unsigned argc,
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 SelectForGC(JSContext *cx, unsigned argc, jsval *vp)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     for (unsigned i = 0; i < argc; i++) {
         Value arg(JS_ARGV(cx, vp)[i]);
         if (arg.isObject()) {
             if (!rt->gcSelectedForMarking.append(&arg.toObject()))
                 return false;
         }
     }
@@ -433,47 +433,47 @@ VerifyPreBarriers(JSContext *cx, unsigne
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (argc) {
         RootedObject callee(cx, &args.callee());
         ReportUsageError(cx, callee, "Too many arguments");
         return JS_FALSE;
     }
-    gc::VerifyBarriers(cx->runtime, gc::PreBarrierVerifier);
+    gc::VerifyBarriers(cx->runtime(), gc::PreBarrierVerifier);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 VerifyPostBarriers(JSContext *cx, unsigned argc, jsval *vp)
 {
     if (argc) {
         RootedObject callee(cx, &JS_CALLEE(cx, vp).toObject());
         ReportUsageError(cx, callee, "Too many arguments");
         return JS_FALSE;
     }
-    gc::VerifyBarriers(cx->runtime, gc::PostBarrierVerifier);
+    gc::VerifyBarriers(cx->runtime(), gc::PostBarrierVerifier);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 GCState(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (argc != 0) {
         RootedObject callee(cx, &args.callee());
         ReportUsageError(cx, callee, "Too many arguments");
         return false;
     }
 
     const char *state;
-    gc::State globalState = cx->runtime->gcIncrementalState;
+    gc::State globalState = cx->runtime()->gcIncrementalState;
     if (globalState == gc::NO_INCREMENTAL)
         state = "none";
     else if (globalState == gc::MARK)
         state = "mark";
     else if (globalState == gc::SWEEP)
         state = "sweep";
     else
         JS_NOT_REACHED("Unobserveable global GC state");
@@ -517,17 +517,17 @@ GCSlice(JSContext *cx, unsigned argc, js
 
     if (argc == 1) {
         if (!JS_ValueToECMAUint32(cx, args[0], &budget))
             return false;
     } else {
         limit = false;
     }
 
-    GCDebugSlice(cx->runtime, limit, budget);
+    GCDebugSlice(cx->runtime(), limit, budget);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
 ValidateGC(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -845,45 +845,45 @@ EnableSPSProfilingAssertions(JSContext *
         RootedObject arg(cx, &args.callee());
         ReportUsageError(cx, arg, "Must have one boolean argument");
         return false;
     }
 
     static ProfileEntry stack[1000];
     static uint32_t stack_size = 0;
 
-    SetRuntimeProfilingStack(cx->runtime, stack, &stack_size, 1000);
-    cx->runtime->spsProfiler.enableSlowAssertions(args[0].toBoolean());
-    cx->runtime->spsProfiler.enable(true);
+    SetRuntimeProfilingStack(cx->runtime(), stack, &stack_size, 1000);
+    cx->runtime()->spsProfiler.enableSlowAssertions(args[0].toBoolean());
+    cx->runtime()->spsProfiler.enable(true);
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSBool
 DisableSPSProfiling(JSContext *cx, unsigned argc, jsval *vp)
 {
-    if (cx->runtime->spsProfiler.installed())
-        cx->runtime->spsProfiler.enable(false);
+    if (cx->runtime()->spsProfiler.installed())
+        cx->runtime()->spsProfiler.enable(false);
     return true;
 }
 
 static JSBool
 DisplayName(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (argc == 0 || !args[0].isObject() || !args[0].toObject().isFunction()) {
         RootedObject arg(cx, &args.callee());
         ReportUsageError(cx, arg, "Must have one function argument");
         return false;
     }
 
     JSFunction *fun = args[0].toObject().toFunction();
     JSString *str = fun->displayAtom();
-    vp->setString(str == NULL ? cx->runtime->emptyString : str);
+    vp->setString(str == NULL ? cx->runtime()->emptyString : str);
     return true;
 }
 
 JSBool
 js::testingFunc_inParallelSection(JSContext *cx, unsigned argc, jsval *vp)
 {
     // If we were actually *in* a parallel section, then this function
     // would be inlined to TRUE in ion-generated code.
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -6513,17 +6513,17 @@ CData::GetRuntime(JSContext* cx, unsigne
   RootedObject targetType(cx, &args[0].toObject());
   size_t targetSize;
   if (!CType::GetSafeSize(targetType, &targetSize) ||
       targetSize != sizeof(void*)) {
     JS_ReportError(cx, "target CType has non-pointer size");
     return JS_FALSE;
   }
 
-  void* data = static_cast<void*>(cx->runtime);
+  void* data = static_cast<void*>(cx->runtime());
   JSObject* result = CData::Create(cx, targetType, NullPtr(), &data, true);
   if (!result)
     return JS_FALSE;
 
   args.rval().setObject(*result);
   return JS_TRUE;
 }
 
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -309,17 +309,17 @@ frontend::CompileScript(JSContext *cx, H
     return script;
 }
 
 bool
 frontend::CompileLazyFunction(JSContext *cx, HandleFunction fun, LazyScript *lazy,
                               const jschar *chars, size_t length)
 {
     CompileOptions options(cx);
-    options.setPrincipals(cx->compartment->principals)
+    options.setPrincipals(cx->compartment()->principals)
            .setOriginPrincipals(lazy->parent()->originPrincipals)
            .setVersion(lazy->parent()->getVersion())
            .setFileAndLine(lazy->parent()->filename(), lazy->lineno())
            .setColumn(lazy->column())
            .setCompileAndGo(lazy->parent()->compileAndGo)
            .setNoScriptRval(false)
            .setSelfHostingMode(false);
 
--- a/js/src/frontend/ParseMaps-inl.h
+++ b/js/src/frontend/ParseMaps-inl.h
@@ -82,42 +82,42 @@ AtomDecls<ParseHandler>::addUnique(JSAto
 }
 
 template <class Map>
 inline bool
 AtomThingMapPtr<Map>::ensureMap(JSContext *cx)
 {
     if (map_)
         return true;
-    map_ = cx->runtime->parseMapPool.acquire<Map>();
+    map_ = cx->runtime()->parseMapPool.acquire<Map>();
     return !!map_;
 }
 
 template <class Map>
 inline void
 AtomThingMapPtr<Map>::releaseMap(JSContext *cx)
 {
     if (!map_)
         return;
-    cx->runtime->parseMapPool.release(map_);
+    cx->runtime()->parseMapPool.release(map_);
     map_ = NULL;
 }
 
 template <typename ParseHandler>
 inline bool
 AtomDecls<ParseHandler>::init()
 {
-    map = cx->runtime->parseMapPool.acquire<AtomDefnListMap>();
+    map = cx->runtime()->parseMapPool.acquire<AtomDefnListMap>();
     return map;
 }
 
 template <typename ParseHandler>
 inline
 AtomDecls<ParseHandler>::~AtomDecls()
 {
     if (map)
-        cx->runtime->parseMapPool.release(map);
+        cx->runtime()->parseMapPool.release(map);
 }
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -407,43 +407,43 @@ Parser<ParseHandler>::Parser(JSContext *
                              Parser<SyntaxParseHandler> *syntaxParser,
                              LazyScript *lazyOuterFunction)
   : AutoGCRooter(cx, PARSER),
     context(cx),
     tokenStream(cx, options, chars, length, thisForCtor(), keepAtoms),
     traceListHead(NULL),
     pc(NULL),
     sct(NULL),
-    keepAtoms(cx->runtime),
+    keepAtoms(cx->runtime()),
     foldConstants(foldConstants),
     compileAndGo(options.compileAndGo),
     selfHostingMode(options.selfHostingMode),
     abortedSyntaxParse(false),
     handler(cx, tokenStream, foldConstants, syntaxParser, lazyOuterFunction)
 {
     // XXX bug 678037 always disable syntax parsing for now.
     handler.disableSyntaxParser();
 
-    cx->runtime->activeCompilations++;
+    cx->runtime()->activeCompilations++;
 
     // The Mozilla specific 'strict' option adds extra warnings which are not
     // generated if functions are parsed lazily. Note that the standard
     // "use strict" does not inhibit lazy parsing.
     if (context->hasStrictOption())
         handler.disableSyntaxParser();
 
     tempPoolMark = cx->tempLifoAlloc().mark();
 }
 
 template <typename ParseHandler>
 Parser<ParseHandler>::~Parser()
 {
     JSContext *cx = context;
     cx->tempLifoAlloc().release(tempPoolMark);
-    cx->runtime->activeCompilations--;
+    cx->runtime()->activeCompilations--;
 
     /*
      * The parser can allocate enormous amounts of memory for large functions.
      * Eagerly free the memory now (which otherwise won't be freed until the
      * next GC) to avoid unnecessary OOMs.
      */
     cx->tempLifoAlloc().freeAllIfHugeAndUnused();
 }
@@ -2318,17 +2318,17 @@ Parser<ParseHandler>::functionArgsAndBod
 
     return finishFunctionDefinition(pn, funbox, prelude, body);
 }
 
 template <>
 ParseNode *
 Parser<FullParseHandler>::moduleDecl()
 {
-    JS_ASSERT(tokenStream.currentToken().name() == context->runtime->atomState.module);
+    JS_ASSERT(tokenStream.currentToken().name() == context->runtime()->atomState.module);
     if (!((pc->sc->isGlobalSharedContext() || pc->sc->isModuleBox()) && pc->atBodyLevel()))
     {
         report(ParseError, false, NULL, JSMSG_MODULE_STATEMENT);
         return NULL;
     }
 
     ParseNode *pn = CodeNode::create(PNK_MODULE, &handler);
     if (!pn)
@@ -2459,17 +2459,17 @@ Parser<ParseHandler>::maybeParseDirectiv
         //
         // Note that even if the string isn't one we recognize as a directive,
         // the emitter still shouldn't flag it as useless, as it could become a
         // directive in the future. We don't want to interfere with people
         // taking advantage of directive-prologue-enabled features that appear
         // in other browsers first.
         handler.setPrologue(pn);
 
-        if (directive == context->runtime->atomState.useStrict) {
+        if (directive == context->runtime()->atomState.useStrict) {
             // We're going to be in strict mode. Note that this scope explicitly
             // had "use strict";
             pc->sc->setExplicitUseStrict();
             if (!pc->sc->strict) {
                 if (pc->sc->isFunctionBox()) {
                     // Request that this function be reparsed as strict.
                     pc->funBecameStrict = true;
                     return false;
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -306,18 +306,18 @@ TokenStream::TokenStream(JSContext *cx, 
     // initial line's base must be included in the buffer. linebase and userbuf
     // were adjusted above, and if we are starting tokenization part way through
     // this line then adjust the next character.
     userbuf.setAddressOfNextRawChar(base);
 
     if (originPrincipals)
         JS_HoldPrincipals(originPrincipals);
 
-    JSSourceHandler listener = cx->runtime->debugHooks.sourceHandler;
-    void *listenerData = cx->runtime->debugHooks.sourceHandlerData;
+    JSSourceHandler listener = cx->runtime()->debugHooks.sourceHandler;
+    void *listenerData = cx->runtime()->debugHooks.sourceHandlerData;
 
     if (listener)
         listener(options.filename, options.lineno, base, length, &listenerTSData, listenerData);
 
     /*
      * This table holds all the token kinds that satisfy these properties:
      * - A single char long.
      * - Cannot be a prefix of any longer token (e.g. '+' is excluded because
@@ -365,17 +365,17 @@ TokenStream::TokenStream(JSContext *cx, 
 #pragma warning(pop)
 #endif
 
 TokenStream::~TokenStream()
 {
     if (sourceMap)
         js_free(sourceMap);
     if (originPrincipals)
-        JS_DropPrincipals(cx->runtime, originPrincipals);
+        JS_DropPrincipals(cx->runtime(), originPrincipals);
 }
 
 /* Use the fastest available getc. */
 #if defined(HAVE_GETC_UNLOCKED)
 # define fast_getc getc_unlocked
 #elif defined(HAVE__GETC_NOLOCK)
 # define fast_getc _getc_nolock
 #else
@@ -630,18 +630,18 @@ CompileError::throwError()
      * uncaught exception report.
      */
     if (!js_ErrorToException(cx, message, &report, NULL, NULL)) {
         /*
          * If debugErrorHook is present then we give it a chance to veto
          * sending the error on to the regular error reporter.
          */
         bool reportError = true;
-        if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) {
-            reportError = hook(cx, message, &report, cx->runtime->debugHooks.debugErrorHookData);
+        if (JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook) {
+            reportError = hook(cx, message, &report, cx->runtime()->debugHooks.debugErrorHookData);
         }
 
         /* Report the error */
         if (reportError && cx->errorReporter)
             cx->errorReporter(cx, message, &report);
     }
 }
 
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -221,30 +221,30 @@ GatherRooters(Vector<Rooter, 0, SystemAl
         JS_ALWAYS_TRUE(rooters.append(r));
         rooter = rooter->previous();
     }
 }
 
 void
 JS::CheckStackRoots(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     if (rt->gcZeal_ != ZealStackRootingValue)
         return;
 
     // GCs can't happen when analysis/inference/compilation are active.
-    if (cx->compartment->activeAnalysis)
+    if (cx->compartment()->activeAnalysis)
         return;
 
     if (rt->mainThread.suppressGC)
         return;
 
     // Can switch to the atoms compartment during analysis.
-    if (IsAtomsCompartment(cx->compartment)) {
+    if (IsAtomsCompartment(cx->compartment())) {
         for (CompartmentsIter c(rt); !c.done(); c.next()) {
             if (c.get()->activeAnalysis)
                 return;
         }
     }
 
     AutoCopyFreeListToArenas copy(rt);
 
@@ -847,18 +847,18 @@ MaybeVerifyPostBarriers(JSRuntime *rt, b
         EndVerifyPostBarriers(rt);
     }
     StartVerifyPostBarriers(rt);
 }
 
 void
 js::gc::MaybeVerifyBarriers(JSContext *cx, bool always)
 {
-    MaybeVerifyPreBarriers(cx->runtime, always);
-    MaybeVerifyPostBarriers(cx->runtime, always);
+    MaybeVerifyPreBarriers(cx->runtime(), always);
+    MaybeVerifyPostBarriers(cx->runtime(), always);
 }
 
 void
 js::gc::FinishVerifier(JSRuntime *rt)
 {
     if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
         js_delete(trc);
         rt->gcVerifyPreData = NULL;
--- a/js/src/ion/AsmJS.cpp
+++ b/js/src/ion/AsmJS.cpp
@@ -1151,17 +1151,17 @@ class MOZ_STACK_CLASS ModuleCompiler
         // Avoid spurious Label assertions on compilation failure.
         if (!stackOverflowLabel_.bound())
             stackOverflowLabel_.bind(0);
         if (!operationCallbackLabel_.bound())
             operationCallbackLabel_.bind(0);
     }
 
     bool init() {
-        if (!cx_->compartment->ensureIonCompartmentExists(cx_))
+        if (!cx_->compartment()->ensureIonCompartmentExists(cx_))
             return false;
 
         if (!globals_.init() || !exits_.init())
             return false;
 
         if (!standardLibraryMathNames_.init() ||
             !addStandardLibraryMathName("sin", AsmJSMathBuiltin_sin) ||
             !addStandardLibraryMathName("cos", AsmJSMathBuiltin_cos) ||
@@ -1455,17 +1455,17 @@ class MOZ_STACK_CLASS ModuleCompiler
         size_t codeBytes = AlignBytes(masm_.bytesNeeded(), sizeof(double));
         size_t totalBytes = codeBytes + module_->globalDataBytes();
 
         // The code must be page aligned, so include extra space so that we can
         // AlignBytes the allocation result below.
         size_t allocedBytes = totalBytes + gc::PageSize;
 
         // Allocate the slab of memory.
-        JSC::ExecutableAllocator *execAlloc = cx_->compartment->ionCompartment()->execAlloc();
+        JSC::ExecutableAllocator *execAlloc = cx_->compartment()->ionCompartment()->execAlloc();
         JSC::ExecutablePool *pool;
         uint8_t *unalignedBytes = (uint8_t*)execAlloc->alloc(allocedBytes, &pool, JSC::ASMJS_CODE);
         if (!unalignedBytes)
             return false;
         uint8_t *code = (uint8_t*)AlignBytes((uintptr_t)unalignedBytes, gc::PageSize);
 
         // The ExecutablePool owns the memory and must be released by the AsmJSModule.
         module_->takeOwnership(pool, code, codeBytes, totalBytes);
@@ -4627,25 +4627,25 @@ CheckFunctionBody(ModuleCompiler &m, Mod
             return NULL;
     }
 
     if (!CheckVariableDecls(m, &locals, &stmtIter))
         return NULL;
 
     // Force Ion allocations to occur in the LifoAlloc while in scope.
     TempAllocator *tempAlloc = lifo.new_<TempAllocator>(&lifo);
-    IonContext icx(m.cx()->compartment, tempAlloc);
+    IonContext icx(m.cx()->compartment(), tempAlloc);
 
     // Allocate objects required for MIR generation.
     // Memory for the objects is provided by the LifoAlloc argument,
     // which may be explicitly tracked by the caller.
     MIRGraph *graph = lifo.new_<MIRGraph>(tempAlloc);
     CompileInfo *info = lifo.new_<CompileInfo>(locals.count(),
                                                SequentialExecution);
-    MIRGenerator *mirGen = lifo.new_<MIRGenerator>(m.cx()->compartment, tempAlloc, graph, info);
+    MIRGenerator *mirGen = lifo.new_<MIRGenerator>(m.cx()->compartment(), tempAlloc, graph, info);
     JS_ASSERT(tempAlloc && graph && info && mirGen);
 
     FunctionCompiler f(m, func, Move(locals), mirGen);
     if (!f.init())
         return NULL;
 
     if (!CheckStatements(f, stmtIter))
         return NULL;
@@ -4714,17 +4714,17 @@ CheckFunctionBodiesSequential(ModuleComp
         LifoAllocScope scope(&lifo);
 
         MIRGenerator *mirGen = CheckFunctionBody(m, func, lifo);
         if (!mirGen)
             return false;
 
         IonSpewNewFunction(&mirGen->graph(), NullPtr());
 
-        IonContext icx(m.cx()->compartment, &mirGen->temp());
+        IonContext icx(m.cx()->compartment(), &mirGen->temp());
 
         if (!OptimizeMIR(mirGen))
             return m.fail(func.fn(), "internal compiler failure (probably out of memory)");
 
         LIRGraph *lir = GenerateLIR(mirGen);
         if (!lir)
             return m.fail(func.fn(), "internal compiler failure (probably out of memory)");
 
@@ -4750,17 +4750,17 @@ struct ParallelGroupState
       : state(state), tasks(tasks), outstandingJobs(0), compiledJobs(0)
     { }
 };
 
 // Block until a worker-assigned LifoAlloc becomes finished.
 static AsmJSParallelTask *
 GetFinishedCompilation(ModuleCompiler &m, ParallelGroupState &group)
 {
-    AutoLockWorkerThreadState lock(m.cx()->runtime);
+    AutoLockWorkerThreadState lock(m.cx()->runtime());
 
     while (!group.state.asmJSWorkerFailed()) {
         if (!group.state.asmJSFinishedList.empty()) {
             group.outstandingJobs--;
             return group.state.asmJSFinishedList.popCopy();
         }
         group.state.wait(WorkerThreadState::MAIN);
     }
@@ -4855,17 +4855,17 @@ CancelOutstandingJobs(ModuleCompiler &m,
     // maintained in the scope of CheckFunctionBodiesParallel() -- so in order
     // for that function to safely return, and thereby remove the LifoAllocs,
     // none of that memory can be in use or reachable by workers.
 
     JS_ASSERT(group.outstandingJobs >= 0);
     if (!group.outstandingJobs)
         return;
 
-    AutoLockWorkerThreadState lock(m.cx()->runtime);
+    AutoLockWorkerThreadState lock(m.cx()->runtime());
 
     // From the compiling tasks, eliminate those waiting for worker assignation.
     group.outstandingJobs -= group.state.asmJSWorklist.length();
     group.state.asmJSWorklist.clear();
 
     // From the compiling tasks, eliminate those waiting for codegen.
     group.outstandingJobs -= group.state.asmJSFinishedList.length();
     group.state.asmJSFinishedList.clear();
@@ -4889,17 +4889,17 @@ CancelOutstandingJobs(ModuleCompiler &m,
 }
 
 static const size_t LIFO_ALLOC_PARALLEL_CHUNK_SIZE = 1 << 12;
 
 static bool
 CheckFunctionBodiesParallel(ModuleCompiler &m)
 {
     // Saturate all worker threads plus the main thread.
-    WorkerThreadState &state = *m.cx()->runtime->workerThreadState;
+    WorkerThreadState &state = *m.cx()->runtime()->workerThreadState;
     size_t numParallelJobs = state.numThreads + 1;
 
     // Allocate scoped AsmJSParallelTask objects. Each contains a unique
     // LifoAlloc that provides all necessary memory for compilation.
     Vector<AsmJSParallelTask, 0> tasks(m.cx());
     if (!tasks.initCapacity(numParallelJobs))
         return false;
 
@@ -5755,26 +5755,26 @@ js::CompileAsmJS(JSContext *cx, TokenStr
                  MutableHandleFunction moduleFun)
 {
     if (!JSC::MacroAssembler().supportsFloatingPoint())
         return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by lack of floating point support");
 
     if (!cx->hasOption(JSOPTION_ASMJS))
         return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by javascript.options.asmjs in about:config");
 
-    if (cx->compartment->debugMode())
+    if (cx->compartment()->debugMode())
         return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
 
 #ifdef JS_ASMJS
-    if (!EnsureAsmJSSignalHandlersInstalled(cx->runtime))
+    if (!EnsureAsmJSSignalHandlersInstalled(cx->runtime()))
         return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform missing signal handler support");
 
 # ifdef JS_PARALLEL_COMPILATION
     if (OffThreadCompilationEnabled(cx)) {
-        if (!EnsureParallelCompilationInitialized(cx->runtime))
+        if (!EnsureParallelCompilationInitialized(cx->runtime()))
             return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Failed compilation thread initialization");
     }
 # endif
 
     ScopedJSDeletePtr<AsmJSModule> module;
     if (!CheckModule(cx, ts, fn, &module))
         return !cx->isExceptionPending();
 
@@ -5806,17 +5806,17 @@ js::CompileAsmJS(JSContext *cx, TokenStr
 
 JSBool
 js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
 #ifdef JS_ASMJS
     bool available = JSC::MacroAssembler().supportsFloatingPoint() &&
-                     !cx->compartment->debugMode() &&
+                     !cx->compartment()->debugMode() &&
                      cx->hasOption(JSOPTION_ASMJS);
 #else
     bool available = false;
 #endif
 
     args.rval().set(BooleanValue(available));
     return true;
 }
--- a/js/src/ion/AsmJSLink.cpp
+++ b/js/src/ion/AsmJSLink.cpp
@@ -253,38 +253,38 @@ DynamicallyLinkModule(JSContext *cx, Cal
 
 AsmJSActivation::AsmJSActivation(JSContext *cx, const AsmJSModule &module)
   : cx_(cx),
     module_(module),
     errorRejoinSP_(NULL),
     profiler_(NULL),
     resumePC_(NULL)
 {
-    if (cx->runtime->spsProfiler.enabled()) {
-        profiler_ = &cx->runtime->spsProfiler;
+    if (cx->runtime()->spsProfiler.enabled()) {
+        profiler_ = &cx->runtime()->spsProfiler;
         profiler_->enterNative("asm.js code", this);
     }
 
-    prev_ = cx_->runtime->mainThread.asmJSActivationStack_;
+    prev_ = cx_->runtime()->mainThread.asmJSActivationStack_;
 
-    JSRuntime::AutoLockForOperationCallback lock(cx_->runtime);
-    cx_->runtime->mainThread.asmJSActivationStack_ = this;
+    JSRuntime::AutoLockForOperationCallback lock(cx_->runtime());
+    cx_->runtime()->mainThread.asmJSActivationStack_ = this;
 
     (void) errorRejoinSP_;  // squelch GCC warning
 }
 
 AsmJSActivation::~AsmJSActivation()
 {
     if (profiler_)
         profiler_->exitNative();
 
-    JS_ASSERT(cx_->runtime->mainThread.asmJSActivationStack_ == this);
+    JS_ASSERT(cx_->runtime()->mainThread.asmJSActivationStack_ == this);
 
-    JSRuntime::AutoLockForOperationCallback lock(cx_->runtime);
-    cx_->runtime->mainThread.asmJSActivationStack_ = prev_;
+    JSRuntime::AutoLockForOperationCallback lock(cx_->runtime());
+    cx_->runtime()->mainThread.asmJSActivationStack_ = prev_;
 }
 
 static const unsigned ASM_MODULE_SLOT = 0;
 static const unsigned ASM_EXPORT_INDEX_SLOT = 1;
 
 extern JSBool
 js::CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
 {
--- a/js/src/ion/Bailouts.cpp
+++ b/js/src/ion/Bailouts.cpp
@@ -128,17 +128,17 @@ ion::InvalidationBailout(InvalidationBai
         frame->replaceCalleeToken(NULL);
         EnsureExitFrame(frame);
 
         IonSpew(IonSpew_Invalidate, "   new  calleeToken %p", (void *) frame->calleeToken());
         IonSpew(IonSpew_Invalidate, "   new  frameSize %u", unsigned(frame->prevFrameLocalSize()));
         IonSpew(IonSpew_Invalidate, "   new  ra %p", (void *) frame->returnAddress());
     }
 
-    iter.ionScript()->decref(cx->runtime->defaultFreeOp());
+    iter.ionScript()->decref(cx->runtime()->defaultFreeOp());
 
     return retval;
 }
 
 // Initialize the decl env Object, call object, and any arguments obj of the current frame.
 bool
 ion::EnsureHasScopeObjects(JSContext *cx, AbstractFramePtr fp)
 {
--- a/js/src/ion/BaselineBailouts.cpp
+++ b/js/src/ion/BaselineBailouts.cpp
@@ -498,17 +498,17 @@ InitFromBailout(JSContext *cx, HandleScr
     IonSpew(IonSpew_BaselineBailouts, "      FrameSize=%d", (int) frameSize);
     blFrame->setFrameSize(frameSize);
 
     uint32_t flags = 0;
 
     // If SPS Profiler is enabled, mark the frame as having pushed an SPS entry.
     // This may be wrong for the last frame of ArgumentCheck bailout, but
     // that will be fixed later.
-    if (cx->runtime->spsProfiler.enabled() && ionScript->hasSPSInstrumentation()) {
+    if (cx->runtime()->spsProfiler.enabled() && ionScript->hasSPSInstrumentation()) {
         IonSpew(IonSpew_BaselineBailouts, "      Setting SPS flag on frame!");
         flags |= BaselineFrame::HAS_PUSHED_SPS_FRAME;
     }
 
     // Initialize BaselineFrame's scopeChain and argsObj
     JSObject *scopeChain = NULL;
     ArgumentsObject *argsObj = NULL;
     BailoutKind bailoutKind = iter.bailoutKind();
@@ -610,21 +610,21 @@ InitFromBailout(JSContext *cx, HandleScr
     IonSpew(IonSpew_BaselineBailouts, "      pushing %d expression stack slots",
                                       (int) exprStackSlots);
     for (uint32_t i = 0; i < exprStackSlots; i++) {
         Value v;
 
         // If coming from an invalidation bailout, and this is the topmost
         // value, and a value override has been specified, don't read from the
         // iterator. Otherwise, we risk using a garbage value.
-        if (!iter.moreFrames() && i == exprStackSlots - 1 && cx->runtime->hasIonReturnOverride()) {
+        if (!iter.moreFrames() && i == exprStackSlots - 1 && cx->runtime()->hasIonReturnOverride()) {
             JS_ASSERT(invalidate);
             iter.skip();
             IonSpew(IonSpew_BaselineBailouts, "      [Return Override]");
-            v = cx->runtime->takeIonReturnOverride();
+            v = cx->runtime()->takeIonReturnOverride();
         } else {
             v = iter.read();
         }
         if (!builder.writeValue(v, "StackValue"))
             return false;
     }
 
     size_t endOfBaselineJSFrameStack = builder.framePushed();
@@ -788,26 +788,26 @@ InitFromBailout(JSContext *cx, HandleScr
                 //              (since this bailout happens before MFunctionBoundary).
                 //          Make sure that's done now.
                 //  2. If resuming into the prologue, and the bailout is NOT because of an
                 //     argument check, then:
                 //          Top SPS profiler entry would be for callee frame.
                 //          Ion would already have pushed an SPS entry for this frame.
                 //          The pc for this entry would be set to NULL.
                 //          Make sure it's set to script->pc.
-                if (cx->runtime->spsProfiler.enabled()) {
+                if (cx->runtime()->spsProfiler.enabled()) {
                     if (caller && bailoutKind == Bailout_ArgumentCheck) {
                         IonSpew(IonSpew_BaselineBailouts, "      Setting PCidx on innermost "
                                 "inlined frame's parent's SPS entry (%s:%d) (pcIdx=%d)!",
                                 caller->filename(), caller->lineno, callerPC - caller->code);
-                        cx->runtime->spsProfiler.updatePC(caller, callerPC);
+                        cx->runtime()->spsProfiler.updatePC(caller, callerPC);
                     } else if (bailoutKind != Bailout_ArgumentCheck) {
                         IonSpew(IonSpew_BaselineBailouts,
                                 "      Popping SPS entry for innermost inlined frame's SPS entry");
-                        cx->runtime->spsProfiler.exit(cx, script, fun);
+                        cx->runtime()->spsProfiler.exit(cx, script, fun);
                     }
                 }
             } else {
                 opReturnAddr = nativeCodeForPC;
             }
             builder.setResumeAddr(opReturnAddr);
             IonSpew(IonSpew_BaselineBailouts, "      Set resumeAddr=%p", opReturnAddr);
         }
@@ -906,17 +906,17 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
     nextCallee.set(calleeFun);
 
     // Push BaselineStub frame descriptor
     if (!builder.writeWord(baselineStubFrameDescr, "Descriptor"))
         return false;
 
     // Push return address into ICCall_Scripted stub, immediately after the call.
-    void *baselineCallReturnAddr = cx->compartment->ionCompartment()->baselineCallReturnAddr();
+    void *baselineCallReturnAddr = cx->compartment()->ionCompartment()->baselineCallReturnAddr();
     JS_ASSERT(baselineCallReturnAddr);
     if (!builder.writePtr(baselineCallReturnAddr, "ReturnAddr"))
         return false;
 
     // If actualArgc >= fun->nargs, then we are done.  Otherwise, we need to push on
     // a reconstructed rectifier frame.
     if (actualArgc >= calleeFun->nargs)
         return true;
@@ -985,17 +985,17 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
 
     // Push rectifier frame descriptor
     if (!builder.writeWord(rectifierFrameDescr, "Descriptor"))
         return false;
 
     // Push return address into the ArgumentsRectifier code, immediately after the ioncode
     // call.
-    void *rectReturnAddr = cx->compartment->ionCompartment()->getArgumentsRectifierReturnAddr();
+    void *rectReturnAddr = cx->compartment()->ionCompartment()->getArgumentsRectifierReturnAddr();
     JS_ASSERT(rectReturnAddr);
     if (!builder.writePtr(rectReturnAddr, "ReturnAddr"))
         return false;
 
     return true;
 }
 
 uint32_t
--- a/js/src/ion/BaselineCompiler.cpp
+++ b/js/src/ion/BaselineCompiler.cpp
@@ -191,17 +191,17 @@ BaselineCompiler::compile()
                                            ImmWord(uintptr_t(-1)));
     }
 
     // All barriers are emitted off-by-default, toggle them on if needed.
     if (cx->zone()->needsBarrier())
         baselineScript->toggleBarriers(true);
 
     // All SPS instrumentation is emitted toggled off.  Toggle them on if needed.
-    if (cx->runtime->spsProfiler.enabled())
+    if (cx->runtime()->spsProfiler.enabled())
         baselineScript->toggleSPS(true);
 
     return Method_Compiled;
 }
 
 bool
 BaselineCompiler::emitPrologue()
 {
@@ -292,17 +292,17 @@ BaselineCompiler::emitOutOfLinePostBarri
     Register scratch = regs.takeAny();
 #if defined(JS_CPU_ARM)
     // On ARM, save the link register before calling.  It contains the return
     // address.  The |masm.ret()| later will pop this into |pc| to return.
     masm.push(lr);
 #endif
 
     masm.setupUnalignedABICall(2, scratch);
-    masm.movePtr(ImmWord(cx->runtime), scratch);
+    masm.movePtr(ImmWord(cx->runtime()), scratch);
     masm.passABIArg(scratch);
     masm.passABIArg(objReg);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
 
     masm.ret();
     return true;
 }
 #endif // JSGC_GENERATIONAL
@@ -406,17 +406,17 @@ BaselineCompiler::initScopeChain()
 typedef bool (*ReportOverRecursedFn)(JSContext *);
 static const VMFunction CheckOverRecursedInfo =
     FunctionInfo<ReportOverRecursedFn>(CheckOverRecursed);
 
 bool
 BaselineCompiler::emitStackCheck()
 {
     Label skipCall;
-    uintptr_t *limitAddr = &cx->runtime->mainThread.ionStackLimit;
+    uintptr_t *limitAddr = &cx->runtime()->mainThread.ionStackLimit;
     masm.loadPtr(AbsoluteAddress(limitAddr), R0.scratchReg());
     masm.branchPtr(Assembler::AboveOrEqual, BaselineStackReg, R0.scratchReg(), &skipCall);
 
     prepareVMCall();
     if (!callVM(CheckOverRecursedInfo))
         return false;
 
     masm.bind(&skipCall);
@@ -425,17 +425,17 @@ BaselineCompiler::emitStackCheck()
 
 typedef bool (*InterruptCheckFn)(JSContext *);
 static const VMFunction InterruptCheckInfo = FunctionInfo<InterruptCheckFn>(InterruptCheck);
 
 bool
 BaselineCompiler::emitInterruptCheck()
 {
     Label done;
-    void *interrupt = (void *)&cx->compartment->rt->interrupt;
+    void *interrupt = (void *)&cx->compartment()->rt->interrupt;
     masm.branch32(Assembler::Equal, AbsoluteAddress(interrupt), Imm32(0), &done);
 
     prepareVMCall();
     if (!callVM(InterruptCheckInfo))
         return false;
 
     masm.bind(&done);
     return true;
@@ -507,17 +507,17 @@ bool
 BaselineCompiler::emitDebugTrap()
 {
     JS_ASSERT(debugMode_);
     JS_ASSERT(frame.numUnsyncedSlots() == 0);
 
     bool enabled = script->stepModeEnabled() || script->hasBreakpointsAt(pc);
 
     // Emit patchable call to debug trap handler.
-    IonCode *handler = cx->compartment->ionCompartment()->debugTrapHandler(cx);
+    IonCode *handler = cx->compartment()->ionCompartment()->debugTrapHandler(cx);
     mozilla::DebugOnly<CodeOffsetLabel> offset = masm.toggledCall(handler, enabled);
 
 #ifdef DEBUG
     // Patchable call offset has to match the pc mapping offset.
     PCMappingEntry &entry = pcMappingEntries_[pcMappingEntries_.length() - 1];
     JS_ASSERT((&offset)->offset() == entry.nativeOffset);
 #endif
 
@@ -550,17 +550,17 @@ BaselineCompiler::emitSPSPush()
 
 void
 BaselineCompiler::emitSPSPop()
 {
     // If profiler entry was pushed on this frame, pop it.
     Label noPop;
     masm.branchTest32(Assembler::Zero, frame.addressOfFlags(),
                       Imm32(BaselineFrame::HAS_PUSHED_SPS_FRAME), &noPop);
-    masm.spsPopFrameSafe(&cx->runtime->spsProfiler, R1.scratchReg());
+    masm.spsPopFrameSafe(&cx->runtime()->spsProfiler, R1.scratchReg());
     masm.bind(&noPop);
 }
 
 MethodStatus
 BaselineCompiler::emitBody()
 {
     JS_ASSERT(pc == script->code);
 
@@ -1592,21 +1592,21 @@ BaselineCompiler::emit_JSOP_GETGNAME()
 {
     RootedPropertyName name(cx, script->getName(pc));
 
     if (name == cx->names().undefined) {
         frame.push(UndefinedValue());
         return true;
     }
     if (name == cx->names().NaN) {
-        frame.push(cx->runtime->NaNValue);
+        frame.push(cx->runtime()->NaNValue);
         return true;
     }
     if (name == cx->names().Infinity) {
-        frame.push(cx->runtime->positiveInfinityValue);
+        frame.push(cx->runtime()->positiveInfinityValue);
         return true;
     }
 
     frame.syncStack(0);
 
     masm.movePtr(ImmGCPtr(&script->global()), R0.scratchReg());
 
     // Call IC.
@@ -1809,17 +1809,17 @@ BaselineCompiler::emit_JSOP_SETALIASEDVA
     masm.storeValue(R0, address);
     frame.push(R0);
 
 #ifdef JSGC_GENERATIONAL
     // Fully sync the stack if post-barrier is needed.
     // Scope coordinate object is already in R2.scratchReg().
     frame.syncStack(0);
 
-    Nursery &nursery = cx->runtime->gcNursery;
+    Nursery &nursery = cx->runtime()->gcNursery;
     Label skipBarrier;
     Label isTenured;
     masm.branchTestObject(Assembler::NotEqual, R0, &skipBarrier);
     masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.start()), &isTenured);
     masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.heapEnd()), &skipBarrier);
 
     masm.bind(&isTenured);
     masm.call(postBarrierSlot_);
--- a/js/src/ion/BaselineFrame-inl.h
+++ b/js/src/ion/BaselineFrame-inl.h
@@ -47,17 +47,17 @@ BaselineFrame::pushBlock(JSContext *cx, 
     return true;
 }
 
 inline void
 BaselineFrame::popBlock(JSContext *cx)
 {
     JS_ASSERT(hasBlockChain());
 
-    if (cx->compartment->debugMode())
+    if (cx->compartment()->debugMode())
         DebugScopes::onPopBlock(cx, this);
 
     if (blockChain_->needsClone()) {
         JS_ASSERT(scopeChain_->asClonedBlock().staticBlock() == *blockChain_);
         popOffScopeChain();
     }
 
     setBlockChain(*blockChain_->enclosingBlock());
--- a/js/src/ion/BaselineFrame.cpp
+++ b/js/src/ion/BaselineFrame.cpp
@@ -140,17 +140,17 @@ BaselineFrame::initForOsr(StackFrame *fp
         numStackValues * sizeof(Value);
 
     JS_ASSERT(numValueSlots() == numStackValues);
 
     for (uint32_t i = 0; i < numStackValues; i++)
         *valueSlot(i) = fp->slots()[i];
 
     JSContext *cx = GetIonContext()->cx;
-    if (cx->compartment->debugMode()) {
+    if (cx->compartment()->debugMode()) {
         // In debug mode, update any Debugger.Frame objects for the StackFrame to
         // point to the BaselineFrame.
 
         // The caller pushed a fake return address. ScriptFrameIter, used by the
         // debugger, wants a valid return address, but it's okay to just pick one.
         // In debug mode there's always at least 1 ICEntry (since there are always
         // debug prologue/epilogue calls).
         IonFrameIterator iter(cx->mainThread().ionTop);
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -515,31 +515,31 @@ ICUpdatedStub::initUpdatingChain(JSConte
 
     firstUpdateStub_ = stub;
     return true;
 }
 
 IonCode *
 ICStubCompiler::getStubCode()
 {
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
 
     // Check for existing cached stubcode.
     uint32_t stubKey = getKey();
     IonCode *stubCode = ion->getStubCode(stubKey);
     if (stubCode)
         return stubCode;
 
     // Compile new stubcode.
     MacroAssembler masm;
 #ifdef JS_CPU_ARM
     masm.setSecondScratchReg(BaselineSecondScratchReg);
 #endif
 
-    AutoFlushCache afc("ICStubCompiler::getStubCode", cx->runtime->ionRuntime());
+    AutoFlushCache afc("ICStubCompiler::getStubCode", cx->runtime()->ionRuntime());
     if (!generateStubCode(masm))
         return NULL;
     Linker linker(masm);
     Rooted<IonCode *> newStubCode(cx, linker.newCode(cx, JSC::BASELINE_CODE));
     if (!newStubCode)
         return NULL;
 
     // After generating code, run postGenerateStubCode()
@@ -557,42 +557,42 @@ ICStubCompiler::getStubCode()
     JS_ASSERT(entersStubFrame_ == ICStub::CanMakeCalls(kind));
 
     return newStubCode;
 }
 
 bool
 ICStubCompiler::tailCallVM(const VMFunction &fun, MacroAssembler &masm)
 {
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(fun);
     if (!code)
         return false;
 
     uint32_t argSize = fun.explicitStackSlots() * sizeof(void *);
     EmitTailCallVM(code, masm, argSize);
     return true;
 }
 
 bool
 ICStubCompiler::callVM(const VMFunction &fun, MacroAssembler &masm)
 {
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(fun);
     if (!code)
         return false;
 
     EmitCallVM(code, masm);
     return true;
 }
 
 bool
 ICStubCompiler::callTypeUpdateIC(MacroAssembler &masm, uint32_t objectOffset)
 {
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(DoTypeUpdateFallbackInfo);
     if (!code)
         return false;
 
     EmitCallTypeUpdateIC(masm, code, objectOffset);
     return true;
 }
 
@@ -630,41 +630,41 @@ ICStubCompiler::guardProfilingEnabled(Ma
     JS_ASSERT(entersStubFrame_);
     masm.loadPtr(Address(BaselineFrameReg, 0), scratch);
     masm.branchTest32(Assembler::Zero,
                       Address(scratch, BaselineFrame::reverseOffsetOfFlags()),
                       Imm32(BaselineFrame::HAS_PUSHED_SPS_FRAME),
                       skip);
 
     // Check if profiling is enabled
-    uint32_t *enabledAddr = cx->runtime->spsProfiler.addressOfEnabled();
+    uint32_t *enabledAddr = cx->runtime()->spsProfiler.addressOfEnabled();
     masm.branch32(Assembler::Equal, AbsoluteAddress(enabledAddr), Imm32(0), skip);
 }
 
 #ifdef JSGC_GENERATIONAL
 inline bool
 ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, Register scratch,
                                          GeneralRegisterSet saveRegs)
 {
-    Nursery &nursery = cx->runtime->gcNursery;
+    Nursery &nursery = cx->runtime()->gcNursery;
 
     Label skipBarrier;
     Label isTenured;
     masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.start()), &isTenured);
     masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.heapEnd()), &skipBarrier);
     masm.bind(&isTenured);
 
     // void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
 #ifdef JS_CPU_ARM
     saveRegs.add(BaselineTailCallReg);
 #endif
     saveRegs = GeneralRegisterSet::Intersect(saveRegs, GeneralRegisterSet::Volatile());
     masm.PushRegsInMask(saveRegs);
     masm.setupUnalignedABICall(2, scratch);
-    masm.movePtr(ImmWord(cx->runtime), scratch);
+    masm.movePtr(ImmWord(cx->runtime()), scratch);
     masm.passABIArg(scratch);
     masm.passABIArg(obj);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
     masm.PopRegsInMask(saveRegs);
 
     masm.bind(&skipBarrier);
     return true;
 }
@@ -796,17 +796,17 @@ PrepareOsrTempData(JSContext *cx, ICUseC
 
     size_t stackFrameSpace = (sizeof(Value) * numLocalsAndStackVals) + sizeof(StackFrame)
                            + (sizeof(Value) * (numFormalArgs + 1));
     size_t ionOsrTempDataSpace = sizeof(IonOsrTempData);
 
     size_t totalSpace = AlignBytes(stackFrameSpace, sizeof(Value)) +
                         AlignBytes(ionOsrTempDataSpace, sizeof(Value));
 
-    IonOsrTempData *info = (IonOsrTempData *)cx->runtime->getIonRuntime(cx)->allocateOsrTempData(totalSpace);
+    IonOsrTempData *info = (IonOsrTempData *)cx->runtime()->getIonRuntime(cx)->allocateOsrTempData(totalSpace);
     if (!info)
         return NULL;
 
     memset(info, 0, totalSpace);
 
     info->jitcode = jitcode;
 
     uint8_t *stackFrameStart = (uint8_t *)info + AlignBytes(ionOsrTempDataSpace, sizeof(Value));
@@ -988,21 +988,21 @@ static bool
 DoProfilerFallback(JSContext *cx, BaselineFrame *frame, ICProfiler_Fallback *stub)
 {
     RootedScript script(cx, frame->script());
     RootedFunction func(cx, frame->maybeFun());
     mozilla::DebugOnly<ICEntry *> icEntry = stub->icEntry();
 
     FallbackICSpew(cx, stub, "Profiler");
 
-    SPSProfiler *profiler = &cx->runtime->spsProfiler;
+    SPSProfiler *profiler = &cx->runtime()->spsProfiler;
 
     // Manually enter SPS this time.
     JS_ASSERT(profiler->enabled());
-    if (!cx->runtime->spsProfiler.enter(cx, script, func))
+    if (!cx->runtime()->spsProfiler.enter(cx, script, func))
         return false;
     frame->setPushedSPSFrame();
 
     // Unlink any existing PushFunction stub (which may hold stale 'const char *' to
     // the profile string.
     JS_ASSERT_IF(icEntry->firstStub() != stub,
                  icEntry->firstStub()->isProfiler_PushFunction() &&
                  icEntry->firstStub()->next() == stub);
@@ -1047,24 +1047,24 @@ ICProfiler_PushFunction::Compiler::gener
 {
 
     Register scratch = R0.scratchReg();
     Register scratch2 = R1.scratchReg();
 
     // Profiling should be enabled if we ever reach here.
 #ifdef DEBUG
     Label spsEnabled;
-    uint32_t *enabledAddr = cx->runtime->spsProfiler.addressOfEnabled();
+    uint32_t *enabledAddr = cx->runtime()->spsProfiler.addressOfEnabled();
     masm.branch32(Assembler::NotEqual, AbsoluteAddress(enabledAddr), Imm32(0), &spsEnabled);
     masm.breakpoint();
     masm.bind(&spsEnabled);
 #endif
 
     // Push SPS entry.
-    masm.spsPushFrame(&cx->runtime->spsProfiler,
+    masm.spsPushFrame(&cx->runtime()->spsProfiler,
                       Address(BaselineStubReg, ICProfiler_PushFunction::offsetOfStr()),
                       Address(BaselineStubReg, ICProfiler_PushFunction::offsetOfScript()),
                       scratch,
                       scratch2);
 
     // Mark frame as having profiler entry pushed.
     Address flagsOffset(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags());
     masm.or32(Imm32(BaselineFrame::HAS_PUSHED_SPS_FRAME), flagsOffset);
@@ -1717,17 +1717,17 @@ DoCompareFallback(JSContext *cx, Baselin
         ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script));
         if (!int32Stub)
             return false;
 
         stub->addNewStub(int32Stub);
         return true;
     }
 
-    if (!cx->runtime->jitSupportsFloatingPoint && (lhs.isNumber() || rhs.isNumber()))
+    if (!cx->runtime()->jitSupportsFloatingPoint && (lhs.isNumber() || rhs.isNumber()))
         return true;
 
     if (lhs.isNumber() && rhs.isNumber()) {
         IonSpew(IonSpew_BaselineIC, "  Generating %s(Number, Number) stub", js_CodeName[op]);
 
         // Unlink int32 stubs, it's faster to always use the double stub.
         stub->unlinkStubsWithKind(cx, ICStub::Compare_Int32);
 
@@ -2128,17 +2128,17 @@ DoToBoolFallback(JSContext *cx, Baseline
         ICStub *int32Stub = compiler.getStub(compiler.getStubSpace(script));
         if (!int32Stub)
             return false;
 
         stub->addNewStub(int32Stub);
         return true;
     }
 
-    if (arg.isDouble() && cx->runtime->jitSupportsFloatingPoint) {
+    if (arg.isDouble() && cx->runtime()->jitSupportsFloatingPoint) {
         IonSpew(IonSpew_BaselineIC, "  Generating ToBool(Double) stub.");
         ICToBool_Double::Compiler compiler(cx);
         ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
         if (!doubleStub)
             return false;
 
         stub->addNewStub(doubleStub);
         return true;
@@ -2514,17 +2514,17 @@ DoBinaryArithFallback(JSContext *cx, Bas
 
     // Handle only int32 or double.
     if (!lhs.isNumber() || !rhs.isNumber())
         return true;
 
     JS_ASSERT(ret.isNumber());
 
     if (lhs.isDouble() || rhs.isDouble() || ret.isDouble()) {
-        if (!cx->runtime->jitSupportsFloatingPoint)
+        if (!cx->runtime()->jitSupportsFloatingPoint)
             return true;
 
         switch (op) {
           case JSOP_ADD:
           case JSOP_SUB:
           case JSOP_MUL:
           case JSOP_DIV:
           case JSOP_MOD: {
@@ -2976,17 +2976,17 @@ DoUnaryArithFallback(JSContext *cx, Base
         if (!int32Stub)
             return false;
         stub->addNewStub(int32Stub);
         return true;
     }
 
     if (val.isNumber() && res.isNumber() &&
         op == JSOP_NEG &&
-        cx->runtime->jitSupportsFloatingPoint)
+        cx->runtime()->jitSupportsFloatingPoint)
     {
         IonSpew(IonSpew_BaselineIC, "  Generating %s(Number => Number) stub", js_CodeName[op]);
         // Unlink int32 stubs, the double stub handles both cases and TI specializes for both.
         stub->unlinkStubsWithKind(cx, ICStub::UnaryArith_Int32);
 
         ICUnaryArith_Double::Compiler compiler(cx, op);
         ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
         if (!doubleStub)
@@ -3564,17 +3564,17 @@ TryAttachGetElemStub(JSContext *cx, Hand
                 return false;
         }
     }
 
     // Check for TypedArray[int] => Number accesses.
     if (obj->isTypedArray() && rhs.isInt32() && res.isNumber() &&
         !TypedArrayGetElemStubExists(stub, obj))
     {
-        if (!cx->runtime->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
+        if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
             return true;
 
         IonSpew(IonSpew_BaselineIC, "  Generating GetElem(TypedArray[Int32]) stub");
         ICGetElem_TypedArray::Compiler compiler(cx, obj->lastProperty(), TypedArray::type(obj));
         ICStub *typedArrayStub = compiler.getStub(compiler.getStubSpace(script));
         if (!typedArrayStub)
             return false;
 
@@ -3768,17 +3768,17 @@ ICGetElem_String::Compiler::generateStub
     masm.loadPtr(charsAddr, scratchReg);
     masm.load16ZeroExtend(BaseIndex(scratchReg, key, TimesTwo, 0), scratchReg);
 
     // Check if char code >= UNIT_STATIC_LIMIT.
     masm.branch32(Assembler::AboveOrEqual, scratchReg, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
                   &failure);
 
     // Load static string.
-    masm.movePtr(ImmWord(&cx->compartment->rt->staticStrings.unitStaticTable), str);
+    masm.movePtr(ImmWord(&cx->compartment()->rt->staticStrings.unitStaticTable), str);
     masm.loadPtr(BaseIndex(str, scratchReg, ScalePointer), str);
 
     // Return.
     masm.tagValue(JSVAL_TYPE_STRING, str, R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
@@ -4230,17 +4230,17 @@ DoSetElemFallback(JSContext *cx, Baselin
                 stub->addNewStub(denseStub);
             }
         }
 
         return true;
     }
 
     if (obj->isTypedArray() && index.isInt32() && rhs.isNumber()) {
-        if (!cx->runtime->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
+        if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
             return true;
 
         uint32_t len = TypedArray::length(obj);
         int32_t idx = index.toInt32();
         bool expectOutOfBounds = (idx < 0) || (static_cast<uint32_t>(idx) >= len);
 
         if (!TypedArraySetElemStubExists(stub, obj, expectOutOfBounds)) {
             // Remove any existing TypedArraySetElemStub that doesn't handle out-of-bounds
@@ -4386,17 +4386,17 @@ ICSetElem_Dense::Compiler::generateStubC
     // it's okay to store a double.
     Label dontConvertDoubles;
     Address elementsFlags(scratchReg, ObjectElements::offsetOfFlags());
     masm.branchTest32(Assembler::Zero, elementsFlags,
                       Imm32(ObjectElements::CONVERT_DOUBLE_ELEMENTS),
                       &dontConvertDoubles);
     // Note that double arrays are only created by IonMonkey, so if we have no
     // floating-point support Ion is disabled and there should be no double arrays.
-    if (cx->runtime->jitSupportsFloatingPoint)
+    if (cx->runtime()->jitSupportsFloatingPoint)
         masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &dontConvertDoubles);
     else
         masm.breakpoint();
     masm.bind(&dontConvertDoubles);
 
     // Don't overwrite R0 becuase |obj| might overlap with it, and it's needed
     // for post-write barrier later.
     ValueOperand tmpVal = regs.takeAnyValue();
@@ -4574,17 +4574,17 @@ ICSetElemDenseAddCompiler::generateStubC
     // it's okay to store a double.
     Label dontConvertDoubles;
     Address elementsFlags(scratchReg, ObjectElements::offsetOfFlags());
     masm.branchTest32(Assembler::Zero, elementsFlags,
                       Imm32(ObjectElements::CONVERT_DOUBLE_ELEMENTS),
                       &dontConvertDoubles);
     // Note that double arrays are only created by IonMonkey, so if we have no
     // floating-point support Ion is disabled and there should be no double arrays.
-    if (cx->runtime->jitSupportsFloatingPoint)
+    if (cx->runtime()->jitSupportsFloatingPoint)
         masm.convertInt32ValueToDouble(valueAddr, regs.getAny(), &dontConvertDoubles);
     else
         masm.breakpoint();
     masm.bind(&dontConvertDoubles);
 
     // Write the value.  No need for pre-barrier since we're not overwriting an old value.
     ValueOperand tmpVal = regs.takeAnyValue();
     BaseIndex element(scratchReg, key, TimesEight);
@@ -4670,17 +4670,17 @@ ICSetElem_TypedArray::Compiler::generate
         Label clamped;
         masm.bind(&clamped);
         masm.storeToTypedIntArray(type_, secondScratch, dest);
         EmitReturnFromIC(masm);
 
         // If the value is a double, clamp to uint8 and jump back.
         // Else, jump to failure.
         masm.bind(&notInt32);
-        if (cx->runtime->jitSupportsFloatingPoint) {
+        if (cx->runtime()->jitSupportsFloatingPoint) {
             masm.branchTestDouble(Assembler::NotEqual, value, &failure);
             masm.unboxDouble(value, FloatReg0);
             masm.clampDoubleToUint8(FloatReg0, secondScratch);
             masm.jump(&clamped);
         } else {
             masm.jump(&failure);
         }
     } else {
@@ -4692,17 +4692,17 @@ ICSetElem_TypedArray::Compiler::generate
         masm.bind(&isInt32);
         masm.storeToTypedIntArray(type_, secondScratch, dest);
         EmitReturnFromIC(masm);
 
         // If the value is a double, truncate and jump back.
         // Else, jump to failure.
         Label failureRestoreRegs;
         masm.bind(&notInt32);
-        if (cx->runtime->jitSupportsFloatingPoint) {
+        if (cx->runtime()->jitSupportsFloatingPoint) {
             masm.branchTestDouble(Assembler::NotEqual, value, &failure);
             masm.unboxDouble(value, FloatReg0);
             masm.branchTruncateDouble(FloatReg0, secondScratch, &failureRestoreRegs);
             masm.jump(&isInt32);
         } else {
             masm.jump(&failure);
         }
 
@@ -5710,17 +5710,17 @@ ICGetProp_CallScripted::Compiler::genera
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, offsetof(JSFunction, nargs)), scratch);
     masm.branch32(Assembler::Equal, scratch, Imm32(0), &noUnderflow);
     {
         // Call the arguments rectifier.
         JS_ASSERT(ArgumentsRectifierReg != code);
 
         IonCode *argumentsRectifier =
-            cx->compartment->ionCompartment()->getArgumentsRectifier(SequentialExecution);
+            cx->compartment()->ionCompartment()->getArgumentsRectifier(SequentialExecution);
 
         masm.movePtr(ImmGCPtr(argumentsRectifier), code);
         masm.loadPtr(Address(code, IonCode::offsetOfCode()), code);
         masm.mov(Imm32(0), ArgumentsRectifierReg);
     }
 
     masm.bind(&noUnderflow);
 
@@ -5736,17 +5736,17 @@ ICGetProp_CallScripted::Compiler::genera
         Register scratch = availRegs.takeAny();
         Register pcIdx = availRegs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
     }
     masm.callIon(code);
 
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
@@ -5824,17 +5824,17 @@ ICGetProp_CallNative::Compiler::generate
         Register scratch = regs.takeAny();
         Register pcIdx = regs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
         regs.add(scratch);
         regs.add(pcIdx);
     }
     if (!callVM(DoCallNativeGetterInfo, masm))
         return false;
     leaveStubFrame(masm);
@@ -5912,17 +5912,17 @@ ICGetPropCallDOMProxyNativeCompiler::gen
         Register pcIdx = regs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICGetProp_CallDOMProxyNative::offsetOfPCOffset()),
                     pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
         regs.add(scratch);
         regs.add(pcIdx);
     }
     if (!callVM(DoCallNativeGetterInfo, masm))
         return false;
     leaveStubFrame(masm);
@@ -6059,17 +6059,17 @@ ICGetProp_DOMProxyShadowed::Compiler::ge
         Register scratch = regs.takeAny();
         Register pcIdx = regs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICGetProp_DOMProxyShadowed::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
         regs.add(scratch);
         regs.add(pcIdx);
     }
     if (!callVM(ProxyGetInfo, masm))
         return false;
     leaveStubFrame(masm);
@@ -6610,17 +6610,17 @@ ICSetProp_CallScripted::Compiler::genera
     Label noUnderflow;
     masm.load16ZeroExtend(Address(callee, offsetof(JSFunction, nargs)), scratch);
     masm.branch32(Assembler::BelowOrEqual, scratch, Imm32(1), &noUnderflow);
     {
         // Call the arguments rectifier.
         JS_ASSERT(ArgumentsRectifierReg != code);
 
         IonCode *argumentsRectifier =
-            cx->compartment->ionCompartment()->getArgumentsRectifier(SequentialExecution);
+            cx->compartment()->ionCompartment()->getArgumentsRectifier(SequentialExecution);
 
         masm.movePtr(ImmGCPtr(argumentsRectifier), code);
         masm.loadPtr(Address(code, IonCode::offsetOfCode()), code);
         masm.mov(Imm32(1), ArgumentsRectifierReg);
     }
 
     masm.bind(&noUnderflow);
 
@@ -6636,17 +6636,17 @@ ICSetProp_CallScripted::Compiler::genera
         Register scratch = availRegs.takeAny();
         Register pcIdx = availRegs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
     }
     masm.callIon(code);
 
     leaveStubFrame(masm, true);
     // Do not care about return value from function. The original RHS should be returned
     // as the result of this operation.
@@ -6734,17 +6734,17 @@ ICSetProp_CallNative::Compiler::generate
         Register scratch = regs.takeAny();
         Register pcIdx = regs.takeAny();
 
         // Check if profiling is enabled.
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         masm.load32(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
         regs.add(scratch);
         regs.add(pcIdx);
     }
     if (!callVM(DoCallNativeSetterInfo, masm))
         return false;
     leaveStubFrame(masm);
@@ -6969,18 +6969,18 @@ DoCallFallback(JSContext *cx, BaselineFr
     if (cx->typeInferenceEnabled())
         newType = types::UseNewType(cx, script, pc);
 
     // Try attaching a call stub.
     if (!TryAttachCallStub(cx, stub, script, pc, op, argc, vp, constructing, newType))
         return false;
 
     // Maybe update PC in profiler entry before leaving this script by call.
-    if (cx->runtime->spsProfiler.enabled() && frame->hasPushedSPSFrame())
-        cx->runtime->spsProfiler.updatePC(script, pc);
+    if (cx->runtime()->spsProfiler.enabled() && frame->hasPushedSPSFrame())
+        cx->runtime()->spsProfiler.updatePC(script, pc);
 
     if (!MaybeCloneFunctionAtCallsite(cx, &callee, script, pc))
         return false;
 
     if (op == JSOP_NEW) {
         if (!InvokeConstructor(cx, callee, argc, args, res.address()))
             return false;
     } else if (op == JSOP_EVAL && IsBuiltinEvalForScope(frame->scopeChain(), callee)) {
@@ -7200,17 +7200,17 @@ ICCall_Fallback::Compiler::generateStubC
     return true;
 }
 
 bool
 ICCall_Fallback::Compiler::postGenerateStubCode(MacroAssembler &masm, Handle<IonCode *> code)
 {
     CodeOffsetLabel offset(returnOffset_);
     offset.fixup(&masm);
-    cx->compartment->ionCompartment()->initBaselineCallReturnAddr(code->raw() + offset.offset());
+    cx->compartment()->ionCompartment()->initBaselineCallReturnAddr(code->raw() + offset.offset());
     return true;
 }
 
 typedef bool (*CreateThisFn)(JSContext *cx, HandleObject callee, MutableHandleValue rval);
 static const VMFunction CreateThisInfo = FunctionInfo<CreateThisFn>(CreateThis);
 
 bool
 ICCallScriptedCompiler::generateStubCode(MacroAssembler &masm)
@@ -7366,17 +7366,17 @@ ICCallScriptedCompiler::generateStubCode
     masm.load16ZeroExtend(Address(callee, offsetof(JSFunction, nargs)), callee);
     masm.branch32(Assembler::AboveOrEqual, argcReg, callee, &noUnderflow);
     {
         // Call the arguments rectifier.
         JS_ASSERT(ArgumentsRectifierReg != code);
         JS_ASSERT(ArgumentsRectifierReg != argcReg);
 
         IonCode *argumentsRectifier =
-            cx->compartment->ionCompartment()->getArgumentsRectifier(SequentialExecution);
+            cx->compartment()->ionCompartment()->getArgumentsRectifier(SequentialExecution);
 
         masm.movePtr(ImmGCPtr(argumentsRectifier), code);
         masm.loadPtr(Address(code, IonCode::offsetOfCode()), code);
         masm.mov(argcReg, ArgumentsRectifierReg);
     }
 
     masm.bind(&noUnderflow);
 
@@ -7395,17 +7395,17 @@ ICCallScriptedCompiler::generateStubCode
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         // Update profiling entry before leaving function.
         JS_ASSERT(kind == ICStub::Call_Scripted || kind == ICStub::Call_AnyScripted);
         if (kind == ICStub::Call_Scripted)
             masm.load32(Address(BaselineStubReg, ICCall_Scripted::offsetOfPCOffset()), pcIdx);
         else
             masm.load32(Address(BaselineStubReg, ICCall_AnyScripted::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
     }
 
     masm.callIon(code);
 
     // If this is a constructing call, and the callee returns a non-object, replace it with
     // the |this| object passed in.
@@ -7518,17 +7518,17 @@ ICCall_Native::Compiler::generateStubCod
     // If needed, update SPS Profiler frame entry.  At this point, BaselineTailCallReg
     // and scratch can be clobbered.
     {
         Label skipProfilerUpdate;
         Register pcIdx = BaselineTailCallReg;
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         masm.load32(Address(BaselineStubReg, ICCall_Native::offsetOfPCOffset()), pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
     }
     // Execute call.
     masm.setupUnalignedABICall(3, scratch);
     masm.loadJSContext(scratch);
     masm.passABIArg(scratch);
     masm.passABIArg(argcReg);
@@ -7625,17 +7625,17 @@ ICCall_ScriptedApplyArguments::Compiler:
     Label noUnderflow;
     masm.branch32(Assembler::AboveOrEqual, argcReg, scratch, &noUnderflow);
     {
         // Call the arguments rectifier.
         JS_ASSERT(ArgumentsRectifierReg != target);
         JS_ASSERT(ArgumentsRectifierReg != argcReg);
 
         IonCode *argumentsRectifier =
-            cx->compartment->ionCompartment()->getArgumentsRectifier(SequentialExecution);
+            cx->compartment()->ionCompartment()->getArgumentsRectifier(SequentialExecution);
 
         masm.movePtr(ImmGCPtr(argumentsRectifier), target);
         masm.loadPtr(Address(target, IonCode::offsetOfCode()), target);
         masm.mov(argcReg, ArgumentsRectifierReg);
     }
     masm.bind(&noUnderflow);
     regs.add(argcReg);
 
@@ -7645,17 +7645,17 @@ ICCall_ScriptedApplyArguments::Compiler:
         Label skipProfilerUpdate;
         Register pcIdx = regs.getAny();
         JS_ASSERT(pcIdx != ArgumentsRectifierReg);
         JS_ASSERT(pcIdx != target);
         guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
 
         masm.load32(Address(BaselineStubReg, ICCall_ScriptedApplyArguments::offsetOfPCOffset()),
                     pcIdx);
-        masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
+        masm.spsUpdatePCIdx(&cx->runtime()->spsProfiler, pcIdx, scratch);
 
         masm.bind(&skipProfilerUpdate);
     }
     // Do call
     masm.callIon(target);
     leaveStubFrame(masm, true);
 
     // Enter type monitor IC to type-check result.
@@ -7699,17 +7699,17 @@ ICTableSwitch::Compiler::generateStubCod
     masm.loadPtr(BaseIndex(scratch, key, ScalePointer), scratch);
 
     EmitChangeICReturnAddress(masm, scratch);
     EmitReturnFromIC(masm);
 
     masm.bind(&notInt32);
 
     masm.branchTestDouble(Assembler::NotEqual, R0, &outOfRange);
-    if (cx->runtime->jitSupportsFloatingPoint) {
+    if (cx->runtime()->jitSupportsFloatingPoint) {
         masm.unboxDouble(R0, FloatReg0);
 
         // N.B. -0 === 0, so convert -0 to a 0 int32.
         masm.convertDoubleToInt32(FloatReg0, key, &outOfRange, /* negativeZeroCheck = */ false);
     } else {
         // Pass pointer to double value.
         masm.pushValue(R0);
         masm.movePtr(StackPointer, R0.scratchReg());
--- a/js/src/ion/BaselineJIT.cpp
+++ b/js/src/ion/BaselineJIT.cpp
@@ -68,27 +68,27 @@ CheckFrame(StackFrame *fp)
     }
 
     return true;
 }
 
 static bool
 IsJSDEnabled(JSContext *cx)
 {
-    return cx->compartment->debugMode() && cx->runtime->debugHooks.callHook;
+    return cx->compartment()->debugMode() && cx->runtime()->debugHooks.callHook;
 }
 
 static IonExecStatus
 EnterBaseline(JSContext *cx, StackFrame *fp, void *jitcode, bool osr)
 {
     JS_CHECK_RECURSION(cx, return IonExec_Aborted);
     JS_ASSERT(ion::IsBaselineEnabled(cx));
     JS_ASSERT(CheckFrame(fp));
 
-    EnterIonCode enter = cx->compartment->ionCompartment()->enterBaselineJIT();
+    EnterIonCode enter = cx->compartment()->ionCompartment()->enterBaselineJIT();
 
     // maxArgc is the maximum of arguments between the number of actual
     // arguments and the number of formal arguments. It accounts for |this|.
     int maxArgc = 0;
     Value *maxArgv = NULL;
     unsigned numActualArgs = 0;
     RootedValue thisv(cx);
 
@@ -123,34 +123,34 @@ EnterBaseline(JSContext *cx, StackFrame 
         JSObject *scopeChain = NULL;
         if (!fp->isNonEvalFunctionFrame())
             scopeChain = fp->scopeChain();
 
         // For OSR, pass the number of locals + stack values.
         uint32_t numStackValues = osr ? fp->script()->nfixed + cx->regs().stackDepth() : 0;
         JS_ASSERT_IF(osr, !IsJSDEnabled(cx));
 
-        AutoFlushInhibitor afi(cx->compartment->ionCompartment());
+        AutoFlushInhibitor afi(cx->compartment()->ionCompartment());
         // Single transition point from Interpreter to Baseline.
         enter(jitcode, maxArgc, maxArgv, osr ? fp : NULL, calleeToken, scopeChain, numStackValues,
               result.address());
     }
 
     JS_ASSERT(fp == cx->fp());
-    JS_ASSERT(!cx->runtime->hasIonReturnOverride());
+    JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
 
     // The trampoline wrote the return value but did not set the HAS_RVAL flag.
     fp->setReturnValue(result);
 
     // Ion callers wrap primitive constructor return.
     if (!result.isMagic() && fp->isConstructing() && fp->returnValue().isPrimitive())
         fp->setReturnValue(ObjectValue(fp->constructorThis()));
 
     // Release temporary buffer used for OSR into Ion.
-    cx->runtime->getIonRuntime(cx)->freeOsrTempData();
+    cx->runtime()->getIonRuntime(cx)->freeOsrTempData();
 
     JS_ASSERT_IF(result.isMagic(), result.isMagic(JS_ION_ERROR));
     return result.isMagic() ? IonExec_Error : IonExec_Ok;
 }
 
 IonExecStatus
 ion::EnterBaselineMethod(JSContext *cx, StackFrame *fp)
 {
@@ -165,17 +165,17 @@ ion::EnterBaselineAtBranch(JSContext *cx
 {
     JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
 
     BaselineScript *baseline = fp->script()->baselineScript();
     uint8_t *jitcode = baseline->nativeCodeForPC(fp->script(), pc);
 
     // Skip debug breakpoint/trap handler, the interpreter already handled it
     // for the current op.
-    if (cx->compartment->debugMode())
+    if (cx->compartment()->debugMode())
         jitcode += MacroAssembler::ToggledCallSize();
 
     return EnterBaseline(cx, fp, jitcode, /* osr = */true);
 }
 
 static MethodStatus
 BaselineCompile(JSContext *cx, HandleScript script)
 {
@@ -189,17 +189,17 @@ BaselineCompile(JSContext *cx, HandleScr
         return Method_Error;
 
     IonContext ictx(cx, temp);
 
     BaselineCompiler compiler(cx, script);
     if (!compiler.init())
         return Method_Error;
 
-    AutoFlushCache afc("BaselineJIT", cx->runtime->ionRuntime());
+    AutoFlushCache afc("BaselineJIT", cx->runtime()->ionRuntime());
     MethodStatus status = compiler.compile();
 
     JS_ASSERT_IF(status == Method_Compiled, script->hasBaselineScript());
     JS_ASSERT_IF(status != Method_Compiled, !script->hasBaselineScript());
 
     if (status == Method_CantCompile)
         script->setBaselineScript(BASELINE_DISABLED_SCRIPT);
 
@@ -228,17 +228,17 @@ ion::CanEnterBaselineJIT(JSContext *cx, 
         if (!obj)
             return Method_Skipped;
         fp->functionThis().setObject(*obj);
     }
 
     if (!CheckFrame(fp))
         return Method_CantCompile;
 
-    if (!cx->compartment->ensureIonCompartmentExists(cx))
+    if (!cx->compartment()->ensureIonCompartmentExists(cx))
         return Method_Error;
 
     if (script->hasBaselineScript())
         return Method_Compiled;
 
     // Check script use count. However, always eagerly compile scripts if JSD
     // is enabled, so that we don't have to OSR and don't have to update the
     // frame pointer stored in JSD's frames list.
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -2350,17 +2350,17 @@ CodeGenerator::maybeCreateScriptCounts()
     if (!cx)
         return NULL;
 
     IonScriptCounts *counts = NULL;
 
     CompileInfo *outerInfo = &gen->info();
     JSScript *script = outerInfo->script();
 
-    if (cx->runtime->profilingScripts) {
+    if (cx->runtime()->profilingScripts) {
         if (script && !script->hasScriptCounts && !script->initScriptCounts(cx))
             return NULL;
     } else if (!script) {
         return NULL;
     }
 
     if (script && !script->hasScriptCounts)
         return NULL;
@@ -5229,17 +5229,17 @@ CodeGenerator::link()
     JS_ASSERT(!HasIonScript(script, executionMode));
 
     uint32_t scriptFrameSize = frameClass_ == FrameSizeClass::None()
                            ? frameDepth_
                            : FrameSizeClass::FromDepth(frameDepth_).frameSize();
 
     // Check to make sure we didn't have a mid-build invalidation. If so, we
     // will trickle to ion::Compile() and return Method_Skipped.
-    if (cx->compartment->types.compiledInfo.compilerOutput(cx)->isInvalidated())
+    if (cx->compartment()->types.compiledInfo.compilerOutput(cx)->isInvalidated())
         return true;
 
     // List of possible scripts that this graph may call. Currently this is
     // only tracked when compiling for parallel execution.
     CallTargetVector callTargets;
     if (executionMode == ParallelExecution)
         AddPossibleCallees(graph.mir(), callTargets);
 
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -104,19 +104,19 @@ ion::GetIonContext()
 
 IonContext *
 ion::MaybeGetIonContext()
 {
     return CurrentIonContext();
 }
 
 IonContext::IonContext(JSContext *cx, TempAllocator *temp)
-  : runtime(cx->runtime),
+  : runtime(cx->runtime()),
     cx(cx),
-    compartment(cx->compartment),
+    compartment(cx->compartment()),
     temp(temp),
     prev_(CurrentIonContext()),
     assemblerCount_(0)
 {
     SetIonContext(this);
 }
 
 IonContext::IonContext(JSCompartment *comp, TempAllocator *temp)
@@ -187,28 +187,28 @@ IonRuntime::~IonRuntime()
 bool
 IonRuntime::initialize(JSContext *cx)
 {
     AutoEnterAtomsCompartment ac(cx);
 
     IonContext ictx(cx, NULL);
     AutoFlushCache afc("IonRuntime::initialize");
 
-    execAlloc_ = cx->runtime->getExecAlloc(cx);
+    execAlloc_ = cx->runtime()->getExecAlloc(cx);
     if (!execAlloc_)
         return false;
 
-    if (!cx->compartment->ensureIonCompartmentExists(cx))
+    if (!cx->compartment()->ensureIonCompartmentExists(cx))
         return false;
 
     functionWrappers_ = cx->new_<VMWrapperMap>(cx);
     if (!functionWrappers_ || !functionWrappers_->init())
         return false;
 
-    if (cx->runtime->jitSupportsFloatingPoint) {
+    if (cx->runtime()->jitSupportsFloatingPoint) {
         // Initialize some Ion-only stubs that require floating-point support.
         if (!bailoutTables_.reserve(FrameSizeClass::ClassLimit().classId()))
             return false;
 
         for (uint32_t id = 0;; id++) {
             FrameSizeClass class_ = FrameSizeClass::FromClass(id);
             if (class_ == FrameSizeClass::ClassLimit())
                 break;
@@ -405,17 +405,17 @@ IonCompartment::getVMWrapper(const VMFun
     IonRuntime::VMWrapperMap::Ptr p = rt->functionWrappers_->readonlyThreadsafeLookup(&f);
     JS_ASSERT(p);
 
     return p->value;
 }
 
 IonActivation::IonActivation(JSContext *cx, StackFrame *fp)
   : cx_(cx),
-    compartment_(cx->compartment),
+    compartment_(cx->compartment()),
     prev_(cx->mainThread().ionActivation),
     entryfp_(fp),
     prevIonTop_(cx->mainThread().ionTop),
     prevIonJSContext_(cx->mainThread().ionJSContext),
     prevpc_(NULL)
 {
     if (fp)
         fp->setRunningInIon();
@@ -680,17 +680,17 @@ IonScript::New(JSContext *cx, uint32_t f
 
     script->callTargetList_ = offsetCursor;
     script->callTargetEntries_ = callTargetEntries;
     offsetCursor += paddedCallTargetSize;
 
     script->frameSlots_ = frameSlots;
     script->frameSize_ = frameSize;
 
-    script->recompileInfo_ = cx->compartment->types.compiledInfo;
+    script->recompileInfo_ = cx->compartment()->types.compiledInfo;
 
     return script;
 }
 
 void
 IonScript::trace(JSTracer *trc)
 {
     if (method_)
@@ -1252,21 +1252,21 @@ CompileBackEnd(MIRGenerator *mir, MacroA
 
     return GenerateCode(mir, lir, maybeMasm);
 }
 
 void
 AttachFinishedCompilations(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
-    IonCompartment *ion = cx->compartment->ionCompartment();
-    if (!ion || !cx->runtime->workerThreadState)
+    IonCompartment *ion = cx->compartment()->ionCompartment();
+    if (!ion || !cx->runtime()->workerThreadState)
         return;
 
-    AutoLockWorkerThreadState lock(cx->runtime);
+    AutoLockWorkerThreadState lock(cx->runtime());
 
     OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations();
 
     // Incorporate any off thread compilations which have finished, failed or
     // have been cancelled, and destroy JM jitcode for any compilations which
     // succeeded, to allow entering the Ion code from the interpreter.
     while (!compilations.empty()) {
         IonBuilder *builder = compilations.popCopy();
@@ -1285,17 +1285,17 @@ AttachFinishedCompilations(JSContext *cx
             ExecutionMode executionMode = builder->info().executionMode();
             types::AutoEnterCompilation enterCompiler(cx, CompilerOutputKind(executionMode));
             enterCompiler.initExisting(builder->recompileInfo);
 
             bool success;
             {
                 // Release the worker thread lock and root the compiler for GC.
                 AutoTempAllocatorRooter root(cx, &builder->temp());
-                AutoUnlockWorkerThreadState unlock(cx->runtime);
+                AutoUnlockWorkerThreadState unlock(cx->runtime());
                 AutoFlushCache afc("AttachFinishedCompilations");
                 success = codegen->link();
             }
 
             if (!success) {
                 // Silently ignore OOM during code generation, we're at an
                 // operation callback and can't propagate failures.
                 cx->clearPendingException();
@@ -1321,19 +1321,19 @@ OffThreadCompilationAvailable(JSContext 
     // Skip off thread compilation if PC count profiling is enabled, as
     // CodeGenerator::maybeCreateScriptCounts will not attach script profiles
     // when running off thread.
     //
     // Also skip off thread compilation if the SPS profiler is enabled, as it
     // stores strings in the spsProfiler data structure, which is not protected
     // by a lock.
     return OffThreadCompilationEnabled(cx)
-        && cx->runtime->gcIncrementalState == gc::NO_INCREMENTAL
-        && !cx->runtime->profilingScripts
-        && !cx->runtime->spsProfiler.enabled();
+        && cx->runtime()->gcIncrementalState == gc::NO_INCREMENTAL
+        && !cx->runtime()->profilingScripts
+        && !cx->runtime()->spsProfiler.enabled();
 }
 
 static AbortReason
 IonCompile(JSContext *cx, JSScript *script,
            AbstractFramePtr fp, jsbytecode *osrPc, bool constructing,
            ExecutionMode executionMode)
 {
 #if JS_TRACE_LOGGING
@@ -1355,20 +1355,20 @@ IonCompile(JSContext *cx, JSScript *scri
     TempAllocator *temp = alloc->new_<TempAllocator>(alloc);
     if (!temp)
         return AbortReason_Alloc;
 
     IonContext ictx(cx, temp);
 
     types::AutoEnterAnalysis enter(cx);
 
-    if (!cx->compartment->ensureIonCompartmentExists(cx))
+    if (!cx->compartment()->ensureIonCompartmentExists(cx))
         return AbortReason_Alloc;
 
-    if (!cx->compartment->ionCompartment()->ensureIonStubsExist(cx))
+    if (!cx->compartment()->ionCompartment()->ensureIonStubsExist(cx))
         return AbortReason_Alloc;
 
     MIRGraph *graph = alloc->new_<MIRGraph>(temp);
     CompileInfo *info = alloc->new_<CompileInfo>(script, script->function(), osrPc, constructing,
                                                  executionMode);
     if (!info)
         return AbortReason_Alloc;
 
@@ -1503,17 +1503,17 @@ CheckScriptSize(JSContext *cx, JSScript*
 
     if (script->length > MAX_MAIN_THREAD_SCRIPT_SIZE) {
         if (OffThreadCompilationEnabled(cx)) {
             // Even if off thread compilation is enabled, there are cases where
             // compilation must still occur on the main thread. Don't compile
             // in these cases (except when profiling scripts, as compilations
             // occurring with profiling should reflect those without), but do
             // not forbid compilation so that the script may be compiled later.
-            if (!OffThreadCompilationAvailable(cx) && !cx->runtime->profilingScripts) {
+            if (!OffThreadCompilationAvailable(cx) && !cx->runtime()->profilingScripts) {
                 IonSpew(IonSpew_Abort, "Script too large for main thread, skipping (%u bytes)", script->length);
                 return Method_Skipped;
             }
         } else {
             IonSpew(IonSpew_Abort, "Script too large (%u bytes)", script->length);
             return Method_CantCompile;
         }
     }
@@ -1542,17 +1542,17 @@ Compile(JSContext *cx, HandleScript scri
 {
     JS_ASSERT(ion::IsEnabled(cx));
     JS_ASSERT(ion::IsBaselineEnabled(cx));
     JS_ASSERT_IF(osrPc != NULL, (JSOp)*osrPc == JSOP_LOOPENTRY);
 
     if (executionMode == SequentialExecution && !script->hasBaselineScript())
         return Method_Skipped;
 
-    if (cx->compartment->debugMode()) {
+    if (cx->compartment()->debugMode()) {
         IonSpew(IonSpew_Abort, "debugging");
         return Method_CantCompile;
     }
 
     if (!CheckScript(cx, script, bool(osrPc))) {
         IonSpew(IonSpew_Abort, "Aborted compilation of %s:%d", script->filename(), script->lineno);
         return Method_CantCompile;
     }
@@ -1749,17 +1749,17 @@ ion::CanEnterInParallel(JSContext *cx, H
     if (status != Method_Compiled) {
         if (status == Method_CantCompile)
             ForbidCompilation(cx, script, ParallelExecution);
         return status;
     }
 
     // This can GC, so afterward, script->parallelIon is
     // not guaranteed to be valid.
-    if (!cx->compartment->ionCompartment()->enterJIT())
+    if (!cx->compartment()->ionCompartment()->enterJIT())
         return Method_Error;
 
     // Subtle: it is possible for GC to occur during
     // compilation of one of the invoked functions, which
     // would cause the earlier functions (such as the
     // kernel itself) to be collected.  In this event, we
     // give up and fallback to sequential for now.
     if (!script->hasParallelIonScript()) {
@@ -1782,38 +1782,38 @@ ion::CanEnterUsingFastInvoke(JSContext *
     if (!script->hasIonScript() || script->ionScript()->bailoutExpected())
         return Method_Skipped;
 
     // Don't handle arguments underflow, to make this work we would have to pad
     // missing arguments with |undefined|.
     if (numActualArgs < script->function()->nargs)
         return Method_Skipped;
 
-    if (!cx->compartment->ensureIonCompartmentExists(cx))
+    if (!cx->compartment()->ensureIonCompartmentExists(cx))
         return Method_Error;
 
     // This can GC, so afterward, script->ion is not guaranteed to be valid.
-    if (!cx->compartment->ionCompartment()->enterJIT())
+    if (!cx->compartment()->ionCompartment()->enterJIT())
         return Method_Error;
 
     if (!script->hasIonScript())
         return Method_Skipped;
 
     return Method_Compiled;
 }
 
 static IonExecStatus
 EnterIon(JSContext *cx, StackFrame *fp, void *jitcode)
 {
     JS_CHECK_RECURSION(cx, return IonExec_Aborted);
     JS_ASSERT(ion::IsEnabled(cx));
     JS_ASSERT(CheckFrame(fp));
     JS_ASSERT(!fp->script()->ionScript()->bailoutExpected());
 
-    EnterIonCode enter = cx->compartment->ionCompartment()->enterJIT();
+    EnterIonCode enter = cx->compartment()->ionCompartment()->enterJIT();
 
     // maxArgc is the maximum of arguments between the number of actual
     // arguments and the number of formal arguments. It accounts for |this|.
     int maxArgc = 0;
     Value *maxArgv = NULL;
     unsigned numActualArgs = 0;
     RootedValue thisv(cx);
 
@@ -1833,24 +1833,24 @@ EnterIon(JSContext *cx, StackFrame *fp, 
     // Caller must construct |this| before invoking the Ion function.
     JS_ASSERT_IF(fp->isConstructing(), fp->functionThis().isObject());
     RootedValue result(cx, Int32Value(numActualArgs));
     {
         AssertCompartmentUnchanged pcc(cx);
         IonContext ictx(cx, NULL);
         IonActivation activation(cx, fp);
         JSAutoResolveFlags rf(cx, RESOLVE_INFER);
-        AutoFlushInhibitor afi(cx->compartment->ionCompartment());
+        AutoFlushInhibitor afi(cx->compartment()->ionCompartment());
         // Single transition point from Interpreter to Ion.
         enter(jitcode, maxArgc, maxArgv, fp, calleeToken, /* scopeChain = */ NULL, 0,
               result.address());
     }
 
     JS_ASSERT(fp == cx->fp());
-    JS_ASSERT(!cx->runtime->hasIonReturnOverride());
+    JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
 
     // The trampoline wrote the return value but did not set the HAS_RVAL flag.
     fp->setReturnValue(result);
 
     // Ion callers wrap primitive constructor return.
     if (!result.isMagic() && fp->isConstructing() && fp->returnValue().isPrimitive())
         fp->setReturnValue(ObjectValue(fp->constructorThis()));
 
@@ -1920,31 +1920,31 @@ ion::FastInvoke(JSContext *cx, HandleFun
         clearCallingIntoIon = true;
         activation.setEntryFp(fp);
     } else {
         JS_ASSERT(!activation.entryfp());
     }
 
     activation.setPrevPc(cx->regs().pc);
 
-    EnterIonCode enter = cx->compartment->ionCompartment()->enterJIT();
+    EnterIonCode enter = cx->compartment()->ionCompartment()->enterJIT();
     void *calleeToken = CalleeToToken(fun);
 
     RootedValue result(cx, Int32Value(args.length()));
     JS_ASSERT(args.length() >= fun->nargs);
 
     JSAutoResolveFlags rf(cx, RESOLVE_INFER);
     enter(jitcode, args.length() + 1, args.array() - 1, fp, calleeToken,
           /* scopeChain = */ NULL, 0, result.address());
 
     if (clearCallingIntoIon)
         fp->clearCallingIntoIon();
 
     JS_ASSERT(fp == cx->fp());
-    JS_ASSERT(!cx->runtime->hasIonReturnOverride());
+    JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
 
     args.rval().set(result);
 
     JS_ASSERT_IF(result.isMagic(), result.isMagic(JS_ION_ERROR));
     return result.isMagic() ? IonExec_Error : IonExec_Ok;
 }
 
 static void
@@ -2173,17 +2173,17 @@ ion::Invalidate(types::TypeCompartment &
         if (resetUses && executionMode != ParallelExecution)
             script->resetUseCount();
     }
 }
 
 void
 ion::Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses)
 {
-    ion::Invalidate(cx->compartment->types, cx->runtime->defaultFreeOp(), invalid, resetUses);
+    ion::Invalidate(cx->compartment()->types, cx->runtime()->defaultFreeOp(), invalid, resetUses);
 }
 
 bool
 ion::Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses)
 {
     JS_ASSERT(script->hasIonScript());
 
     Vector<types::RecompileInfo> scripts(cx);
@@ -2260,17 +2260,17 @@ ion::ForbidCompilation(JSContext *cx, JS
 }
 
 void
 ion::ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode)
 {
     IonSpew(IonSpew_Abort, "Disabling Ion mode %d compilation of script %s:%d",
             mode, script->filename(), script->lineno);
 
-    CancelOffThreadIonCompile(cx->compartment, script);
+    CancelOffThreadIonCompile(cx->compartment(), script);
 
     switch (mode) {
       case SequentialExecution:
         if (script->hasIonScript()) {
             // It is only safe to modify script->ion if the script is not currently
             // running, because IonFrameIterator needs to tell what ionScript to
             // use (either the one on the JSScript, or the one hidden in the
             // breadcrumbs Invalidation() leaves). Therefore, if invalidation
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -31,19 +31,19 @@
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 
 IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
                        BaselineInspector *inspector, CompileInfo *info, AbstractFramePtr fp,
                        size_t inliningDepth, uint32_t loopDepth)
-  : MIRGenerator(cx->compartment, temp, graph, info),
+  : MIRGenerator(cx->compartment(), temp, graph, info),
     backgroundCodegen_(NULL),
-    recompileInfo(cx->compartment->types.compiledInfo),
+    recompileInfo(cx->compartment()->types.compiledInfo),
     cx(cx),
     fp(fp),
     abortReason_(AbortReason_Disable),
     loopDepth_(loopDepth),
     callerResumePoint_(NULL),
     callerBuilder_(NULL),
     inspector(inspector),
     inliningDepth_(inliningDepth),
@@ -4737,17 +4737,17 @@ TestShouldDOMCall(JSContext *cx, types::
                   JSJitInfo::OpType opType)
 {
     if (!func->isNative() || !func->jitInfo())
         return false;
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassMatchesProto instanceChecker =
-        GetDOMCallbacks(cx->runtime)->instanceClassMatchesProto;
+        GetDOMCallbacks(cx->runtime())->instanceClassMatchesProto;
 
     const JSJitInfo *jinfo = func->jitInfo();
     if (jinfo->type != opType)
         return false;
 
     for (unsigned i = 0; i < inTypes->getObjectCount(); i++) {
         types::TypeObject *curType = inTypes->getTypeObject(i);
 
@@ -5928,19 +5928,19 @@ IonBuilder::getStaticName(HandleObject s
 
     *psucceeded = true;
 
     if (staticObject->isGlobal()) {
         // Optimize undefined, NaN, and Infinity.
         if (name == cx->names().undefined)
             return pushConstant(UndefinedValue());
         if (name == cx->names().NaN)
-            return pushConstant(cx->runtime->NaNValue);
+            return pushConstant(cx->runtime()->NaNValue);
         if (name == cx->names().Infinity)
-            return pushConstant(cx->runtime->positiveInfinityValue);
+            return pushConstant(cx->runtime()->positiveInfinityValue);
     }
 
     RootedId id(cx, NameToId(name));
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
     RootedShape shape(cx, staticObject->nativeLookup(cx, id));
     if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot()) {
--- a/js/src/ion/IonFrames.cpp
+++ b/js/src/ion/IonFrames.cpp
@@ -359,17 +359,17 @@ HandleException(JSContext *cx, const Ion
 {
     JS_ASSERT(frame.isBaselineJS());
     JS_ASSERT(!*calledDebugEpilogue);
 
     RootedScript script(cx);
     jsbytecode *pc;
     frame.baselineScriptAndPc(script.address(), &pc);
 
-    if (cx->isExceptionPending() && cx->compartment->debugMode()) {
+    if (cx->isExceptionPending() && cx->compartment()->debugMode()) {
         BaselineFrame *baselineFrame = frame.baselineFrame();
         JSTrapStatus status = DebugExceptionUnwind(cx, baselineFrame, pc);
         switch (status) {
           case JSTRAP_ERROR:
             // Uncatchable exception.
             JS_ASSERT(!cx->isExceptionPending());
             break;
 
@@ -457,18 +457,18 @@ HandleException(ResumeFromException *rfe
     rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME;
 
     IonSpew(IonSpew_Invalidate, "handling exception");
 
     // Clear any Ion return override that's been set.
     // This may happen if a callVM function causes an invalidation (setting the
     // override), and then fails, bypassing the bailout handlers that would
     // otherwise clear the return override.
-    if (cx->runtime->hasIonReturnOverride())
-        cx->runtime->takeIonReturnOverride();
+    if (cx->runtime()->hasIonReturnOverride())
+        cx->runtime()->takeIonReturnOverride();
 
     IonFrameIterator iter(cx->mainThread().ionTop);
     while (!iter.isEntry()) {
         if (iter.isOptimizedJS()) {
             // Search each inlined frame for live iterator objects, and close
             // them.
             InlineFrameIterator frames(cx, &iter);
             for (;;) {
@@ -481,17 +481,17 @@ HandleException(ResumeFromException *rfe
                 Probes::exitScript(cx, script, script->function(), NULL);
                 if (!frames.more())
                     break;
                 ++frames;
             }
 
             IonScript *ionScript = NULL;
             if (iter.checkInvalidation(&ionScript))
-                ionScript->decref(cx->runtime->defaultFreeOp());
+                ionScript->decref(cx->runtime()->defaultFreeOp());
 
         } else if (iter.isBaselineJS()) {
             // It's invalid to call DebugEpilogue twice for the same frame.
             bool calledDebugEpilogue = false;
 
             HandleException(cx, iter, rfe, &calledDebugEpilogue);
             if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME)
                 return;
@@ -499,17 +499,17 @@ HandleException(ResumeFromException *rfe
             // Unwind profiler pseudo-stack
             JSScript *script = iter.script();
             Probes::exitScript(cx, script, script->function(), iter.baselineFrame());
             // After this point, any pushed SPS frame would have been popped if it needed
             // to be.  Unset the flag here so that if we call DebugEpilogue below,
             // it doesn't try to pop the SPS frame again.
             iter.baselineFrame()->unsetPushedSPSFrame();
  
-            if (cx->compartment->debugMode() && !calledDebugEpilogue) {
+            if (cx->compartment()->debugMode() && !calledDebugEpilogue) {
                 // If DebugEpilogue returns |true|, we have to perform a forced
                 // return, e.g. return frame->returnValue() to the caller.
                 BaselineFrame *frame = iter.baselineFrame();
                 if (ion::DebugEpilogue(cx, frame, false)) {
                     JS_ASSERT(frame->hasReturnValue());
                     rfe->kind = ResumeFromException::RESUME_FORCED_RETURN;
                     rfe->framePointer = iter.fp() - BaselineFrame::FramePointerOffset;
                     rfe->stackPointer = reinterpret_cast<uint8_t *>(frame);
@@ -1018,17 +1018,17 @@ AutoTempAllocatorRooter::trace(JSTracer 
 }
 
 void
 GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes)
 {
     JS_ASSERT(cx->fp()->beginsIonActivation());
     IonSpew(IonSpew_Snapshots, "Recover PC & Script from the last frame.");
 
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     // Recover the return address.
     IonFrameIterator it(rt->mainThread.ionTop);
 
     // If the previous frame is a stub frame, skip the exit frame so that
     // returnAddress below gets the return address into the BaselineJS
     // frame.
     if (it.prevType() == IonFrame_BaselineStub || it.prevType() == IonFrame_Unwound_BaselineStub) {
--- a/js/src/ion/IonLinker.h
+++ b/js/src/ion/IonLinker.h
@@ -64,17 +64,17 @@ class Linker
   public:
     Linker(MacroAssembler &masm)
       : masm(masm)
     {
         masm.finish();
     }
 
     IonCode *newCode(JSContext *cx, JSC::CodeKind kind) {
-        return newCode(cx, cx->compartment->ionCompartment(), kind);
+        return newCode(cx, cx->compartment()->ionCompartment(), kind);
     }
 };
 
 } // namespace ion
 } // namespace js
 
 #endif // jsion_linker_h__
 
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -142,17 +142,17 @@ IonBuilder::inlineMathFunction(CallInfo 
 
     if (getInlineReturnType() != MIRType_Double)
         return InliningStatus_NotInlined;
     if (!IsNumberType(callInfo.getArg(0)->type()))
         return InliningStatus_NotInlined;
 
     callInfo.unwrapArgs();
 
-    MathCache *cache = cx->runtime->getMathCache(cx);
+    MathCache *cache = cx->runtime()->getMathCache(cx);
     if (!cache)
         return InliningStatus_Error;
 
     MMathFunction *ins = MMathFunction::New(callInfo.getArg(0), function, cache);
     current->add(ins);
     current->push(ins);
     return InliningStatus_Inlined;
 }
@@ -806,17 +806,17 @@ IonBuilder::inlineStringObject(CallInfo 
 
     // MToString only supports int32 or string values.
     MIRType type = callInfo.getArg(0)->type();
     if (type != MIRType_Int32 && type != MIRType_String)
         return InliningStatus_NotInlined;
 
     callInfo.unwrapArgs();
 
-    RootedString emptyString(cx, cx->runtime->emptyString);
+    RootedString emptyString(cx, cx->runtime()->emptyString);
     RootedObject templateObj(cx, StringObject::create(cx, emptyString, TenuredObject));
     if (!templateObj)
         return InliningStatus_Error;
 
     MNewStringObject *ins = MNewStringObject::New(callInfo.getArg(0), templateObj);
     current->add(ins);
     current->push(ins);
 
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -96,17 +96,17 @@ CheckOverRecursed(JSContext *cx)
     //   (2) The stack limit has been exceeded, and we need to throw an error.
     //
     // Note that we can reach here if ionStackLimit is MAXADDR, but interrupt
     // has not yet been set to 1. That's okay; it will be set to 1 very shortly,
     // and in the interim we might just fire a few useless calls to
     // CheckOverRecursed.
     JS_CHECK_RECURSION(cx, return false);
 
-    if (cx->runtime->interrupt)
+    if (cx->runtime()->interrupt)
         return InterruptCheck(cx);
 
     return true;
 }
 
 bool
 DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain)
 {
@@ -375,17 +375,17 @@ CharCodeAt(JSContext *cx, HandleString s
 }
 
 JSFlatString *
 StringFromCharCode(JSContext *cx, int32_t code)
 {
     jschar c = jschar(code);
 
     if (StaticStrings::hasUnit(c))
-        return cx->runtime->staticStrings.getUnit(c);
+        return cx->runtime()->staticStrings.getUnit(c);
 
     return js_NewStringCopyN<CanGC>(cx, &c, 1);
 }
 
 bool
 SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
             bool strict, int jsop)
 {
@@ -443,23 +443,23 @@ JSObject *
 NewStringObject(JSContext *cx, HandleString str)
 {
     return StringObject::create(cx, str);
 }
 
 bool
 SPSEnter(JSContext *cx, HandleScript script)
 {
-    return cx->runtime->spsProfiler.enter(cx, script, script->function());
+    return cx->runtime()->spsProfiler.enter(cx, script, script->function());
 }
 
 bool
 SPSExit(JSContext *cx, HandleScript script)
 {
-    cx->runtime->spsProfiler.exit(cx, script, script->function());
+    cx->runtime()->spsProfiler.exit(cx, script, script->function());
     return true;
 }
 
 bool
 OperatorIn(JSContext *cx, HandleValue key, HandleObject obj, JSBool *out)
 {
     RootedId id(cx);
     if (!ValueToId<CanGC>(cx, key, &id))
@@ -640,17 +640,17 @@ DebugEpilogue(JSContext *cx, BaselineFra
         DebugScopes::onPopCall(frame, cx);
     } else if (frame->isStrictEvalFrame()) {
         JS_ASSERT_IF(frame->hasCallObj(), frame->scopeChain()->asCall().isForEval());
         DebugScopes::onPopStrictEvalScope(frame);
     }
 
     // If the frame has a pushed SPS frame, make sure to pop it.
     if (frame->hasPushedSPSFrame()) {
-        cx->runtime->spsProfiler.exit(cx, frame->script(), frame->maybeFun());
+        cx->runtime()->spsProfiler.exit(cx, frame->script(), frame->maybeFun());
         // Unset the pushedSPSFrame flag because DebugEpilogue may get called before
         // Probes::exitScript in baseline during exception handling, and we don't
         // want to double-pop SPS frames.
         frame->unsetPushedSPSFrame();
     }
 
     if (!ok) {
         // Pop this frame by updating ionTop, so that the exception handling
@@ -726,26 +726,26 @@ InitRestParameter(JSContext *cx, uint32_
 bool
 HandleDebugTrap(JSContext *cx, BaselineFrame *frame, uint8_t *retAddr, JSBool *mustReturn)
 {
     *mustReturn = false;
 
     RootedScript script(cx, frame->script());
     jsbytecode *pc = script->baselineScript()->icEntryFromReturnAddress(retAddr).pc(script);
 
-    JS_ASSERT(cx->compartment->debugMode());
+    JS_ASSERT(cx->compartment()->debugMode());
     JS_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc));
 
     RootedValue rval(cx);
     JSTrapStatus status = JSTRAP_CONTINUE;
-    JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
+    JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook;
 
     if (hook || script->stepModeEnabled()) {
         if (hook)
-            status = hook(cx, script, pc, rval.address(), cx->runtime->debugHooks.interruptHookData);
+            status = hook(cx, script, pc, rval.address(), cx->runtime()->debugHooks.interruptHookData);
         if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
             status = Debugger::onSingleStep(cx, &rval);
     }
 
     if (status == JSTRAP_CONTINUE && script->hasBreakpointsAt(pc))
         status = Debugger::onTrap(cx, &rval);
 
     switch (status) {
@@ -775,18 +775,18 @@ bool
 OnDebuggerStatement(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, JSBool *mustReturn)
 {
     *mustReturn = false;
 
     RootedScript script(cx, frame->script());
     JSTrapStatus status = JSTRAP_CONTINUE;
     RootedValue rval(cx);
 
-    if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
-        status = handler(cx, script, pc, rval.address(), cx->runtime->debugHooks.debuggerHandlerData);
+    if (JSDebuggerHandler handler = cx->runtime()->debugHooks.debuggerHandler)
+        status = handler(cx, script, pc, rval.address(), cx->runtime()->debugHooks.debuggerHandlerData);
 
     if (status == JSTRAP_CONTINUE)
         status = Debugger::onDebuggerStatement(cx, &rval);
 
     switch (status) {
       case JSTRAP_ERROR:
         return false;
 
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -516,17 +516,17 @@ class AutoDetectInvalidation
 
     void disable() {
         JS_ASSERT(!disabled_);
         disabled_ = true;
     }
 
     ~AutoDetectInvalidation() {
         if (!disabled_ && ionScript_->invalidated())
-            cx_->runtime->setIonReturnOverride(*rval_);
+            cx_->runtime()->setIonReturnOverride(*rval_);
     }
 };
 
 bool InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, Value *rval);
 JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
 
 bool CheckOverRecursed(JSContext *cx);
 
--- a/js/src/ion/arm/Trampoline-arm.cpp
+++ b/js/src/ion/arm/Trampoline-arm.cpp
@@ -82,17 +82,17 @@ IonRuntime::generateEnterJIT(JSContext *
     const Register reg_frame = r3;
 
     const Address slot_token(sp, offsetof(EnterJITStack, token));
     const Address slot_vp(sp, offsetof(EnterJITStack, vp));
 
     JS_ASSERT(OsrFrameReg == reg_frame);
 
     MacroAssembler masm(cx);
-    AutoFlushCache afc("GenerateEnterJIT", cx->runtime->ionRuntime());
+    AutoFlushCache afc("GenerateEnterJIT", cx->runtime()->ionRuntime());
     Assembler *aasm = &masm;
 
     // Save non-volatile registers. These must be saved by the trampoline,
     // rather than the JIT'd code, because they are scanned by the conservative
     // scanner.
     masm.startDataTransferM(IsStore, sp, DB, WriteBack);
     masm.transferReg(r0); // [sp,0]
     masm.transferReg(r4); // [sp,4]
@@ -740,27 +740,27 @@ IonRuntime::generateVMWrapper(JSContext 
 }
 
 IonCode *
 IonRuntime::generatePreBarrier(JSContext *cx, MIRType type)
 {
     MacroAssembler masm(cx);
 
     RegisterSet save;
-    if (cx->runtime->jitSupportsFloatingPoint) {
+    if (cx->runtime()->jitSupportsFloatingPoint) {
         save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
                            FloatRegisterSet(FloatRegisters::VolatileMask));
     } else {
         save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
                            FloatRegisterSet());
     }
     masm.PushRegsInMask(save);
 
     JS_ASSERT(PreBarrierReg == r1);
-    masm.movePtr(ImmWord(cx->runtime), r0);
+    masm.movePtr(ImmWord(cx->runtime()), r0);
 
     masm.setupUnalignedABICall(2, r2);
     masm.passABIArg(r0);
     masm.passABIArg(r1);
     if (type == MIRType_Value) {
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon));
     } else {
         JS_ASSERT(type == MIRType_Shape);
@@ -790,17 +790,17 @@ IonRuntime::generateDebugTrapHandler(JSC
     masm.subPtr(Imm32(BaselineFrame::Size()), scratch1);
 
     // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
     // the stub frame has a NULL ICStub pointer, since this pointer is marked
     // during GC.
     masm.movePtr(ImmWord((void *)NULL), BaselineStubReg);
     EmitEnterStubFrame(masm, scratch2);
 
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(HandleDebugTrapInfo);
     if (!code)
         return NULL;
 
     masm.push(lr);
     masm.push(scratch1);
     EmitCallVM(code, masm);
 
--- a/js/src/ion/shared/BaselineCompiler-shared.cpp
+++ b/js/src/ion/shared/BaselineCompiler-shared.cpp
@@ -12,32 +12,32 @@ using namespace js;
 using namespace js::ion;
 
 BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, HandleScript script)
   : cx(cx),
     script(cx, script),
     pc(script->code),
     ionCompileable_(ion::IsEnabled(cx) && CanIonCompileScript(cx, script, false)),
     ionOSRCompileable_(ion::IsEnabled(cx) && CanIonCompileScript(cx, script, true)),
-    debugMode_(cx->compartment->debugMode()),
+    debugMode_(cx->compartment()->debugMode()),
     analysis_(script),
     frame(cx, script, masm),
     stubSpace_(),
     icEntries_(),
     pcMappingEntries_(),
     icLoadLabels_(),
     pushedBeforeCall_(0),
     inCall_(false),
     spsPushToggleOffset_()
 { }
 
 bool
 BaselineCompilerShared::callVM(const VMFunction &fun)
 {
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(fun);
     if (!code)
         return false;
 
 #ifdef DEBUG
     // Assert prepareVMCall() has been called.
     JS_ASSERT(inCall_);
     inCall_ = false;
--- a/js/src/ion/x64/Trampoline-x64.cpp
+++ b/js/src/ion/x64/Trampoline-x64.cpp
@@ -642,17 +642,17 @@ IonRuntime::generatePreBarrier(JSContext
 {
     MacroAssembler masm;
 
     RegisterSet regs = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
                                    FloatRegisterSet(FloatRegisters::VolatileMask));
     masm.PushRegsInMask(regs);
 
     JS_ASSERT(PreBarrierReg == rdx);
-    masm.mov(ImmWord(cx->runtime), rcx);
+    masm.mov(ImmWord(cx->runtime()), rcx);
 
     masm.setupUnalignedABICall(2, rax);
     masm.passABIArg(rcx);
     masm.passABIArg(rdx);
     if (type == MIRType_Value) {
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon));
     } else {
         JS_ASSERT(type == MIRType_Shape);
@@ -686,17 +686,17 @@ IonRuntime::generateDebugTrapHandler(JSC
     masm.subPtr(Imm32(BaselineFrame::Size()), scratch2);
 
     // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
     // the stub frame has a NULL ICStub pointer, since this pointer is marked
     // during GC.
     masm.movePtr(ImmWord((void *)NULL), BaselineStubReg);
     EmitEnterStubFrame(masm, scratch3);
 
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(HandleDebugTrapInfo);
     if (!code)
         return NULL;
 
     masm.push(scratch1);
     masm.push(scratch2);
     EmitCallVM(code, masm);
 
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -660,27 +660,27 @@ IonRuntime::generateVMWrapper(JSContext 
 }
 
 IonCode *
 IonRuntime::generatePreBarrier(JSContext *cx, MIRType type)
 {
     MacroAssembler masm;
 
     RegisterSet save;
-    if (cx->runtime->jitSupportsFloatingPoint) {
+    if (cx->runtime()->jitSupportsFloatingPoint) {
         save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
                            FloatRegisterSet(FloatRegisters::VolatileMask));
     } else {
         save = RegisterSet(GeneralRegisterSet(Registers::VolatileMask),
                            FloatRegisterSet());
     }
     masm.PushRegsInMask(save);
 
     JS_ASSERT(PreBarrierReg == edx);
-    masm.movl(ImmWord(cx->runtime), ecx);
+    masm.movl(ImmWord(cx->runtime()), ecx);
 
     masm.setupUnalignedABICall(2, eax);
     masm.passABIArg(ecx);
     masm.passABIArg(edx);
 
     if (type == MIRType_Value) {
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, MarkValueFromIon));
     } else {
@@ -715,17 +715,17 @@ IonRuntime::generateDebugTrapHandler(JSC
     masm.subPtr(Imm32(BaselineFrame::Size()), scratch2);
 
     // Enter a stub frame and call the HandleDebugTrap VM function. Ensure
     // the stub frame has a NULL ICStub pointer, since this pointer is marked
     // during GC.
     masm.movePtr(ImmWord((void *)NULL), BaselineStubReg);
     EmitEnterStubFrame(masm, scratch3);
 
-    IonCompartment *ion = cx->compartment->ionCompartment();
+    IonCompartment *ion = cx->compartment()->ionCompartment();
     IonCode *code = ion->getVMWrapper(HandleDebugTrapInfo);
     if (!code)
         return NULL;
 
     masm.push(scratch1);
     masm.push(scratch2);
     EmitCallVM(code, masm);
 
--- a/js/src/jsalloc.cpp
+++ b/js/src/jsalloc.cpp
@@ -8,16 +8,16 @@
 
 #include "jscntxt.h"
 
 using namespace js;
 
 void *
 TempAllocPolicy::onOutOfMemory(void *p, size_t nbytes)
 {
-    return cx_->runtime->onOutOfMemory(p, nbytes, cx_);
+    return cx_->runtime()->onOutOfMemory(p, nbytes, cx_);
 }
 
 void
 TempAllocPolicy::reportAllocOverflow() const
 {
     js_ReportAllocationOverflow(cx_);
 }
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -95,17 +95,17 @@ ScriptAnalysis::addJump(JSContext *cx, u
     }
 
     return true;
 }
 
 void
 ScriptAnalysis::analyzeBytecode(JSContext *cx)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
     JS_ASSERT(!ranBytecode());
     LifoAlloc &alloc = cx->analysisLifoAlloc();
 
     numSlots = TotalSlots(script_);
 
     unsigned length = script_->length;
     codeArray = alloc.newArray<Bytecode*>(length);
     escapedSlots = alloc.newArray<bool>(numSlots);
@@ -141,23 +141,23 @@ ScriptAnalysis::analyzeBytecode(JSContex
         else
             escapedSlots[LocalSlot(script_, bi.frameIndex())] = allVarsAliased || bi->aliased();
     }
 
     /*
      * If the script is in debug mode, JS_SetFrameReturnValue can be called at
      * any safe point.
      */
-    if (cx->compartment->debugMode())
+    if (cx->compartment()->debugMode())
         usesReturnValue_ = true;
 
     bool heavyweight = script_->function() && script_->function()->isHeavyweight();
 
     isIonInlineable = true;
-    if (heavyweight || cx->compartment->debugMode())
+    if (heavyweight || cx->compartment()->debugMode())
         isIonInlineable = false;
 
     modifiesArguments_ = false;
     if (heavyweight)
         modifiesArguments_ = true;
 
     canTrackVars = true;
 
@@ -584,17 +584,17 @@ ScriptAnalysis::analyzeBytecode(JSContex
 
 /////////////////////////////////////////////////////////////////////
 // Lifetime Analysis
 /////////////////////////////////////////////////////////////////////
 
 void
 ScriptAnalysis::analyzeLifetimes(JSContext *cx)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis && !ranLifetimes() && !failed());
+    JS_ASSERT(cx->compartment()->activeAnalysis && !ranLifetimes() && !failed());
 
     if (!ranBytecode()) {
         analyzeBytecode(cx);
         if (failed())
             return;
     }
 
     LifoAlloc &alloc = cx->analysisLifoAlloc();
@@ -1073,17 +1073,17 @@ ScriptAnalysis::ensureVariable(LifetimeV
 
 /////////////////////////////////////////////////////////////////////
 // SSA Analysis
 /////////////////////////////////////////////////////////////////////
 
 void
 ScriptAnalysis::analyzeSSA(JSContext *cx)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis && !ranSSA() && !failed());
+    JS_ASSERT(cx->compartment()->activeAnalysis && !ranSSA() && !failed());
 
     if (!ranLifetimes()) {
         analyzeLifetimes(cx);
         if (failed())
             return;
     }
 
     LifoAlloc &alloc = cx->analysisLifoAlloc();
@@ -1759,17 +1759,17 @@ ScriptAnalysis::needsArgsObj(JSContext *
     if (!trackUseChain(v))
         return false;
 
     for (unsigned i = 0; i < seen.length(); i++) {
         if (v == seen[i])
             return false;
     }
     if (!seen.append(v)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return true;
     }
 
     SSAUseChain *use = useChain(v);
     while (use) {
         if (needsArgsObj(cx, seen, use))
             return true;
         use = use->next;
@@ -1822,17 +1822,17 @@ bool
 ScriptAnalysis::needsArgsObj(JSContext *cx)
 {
     JS_ASSERT(script_->argumentsHasVarBinding());
 
     /*
      * Always construct arguments objects when in debug mode and for generator
      * scripts (generators can be suspended when speculation fails).
      */
-    if (cx->compartment->debugMode() || script_->isGenerator)
+    if (cx->compartment()->debugMode() || script_->isGenerator)
         return true;
 
     /*
      * If the script has dynamic name accesses which could reach 'arguments',
      * the parser will already have checked to ensure there are no explicit
      * uses of 'arguments' in the function. If there are such uses, the script
      * will be marked as definitely needing an arguments object.
      *
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -234,17 +234,17 @@ bool testIndirectEval(JS::HandleObject s
     EVAL("hits", hitsv.address());
     CHECK_SAME(hitsv, INT_TO_JSVAL(1));
     return true;
 }
 END_TEST(testDebugger_newScriptHook)
 
 BEGIN_TEST(testDebugger_singleStepThrow)
     {
-        CHECK(JS_SetDebugModeForCompartment(cx, cx->compartment, true));
+        CHECK(JS_SetDebugModeForCompartment(cx, cx->compartment(), true));
         CHECK(JS_SetInterrupt(rt, onStep, NULL));
 
         CHECK(JS_DefineFunction(cx, global, "setStepMode", setStepMode, 0, 0));
         EXEC("var e;\n"
              "setStepMode();\n"
              "function f() { throw 0; }\n"
              "try { f(); }\n"
              "catch (x) { e = x; }\n");
--- a/js/src/jsapi-tests/testIndexToString.cpp
+++ b/js/src/jsapi-tests/testIndexToString.cpp
@@ -58,17 +58,17 @@ static const struct TestPair {
 BEGIN_TEST(testIndexToString)
 {
     for (size_t i = 0, sz = ArrayLength(tests); i < sz; i++) {
         uint32_t u = tests[i].num;
         JSString *str = js::IndexToString(cx, u);
         CHECK(str);
 
         if (!js::StaticStrings::hasUint(u))
-            CHECK(cx->compartment->dtoaCache.lookup(10, u) == str);
+            CHECK(cx->compartment()->dtoaCache.lookup(10, u) == str);
 
         JSBool match = JS_FALSE;
         CHECK(JS_StringEqualsAscii(cx, str, tests[i].expected, &match));
         CHECK(match);
     }
 
     return true;
 }
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -16,19 +16,19 @@ static js::ProfileEntry pstack[10];
 static uint32_t psize = 0;
 static uint32_t max_stack = 0;
 
 static void
 reset(JSContext *cx)
 {
     psize = max_stack = 0;
     memset(pstack, 0, sizeof(pstack));
-    cx->runtime->spsProfiler.stringsReset();
-    cx->runtime->spsProfiler.enableSlowAssertions(true);
-    js::EnableRuntimeProfilingStack(cx->runtime, true);
+    cx->runtime()->spsProfiler.stringsReset();
+    cx->runtime()->spsProfiler.enableSlowAssertions(true);
+    js::EnableRuntimeProfilingStack(cx->runtime(), true);
 }
 
 static JSClass ptestClass = {
     "Prof", 0, JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub,
     JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
 static JSBool
@@ -44,24 +44,24 @@ test_fn2(JSContext *cx, unsigned argc, j
     jsval r;
     JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx));
     return JS_CallFunctionName(cx, global, "d", 0, NULL, &r);
 }
 
 static JSBool
 enable(JSContext *cx, unsigned argc, jsval *vp)
 {
-    js::EnableRuntimeProfilingStack(cx->runtime, true);
+    js::EnableRuntimeProfilingStack(cx->runtime(), true);
     return JS_TRUE;
 }
 
 static JSBool
 disable(JSContext *cx, unsigned argc, jsval *vp)
 {
-    js::EnableRuntimeProfilingStack(cx->runtime, false);
+    js::EnableRuntimeProfilingStack(cx->runtime(), false);
     return JS_TRUE;
 }
 
 static JSBool
 Prof(JSContext* cx, unsigned argc, jsval *vp)
 {
     JSObject *obj = JS_NewObjectForConstructor(cx, &ptestClass, vp);
     if (!obj)
@@ -76,17 +76,17 @@ static const JSFunctionSpec ptestFunctio
     JS_FS("enable", enable, 0, 0),
     JS_FS("disable", disable, 0, 0),
     JS_FS_END
 };
 
 static JSObject*
 initialize(JSContext *cx)
 {
-    js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 10);
+    js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 10);
     JS::RootedObject global(cx, JS_GetGlobalForScopeChain(cx));
     return JS_InitClass(cx, global, NULL, &ptestClass, Prof, 0,
                         NULL, ptestFunctions, NULL, NULL);
 }
 
 BEGIN_TEST(testProfileStrings_isCalledWithInterpreter)
 {
     CHECK(initialize(cx));
@@ -103,34 +103,34 @@ BEGIN_TEST(testProfileStrings_isCalledWi
 
     reset(cx);
     {
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
-        CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
         /* Make sure the stack resets and we added no new entries */
         max_stack = 0;
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
-        CHECK(cx->runtime->spsProfiler.stringsCount() == 8);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
     }
     reset(cx);
     {
         JS::RootedValue rval(cx);
         CHECK(JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address()));
-        CHECK(cx->runtime->spsProfiler.stringsCount() == 5);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == 5);
         CHECK(max_stack >= 6);
         CHECK(psize == 0);
     }
-    js::EnableRuntimeProfilingStack(cx->runtime, false);
-    js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 3);
+    js::EnableRuntimeProfilingStack(cx->runtime(), false);
+    js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 3);
     reset(cx);
     {
         JS::RootedValue rval(cx);
         pstack[3].setLabel((char*) 1234);
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK((size_t) pstack[3].label() == 1234);
         CHECK(max_stack >= 8);
         CHECK(psize == 0);
@@ -158,26 +158,26 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     {
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
 
         /* Make sure the stack resets and we added no new entries */
-        uint32_t cnt = cx->runtime->spsProfiler.stringsCount();
+        uint32_t cnt = cx->runtime()->spsProfiler.stringsCount();
         max_stack = 0;
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
-        CHECK(cx->runtime->spsProfiler.stringsCount() == cnt);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == cnt);
         CHECK(max_stack >= 8);
     }
 
-    js::EnableRuntimeProfilingStack(cx->runtime, false);
-    js::SetRuntimeProfilingStack(cx->runtime, pstack, &psize, 3);
+    js::EnableRuntimeProfilingStack(cx->runtime(), false);
+    js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 3);
     reset(cx);
     {
         /* Limit the size of the stack and make sure we don't overflow */
         JS::RootedValue rval(cx);
         pstack[3].setLabel((char*) 1234);
         CHECK(JS_CallFunctionName(cx, global, "check", 0, NULL, rval.address()));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
@@ -197,40 +197,40 @@ BEGIN_TEST(testProfileStrings_isCalledWh
     reset(cx);
     JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
     {
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         JSBool ok = JS_CallFunctionName(cx, global, "check2", 0, NULL, rval.address());
         CHECK(!ok);
         CHECK(psize == 0);
-        CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
 
         JS_ClearPendingException(cx);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
 
 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
 {
     CHECK(initialize(cx));
     JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_BASELINE | JSOPTION_ION);
 
     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);
+    js::EnableRuntimeProfilingStack(cx->runtime(), false);
     {
         /* enable it in the middle of JS and make sure things check out */
         JS::RootedValue rval(cx);
         JS_CallFunctionName(cx, global, "a", 0, NULL, rval.address());
         CHECK(psize == 0);
         CHECK(max_stack >= 1);
-        CHECK(cx->runtime->spsProfiler.stringsCount() == 1);
+        CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
     }
 
     EXEC("function d(p) { p.disable(); }");
     EXEC("function c() { var p = new Prof(); d(p); }");
     reset(cx);
     {
         /* now disable in the middle of js */
         JS::RootedValue rval(cx);
@@ -247,17 +247,17 @@ BEGIN_TEST(testProfileStrings_worksWhenE
         CHECK(psize == 0);
         CHECK(max_stack >= 3);
     }
 
     EXEC("function h() { }");
     EXEC("function g(p) { p.disable(); for (var i = 0; i < 100; i++) i++; }");
     EXEC("function f() { g(new Prof()); }");
     reset(cx);
-    cx->runtime->spsProfiler.enableSlowAssertions(false);
+    cx->runtime()->spsProfiler.enableSlowAssertions(false);
     {
         JS::RootedValue rval(cx);
         /* disable, and make sure that if we try to re-enter the JIT the pop
          * will still happen */
         JS_CallFunctionName(cx, global, "f", 0, NULL, rval.address());
         CHECK(psize == 0);
     }
     return true;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -198,35 +198,35 @@ JS_PUBLIC_API(int64_t)
 JS_Now()
 {
     return PRMJ_Now();
 }
 
 JS_PUBLIC_API(jsval)
 JS_GetNaNValue(JSContext *cx)
 {
-    return cx->runtime->NaNValue;
+    return cx->runtime()->NaNValue;
 }
 
 JS_PUBLIC_API(jsval)
 JS_GetNegativeInfinityValue(JSContext *cx)
 {
-    return cx->runtime->negativeInfinityValue;
+    return cx->runtime()->negativeInfinityValue;
 }
 
 JS_PUBLIC_API(jsval)
 JS_GetPositiveInfinityValue(JSContext *cx)
 {
-    return cx->runtime->positiveInfinityValue;
+    return cx->runtime()->positiveInfinityValue;
 }
 
 JS_PUBLIC_API(jsval)
 JS_GetEmptyStringValue(JSContext *cx)
 {
-    return STRING_TO_JSVAL(cx->runtime->emptyString);
+    return STRING_TO_JSVAL(cx->runtime()->emptyString);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetEmptyString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
     return rt->emptyString;
 }
@@ -235,39 +235,39 @@ static void
 AssertHeapIsIdle(JSRuntime *rt)
 {
     JS_ASSERT(rt->heapState == js::Idle);
 }
 
 static void
 AssertHeapIsIdle(JSContext *cx)
 {
-    AssertHeapIsIdle(cx->runtime);
+    AssertHeapIsIdle(cx->runtime());
 }
 
 static void
 AssertHeapIsIdleOrIterating(JSRuntime *rt)
 {
     JS_ASSERT(!rt->isHeapCollecting());
 }
 
 static void
 AssertHeapIsIdleOrIterating(JSContext *cx)
 {
-    AssertHeapIsIdleOrIterating(cx->runtime);
+    AssertHeapIsIdleOrIterating(cx->runtime());
 }
 
 static void
 AssertHeapIsIdleOrStringIsFlat(JSContext *cx, JSString *str)
 {
     /*
      * We allow some functions to be called during a GC as long as the argument
      * is a flat string, since that will not cause allocation.
      */
-    JS_ASSERT_IF(cx->runtime->isHeapBusy(), str->isFlat());
+    JS_ASSERT_IF(cx->runtime()->isHeapBusy(), str->isFlat());
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertArguments(JSContext *cx, unsigned argc, jsval *argv, const char *format, ...)
 {
     va_list ap;
     JSBool ok;
 
@@ -1199,34 +1199,34 @@ JS_SetRuntimePrivate(JSRuntime *rt, void
 {
     rt->data = data;
 }
 
 #ifdef JS_THREADSAFE
 static void
 StartRequest(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->assertValidThread();
 
     if (rt->requestDepth) {
         rt->requestDepth++;
     } else {
         /* Indicate that a request is running. */
         rt->requestDepth = 1;
 
         if (rt->activityCallback)
             rt->activityCallback(rt->activityCallbackArg, true);
     }
 }
 
 static void
 StopRequest(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->assertValidThread();
     JS_ASSERT(rt->requestDepth != 0);
     if (rt->requestDepth != 1) {
         rt->requestDepth--;
     } else {
         rt->conservativeGC.updateForRequestEnd();
         rt->requestDepth = 0;
 
@@ -1316,17 +1316,17 @@ JS_PUBLIC_API(void)
 JS_SetSecondContextPrivate(JSContext *cx, void *data)
 {
     cx->data2 = data;
 }
 
 JS_PUBLIC_API(JSRuntime *)
 JS_GetRuntime(JSContext *cx)
 {
-    return cx->runtime;
+    return cx->runtime();
 }
 
 JS_PUBLIC_API(JSContext *)
 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
 {
     JSContext *cx = *iterp;
     cx = cx ? cx->getNext() : rt->contextList.getFirst();
     *iterp = cx;
@@ -1471,17 +1471,17 @@ JS_SetWrapObjectCallbacks(JSRuntime *rt,
 }
 
 JS_PUBLIC_API(JSCompartment *)
 JS_EnterCompartment(JSContext *cx, JSObject *target)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    JSCompartment *oldCompartment = cx->compartment;
+    JSCompartment *oldCompartment = cx->compartment();
     cx->enterCompartment(target->compartment());
     return oldCompartment;
 }
 
 JS_PUBLIC_API(JSCompartment *)
 JS_EnterCompartmentOfScript(JSContext *cx, JSScript *target)
 {
     AssertHeapIsIdle(cx);
@@ -1495,25 +1495,25 @@ JS_LeaveCompartment(JSContext *cx, JSCom
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     cx->leaveCompartment(oldCompartment);
 }
 
 JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSObject *target)
   : cx_(cx),
-    oldCompartment_(cx->compartment)
+    oldCompartment_(cx->compartment())
 {
     AssertHeapIsIdleOrIterating(cx_);
     cx_->enterCompartment(target->compartment());
 }
 
 JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSScript *target)
   : cx_(cx),
-    oldCompartment_(cx->compartment)
+    oldCompartment_(cx->compartment())
 {
     AssertHeapIsIdleOrIterating(cx_);
     cx_->enterCompartment(target->compartment());
 }
 
 JSAutoCompartment::~JSAutoCompartment()
 {
     cx_->leaveCompartment(oldCompartment_);
@@ -1533,45 +1533,45 @@ JS_GetCompartmentPrivate(JSCompartment *
 
 JS_PUBLIC_API(JSBool)
 JS_WrapObject(JSContext *cx, JSObject **objp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (*objp)
         JS::ExposeGCThingToActiveJS(*objp, JSTRACE_OBJECT);
-    return cx->compartment->wrap(cx, objp);
+    return cx->compartment()->wrap(cx, objp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_WrapValue(JSContext *cx, jsval *vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (vp)
         JS::ExposeValueToActiveJS(*vp);
     RootedValue value(cx, *vp);
-    bool ok = cx->compartment->wrap(cx, &value);
+    bool ok = cx->compartment()->wrap(cx, &value);
     *vp = value.get();
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_WrapId(JSContext *cx, jsid *idp)
 {
   AssertHeapIsIdle(cx);
   CHECK_REQUEST(cx);
   if (idp) {
       jsid id = *idp;
       if (JSID_IS_STRING(id))
           JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING);
       else if (JSID_IS_OBJECT(id))
           JS::ExposeGCThingToActiveJS(JSID_TO_OBJECT(id), JSTRACE_OBJECT);
   }
-  return cx->compartment->wrapId(cx, idp);
+  return cx->compartment()->wrapId(cx, idp);
 }
 
 /*
  * Identity remapping. Not for casual consumers.
  *
  * Normally, an object's contents and its identity are inextricably linked.
  * Identity is determined by the address of the JSObject* in the heap, and
  * the contents are what is located at that address. Transplanting allows these
@@ -1606,17 +1606,17 @@ JS_TransplantObject(JSContext *cx, JSObj
     RootedObject origobj(cx, origobjArg);
     RootedObject target(cx, targetArg);
     AssertHeapIsIdle(cx);
     JS_ASSERT(origobj != target);
     JS_ASSERT(!IsCrossCompartmentWrapper(origobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(target));
 
     AutoMaybeTouchDeadZones agc(cx);
-    AutoDisableProxyCheck adpc(cx->runtime);
+    AutoDisableProxyCheck adpc(cx->runtime());
 
     JSCompartment *destination = target->compartment();
     RootedValue origv(cx, ObjectValue(*origobj));
     RootedObject newIdentity(cx);
 
     if (origobj->compartment() == destination) {
         // If the original object is in the same compartment as the
         // destination, then we know that we won't find a wrapper in the
@@ -1680,17 +1680,17 @@ js_TransplantObjectWithWrapper(JSContext
                                JSObject *targetwrapperArg)
 {
     RootedObject origobj(cx, origobjArg);
     RootedObject origwrapper(cx, origwrapperArg);
     RootedObject targetobj(cx, targetobjArg);
     RootedObject targetwrapper(cx, targetwrapperArg);
 
     AutoMaybeTouchDeadZones agc(cx);
-    AutoDisableProxyCheck adpc(cx->runtime);
+    AutoDisableProxyCheck adpc(cx->runtime());
 
     AssertHeapIsIdle(cx);
     JS_ASSERT(!IsCrossCompartmentWrapper(origobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(origwrapper));
     JS_ASSERT(!IsCrossCompartmentWrapper(targetobj));
     JS_ASSERT(!IsCrossCompartmentWrapper(targetwrapper));
 
     RootedObject newWrapper(cx);
@@ -1776,17 +1776,17 @@ JS_SetGlobalObject(JSContext *cx, JSObje
 
     cx->setDefaultCompartmentObject(obj);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_InitStandardClasses(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     cx->setDefaultCompartmentObjectIfUnset(obj);
     assertSameCompartment(cx, obj);
 
     Rooted<GlobalObject*> global(cx, &obj->global());
     return GlobalObject::initStandardClasses(cx, global);
@@ -1802,17 +1802,17 @@ typedef struct JSStdName {
     JSClassInitializerOp init;
     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
     Class       *clasp;
 } JSStdName;
 
 static Handle<PropertyName*>
 StdNameToPropertyName(JSContext *cx, JSStdName *stdn)
 {
-    return OFFSET_TO_NAME(cx->runtime, stdn->atomOffset);
+    return OFFSET_TO_NAME(cx->runtime(), stdn->atomOffset);
 }
 
 /*
  * Table of class initializers and their atom offsets in rt->atomState.
  * If you add a "standard" class, remember to update this table.
  */
 static JSStdName standard_class_atoms[] = {
     {js_InitFunctionClass,              EAGER_ATOM_AND_CLASP(Function)},
@@ -1934,17 +1934,17 @@ JS_ResolveStandardClass(JSContext *cx, J
     JSStdName *stdnm;
     unsigned i;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     *resolved = false;
 
-    rt = cx->runtime;
+    rt = cx->runtime();
     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
         return true;
 
     RootedString idstr(cx, JSID_TO_STRING(id));
 
     /* Check whether we're resolving 'undefined', and define it if so. */
     atom = rt->atomState.undefined;
     if (idstr == atom) {
@@ -2117,17 +2117,17 @@ JS_EnumerateResolvedStandardClasses(JSCo
     JSRuntime *rt;
     int i, j, k;
     JSBool found;
     JSClassInitializerOp init;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, ida);
-    rt = cx->runtime;
+    rt = cx->runtime();
     if (ida) {
         i = ida->length;
     } else {
         ida = NewIdArray(cx, 8);
         if (!ida)
             return NULL;
         i = 0;
     }
@@ -2310,17 +2310,17 @@ JS_PUBLIC_API(JSFreeOp *)
 JS_GetDefaultFreeOp(JSRuntime *rt)
 {
     return rt->defaultFreeOp();
 }
 
 JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext *cx, size_t nbytes)
 {
-    return cx->runtime->updateMallocCounter(cx->zone(), nbytes);
+    return cx->runtime()->updateMallocCounter(cx->zone(), nbytes);
 }
 
 JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s)
 {
     AssertHeapIsIdle(cx);
     size_t n = strlen(s) + 1;
     void *p = cx->malloc_(n);
@@ -2405,38 +2405,38 @@ JS_AddNamedScriptRoot(JSContext *cx, JSS
 }
 
 /* We allow unrooting from finalizers within the GC */
 
 JS_PUBLIC_API(void)
 JS_RemoveValueRoot(JSContext *cx, jsval *vp)
 {
     CHECK_REQUEST(cx);
-    js_RemoveRoot(cx->runtime, (void *)vp);
+    js_RemoveRoot(cx->runtime(), (void *)vp);
 }
 
 JS_PUBLIC_API(void)
 JS_RemoveStringRoot(JSContext *cx, JSString **rp)
 {
     CHECK_REQUEST(cx);
-    js_RemoveRoot(cx->runtime, (void *)rp);
+    js_RemoveRoot(cx->runtime(), (void *)rp);
 }
 
 JS_PUBLIC_API(void)
 JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
 {
     CHECK_REQUEST(cx);
-    js_RemoveRoot(cx->runtime, (void *)rp);
+    js_RemoveRoot(cx->runtime(), (void *)rp);
 }
 
 JS_PUBLIC_API(void)
 JS_RemoveScriptRoot(JSContext *cx, JSScript **rp)
 {
     CHECK_REQUEST(cx);
-    js_RemoveRoot(cx->runtime, (void *)rp);
+    js_RemoveRoot(cx->runtime(), (void *)rp);
 }
 
 JS_PUBLIC_API(void)
 JS_RemoveValueRootRT(JSRuntime *rt, jsval *vp)
 {
     js_RemoveRoot(rt, (void *)vp);
 }
 
@@ -3159,17 +3159,17 @@ JS_IdArrayGet(JSContext *cx, JSIdArray *
 {
     JS_ASSERT(index >= 0 && index < ida->length);
     return ida->vector[index];
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
 {
-    DestroyIdArray(cx->runtime->defaultFreeOp(), ida);
+    DestroyIdArray(cx->runtime()->defaultFreeOp(), ida);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ValueToId(JSContext *cx, jsval valueArg, jsid *idp)
 {
     RootedValue value(cx, valueArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -3426,19 +3426,19 @@ class AutoHoldZone
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 JS_PUBLIC_API(JSObject *)
 JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, JS::ZoneSpecifier zoneSpec)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
-
-    JSRuntime *rt = cx->runtime;
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
+
+    JSRuntime *rt = cx->runtime();
 
     Zone *zone;
     if (zoneSpec == JS::SystemZone)
         zone = rt->systemZone;
     else if (zoneSpec == JS::FreshZone)
         zone = NULL;
     else
         zone = ((JSObject *)zoneSpec)->zone();
@@ -3449,17 +3449,17 @@ JS_NewGlobalObject(JSContext *cx, JSClas
 
     if (zoneSpec == JS::SystemZone) {
         rt->systemZone = compartment->zone();
         rt->systemZone->isSystem = true;
     }
 
     AutoHoldZone hold(compartment->zone());
 
-    JSCompartment *saved = cx->compartment;
+    JSCompartment *saved = cx->compartment();
     cx->setCompartment(compartment);
     Rooted<GlobalObject *> global(cx, GlobalObject::create(cx, Valueify(clasp)));
     cx->setCompartment(saved);
     if (!global)
         return NULL;
 
     if (!Debugger::onNewGlobalObject(cx, global))
         return NULL;
@@ -3467,17 +3467,17 @@ JS_NewGlobalObject(JSContext *cx, JSClas
     return global;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObject(JSContext *cx, JSClass *jsclasp, JSObject *protoArg, JSObject *parentArg)
 {
     RootedObject proto(cx, protoArg);
     RootedObject parent(cx, parentArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
@@ -3497,17 +3497,17 @@ JS_NewObject(JSContext *cx, JSClass *jsc
     return obj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewObjectWithGivenProto(JSContext *cx, JSClass *jsclasp, JSObject *protoArg, JSObject *parentArg)
 {
     RootedObject proto(cx, protoArg);
     RootedObject parent(cx, parentArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
 
     Class *clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &ObjectClass;    /* default class is Object */
 
@@ -4768,17 +4768,17 @@ JS_SetReservedSlot(JSObject *obj, uint32
     obj->setReservedSlot(index, value);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewArrayObject(JSContext *cx, int length, jsval *vector)
 {
     AutoArrayRooter tvr(cx, length, vector);
 
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     assertSameCompartment(cx, JSValueArray(vector, vector ? (uint32_t)length : 0));
     return NewDenseCopiedArray(cx, (uint32_t)length, vector);
 }
 
 JS_PUBLIC_API(JSBool)
@@ -4866,17 +4866,17 @@ JS_InitDestroyPrincipalsCallback(JSRunti
     rt->destroyPrincipals = destroyPrincipals;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
                JSObject *parentArg, const char *name)
 {
     RootedObject parent(cx, parentArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
@@ -4889,17 +4889,17 @@ JS_NewFunction(JSContext *cx, JSNative n
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                    jsid id)
 {
     RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
 }
@@ -5038,17 +5038,17 @@ js_generic_native_method_dispatcher(JSCo
     vp[2 + --argc].setUndefined();
 
     return fs->call.op(cx, argc, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *objArg, const JSFunctionSpec *fs)
 {
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, objArg);
 
     RootedObject obj(cx, objArg);
     RootedObject ctor(cx);
 
     for (; fs->name; fs++) {
@@ -5094,25 +5094,25 @@ JS_DefineFunctions(JSContext *cx, JSObje
         if (fs->selfHostedName) {
             /*
              * During creation of the self-hosting global, we ignore all
              * self-hosted functions, as that means we're currently setting up
              * the global object that the self-hosted code is then compiled
              * in. Self-hosted functions can access each other via their names,
              * but not via the builtin classes they get installed into.
              */
-            if (cx->runtime->isSelfHostingGlobal(cx->global()))
+            if (cx->runtime()->isSelfHostingGlobal(cx->global()))
                 continue;
 
             RootedAtom shAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
             if (!shAtom)
                 return JS_FALSE;
             RootedPropertyName shName(cx, shAtom->asPropertyName());
             RootedValue funVal(cx);
-            if (!cx->runtime->maybeWrappedSelfHostedFunction(cx, shName, &funVal))
+            if (!cx->runtime()->maybeWrappedSelfHostedFunction(cx, shName, &funVal))
                 return JS_FALSE;
             if (!funVal.isUndefined()) {
                 if (!JSObject::defineProperty(cx, obj, atom->asPropertyName(), funVal,
                                              NULL, NULL, flags & ~JSFUN_FLAGS_MASK))
                 {
                     return JS_FALSE;
                 }
             } else {
@@ -5138,51 +5138,51 @@ JS_DefineFunctions(JSContext *cx, JSObje
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineUCFunction(JSContext *cx, JSObject *objArg,
                     const jschar *name, size_t namelen, JSNative call,
                     unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunctionById(JSContext *cx, JSObject *objArg, jsid id_, JSNative call,
                       unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
     RootedId id(cx, id_);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 struct AutoLastFrameCheck
 {
@@ -5313,21 +5313,21 @@ JS::Compile(JSContext *cx, HandleObject 
 {
     Maybe<AutoVersionAPI> mava;
     if (options.versionSet) {
         mava.construct(cx, options.version);
         // AutoVersionAPI propagates some compilation flags through.
         options.version = mava.ref().version();
     }
 
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals, cx->compartment->principals == options.principals);
+    JS_ASSERT_IF(options.principals, cx->compartment()->principals == options.principals);
     AutoLastFrameCheck lfc(cx);
 
     return frontend::CompileScript(cx, obj, NullPtr(), options, chars, length);
 }
 
 JSScript *
 JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options,
             const char *bytes, size_t length)
@@ -5472,21 +5472,21 @@ JS::CompileFunction(JSContext *cx, Handl
 {
     Maybe<AutoVersionAPI> mava;
     if (options.versionSet) {
         mava.construct(cx, options.version);
         // AutoVersionAPI propagates some compilation flags through.
         options.version = mava.ref().version();
     }
 
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals, cx->compartment->principals == options.principals);
+    JS_ASSERT_IF(options.principals, cx->compartment()->principals == options.principals);
     AutoLastFrameCheck lfc(cx);
 
     RootedAtom funAtom(cx);
     if (name) {
         funAtom = Atomize(cx, name, strlen(name));
         if (!funAtom)
             return NULL;
     }
@@ -5572,63 +5572,63 @@ JS_CompileFunction(JSContext *cx, JSObje
     options.setFileAndLine(filename, lineno);
 
     return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *scriptArg, const char *name, unsigned indent)
 {
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     RootedScript script(cx, scriptArg);
     RootedFunction fun(cx, script->function());
     if (fun)
         return JS_DecompileFunction(cx, fun, indent);
     bool haveSource = script->scriptSource()->hasSourceData();
     if (!haveSource && !JSScript::loadSource(cx, script, &haveSource))
         return NULL;
     return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileFunction(JSContext *cx, JSFunction *funArg, unsigned indent)
 {
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, funArg);
     RootedFunction fun(cx, funArg);
     return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_PUBLIC_API(JSString *)
 JS_DecompileFunctionBody(JSContext *cx, JSFunction *funArg, unsigned indent)
 {
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, funArg);
     RootedFunction fun(cx, funArg);
     return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(JSBool)
 JS_ExecuteScript(JSContext *cx, JSObject *objArg, JSScript *scriptArg, jsval *rval)
 {
     RootedObject obj(cx, objArg);
     RootedScript script(cx, scriptArg);
 
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    if (cx->compartment != obj->compartment())
+    if (cx->compartment() != obj->compartment())
         *(volatile int *) 0 = 0xf0;
     AutoLastFrameCheck lfc(cx);
 
     /*
      * Mozilla caches pre-compiled scripts (e.g., in the XUL prototype cache)
      * and runs them against multiple globals. With a compartment per global,
      * this requires cloning the pre-compiled script into each new global.
      * Since each script gets run once, there is no point in trying to cache
@@ -5663,21 +5663,21 @@ JS::Evaluate(JSContext *cx, HandleObject
 {
     Maybe<AutoVersionAPI> mava;
     if (options.versionSet) {
         mava.construct(cx, options.version);
         // AutoVersionAPI propagates some compilation flags through.
         options.version = mava.ref().version();
     }
 
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-    JS_ASSERT_IF(options.principals, cx->compartment->principals == options.principals);
+    JS_ASSERT_IF(options.principals, cx->compartment()->principals == options.principals);
 
     AutoLastFrameCheck lfc(cx);
 
     options.setCompileAndGo(true);
     options.setNoScriptRval(!rval);
     SourceCompressionToken sct(cx);
     RootedScript script(cx, frontend::CompileScript(cx, obj, NullPtr(), options,
                                                     chars, length, NULL, 0, &sct));
@@ -5693,17 +5693,17 @@ JS::Evaluate(JSContext *cx, HandleObject
     // After evaluation, the compiled script will not be run again.
     // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
     // which for large scripts means significant memory. Perform a GC eagerly
     // to clear out this analysis data before anything happens to inhibit the
     // flushing of this memory (such as setting requestAnimationFrame).
     if (script->length > LARGE_SCRIPT_LENGTH) {
         script = NULL;
         PrepareZoneForGC(cx->zone());
-        GC(cx->runtime, GC_NORMAL, gcreason::FINISH_LARGE_EVALUTE);
+        GC(cx->runtime(), GC_NORMAL, gcreason::FINISH_LARGE_EVALUTE);
     }
 
     return result;
 }
 
 extern JS_PUBLIC_API(bool)
 JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
              const char *bytes, size_t length, jsval *rval)
@@ -5836,31 +5836,31 @@ JS_EvaluateScript(JSContext *cx, JSObjec
     return Evaluate(cx, obj, options, bytes, nbytes, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunction(JSContext *cx, JSObject *objArg, JSFunction *fun, unsigned argc, jsval *argv,
                 jsval *rval)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionName(JSContext *cx, JSObject *objArg, const char *name, unsigned argc, jsval *argv,
                     jsval *rval)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     JSAtom *atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
@@ -5871,17 +5871,17 @@ JS_CallFunctionName(JSContext *cx, JSObj
            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *objArg, jsval fval, unsigned argc, jsval *argv,
                      jsval *rval)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     return Invoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
 }
 
@@ -6006,17 +6006,17 @@ JS_NewStringCopyZ(JSContext *cx, const c
 {
     size_t n;
     jschar *js;
     JSString *str;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (!s || !*s)
-        return cx->runtime->emptyString;
+        return cx->runtime()->emptyString;
     n = strlen(s);
     js = InflateString(cx, s, &n);
     if (!js)
         return NULL;
     str = js_NewString<CanGC>(cx, js, n);
     if (!str)
         js_free(js);
     return str;
@@ -6086,17 +6086,17 @@ JS_NewUCStringCopyN(JSContext *cx, const
 }
 
 JS_PUBLIC_API(JSString *)
 JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     if (!s)
-        return cx->runtime->emptyString;
+        return cx->runtime()->emptyString;
     return js_NewStringCopyZ<CanGC>(cx, s);
 }
 
 JS_PUBLIC_API(JSString *)
 JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -6123,17 +6123,17 @@ JS_GetStringCharsZ(JSContext *cx, JSStri
     size_t dummy;
     return JS_GetStringCharsZAndLength(cx, str, &dummy);
 }
 
 JS_PUBLIC_API(const jschar *)
 JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
 {
     /*
-     * Don't require |cx->compartment| to be |str|'s compartment. We don't need
+     * Don't require |cx->compartment()| to be |str|'s compartment. We don't need
      * it, and it's annoying for callers.
      */
     JS_ASSERT(plength);
     AssertHeapIsIdleOrStringIsFlat(cx, str);
     CHECK_REQUEST(cx);
     JSFlatString *flat = str->ensureFlat(cx);
     if (!flat)
         return NULL;
@@ -6401,34 +6401,34 @@ JS_ReadStructuredClone(JSContext *cx, ui
 
     if (version > JS_STRUCTURED_CLONE_VERSION) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_VERSION);
         return false;
     }
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
-        cx->runtime->structuredCloneCallbacks;
+        cx->runtime()->structuredCloneCallbacks;
     return ReadStructuredClone(cx, buf, nbytes, vp, callbacks, closure);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_WriteStructuredClone(JSContext *cx, jsval valueArg, uint64_t **bufp, size_t *nbytesp,
                         const JSStructuredCloneCallbacks *optionalCallbacks,
                         void *closure, jsval transferable)
 {
     RootedValue value(cx, valueArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
 
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
-        cx->runtime->structuredCloneCallbacks;
+        cx->runtime()->structuredCloneCallbacks;
     return WriteStructuredClone(cx, value, (uint64_t **) bufp, nbytesp,
                                 callbacks, closure, transferable);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearStructuredClone(const uint64_t *data, size_t nbytes)
 {
     return ClearStructuredClone(data, nbytes);
@@ -6454,17 +6454,17 @@ JS_StructuredClone(JSContext *cx, jsval 
     RootedValue value(cx, valueArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
 
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
-        cx->runtime->structuredCloneCallbacks;
+        cx->runtime()->structuredCloneCallbacks;
     JSAutoStructuredCloneBuffer buf;
     return buf.write(cx, value, callbacks, closure) &&
            buf.read(cx, vp, callbacks, closure);
 }
 
 void
 JSAutoStructuredCloneBuffer::clear()
 {
@@ -6762,17 +6762,17 @@ JS_ObjectIsDate(JSContext *cx, JSObject 
     return ObjectClassIs(obj, ESClass_Date, cx);
 }
 
 JS_PUBLIC_API(void)
 JS_ClearDateCaches(JSContext *cx)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    cx->runtime->dateTimeInfo.updateTimeZoneAdjustment();
+    cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
 }
 
 /************************************************************************/
 
 /*
  * Regular Expressions.
  */
 JS_PUBLIC_API(JSObject *)
@@ -7100,23 +7100,23 @@ JS_AbortIfWrongThread(JSRuntime *rt)
 {
     rt->abortIfWrongThread();
 }
 
 #ifdef JS_GC_ZEAL
 JS_PUBLIC_API(void)
 JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
 {
-    SetGCZeal(cx->runtime, zeal, frequency);
+    SetGCZeal(cx->runtime(), zeal, frequency);
 }
 
 JS_PUBLIC_API(void)
 JS_ScheduleGC(JSContext *cx, uint32_t count)
 {
-    cx->runtime->gcNextScheduled = count;
+    cx->runtime()->gcNextScheduled = count;
 }
 #endif
 
 JS_PUBLIC_API(void)
 JS_SetParallelCompilationEnabled(JSContext *cx, bool enabled)
 {
 #ifdef JS_ION
     ion::js_IonOptions.parallelCompilation = enabled;
@@ -7215,17 +7215,17 @@ JS_CallOnce(JSCallOnceType *once, JSInit
         return func();
     } else {
         return JS_TRUE;
     }
 #endif
 }
 
 AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
-  : down(cx->runtime->autoGCRooters), tag_(tag), stackTop(&cx->runtime->autoGCRooters)
+  : down(cx->runtime()->autoGCRooters), tag_(tag), stackTop(&cx->runtime()->autoGCRooters)
 {
     JS_ASSERT(this != *stackTop);
     *stackTop = this;
 }
 
 #ifdef DEBUG
 JS_PUBLIC_API(void)
 JS::AssertArgumentsAreSane(JSContext *cx, const JS::Value &value)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -819,17 +819,17 @@ array_toSource_impl(JSContext *cx, CallA
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, index, &hole, &elt)) {
             return false;
         }
 
         /* Get element's character string. */
         JSString *str;
         if (hole) {
-            str = cx->runtime->emptyString;
+            str = cx->runtime()->emptyString;
         } else {
             str = ValueToSource(cx, elt);
             if (!str)
                 return false;
         }
 
         /* Append element to buffer. */
         if (!sb.append(str))
@@ -2881,21 +2881,21 @@ EnsureNewArrayElements(JSContext *cx, JS
 template<bool allocateCapacity>
 static JS_ALWAYS_INLINE JSObject *
 NewArray(JSContext *cx, uint32_t length, JSObject *protoArg, NewObjectKind newKind = GenericObject)
 {
     gc::AllocKind allocKind = GuessArrayGCKind(length);
     JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayClass));
     allocKind = GetBackgroundAllocKind(allocKind);
 
-    NewObjectCache &cache = cx->runtime->newObjectCache;
+    NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
     if (newKind == GenericObject &&
-        !cx->compartment->objectMetadataCallback &&
+        !cx->compartment()->objectMetadataCallback &&
         cache.lookupGlobal(&ArrayClass, cx->global(), allocKind, &entry))
     {
         RootedObject obj(cx, cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, &ArrayClass)));
         if (obj) {
             /* Fixup the elements pointer and length, which may be incorrect. */
             obj->setFixedElements();
             JSObject::setArrayLength(cx, obj, length);
             if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -149,26 +149,26 @@ js::InitCommonNames(JSContext *cx)
 #define COMMON_NAME_INFO(idpart, id, text) { js_##idpart##_str, sizeof(text) - 1 },
         FOR_EACH_COMMON_PROPERTYNAME(COMMON_NAME_INFO)
 #undef COMMON_NAME_INFO
 #define COMMON_NAME_INFO(name, code, init) { js_##name##_str, sizeof(#name) - 1 },
         JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INFO)
 #undef COMMON_NAME_INFO
     };
 
-    FixedHeapPtr<PropertyName> *names = &cx->runtime->firstCachedName;
+    FixedHeapPtr<PropertyName> *names = &cx->runtime()->firstCachedName;
     for (size_t i = 0; i < ArrayLength(cachedNames); i++, names++) {
         JSAtom *atom = Atomize(cx, cachedNames[i].str, cachedNames[i].length, InternAtom);
         if (!atom)
             return false;
         names->init(atom->asPropertyName());
     }
-    JS_ASSERT(uintptr_t(names) == uintptr_t(&cx->runtime->atomState + 1));
+    JS_ASSERT(uintptr_t(names) == uintptr_t(&cx->runtime()->atomState + 1));
 
-    cx->runtime->emptyString = cx->names().empty;
+    cx->runtime()->emptyString = cx->names().empty;
     return true;
 }
 
 void
 js::FinishCommonNames(JSRuntime *rt)
 {
     rt->emptyString = NULL;
 #ifdef DEBUG
@@ -209,17 +209,17 @@ js::SweepAtoms(JSRuntime *rt)
 
 bool
 AtomIsInterned(JSContext *cx, JSAtom *atom)
 {
     /* We treat static strings as interned because they're never collected. */
     if (StaticStrings::isStatic(atom))
         return true;
 
-    AtomSet::Ptr p = cx->runtime->atoms.lookup(atom);
+    AtomSet::Ptr p = cx->runtime()->atoms.lookup(atom);
     if (!p)
         return false;
 
     return p->isTagged();
 }
 
 enum OwnCharsBehavior
 {
@@ -233,28 +233,28 @@ enum OwnCharsBehavior
  * longer owns the memory and this method is responsible for freeing the memory.
  */
 JS_ALWAYS_INLINE
 static JSAtom *
 AtomizeAndTakeOwnership(JSContext *cx, jschar *tbchars, size_t length, InternBehavior ib)
 {
     JS_ASSERT(tbchars[length] == 0);
 
-    if (JSAtom *s = cx->runtime->staticStrings.lookup(tbchars, length)) {
+    if (JSAtom *s = cx->runtime()->staticStrings.lookup(tbchars, length)) {
         js_free(tbchars);
         return s;
     }
 
     /*
      * If a GC occurs at js_NewStringCopy then |p| will still have the correct
      * hash, allowing us to avoid rehashing it. Even though the hash is
      * unchanged, we need to re-lookup the table position because a last-ditch
      * GC will potentially free some table entries.
      */
-    AtomSet& atoms = cx->runtime->atoms;
+    AtomSet& atoms = cx->runtime()->atoms;
     AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         js_free(tbchars);
         return atom;
     }
@@ -279,27 +279,27 @@ AtomizeAndTakeOwnership(JSContext *cx, j
 }
 
 /* |tbchars| must not point into an inline or short string. */
 template <AllowGC allowGC>
 JS_ALWAYS_INLINE
 static JSAtom *
 AtomizeAndCopyChars(JSContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
 {
-    if (JSAtom *s = cx->runtime->staticStrings.lookup(tbchars, length))
+    if (JSAtom *s = cx->runtime()->staticStrings.lookup(tbchars, length))
          return s;
 
     /*
      * If a GC occurs at js_NewStringCopy then |p| will still have the correct
      * hash, allowing us to avoid rehashing it. Even though the hash is
      * unchanged, we need to re-lookup the table position because a last-ditch
      * GC will potentially free some table entries.
      */
 
-    AtomSet& atoms = cx->runtime->atoms;
+    AtomSet& atoms = cx->runtime()->atoms;
     AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         return atom;
     }
 
@@ -325,17 +325,17 @@ JSAtom *
 js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::DoNotInternAtom */)
 {
     if (str->isAtom()) {
         JSAtom &atom = str->asAtom();
         /* N.B. static atoms are effectively always interned. */
         if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
             return &atom;
 
-        AtomSet::Ptr p = cx->runtime->atoms.lookup(AtomHasher::Lookup(&atom));
+        AtomSet::Ptr p = cx->runtime()->atoms.lookup(AtomHasher::Lookup(&atom));
         JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
         JS_ASSERT(p->asPtr() == &atom);
         JS_ASSERT(ib == InternAtom);
         p->setTagged(bool(ib));
         return &atom;
     }
 
     const jschar *chars = str->getChars(cx);
@@ -471,17 +471,17 @@ js::XDRAtom(XDRState<mode> *xdr, Mutable
     if (nchars <= ArrayLength(stackChars)) {
         chars = stackChars;
     } else {
         /*
          * This is very uncommon. Don't use the tempLifoAlloc arena for this as
          * most allocations here will be bigger than tempLifoAlloc's default
          * chunk size.
          */
-        chars = cx->runtime->pod_malloc<jschar>(nchars);
+        chars = cx->runtime()->pod_malloc<jschar>(nchars);
         if (!chars)
             return false;
     }
 
     JS_ALWAYS_TRUE(xdr->codeChars(chars, nchars));
     atom = AtomizeChars<CanGC>(cx, chars, nchars);
     if (chars != stackChars)
         js_free(chars);
--- a/js/src/jsatominlines.h
+++ b/js/src/jsatominlines.h
@@ -179,25 +179,25 @@ TypeName(JSType type, JSRuntime *rt)
                      sizeof(JSAtomState));
     JS_STATIC_ASSERT(JSTYPE_VOID == 0);
     return (&rt->atomState.undefined)[type];
 }
 
 inline Handle<PropertyName*>
 TypeName(JSType type, JSContext *cx)
 {
-    return TypeName(type, cx->runtime);
+    return TypeName(type, cx->runtime());
 }
 
 inline Handle<PropertyName*>
 ClassName(JSProtoKey key, JSContext *cx)
 {
     JS_ASSERT(key < JSProto_LIMIT);
     JS_STATIC_ASSERT(offsetof(JSAtomState, Null) +
                      JSProto_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <=
                      sizeof(JSAtomState));
     JS_STATIC_ASSERT(JSProto_Null == 0);
-    return (&cx->runtime->atomState.Null)[key];
+    return (&cx->runtime()->atomState.Null)[key];
 }
 
 } // namespace js
 
 #endif /* jsatominlines_h___ */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -179,17 +179,17 @@ js_InitBooleanClass(JSContext *cx, Handl
         return NULL;
 
     return booleanProto;
 }
 
 JSString *
 js_BooleanToString(JSContext *cx, JSBool b)
 {
-    return b ? cx->runtime->atomState.true_ : cx->runtime->atomState.false_;
+    return b ? cx->runtime()->atomState.true_ : cx->runtime()->atomState.false_;
 }
 
 JS_PUBLIC_API(bool)
 js::ToBooleanSlow(const Value &v)
 {
     if (v.isString())
         return v.toString()->length() != 0;
 
@@ -198,15 +198,15 @@ js::ToBooleanSlow(const Value &v)
 }
 
 bool
 js::BooleanGetPrimitiveValueSlow(JSContext *cx, HandleObject obj, Value *vp)
 {
     InvokeArgsGuard ag;
     if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
         return false;
-    ag.setCallee(cx->compartment->maybeGlobal()->booleanValueOf());
+    ag.setCallee(cx->compartment()->maybeGlobal()->booleanValueOf());
     ag.setThis(ObjectValue(*obj));
     if (!Invoke(cx, ag))
         return false;
     *vp = ag.rval();
     return true;
 }
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -162,43 +162,43 @@ JSRuntime::setJitHardening(bool enabled)
     if (execAlloc_)
         execAlloc_->setRandomize(enabled);
 }
 
 JSC::ExecutableAllocator *
 JSRuntime::createExecutableAllocator(JSContext *cx)
 {
     JS_ASSERT(!execAlloc_);
-    JS_ASSERT(cx->runtime == this);
+    JS_ASSERT(cx->runtime() == this);
 
     JSC::AllocationBehavior randomize =
         jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic;
     execAlloc_ = js_new<JSC::ExecutableAllocator>(randomize);
     if (!execAlloc_)
         js_ReportOutOfMemory(cx);
     return execAlloc_;
 }
 
 WTF::BumpPointerAllocator *
 JSRuntime::createBumpPointerAllocator(JSContext *cx)
 {
     JS_ASSERT(!bumpAlloc_);
-    JS_ASSERT(cx->runtime == this);
+    JS_ASSERT(cx->runtime() == this);
 
     bumpAlloc_ = js_new<WTF::BumpPointerAllocator>();
     if (!bumpAlloc_)
         js_ReportOutOfMemory(cx);
     return bumpAlloc_;
 }
 
 MathCache *
 JSRuntime::createMathCache(JSContext *cx)
 {
     JS_ASSERT(!mathCache_);
-    JS_ASSERT(cx->runtime == this);
+    JS_ASSERT(cx->runtime() == this);
 
     MathCache *newMathCache = js_new<MathCache>();
     if (!newMathCache) {
         js_ReportOutOfMemory(cx);
         return NULL;
     }
 
     mathCache_ = newMathCache;
@@ -224,17 +224,17 @@ js::CloneFunctionAtCallsite(JSContext *c
     JS_ASSERT(cx->typeInferenceEnabled());
     JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite);
     JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
     JS_ASSERT(types::UseNewTypeForClone(fun));
 
     typedef CallsiteCloneKey Key;
     typedef CallsiteCloneTable Table;
 
-    Table &table = cx->compartment->callsiteClones;
+    Table &table = cx->compartment()->callsiteClones;
     if (!table.initialized() && !table.init())
         return NULL;
 
     uint32_t offset = pc - script->code;
     void* originalScript = script;
     void* originalFun = fun;
     SkipRoot skipScript(cx, &originalScript);
     SkipRoot skipFun(cx, &originalFun);
@@ -328,17 +328,17 @@ js::NewContext(JSRuntime *rt, size_t sta
     }
 
     return cx;
 }
 
 void
 js::DestroyContext(JSContext *cx, DestroyContextMode mode)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     JS_AbortIfWrongThread(rt);
 
 #ifdef JS_THREADSAFE
     if (cx->outstandingRequests != 0)
         MOZ_CRASH();
 #endif
 
     if (mode != DCM_NEW_FAILED) {
@@ -424,28 +424,28 @@ ReportError(JSContext *cx, const char *m
      * If an exception was raised, then we call the debugErrorHook
      * (if present) to give it a chance to see the error before it
      * propagates out of scope.  This is needed for compatibility
      * with the old scheme.
      */
     if (!JS_IsRunning(cx) ||
         !js_ErrorToException(cx, message, reportp, callback, userRef)) {
         js_ReportErrorAgain(cx, message, reportp);
-    } else if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) {
+    } else if (JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook) {
         /*
          * If we've already chewed up all the C stack, don't call into the
          * error reporter since this may trigger an infinite recursion where
          * the reporter triggers an over-recursion.
          */
         int stackDummy;
         if (!JS_CHECK_STACK_SIZE(cx->mainThread().nativeStackLimit, &stackDummy))
             return;
 
         if (cx->errorReporter)
-            hook(cx, message, reportp, cx->runtime->debugHooks.debugErrorHookData);
+            hook(cx, message, reportp, cx->runtime()->debugHooks.debugErrorHookData);
     }
 }
 
 /*
  * The given JSErrorReport object have been zeroed and must not outlive
  * cx->fp() (otherwise report->originPrincipals may become invalid).
  */
 static void
@@ -471,17 +471,17 @@ PopulateReportBlame(JSContext *cx, JSErr
  * error reporter directly.
  *
  * Furthermore, callers of js_ReportOutOfMemory (viz., malloc) assume a GC does
  * not occur, so GC must be avoided or suppressed.
  */
 void
 js_ReportOutOfMemory(JSContext *cx)
 {
-    cx->runtime->hadOutOfMemory = true;
+    cx->runtime()->hadOutOfMemory = true;
 
     if (JS_IsRunning(cx)) {
         cx->setPendingException(StringValue(cx->names().outOfMemory));
         return;
     }
 
     /* Get the message for this error, but we don't expand any arguments. */
     const JSErrorFormatString *efs =
@@ -956,18 +956,18 @@ js_ReportErrorAgain(JSContext *cx, const
 
     onError = cx->errorReporter;
 
     /*
      * If debugErrorHook is present then we give it a chance to veto
      * sending the error on to the regular ErrorReporter.
      */
     if (onError) {
-        JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
-        if (hook && !hook(cx, message, reportp, cx->runtime->debugHooks.debugErrorHookData))
+        JSDebugErrorHook hook = cx->runtime()->debugHooks.debugErrorHook;
+        if (hook && !hook(cx, message, reportp, cx->runtime()->debugHooks.debugErrorHookData))
             onError = NULL;
     }
     if (onError)
         onError(cx, message, reportp);
 }
 
 void
 js_ReportIsNotDefined(JSContext *cx, const char *name)
@@ -1066,17 +1066,17 @@ js_GetErrorMessage(void *userRef, const 
     return NULL;
 }
 
 JSBool
 js_InvokeOperationCallback(JSContext *cx)
 {
     JS_ASSERT_REQUEST_DEPTH(cx);
 
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     JS_ASSERT(rt->interrupt != 0);
 
     /*
      * Reset the callback counter first, then run GC and yield. If another
      * thread is racing us here we will accumulate another callback request
      * which will be serviced at the next opportunity.
      */
     JS_ATOMIC_SET(&rt->interrupt, 0);
@@ -1108,17 +1108,17 @@ js_InvokeOperationCallback(JSContext *cx
     JSOperationCallback cb = cx->operationCallback;
     return !cb || cb(cx);
 }
 
 JSBool
 js_HandleExecutionInterrupt(JSContext *cx)
 {
     JSBool result = JS_TRUE;
-    if (cx->runtime->interrupt)
+    if (cx->runtime()->interrupt)
         result = js_InvokeOperationCallback(cx) && result;
     return result;
 }
 
 JSContext::JSContext(JSRuntime *rt)
   : ContextFriendFields(rt),
     defaultVersion(JSVERSION_DEFAULT),
     hasVersionOverride(false),
@@ -1218,17 +1218,17 @@ JSRuntime::getDefaultLocale()
  * the caller must subsequently take an error path. If wrapping fails, it will
  * set a new (uncatchable) exception to be used in place of the original.
  */
 void
 JSContext::wrapPendingException()
 {
     RootedValue value(this, getPendingException());
     clearPendingException();
-    if (compartment->wrap(this, &value))
+    if (compartment()->wrap(this, &value))
         setPendingException(value);
 }
 
 
 void
 JSContext::enterGenerator(JSGenerator *gen)
 {
     JS_ASSERT(!gen->prevGenerator);
@@ -1243,26 +1243,26 @@ JSContext::leaveGenerator(JSGenerator *g
     innermostGenerator_ = innermostGenerator_->prevGenerator;
     gen->prevGenerator = NULL;
 }
 
 
 bool
 JSContext::runningWithTrustedPrincipals() const
 {
-    return !compartment || compartment->principals == runtime->trustedPrincipals();
+    return !compartment() || compartment()->principals == runtime()->trustedPrincipals();
 }
 
 bool
 JSContext::saveFrameChain()
 {
     if (!stack.saveFrameChain())
         return false;
 
-    if (!savedFrameChains_.append(SavedFrameChain(compartment, enterCompartmentDepth_))) {
+    if (!savedFrameChains_.append(SavedFrameChain(compartment(), enterCompartmentDepth_))) {
         stack.restoreFrameChain();
         return false;
     }
 
     if (defaultCompartmentObject_)
         setCompartment(defaultCompartmentObject_->compartment());
     else
         setCompartment(NULL);
@@ -1458,20 +1458,20 @@ JSContext::mark(JSTracer *trc)
     MarkValueRoot(trc, &iterValue, "iterValue");
 }
 
 #if defined JS_THREADSAFE && defined DEBUG
 
 JS::AutoCheckRequestDepth::AutoCheckRequestDepth(JSContext *cx)
     : cx(cx)
 {
-    JS_ASSERT(cx->runtime->requestDepth || cx->runtime->isHeapBusy());
-    cx->runtime->assertValidThread();
-    cx->runtime->checkRequestDepth++;
+    JS_ASSERT(cx->runtime()->requestDepth || cx->runtime()->isHeapBusy());
+    cx->runtime()->assertValidThread();
+    cx->runtime()->checkRequestDepth++;
 }
 
 JS::AutoCheckRequestDepth::~AutoCheckRequestDepth()
 {
-    JS_ASSERT(cx->runtime->checkRequestDepth != 0);
-    cx->runtime->checkRequestDepth--;
+    JS_ASSERT(cx->runtime()->checkRequestDepth != 0);
+    cx->runtime()->checkRequestDepth--;
 }
 
 #endif
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1506,18 +1506,21 @@ FreeOp::free_(void *p)
 struct JSContext : js::ContextFriendFields,
                    public mozilla::LinkedListElement<JSContext>,
                    public js::MallocProvider<JSContext>
 {
     explicit JSContext(JSRuntime *rt);
     JSContext *thisDuringConstruction() { return this; }
     ~JSContext();
 
+    JSRuntime *runtime() const { return runtime_; }
+    JSCompartment *compartment() const { return compartment_; }
+
     inline JS::Zone *zone() const;
-    js::PerThreadData &mainThread() { return runtime->mainThread; }
+    js::PerThreadData &mainThread() { return runtime()->mainThread; }
 
   private:
     /* See JSContext::findVersion. */
     JSVersion           defaultVersion;      /* script compilation version */
     JSVersion           versionOverride;     /* supercedes defaultVersion when valid */
     bool                hasVersionOverride;
 
     /* Exception state -- the exception member is a GC root by definition. */
@@ -1689,23 +1692,23 @@ struct JSContext : js::ContextFriendFiel
     bool hasOption(unsigned opt) const {
         JS_ASSERT((opt & JSOPTION_MASK) == opt);
         return !!(options_ & opt);
     }
 
     bool hasStrictOption() const { return hasOption(JSOPTION_STRICT); }
     bool hasWErrorOption() const { return hasOption(JSOPTION_WERROR); }
 
-    js::LifoAlloc &tempLifoAlloc() { return runtime->tempLifoAlloc; }
+    js::LifoAlloc &tempLifoAlloc() { return runtime()->tempLifoAlloc; }
     inline js::LifoAlloc &analysisLifoAlloc();
     inline js::LifoAlloc &typeLifoAlloc();
 
     inline js::PropertyTree &propertyTree();
 
-    js::PropertyCache &propertyCache() { return runtime->propertyCache; }
+    js::PropertyCache &propertyCache() { return runtime()->propertyCache; }
 
 #ifdef JS_THREADSAFE
     unsigned            outstandingRequests;/* number of JS_BeginRequest calls
                                                without the corresponding
                                                JS_EndRequest. */
 #endif
 
     /* Stored here to avoid passing it around as a parameter. */
@@ -1737,17 +1740,17 @@ struct JSContext : js::ContextFriendFiel
     /* Innermost-executing generator or null if no generator are executing. */
     JSGenerator *innermostGenerator_;
   public:
     JSGenerator *innermostGenerator() const { return innermostGenerator_; }
     void enterGenerator(JSGenerator *gen);
     void leaveGenerator(JSGenerator *gen);
 
     void *onOutOfMemory(void *p, size_t nbytes) {
-        return runtime->onOutOfMemory(p, nbytes, this);
+        return runtime()->onOutOfMemory(p, nbytes, this);
     }
     void updateMallocCounter(size_t nbytes);
     void reportAllocationOverflow() {
         js_ReportAllocationOverflow(this);
     }
 
     bool isExceptionPending() {
         return throwing;
@@ -1760,17 +1763,17 @@ struct JSContext : js::ContextFriendFiel
 
     void setPendingException(js::Value v);
 
     void clearPendingException() {
         throwing = false;
         exception.setUndefined();
     }
 
-    JSAtomState & names() { return runtime->atomState; }
+    JSAtomState & names() { return runtime()->atomState; }
 
 #ifdef DEBUG
     /*
      * Controls whether a quadratic-complexity assertion is performed during
      * stack iteration; defaults to true.
      */
     bool stackIterAssertionEnabled;
 #endif
@@ -2078,17 +2081,17 @@ js_ReportValueErrorFlags(JSContext *cx, 
 
 #define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2)     \
     ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber,          \
                                     spindex, v, fallback, arg1, arg2))
 
 extern const JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
 
 #ifdef JS_THREADSAFE
-# define JS_ASSERT_REQUEST_DEPTH(cx)  JS_ASSERT((cx)->runtime->requestDepth >= 1)
+# define JS_ASSERT_REQUEST_DEPTH(cx)  JS_ASSERT((cx)->runtime()->requestDepth >= 1)
 #else
 # define JS_ASSERT_REQUEST_DEPTH(cx)  ((void) 0)
 #endif
 
 /*
  * Invoke the operation callback and return false if the current execution
  * is to be terminated.
  */
@@ -2102,17 +2105,17 @@ js_HandleExecutionInterrupt(JSContext *c
  * If the operation callback flag was set, call the operation callback.
  * This macro can run the full GC. Return true if it is OK to continue and
  * false otherwise.
  */
 static MOZ_ALWAYS_INLINE bool
 JS_CHECK_OPERATION_LIMIT(JSContext *cx)
 {
     JS_ASSERT_REQUEST_DEPTH(cx);
-    return !cx->runtime->interrupt || js_InvokeOperationCallback(cx);
+    return !cx->runtime()->interrupt || js_InvokeOperationCallback(cx);
 }
 
 namespace js {
 
 /************************************************************************/
 
 static JS_ALWAYS_INLINE void
 MakeRangeGCSafe(Value *vec, size_t len)
@@ -2307,17 +2310,17 @@ class AutoAssertNoException
  * FIXME bug 647103 - replace these *AllocPolicy names.
  */
 class RuntimeAllocPolicy
 {
     JSRuntime *const runtime;
 
   public:
     RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
-    RuntimeAllocPolicy(JSContext *cx) : runtime(cx->runtime) {}
+    RuntimeAllocPolicy(JSContext *cx) : runtime(cx->runtime()) {}
     void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
     void *calloc_(size_t bytes) { return runtime->calloc_(bytes); }
     void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
     void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const {}
 };
 
 /*
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -106,17 +106,17 @@ NewObjectCache::fillType(EntryIndex entr
     JS_ASSERT(obj->type() == type);
     return fill(entry, clasp, type, kind, obj);
 }
 
 inline JSObject *
 NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
 {
     // The new object cache does not account for metadata attached via callbacks.
-    JS_ASSERT(!cx->compartment->objectMetadataCallback);
+    JS_ASSERT(!cx->compartment()->objectMetadataCallback);
 
     JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
     Entry *entry = &entries[entry_];
 
     JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
     if (obj) {
         copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject), entry->kind);
         Probes::createObject(cx, obj);
@@ -148,17 +148,17 @@ struct PreserveRegsGuard
 #ifdef JS_CRASH_DIAGNOSTICS
 class CompartmentChecker
 {
     JSContext *context;
     JSCompartment *compartment;
 
   public:
     explicit CompartmentChecker(JSContext *cx)
-      : context(cx), compartment(cx->compartment)
+      : context(cx), compartment(cx->compartment())
     {}
 
     /*
      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      * compartment mismatches.
      */
     static void fail(JSCompartment *c1, JSCompartment *c2) {
         printf("*** Compartment mismatch %p vs. %p\n", (void *) c1, (void *) c2);
@@ -174,17 +174,17 @@ class CompartmentChecker
     static void check(JSCompartment *c1, JSCompartment *c2) {
         JS_ASSERT(c1 != c1->rt->atomsCompartment);
         JS_ASSERT(c2 != c2->rt->atomsCompartment);
         if (c1 != c2)
             fail(c1, c2);
     }
 
     void check(JSCompartment *c) {
-        if (c && c != context->runtime->atomsCompartment) {
+        if (c && c != context->runtime()->atomsCompartment) {
             if (!compartment)
                 compartment = c;
             else if (c != compartment)
                 fail(compartment, c);
         }
     }
 
     void checkZone(JS::Zone *z) {
@@ -260,18 +260,18 @@ class CompartmentChecker
 };
 #endif /* JS_CRASH_DIAGNOSTICS */
 
 /*
  * Don't perform these checks when called from a finalizer. The checking
  * depends on other objects not having been swept yet.
  */
 #define START_ASSERT_SAME_COMPARTMENT()                                       \
-    JS_ASSERT(cx->compartment->zone() == cx->zone());                         \
-    if (cx->runtime->isHeapBusy())                                            \
+    JS_ASSERT(cx->compartment()->zone() == cx->zone());                       \
+    if (cx->runtime()->isHeapBusy())                                          \
         return;                                                               \
     CompartmentChecker c(cx)
 
 template <class T1> inline void
 assertSameCompartment(JSContext *cx, const T1 &t1)
 {
 #ifdef JS_CRASH_DIAGNOSTICS
     START_ASSERT_SAME_COMPARTMENT();
@@ -500,17 +500,17 @@ JSContext::maybeOverrideVersion(JSVersio
     }
     overrideVersion(newVersion);
     return true;
 }
 
 inline js::LifoAlloc &
 JSContext::analysisLifoAlloc()
 {
-    return compartment->analysisLifoAlloc;
+    return compartment()->analysisLifoAlloc;
 }
 
 inline js::LifoAlloc &
 JSContext::typeLifoAlloc()
 {
     return zone()->types.typeLifoAlloc;
 }
 
@@ -520,17 +520,17 @@ JSContext::setPendingException(js::Value
     this->throwing = true;
     this->exception = v;
     js::assertSameCompartment(this, v);
 }
 
 inline js::PropertyTree&
 JSContext::propertyTree()
 {
-    return compartment->propertyTree;
+    return compartment()->propertyTree;
 }
 
 inline void
 JSContext::setDefaultCompartmentObject(JSObject *obj)
 {
     defaultCompartmentObject_ = obj;
 
     if (!hasEnteredCompartment()) {
@@ -565,17 +565,17 @@ JSContext::enterCompartment(JSCompartmen
 }
 
 inline void
 JSContext::leaveCompartment(JSCompartment *oldCompartment)
 {
     JS_ASSERT(hasEnteredCompartment());
     enterCompartmentDepth_--;
 
-    compartment->leave();
+    compartment()->leave();
 
     /*
      * Before we entered the current compartment, 'compartment' was
      * 'oldCompartment', so we might want to simply set it back. However, we
      * currently have this terrible scheme whereby defaultCompartmentObject_ can
      * be updated while enterCompartmentDepth_ > 0. In this case, oldCompartment
      * != defaultCompartmentObject_->compartment and we must ignore
      * oldCompartment.
@@ -587,27 +587,27 @@ JSContext::leaveCompartment(JSCompartmen
 
     if (throwing)
         wrapPendingException();
 }
 
 inline JS::Zone *
 JSContext::zone() const
 {
-    JS_ASSERT_IF(!compartment, !zone_);
-    JS_ASSERT_IF(compartment, compartment->zone() == zone_);
+    JS_ASSERT_IF(!compartment(), !zone_);
+    JS_ASSERT_IF(compartment(), compartment()->zone() == zone_);
     return zone_;
 }
 
 inline void
 JSContext::updateMallocCounter(size_t nbytes)
 {
-    runtime->updateMallocCounter(zone(), nbytes);
+    runtime()->updateMallocCounter(zone(), nbytes);
 }
 
 inline void
 JSContext::setCompartment(JSCompartment *comp)
 {
-    compartment = comp;
+    compartment_ = comp;
     zone_ = comp ? comp->zone() : NULL;
 }
 
 #endif /* jscntxtinlines_h___ */
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -83,17 +83,17 @@ JSCompartment::init(JSContext *cx)
 {
     /*
      * As a hack, we clear our timezone cache every time we create a new
      * compartment.  This ensures that the cache is always relatively fresh, but
      * shouldn't interfere with benchmarks which create tons of date objects
      * (unless they also create tons of iframes, which seems unlikely).
      */
     if (cx)
-        cx->runtime->dateTimeInfo.updateTimeZoneAdjustment();
+        cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
 
     activeAnalysis = false;
 
     if (!crossCompartmentWrappers.init(0))
         return false;
 
     if (!regExps.init(cx))
         return false;
@@ -113,35 +113,35 @@ JSRuntime::createIonRuntime(JSContext *c
 
     if (!ionRuntime_)
         return NULL;
 
     if (!ionRuntime_->initialize(cx)) {
         js_delete(ionRuntime_);
         ionRuntime_ = NULL;
 
-        if (cx->runtime->atomsCompartment->ionCompartment_) {
-            js_delete(cx->runtime->atomsCompartment->ionCompartment_);
-            cx->runtime->atomsCompartment->ionCompartment_ = NULL;
+        if (cx->runtime()->atomsCompartment->ionCompartment_) {
+            js_delete(cx->runtime()->atomsCompartment->ionCompartment_);
+            cx->runtime()->atomsCompartment->ionCompartment_ = NULL;
         }
 
         return NULL;
     }
 
     return ionRuntime_;
 }
 
 bool
 JSCompartment::ensureIonCompartmentExists(JSContext *cx)
 {
     using namespace js::ion;
     if (ionCompartment_)
         return true;
 
-    IonRuntime *ionRuntime = cx->runtime->getIonRuntime(cx);
+    IonRuntime *ionRuntime = cx->runtime()->getIonRuntime(cx);
     if (!ionRuntime)
         return false;
 
     /* Set the compartment early, so linking works. */
     ionCompartment_ = cx->new_<IonCompartment>(ionRuntime);
 
     if (!ionCompartment_)
         return false;
@@ -154,23 +154,23 @@ JSCompartment::ensureIonCompartmentExist
 
     return true;
 }
 #endif
 
 static bool
 WrapForSameCompartment(JSContext *cx, HandleObject obj, MutableHandleValue vp)
 {
-    JS_ASSERT(cx->compartment == obj->compartment());
-    if (!cx->runtime->sameCompartmentWrapObjectCallback) {
+    JS_ASSERT(cx->compartment() == obj->compartment());
+    if (!cx->runtime()->sameCompartmentWrapObjectCallback) {
         vp.setObject(*obj);
         return true;
     }
 
-    JSObject *wrapped = cx->runtime->sameCompartmentWrapObjectCallback(cx, obj);
+    JSObject *wrapped = cx->runtime()->sameCompartmentWrapObjectCallback(cx, obj);
     if (!wrapped)
         return false;
     vp.setObject(*wrapped);
     return true;
 }
 
 bool
 JSCompartment::putWrapper(const CrossCompartmentKey &wrapped, const js::Value &wrapper)
@@ -182,18 +182,18 @@ JSCompartment::putWrapper(const CrossCom
     JS_ASSERT_IF(wrapped.kind == CrossCompartmentKey::StringWrapper, wrapper.isString());
     JS_ASSERT_IF(wrapped.kind != CrossCompartmentKey::StringWrapper, wrapper.isObject());
     return crossCompartmentWrappers.put(wrapped, wrapper);
 }
 
 bool
 JSCompartment::wrap(JSContext *cx, MutableHandleValue vp, HandleObject existingArg)
 {
-    JS_ASSERT(cx->compartment == this);
-    JS_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment);
+    JS_ASSERT(cx->compartment() == this);
+    JS_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment());
     JS_ASSERT_IF(existingArg, vp.isObject());
     JS_ASSERT_IF(existingArg, IsDeadProxyObject(existingArg));
 
     unsigned flags = 0;
 
     JS_CHECK_CHROME_RECURSION(cx, return false);
 
     AutoDisableProxyCheck adpc(rt);
@@ -206,17 +206,17 @@ JSCompartment::wrap(JSContext *cx, Mutab
         JSString *str = vp.toString();
 
         /* If the string is already in this compartment, we are done. */
         if (str->zone() == zone())
             return true;
 
         /* If the string is an atom, we don't have to copy. */
         if (str->isAtom()) {
-            JS_ASSERT(str->zone() == cx->runtime->atomsCompartment->zone());
+            JS_ASSERT(str->zone() == cx->runtime()->atomsCompartment->zone());
             return true;
         }
     }
 
     /*
      * Wrappers should really be parented to the wrapped parent of the wrapped
      * object, but in that case a wrapped global object would have a NULL
      * parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead,
@@ -237,18 +237,18 @@ JSCompartment::wrap(JSContext *cx, Mutab
             return js_FindClassObject(cx, JSProto_StopIteration, vp);
 
         /* Unwrap the object, but don't unwrap outer windows. */
         obj = UncheckedUnwrap(obj, /* stopAtOuter = */ true, &flags);
 
         if (obj->compartment() == this)
             return WrapForSameCompartment(cx, obj, vp);
 
-        if (cx->runtime->preWrapObjectCallback) {
-            obj = cx->runtime->preWrapObjectCallback(cx, global, obj, flags);
+        if (cx->runtime()->preWrapObjectCallback) {
+            obj = cx->runtime()->preWrapObjectCallback(cx, global, obj, flags);
             if (!obj)
                 return false;
         }
 
         if (obj->compartment() == this)
             return WrapForSameCompartment(cx, obj, vp);
         vp.setObject(*obj);
 
@@ -316,17 +316,17 @@ JSCompartment::wrap(JSContext *cx, Mutab
     }
 
     /*
      * We hand in the original wrapped object into the wrap hook to allow
      * the wrap hook to reason over what wrappers are currently applied
      * to the object.
      */
     RootedObject wrapper(cx);
-    wrapper = cx->runtime->wrapObjectCallback(cx, existing, obj, proto, global, flags);
+    wrapper = cx->runtime()->wrapObjectCallback(cx, existing, obj, proto, global, flags);
     if (!wrapper)
         return false;
 
     // We maintain the invariant that the key in the cross-compartment wrapper
     // map is always directly wrapped by the value.
     JS_ASSERT(Wrapper::wrappedObject(wrapper) == &key.get().toObject());
 
     vp.setObject(*wrapper);
@@ -636,28 +636,28 @@ JSCompartment::setDebugModeFromC(JSConte
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
             return false;
         }
     }
 
     debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0);
     JS_ASSERT(debugMode() == enabledAfter);
     if (enabledBefore != enabledAfter) {
-        updateForDebugMode(cx->runtime->defaultFreeOp(), dmgc);
+        updateForDebugMode(cx->runtime()->defaultFreeOp(), dmgc);
         if (!enabledAfter)
             DebugScopes::onCompartmentLeaveDebugMode(this);
     }
     return true;
 }
 
 void
 JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeGC &dmgc)
 {
     for (ContextIter acx(rt); !acx.done(); acx.next()) {
-        if (acx->compartment == this)
+        if (acx->compartment() == this)
             acx->updateJITEnabled();
     }
 
 #ifdef JS_ION
     JS_ASSERT_IF(debugMode(), !hasScriptsOnStack());
 
     // When we change a compartment's debug mode, whether we're turning it
     // on or off, we must always throw away all analyses: debug mode
@@ -676,33 +676,33 @@ JSCompartment::updateForDebugMode(FreeOp
     if (!rt->isHeapBusy())
         dmgc.scheduleGC(zone());
 #endif
 }
 
 bool
 JSCompartment::addDebuggee(JSContext *cx, js::GlobalObject *global)
 {
-    AutoDebugModeGC dmgc(cx->runtime);
+    AutoDebugModeGC dmgc(cx->runtime());
     return addDebuggee(cx, global, dmgc);
 }
 
 bool
 JSCompartment::addDebuggee(JSContext *cx,
                            js::GlobalObject *global,
                            AutoDebugModeGC &dmgc)
 {
     bool wasEnabled = debugMode();
     if (!debuggees.put(global)) {
         js_ReportOutOfMemory(cx);
         return false;
     }
     debugModeBits |= DebugFromJS;
     if (!wasEnabled) {
-        updateForDebugMode(cx->runtime->defaultFreeOp(), dmgc);
+        updateForDebugMode(cx->runtime()->defaultFreeOp(), dmgc);
     }
     return true;
 }
 
 void
 JSCompartment::removeDebuggee(FreeOp *fop,
                               js::GlobalObject *global,
                               js::GlobalObjectSet::Enum *debuggeesEnum)
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -406,45 +406,45 @@ class js::AutoDebugModeGC
         PrepareZoneForGC(zone);
         needGC = true;
     }
 };
 
 inline bool
 JSContext::typeInferenceEnabled() const
 {
-    return compartment->zone()->types.inferenceEnabled;
+    return compartment()->zone()->types.inferenceEnabled;
 }
 
 inline js::Handle<js::GlobalObject*>
 JSContext::global() const
 {
     /*
      * It's safe to use |unsafeGet()| here because any compartment that is
      * on-stack will be marked automatically, so there's no need for a read
      * barrier on it. Once the compartment is popped, the handle is no longer
      * safe to use.
      */
-    return js::Handle<js::GlobalObject*>::fromMarkedLocation(compartment->global_.unsafeGet());
+    return js::Handle<js::GlobalObject*>::fromMarkedLocation(compartment()->global_.unsafeGet());
 }
 
 namespace js {
 
 class AssertCompartmentUnchanged
 {
   public:
     AssertCompartmentUnchanged(JSContext *cx
                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : cx(cx), oldCompartment(cx->compartment)
+      : cx(cx), oldCompartment(cx->compartment())
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     ~AssertCompartmentUnchanged() {
-        JS_ASSERT(cx->compartment == oldCompartment);
+        JS_ASSERT(cx->compartment() == oldCompartment);
     }
 
   protected:
     JSContext * const cx;
     JSCompartment * const oldCompartment;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
--- a/js/src/jscompartmentinlines.h
+++ b/js/src/jscompartmentinlines.h
@@ -21,17 +21,17 @@ js::GlobalObject *
 JSCompartment::maybeGlobal() const
 {
     JS_ASSERT_IF(global_, global_->compartment() == this);
     return global_;
 }
 
 js::AutoCompartment::AutoCompartment(JSContext *cx, JSObject *target)
   : cx_(cx),
-    origin_(cx->compartment)
+    origin_(cx->compartment())
 {
     cx_->enterCompartment(target->compartment());
 }
 
 js::AutoCompartment::~AutoCompartment()
 {
     cx_->leaveCompartment(origin_);
 }
@@ -72,19 +72,19 @@ namespace js {
  */
 class AutoEnterAtomsCompartment
 {
     JSContext *cx;
     JSCompartment *oldCompartment;
   public:
     AutoEnterAtomsCompartment(JSContext *cx)
       : cx(cx),
-        oldCompartment(cx->compartment)
+        oldCompartment(cx->compartment())
     {
-        cx->setCompartment(cx->runtime->atomsCompartment);
+        cx->setCompartment(cx->runtime()->atomsCompartment);
     }
 
     ~AutoEnterAtomsCompartment()
     {
         cx->setCompartment(oldCompartment);
     }
 };
 
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1214,17 +1214,17 @@ date_parse(JSContext *cx, unsigned argc,
     if (!str)
         return false;
 
     JSLinearString *linearStr = str->ensureLinear(cx);
     if (!linearStr)
         return false;
 
     double result;
-    if (!date_parseString(linearStr, &result, &cx->runtime->dateTimeInfo)) {
+    if (!date_parseString(linearStr, &result, &cx->runtime()->dateTimeInfo)) {
         vp->setDouble(js_NaN);
         return true;
     }
 
     result = TimeClip(result);
     vp->setNumber(result);
     return true;
 }
@@ -1434,17 +1434,17 @@ date_getTime(JSContext *cx, unsigned arg
 }
 
 JS_ALWAYS_INLINE bool
 date_getYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     Value yearVal = thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
     if (yearVal.isInt32()) {
         /* Follow ECMA-262 to the letter, contrary to IE JScript. */
         int year = yearVal.toInt32() - 1900;
         args.rval().setInt32(year);
     } else {
         args.rval().set(yearVal);
@@ -1461,17 +1461,17 @@ date_getYear(JSContext *cx, unsigned arg
 }
 
 JS_ALWAYS_INLINE bool
 date_getFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR));
     return true;
 }
 
 static JSBool
 date_getFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1500,17 +1500,17 @@ date_getUTCFullYear(JSContext *cx, unsig
 }
 
 JS_ALWAYS_INLINE bool
 date_getMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH));
     return true;
 }
 
 static JSBool
 date_getMonth(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1536,17 +1536,17 @@ date_getUTCMonth(JSContext *cx, unsigned
 }
 
 JS_ALWAYS_INLINE bool
 date_getDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE));
     return true;
 }
 
 static JSBool
 date_getDate(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1575,17 +1575,17 @@ date_getUTCDate(JSContext *cx, unsigned 
 }
 
 JS_ALWAYS_INLINE bool
 date_getDay_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY));
     return true;
 }
 
 static JSBool
 date_getDay(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1614,17 +1614,17 @@ date_getUTCDay(JSContext *cx, unsigned a
 }
 
 JS_ALWAYS_INLINE bool
 date_getHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS));
     return true;
 }
 
 static JSBool
 date_getHours(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1653,17 +1653,17 @@ date_getUTCHours(JSContext *cx, unsigned
 }
 
 JS_ALWAYS_INLINE bool
 date_getMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES));
     return true;
 }
 
 static JSBool
 date_getMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1694,17 +1694,17 @@ date_getUTCMinutes(JSContext *cx, unsign
 /* Date.getSeconds is mapped to getUTCSeconds */
 
 JS_ALWAYS_INLINE bool
 date_getUTCSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
-    FillLocalTimeSlots(&cx->runtime->dateTimeInfo, thisObj);
+    FillLocalTimeSlots(&cx->runtime()->dateTimeInfo, thisObj);
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS));
     return true;
 }
 
 static JSBool
 date_getUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -1736,17 +1736,17 @@ date_getUTCMilliseconds(JSContext *cx, u
 
 JS_ALWAYS_INLINE bool
 date_getTimezoneOffset_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     JSObject *thisObj = &args.thisv().toObject();
     double utctime = thisObj->getDateUTCTime().toNumber();
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, thisObj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, thisObj);
 
     /*
      * Return the time zone offset in minutes for the current locale that is
      * appropriate for this time. This value would be a constant except for
      * daylight savings time.
      */
     double result = (utctime - localtime) / msPerMinute;
     args.rval().setNumber(result);
@@ -1820,26 +1820,26 @@ GetMinsOrDefault(JSContext *cx, const Ca
 JS_ALWAYS_INLINE bool
 date_setMilliseconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double milli;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &milli))
         return false;
     double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
 
     /* Step 3. */
-    double u = TimeClip(UTC(MakeDate(Day(t), time), &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(MakeDate(Day(t), time), &cx->runtime()->dateTimeInfo));
 
     /* Steps 4-5. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 static JSBool
 date_setMilliseconds(JSContext *cx, unsigned argc, Value *vp)
@@ -1884,33 +1884,33 @@ date_setUTCMilliseconds(JSContext *cx, u
 JS_ALWAYS_INLINE bool
 date_setSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double s;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &s))
         return false;
 
     /* Step 3. */
     double milli;
     if (!GetMsecsOrDefault(cx, args, 1, t, &milli))
         return false;
 
     /* Step 4. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
 
     /* Step 5. */
-    double u = TimeClip(UTC(date, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
 
     /* Steps 6-7. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 /* ES5 15.9.5.31. */
 static JSBool
@@ -1962,17 +1962,17 @@ date_setUTCSeconds(JSContext *cx, unsign
 JS_ALWAYS_INLINE bool
 date_setMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double m;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &m))
         return false;
 
     /* Step 3. */
     double s;
@@ -1983,17 +1983,17 @@ date_setMinutes_impl(JSContext *cx, Call
     double milli;
     if (!GetMsecsOrDefault(cx, args, 2, t, &milli))
         return false;
 
     /* Step 5. */
     double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
 
     /* Step 6. */
-    double u = TimeClip(UTC(date, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
 
     /* Steps 7-8. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 /* ES5 15.9.5.33. */
 static JSBool
@@ -2050,17 +2050,17 @@ date_setUTCMinutes(JSContext *cx, unsign
 JS_ALWAYS_INLINE bool
 date_setHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double h;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &h))
         return false;
 
     /* Step 3. */
     double m;
@@ -2076,17 +2076,17 @@ date_setHours_impl(JSContext *cx, CallAr
     double milli;
     if (!GetMsecsOrDefault(cx, args, 3, t, &milli))
         return false;
 
     /* Step 6. */
     double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
 
     /* Step 6. */
-    double u = TimeClip(UTC(date, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(date, &cx->runtime()->dateTimeInfo));
 
     /* Steps 7-8. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 /* ES5 15.9.5.35. */
 static JSBool
@@ -2148,28 +2148,28 @@ date_setUTCHours(JSContext *cx, unsigned
 JS_ALWAYS_INLINE bool
 date_setDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double dt;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &dt))
         return false;
 
     /* Step 3. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t));
 
     /* Step 4. */
-    double u = TimeClip(UTC(newDate, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
 
     /* Steps 5-6. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 /* ES5 15.9.5.37. */
 static JSBool
@@ -2236,33 +2236,33 @@ GetMonthOrDefault(JSContext *cx, const C
 JS_ALWAYS_INLINE bool
 date_setMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime->dateTimeInfo);
+    double t = LocalTime(thisObj->getDateUTCTime().toNumber(), &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double m;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &m))
         return false;
 
     /* Step 3. */
     double dt;
     if (!GetDateOrDefault(cx, args, 1, t, &dt))
         return false;
 
     /* Step 4. */
     double newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t));
 
     /* Step 5. */
-    double u = TimeClip(UTC(newDate, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
 
     /* Steps 6-7. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 static JSBool
 date_setMonth(JSContext *cx, unsigned argc, Value *vp)
@@ -2330,17 +2330,17 @@ ThisUTCTimeOrZero(HandleObject date)
 JS_ALWAYS_INLINE bool
 date_setFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = ThisLocalTimeOrZero(thisObj, &cx->runtime->dateTimeInfo);
+    double t = ThisLocalTimeOrZero(thisObj, &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double y;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &y))
         return false;
 
     /* Step 3. */
     double m;
@@ -2351,17 +2351,17 @@ date_setFullYear_impl(JSContext *cx, Cal
     double dt;
     if (!GetDateOrDefault(cx, args, 2, t, &dt))
         return false;
 
     /* Step 5. */
     double newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t));
 
     /* Step 6. */
-    double u = TimeClip(UTC(newDate, &cx->runtime->dateTimeInfo));
+    double u = TimeClip(UTC(newDate, &cx->runtime()->dateTimeInfo));
 
     /* Steps 7-8. */
     SetUTCTime(thisObj, u, args.rval().address());
     return true;
 }
 
 static JSBool
 date_setFullYear(JSContext *cx, unsigned argc, Value *vp)
@@ -2418,17 +2418,17 @@ date_setUTCFullYear(JSContext *cx, unsig
 JS_ALWAYS_INLINE bool
 date_setYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
-    double t = ThisLocalTimeOrZero(thisObj, &cx->runtime->dateTimeInfo);
+    double t = ThisLocalTimeOrZero(thisObj, &cx->runtime()->dateTimeInfo);
 
     /* Step 2. */
     double y;
     if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &y))
         return false;
 
     /* Step 3. */
     if (IsNaN(y)) {
@@ -2440,17 +2440,17 @@ date_setYear_impl(JSContext *cx, CallArg
     double yint = ToInteger(y);
     if (0 <= yint && yint <= 99)
         yint += 1900;
 
     /* Step 5. */
     double day = MakeDay(yint, MonthFromTime(t), DateFromTime(t));
 
     /* Step 6. */
-    double u = UTC(MakeDate(day, TimeWithinDay(t)), &cx->runtime->dateTimeInfo);
+    double u = UTC(MakeDate(day, TimeWithinDay(t)), &cx->runtime()->dateTimeInfo);
 
     /* Steps 7-8. */
     SetUTCTime(thisObj, TimeClip(u), args.rval().address());
     return true;
 }
 
 static JSBool
 date_setYear(JSContext *cx, unsigned argc, Value *vp)
@@ -2643,37 +2643,37 @@ date_format(JSContext *cx, double date, 
     size_t i, tzlen;
     PRMJTime split;
 
     if (!IsFinite(date)) {
         JS_snprintf(buf, sizeof buf, js_NaN_date_str);
     } else {
         JS_ASSERT(TimeClip(date) == date);
 
-        double local = LocalTime(date, &cx->runtime->dateTimeInfo);
+        double local = LocalTime(date, &cx->runtime()->dateTimeInfo);
 
         /* offset from GMT in minutes.  The offset includes daylight savings,
            if it applies. */
-        int minutes = (int) floor(AdjustTime(date, &cx->runtime->dateTimeInfo) / msPerMinute);
+        int minutes = (int) floor(AdjustTime(date, &cx->runtime()->dateTimeInfo) / msPerMinute);
 
         /* map 510 minutes to 0830 hours */
         int offset = (minutes / 60) * 100 + minutes % 60;
 
         /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is
          * printed as 'GMT-0800' rather than as 'PST' to avoid
          * operating-system dependence on strftime (which
          * PRMJ_FormatTimeUSEnglish calls, for %Z only.)  win32 prints
          * PST as 'Pacific Standard Time.'  This way we always know
          * what we're getting, and can parse it if we produce it.
          * The OS TZA string is included as a comment.
          */
 
         /* get a timezone string from the OS to include as a
            comment. */
-        new_explode(date, &split, &cx->runtime->dateTimeInfo);
+        new_explode(date, &split, &cx->runtime()->dateTimeInfo);
         if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
 
             /* Decide whether to use the resulting timezone string.
              *
              * Reject it if it contains any non-ASCII, non-alphanumeric
              * characters.  It's then likely in some other character
              * encoding, and we probably won't display it correctly.
              */
@@ -2753,19 +2753,19 @@ ToLocaleFormatHelper(JSContext *cx, Hand
 {
     double utctime = obj->getDateUTCTime().toNumber();
 
     char buf[100];
     if (!IsFinite(utctime)) {
         JS_snprintf(buf, sizeof buf, js_NaN_date_str);
     } else {
         int result_len;
-        double local = LocalTime(utctime, &cx->runtime->dateTimeInfo);
+        double local = LocalTime(utctime, &cx->runtime()->dateTimeInfo);
         PRMJTime split;
-        new_explode(local, &split, &cx->runtime->dateTimeInfo);
+        new_explode(local, &split, &cx->runtime()->dateTimeInfo);
 
         /* Let PRMJTime format it. */
         result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
 
         /* If it failed, default to toString. */
         if (result_len == 0)
             return date_format(cx, utctime, FORMATSPEC_FULL, rval);
 
@@ -2779,18 +2779,18 @@ ToLocaleFormatHelper(JSContext *cx, Hand
             !(isdigit(buf[0]) && isdigit(buf[1]) &&
               isdigit(buf[2]) && isdigit(buf[3]))) {
             JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
                         "%d", js_DateGetYear(cx, obj));
         }
 
     }
 
-    if (cx->runtime->localeCallbacks && cx->runtime->localeCallbacks->localeToUnicode)
-        return cx->runtime->localeCallbacks->localeToUnicode(cx, buf, rval);
+    if (cx->runtime()->localeCallbacks && cx->runtime()->localeCallbacks->localeToUnicode)
+        return cx->runtime()->localeCallbacks->localeToUnicode(cx, buf, rval);
 
     JSString *str = JS_NewStringCopyZ(cx, buf);
     if (!str)
         return false;
     rval.setString(str);
     return true;
 }
 
@@ -3102,33 +3102,33 @@ js_Date(JSContext *cx, unsigned argc, Va
             JSString *str = args[0].toString();
             if (!str)
                 return false;
 
             JSLinearString *linearStr = str->ensureLinear(cx);
             if (!linearStr)
                 return false;
 
-            if (!date_parseString(linearStr, &d, &cx->runtime->dateTimeInfo))
+            if (!date_parseString(linearStr, &d, &cx->runtime()->dateTimeInfo))
                 d = js_NaN;
             else
                 d = TimeClip(d);
         } else {
             /* Step 3. */
             if (!ToNumber(cx, args[0], &d))
                 return false;
             d = TimeClip(d);
         }
     } else {
         double msec_time;
         if (!date_msecFromArgs(cx, args, &msec_time))
             return false;
 
         if (IsFinite(msec_time)) {
-            msec_time = UTC(msec_time, &cx->runtime->dateTimeInfo);
+            msec_time = UTC(msec_time, &cx->runtime()->dateTimeInfo);
             msec_time = TimeClip(msec_time);
         }
         d = msec_time;
     }
 
     JSObject *obj = js_NewDateObjectMsec(cx, d);
     if (!obj)
         return false;
@@ -3194,75 +3194,75 @@ js_NewDateObjectMsec(JSContext *cx, doub
 }
 
 JS_FRIEND_API(JSObject *)
 js_NewDateObject(JSContext *cx, int year, int mon, int mday,
                  int hour, int min, int sec)
 {
     JS_ASSERT(mon < 12);
     double msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
-    return js_NewDateObjectMsec(cx, UTC(msec_time, &cx->runtime->dateTimeInfo));
+    return js_NewDateObjectMsec(cx, UTC(msec_time, &cx->runtime()->dateTimeInfo));
 }
 
 JS_FRIEND_API(JSBool)
 js_DateIsValid(JSObject *obj)
 {
     return obj->isDate() && !IsNaN(obj->getDateUTCTime().toNumber());
 }
 
 JS_FRIEND_API(int)
 js_DateGetYear(JSContext *cx, JSObject *obj)
 {
     /* Preserve legacy API behavior of returning 0 for invalid dates. */
     JS_ASSERT(obj);
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, obj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, obj);
     if (IsNaN(localtime))
         return 0;
 
     return (int) YearFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetMonth(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj);
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, obj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, obj);
     if (IsNaN(localtime))
         return 0;
 
     return (int) MonthFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetDate(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj);
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, obj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, obj);
     if (IsNaN(localtime))
         return 0;
 
     return (int) DateFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetHours(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj);
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, obj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, obj);
     if (IsNaN(localtime))
         return 0;
 
     return (int) HourFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetMinutes(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj);
-    double localtime = GetCachedLocalTime(&cx->runtime->dateTimeInfo, obj);
+    double localtime = GetCachedLocalTime(&cx->runtime()->dateTimeInfo, obj);
     if (IsNaN(localtime))
         return 0;
 
     return (int) MinFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetSeconds(JSObject *obj)
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -45,23 +45,23 @@
 using namespace js;
 using namespace js::gc;
 
 using mozilla::PodZero;
 
 JS_PUBLIC_API(JSBool)
 JS_GetDebugMode(JSContext *cx)
 {
-    return cx->compartment->debugMode();
+    return cx->compartment()->debugMode();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebugMode(JSContext *cx, JSBool debug)
 {
-    return JS_SetDebugModeForCompartment(cx, cx->compartment, debug);
+    return JS_SetDebugModeForCompartment(cx, cx->compartment(), debug);
 }
 
 JS_PUBLIC_API(void)
 JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
 {
     rt->debugMode = !!debug;
 }
 
@@ -75,23 +75,23 @@ IsTopFrameConstructing(JSContext *cx, Ab
 
 JSTrapStatus
 js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
 {
     JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp());
 
     if (!frame.script()->selfHosted) {
         if (frame.isFramePushedByExecute()) {
-            if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
+            if (JSInterpreterHook hook = cx->runtime()->debugHooks.executeHook)
                 frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
-                                       true, 0, cx->runtime->debugHooks.executeHookData));
+                                       true, 0, cx->runtime()->debugHooks.executeHookData));
         } else {
-            if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
+            if (JSInterpreterHook hook = cx->runtime()->debugHooks.callHook)
                 frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
-                                       true, 0, cx->runtime->debugHooks.callHookData));
+                                       true, 0, cx->runtime()->debugHooks.callHookData));
         }
     }
 
     RootedValue rval(cx);
     JSTrapStatus status = Debugger::onEnterFrame(cx, frame, &rval);
     switch (status) {
       case JSTRAP_CONTINUE:
         break;
@@ -114,42 +114,42 @@ bool
 js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg)
 {
     JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp());
     JSBool ok = okArg;
 
     // We don't add hook data for self-hosted scripts, so we don't need to check for them, here.
     if (void *hookData = frame.maybeHookData()) {
         if (frame.isFramePushedByExecute()) {
-            if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
+            if (JSInterpreterHook hook = cx->runtime()->debugHooks.executeHook)
                 hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
         } else {
-            if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
+            if (JSInterpreterHook hook = cx->runtime()->debugHooks.callHook)
                 hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
         }
     }
 
     return Debugger::onLeaveFrame(cx, frame, ok);
 }
 
 JSTrapStatus
 js::DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc)
 {
-    JS_ASSERT(cx->compartment->debugMode());
+    JS_ASSERT(cx->compartment()->debugMode());
 
-    if (!cx->runtime->debugHooks.throwHook && cx->compartment->getDebuggees().empty())
+    if (!cx->runtime()->debugHooks.throwHook && cx->compartment()->getDebuggees().empty())
         return JSTRAP_CONTINUE;
 
     /* Call debugger throw hook if set. */
     RootedValue rval(cx);
     JSTrapStatus status = Debugger::onExceptionUnwind(cx, &rval);
     if (status == JSTRAP_CONTINUE) {
-        if (JSThrowHook handler = cx->runtime->debugHooks.throwHook) {
+        if (JSThrowHook handler = cx->runtime()->debugHooks.throwHook) {
             RootedScript script(cx, frame.script());
-            status = handler(cx, script, pc, rval.address(), cx->runtime->debugHooks.throwHookData);
+            status = handler(cx, script, pc, rval.address(), cx->runtime()->debugHooks.throwHookData);
         }
     }
 
     switch (status) {
       case JSTRAP_ERROR:
         cx->clearPendingException();
         break;
 
@@ -170,32 +170,32 @@ js::DebugExceptionUnwind(JSContext *cx, 
     }
 
     return status;
 }
 
 JS_FRIEND_API(JSBool)
 JS_SetDebugModeForAllCompartments(JSContext *cx, JSBool debug)
 {
-    AutoDebugModeGC dmgc(cx->runtime);
+    AutoDebugModeGC dmgc(cx->runtime());
 
-    for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
+    for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
         // Ignore special compartments (atoms, JSD compartments)
         if (c->principals) {
             if (!c->setDebugModeFromC(cx, !!debug, dmgc))
                 return false;
         }
     }
     return true;
 }
 
 JS_FRIEND_API(JSBool)
 JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
 {
-    AutoDebugModeGC dmgc(cx->runtime);
+    AutoDebugModeGC dmgc(cx->runtime());
     return comp->setDebugModeFromC(cx, !!debug, dmgc);
 }
 
 static JSBool
 CheckDebugMode(JSContext *cx)
 {
     JSBool debugMode = JS_GetDebugMode(cx);
     /*
@@ -230,44 +230,44 @@ JS_SetTrap(JSContext *cx, JSScript *scri
     assertSameCompartment(cx, script, closure);
 
     if (!CheckDebugMode(cx))
         return false;
 
     BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc);
     if (!site)
         return false;
-    site->setTrap(cx->runtime->defaultFreeOp(), handler, closure);
+    site->setTrap(cx->runtime()->defaultFreeOp(), handler, closure);
     return true;
 }
 
 JS_PUBLIC_API(void)
 JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
              JSTrapHandler *handlerp, jsval *closurep)
 {
     if (BreakpointSite *site = script->getBreakpointSite(pc)) {
-        site->clearTrap(cx->runtime->defaultFreeOp(), handlerp, closurep);
+        site->clearTrap(cx->runtime()->defaultFreeOp(), handlerp, closurep);
     } else {
         if (handlerp)
             *handlerp = NULL;
         if (closurep)
             *closurep = JSVAL_VOID;
     }
 }
 
 JS_PUBLIC_API(void)
 JS_ClearScriptTraps(JSContext *cx, JSScript *script)
 {
-    script->clearTraps(cx->runtime->defaultFreeOp());
+    script->clearTraps(cx->runtime()->defaultFreeOp());
 }
 
 JS_PUBLIC_API(void)
 JS_ClearAllTrapsForCompartment(JSContext *cx)
 {
-    cx->compartment->clearTraps(cx->runtime->defaultFreeOp());
+    cx->compartment()->clearTraps(cx->runtime()->defaultFreeOp());
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetInterrupt(JSRuntime *rt, JSInterruptHook hook, void *closure)
 {
     rt->debugHooks.interruptHook = hook;
     rt->debugHooks.interruptHookData = closure;
     for (InterpreterFrames *f = rt->interpreterFrames; f; f = f->older)
@@ -334,53 +334,53 @@ JS_SetWatchPoint(JSContext *cx, JSObject
      * Use sparse indexes for watched objects, as dense elements can be written
      * to without checking the watchpoint map.
      */
     if (!JSObject::sparsifyDenseElements(cx, obj))
         return false;
 
     types::MarkTypePropertyConfigured(cx, obj, propid);
 
-    WatchpointMap *wpmap = cx->compartment->watchpointMap;
+    WatchpointMap *wpmap = cx->compartment()->watchpointMap;
     if (!wpmap) {
-        wpmap = cx->runtime->new_<WatchpointMap>();
+        wpmap = cx->runtime()->new_<WatchpointMap>();
         if (!wpmap || !wpmap->init()) {
             js_ReportOutOfMemory(cx);
             return false;
         }
-        cx->compartment->watchpointMap = wpmap;
+        cx->compartment()->watchpointMap = wpmap;
     }
     return wpmap->watch(cx, obj, propid, handler, closure);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
                    JSWatchPointHandler *handlerp, JSObject **closurep)
 {
     assertSameCompartment(cx, obj, id);
 
-    if (WatchpointMap *wpmap = cx->compartment->watchpointMap)
+    if (WatchpointMap *wpmap = cx->compartment()->watchpointMap)
         wpmap->unwatch(obj, id, handlerp, closurep);
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
 {
     assertSameCompartment(cx, obj);
 
-    if (WatchpointMap *wpmap = cx->compartment->watchpointMap)
+    if (WatchpointMap *wpmap = cx->compartment()->watchpointMap)
         wpmap->unwatchObject(obj);
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearAllWatchPoints(JSContext *cx)
 {
-    if (JSCompartment *comp = cx->compartment) {
+    if (JSCompartment *comp = cx->compartment()) {
         if (WatchpointMap *wpmap = comp->watchpointMap)
             wpmap->clear();
     }
     return true;
 }
 
 /************************************************************************/
 
@@ -760,20 +760,20 @@ bad:
 JS_PUBLIC_API(void)
 JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
 {
     JSPropertyDesc *pd;
     uint32_t i;
 
     pd = pda->array;
     for (i = 0; i < pda->length; i++) {
-        js_RemoveRoot(cx->runtime, &pd[i].id);
-        js_RemoveRoot(cx->runtime, &pd[i].value);
+        js_RemoveRoot(cx->runtime(), &pd[i].id);
+        js_RemoveRoot(cx->runtime(), &pd[i].value);
         if (pd[i].flags & JSPD_ALIAS)
-            js_RemoveRoot(cx->runtime, &pd[i].alias);
+            js_RemoveRoot(cx->runtime(), &pd[i].alias);
     }
     js_free(pd);
     pda->array = NULL;
     pda->length = 0;
 }
 
 /************************************************************************/
 
@@ -887,41 +887,41 @@ DumpBytecodeScriptCallback(JSRuntime *rt
 }
 
 } /* anonymous namespace */
 
 JS_PUBLIC_API(void)
 JS_DumpCompartmentBytecode(JSContext *cx)
 {
     ScriptsToDump scripts;
-    IterateScripts(cx->runtime, cx->compartment, &scripts, DumpBytecodeScriptCallback);
+    IterateScripts(cx->runtime(), cx->compartment(), &scripts, DumpBytecodeScriptCallback);
 
     for (size_t i = 0; i < scripts.length(); i++) {
         if (scripts[i]->enclosingScriptsCompiledSuccessfully())
             JS_DumpBytecode(cx, scripts[i]);
     }
 }
 
 JS_PUBLIC_API(void)
 JS_DumpCompartmentPCCounts(JSContext *cx)
 {
     for (CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
-        if (script->compartment() != cx->compartment)
+        if (script->compartment() != cx->compartment())
             continue;
 
         if (script->hasScriptCounts && script->enclosingScriptsCompiledSuccessfully())
             JS_DumpPCCounts(cx, script);
     }
 
 #if defined(JS_ASMJS) && defined(DEBUG)
     for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
         for (CellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) {
             JSObject *obj = i.get<JSObject>();
-            if (obj->compartment() != cx->compartment)
+            if (obj->compartment() != cx->compartment())
                 continue;
 
             if (IsAsmJSModuleObject(obj)) {
                 AsmJSModule &module = AsmJSModuleObjectToModule(obj);
 
                 Sprinter sprinter(cx);
                 if (!sprinter.init())
                     return;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -247,17 +247,17 @@ SetExnPrivate(JSObject *exnObject, JSExn
 static bool
 InitExnPrivate(JSContext *cx, HandleObject exnObject, HandleString message,
                HandleString filename, unsigned lineno, unsigned column,
                JSErrorReport *report, int exnType)
 {
     JS_ASSERT(exnObject->isError());
     JS_ASSERT(!exnObject->getPrivate());
 
-    JSCheckAccessOp checkAccess = cx->runtime->securityCallbacks->checkObjectAccess;
+    JSCheckAccessOp checkAccess = cx->runtime()->securityCallbacks->checkObjectAccess;
 
     Vector<JSStackTraceStackElem> frames(cx);
     {
         SuppressErrorsGuard seg(cx);
         for (NonBuiltinScriptFrameIter i(cx); !i.done(); ++i) {
 
             /* Ask the crystal CAPS ball whether we can see across compartments. */
             if (checkAccess && i.isNonEvalFunctionFrame()) {
@@ -269,17 +269,17 @@ InitExnPrivate(JSContext *cx, HandleObje
             }
 
             if (!frames.growBy(1))
                 return false;
             JSStackTraceStackElem &frame = frames.back();
             if (i.isNonEvalFunctionFrame()) {
                 JSAtom *atom = i.callee()->displayAtom();
                 if (atom == NULL)
-                    atom = cx->runtime->emptyString;
+                    atom = cx->runtime()->emptyString;
                 frame.funName = atom;
             } else {
                 frame.funName = NULL;
             }
             RootedScript script(cx, i.script());
             const char *cfilename = script->filename();
             if (!cfilename)
                 cfilename = "";
@@ -574,17 +574,17 @@ Exception(JSContext *cx, unsigned argc, 
     RootedScript script(cx, iter.done() ? NULL : iter.script());
     RootedString filename(cx);
     if (args.length() > 1) {
         filename = ToString<CanGC>(cx, args.handleAt(1));
         if (!filename)
             return false;
         args[1].setString(filename);
     } else {
-        filename = cx->runtime->emptyString;
+        filename = cx->runtime()->emptyString;
         if (!iter.done()) {
             if (const char *cfilename = script->filename()) {
                 filename = FilenameToString(cx, cfilename);
                 if (!filename)
                     return false;
             }
         }
     }
@@ -640,17 +640,17 @@ exn_toString(JSContext *cx, unsigned arg
     /* Step 5. */
     RootedValue msgVal(cx);
     if (!JSObject::getProperty(cx, obj, obj, cx->names().message, &msgVal))
         return false;
 
     /* Step 6. */
     RootedString message(cx);
     if (msgVal.isUndefined()) {
-        message = cx->runtime->emptyString;
+        message = cx->runtime()->emptyString;
     } else {
         message = ToString<CanGC>(cx, msgVal);
         if (!message)
             return false;
     }
 
     /* Step 7. */
     if (name->empty() && message->empty()) {
@@ -786,17 +786,17 @@ InitErrorClass(JSContext *cx, Handle<Glo
     JSProtoKey key = GetExceptionProtoKey(type);
     RootedAtom name(cx, ClassName(key, cx));
     RootedObject errorProto(cx, global->createBlankPrototypeInheriting(cx, &ErrorClass, *proto));
     if (!errorProto)
         return NULL;
 
     RootedValue nameValue(cx, StringValue(name));
     RootedValue zeroValue(cx, Int32Value(0));
-    RootedValue empty(cx, StringValue(cx->runtime->emptyString));
+    RootedValue empty(cx, StringValue(cx->runtime()->emptyString));
     RootedId nameId(cx, NameToId(cx->names().name));
     RootedId messageId(cx, NameToId(cx->names().message));
     RootedId fileNameId(cx, NameToId(cx->names().fileName));
     RootedId lineNumberId(cx, NameToId(cx->names().lineNumber));
     RootedId columnNumberId(cx, NameToId(cx->names().columnNumber));
     if (!DefineNativeProperty(cx, errorProto, nameId, nameValue,
                               JS_PropertyStub, JS_StrictPropertyStub, 0, 0, 0) ||
         !DefineNativeProperty(cx, errorProto, messageId, empty,
@@ -860,19 +860,19 @@ js_InitExceptionClasses(JSContext *cx, H
 }
 
 const JSErrorFormatString*
 js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
                             const unsigned errorNumber)
 {
     const JSErrorFormatString *errorString = NULL;
 
-    if (cx->runtime->localeCallbacks && cx->runtime->localeCallbacks->localeGetErrorMessage) {
-        errorString = cx->runtime->localeCallbacks
-                                 ->localeGetErrorMessage(userRef, locale, errorNumber);
+    if (cx->runtime()->localeCallbacks && cx->runtime()->localeCallbacks->localeGetErrorMessage) {
+        errorString = cx->runtime()->localeCallbacks
+                                   ->localeGetErrorMessage(userRef, locale, errorNumber);
     }
     if (!errorString)
         errorString = js_GetErrorMessage(userRef, locale, errorNumber);
     return errorString;
 }
 
 JS_FRIEND_API(const jschar*)
 js::GetErrorTypeName(JSContext* cx, int16_t exnType)
@@ -1155,21 +1155,21 @@ js_CopyErrorObject(JSContext *cx, Handle
         if (!copy->errorReport)
             return NULL;
     } else {
         copy->errorReport = NULL;
     }
     ScopedJSFreePtr<JSErrorReport> autoFreeErrorReport(copy->errorReport);
 
     copy->message.init(priv->message);
-    if (!cx->compartment->wrap(cx, &copy->message))
+    if (!cx->compartment()->wrap(cx, &copy->message))
         return NULL;
     JS::Anchor<JSString *> messageAnchor(copy->message);
     copy->filename.init(priv->filename);
-    if (!cx->compartment->wrap(cx, &copy->filename))
+    if (!cx->compartment()->wrap(cx, &copy->filename))
         return NULL;
     JS::Anchor<JSString *> filenameAnchor(copy->filename);
     copy->lineno = priv->lineno;
     copy->column = priv->column;
     copy->stackDepth = 0;
     copy->exnType = priv->exnType;
 
     // Create the Error object.
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -236,23 +236,23 @@ JS_SetCompartmentPrincipals(JSCompartmen
 
     // Update the system flag.
     compartment->isSystem = isSystem;
 }
 
 JS_FRIEND_API(JSBool)
 JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc)
 {
-    return cx->compartment->wrap(cx, desc);
+    return cx->compartment()->wrap(cx, desc);
 }
 
 JS_FRIEND_API(JSBool)
 JS_WrapAutoIdVector(JSContext *cx, js::AutoIdVector &props)
 {
-    return cx->compartment->wrap(cx, props);
+    return cx->compartment()->wrap(cx, props);
 }
 
 JS_FRIEND_API(void)
 JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
 {
     MarkCycleCollectorChildren(trc, static_cast<Shape *>(shape));
 }
 
@@ -267,17 +267,17 @@ DefineHelpProperty(JSContext *cx, Handle
                              JS_PropertyStub, JS_StrictPropertyStub,
                              JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
 JS_FRIEND_API(bool)
 JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *objArg, const JSFunctionSpecWithHelp *fs)
 {
     RootedObject obj(cx, objArg);
-    JS_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom *atom = Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
 
@@ -297,25 +297,25 @@ JS_DefineFunctionsWithHelp(JSContext *cx
         }
     }
 
     return true;
 }
 
 AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
                                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-  : cx(cx), oldCompartment(cx->compartment)
+  : cx(cx), oldCompartment(cx->compartment())
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     cx->setCompartment(newCompartment);
 }
 
 AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSHandleObject target
                                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-  : cx(cx), oldCompartment(cx->compartment)
+  : cx(cx), oldCompartment(cx->compartment())
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     cx->setCompartment(target->compartment());
 }
 
 AutoSwitchCompartment::~AutoSwitchCompartment()
 {
     /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
@@ -380,17 +380,17 @@ JS_FRIEND_API(uint32_t)
 js::GetObjectSlotSpan(JSObject *obj)
 {
     return obj->slotSpan();
 }
 
 JS_FRIEND_API(bool)
 js::IsObjectInContextCompartment(JSObject *obj, const JSContext *cx)
 {
-    return obj->compartment() == cx->compartment;
+    return obj->compartment() == cx->compartment();
 }
 
 JS_FRIEND_API(bool)
 js::IsOriginalScriptFunction(JSFunction *fun)
 {
     return fun->nonLazyScript()->function() == fun;
 }
 
@@ -413,32 +413,32 @@ js::GetOutermostEnclosingFunctionOfScrip
     return outermost;
 }
 
 JS_FRIEND_API(JSFunction *)
 js::DefineFunctionWithReserved(JSContext *cx, JSObject *objArg, const char *name, JSNative call,
                                unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom *atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return NULL;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
                             JSObject *parentArg, const char *name)
 {
     RootedObject parent(cx, parentArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
@@ -451,17 +451,17 @@ js::NewFunctionWithReserved(JSContext *c
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                                 jsid id)
 {
     RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    JS_THREADSAFE_ASSERT(cx->compartment() != cx->runtime()->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
                        JSFunction::ExtendedFinalizeKind);
 }
@@ -739,33 +739,33 @@ js::DumpHeapComplete(JSRuntime *rt, FILE
                                         DumpHeapVisitCell);
 
     fflush(dtrc.output);
 }
 
 JS_FRIEND_API(const JSStructuredCloneCallbacks *)
 js::GetContextStructuredCloneCallbacks(JSContext *cx)
 {
-    return cx->runtime->structuredCloneCallbacks;
+    return cx->runtime()->structuredCloneCallbacks;
 }
 
 JS_FRIEND_API(bool)
 js::CanCallContextDebugHandler(JSContext *cx)
 {
-    return !!cx->runtime->debugHooks.debuggerHandler;
+    return !!cx->runtime()->debugHooks.debuggerHandler;
 }
 
 JS_FRIEND_API(JSTrapStatus)
 js::CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
 {
-    if (!cx->runtime->debugHooks.debuggerHandler)
+    if (!cx->runtime()->debugHooks.debuggerHandler)
         return JSTRAP_RETURN;
 
-    return cx->runtime->debugHooks.debuggerHandler(cx, script, bc, rval,
-                                                   cx->runtime->debugHooks.debuggerHandlerData);
+    return cx->runtime()->debugHooks.debuggerHandler(cx, script, bc, rval,
+                                                   cx->runtime()->debugHooks.debuggerHandlerData);
 }
 
 #ifdef JS_THREADSAFE
 JS_FRIEND_API(bool)
 js::ContextHasOutstandingRequests(const JSContext *cx)
 {
     return cx->outstandingRequests > 0;
 }
@@ -883,17 +883,17 @@ JS_FRIEND_API(bool)
 JS::IsIncrementalBarrierNeeded(JSRuntime *rt)
 {
     return (rt->gcIncrementalState == gc::MARK && !rt->isHeapBusy());
 }
 
 JS_FRIEND_API(bool)
 JS::IsIncrementalBarrierNeeded(JSContext *cx)
 {
-    return IsIncrementalBarrierNeeded(cx->runtime);
+    return IsIncrementalBarrierNeeded(cx->runtime());
 }
 
 JS_FRIEND_API(void)
 JS::IncrementalObjectBarrier(JSObject *obj)
 {
     if (!obj)
         return;
 
@@ -1044,32 +1044,32 @@ js::SetCTypesActivityCallback(JSRuntime 
 {
     rt->ctypesActivityCallback = cb;
 }
 
 js::AutoCTypesActivityCallback::AutoCTypesActivityCallback(JSContext *cx,
                                                            js::CTypesActivityType beginType,
                                                            js::CTypesActivityType endType
                                                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-  : cx(cx), callback(cx->runtime->ctypesActivityCallback), endType(endType)
+  : cx(cx), callback(cx->runtime()->ctypesActivityCallback), endType(endType)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
     if (callback)
         callback(cx, beginType);
 }
 
 JS_FRIEND_API(void)
 js::SetObjectMetadataCallback(JSContext *cx, ObjectMetadataCallback callback)
 {
     // Clear any jitcode in the runtime, which behaves differently depending on
     // whether there is a creation callback.
-    ReleaseAllJITCode(cx->runtime->defaultFreeOp());
+    ReleaseAllJITCode(cx->runtime()->defaultFreeOp());
 
-    cx->compartment->objectMetadataCallback = callback;
+    cx->compartment()->objectMetadataCallback = callback;
 }
 
 JS_FRIEND_API(bool)
 js::SetObjectMetadata(JSContext *cx, JSHandleObject obj, JSHandleObject metadata)
 {
     return JSObject::setMetadata(cx, obj, metadata);
 }
 
@@ -1080,17 +1080,17 @@ js::GetObjectMetadata(JSObject *obj)
 }
 
 JS_FRIEND_API(JSBool)
 js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
                      const js::PropertyDescriptor& descriptor, JSBool *bp)
 {
     RootedObject obj(cx, objArg);
     RootedId id(cx, idArg);
-    JS_ASSERT(cx->runtime->heapState == js::Idle);
+    JS_ASSERT(cx->runtime()->heapState == js::Idle);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id, descriptor.value);
     if (descriptor.attrs & JSPROP_GETTER)
         assertSameCompartment(cx, CastAsObjectJsval(descriptor.getter));
     if (descriptor.attrs & JSPROP_SETTER)
         assertSameCompartment(cx, CastAsObjectJsval(descriptor.setter));
 
     return js_DefineOwnProperty(cx, HandleObject(obj), id, descriptor, bp);
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -187,23 +187,23 @@ JS_SetSourceHook(JSRuntime *rt, JS_Sourc
 
 namespace js {
 
 extern mozilla::ThreadLocal<PerThreadData *> TlsPerThreadData;
 
 inline JSRuntime *
 GetRuntime(const JSContext *cx)
 {
-    return ContextFriendFields::get(cx)->runtime;
+    return ContextFriendFields::get(cx)->runtime_;
 }
 
 inline JSCompartment *
 GetContextCompartment(const JSContext *cx)
 {
-    return ContextFriendFields::get(cx)->compartment;
+    return ContextFriendFields::get(cx)->compartment_;
 }
 
 inline JS::Zone *
 GetContextZone(const JSContext *cx)
 {
     return ContextFriendFields::get(cx)->zone_;
 }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -118,17 +118,17 @@ fun_getProperty(JSContext *cx, HandleObj
 
         /* Callsite clones should never escape to script. */
         JSObject &maybeClone = iter.calleev().toObject();
         if (maybeClone.isFunction() && maybeClone.toFunction()->nonLazyScript()->isCallsiteClone)
             vp.setObject(*maybeClone.toFunction()->nonLazyScript()->originalFunction());
         else
             vp.set(iter.calleev());
 
-        if (!cx->compartment->wrap(cx, vp))
+        if (!cx->compartment()->wrap(cx, vp))
             return false;
 
         /*
          * Censor the caller if we don't have full access to it.
          */
         RootedObject caller(cx, &vp.toObject());
         if (caller->isWrapper() && !Wrapper::wrapperHandler(caller)->isSafeToUnwrap()) {
             vp.setNull();
@@ -176,17 +176,17 @@ fun_enumerate(JSContext *cx, HandleObjec
         return false;
 
     id = NameToId(cx->names().name);
     if (!JSObject::hasProperty(cx, obj, id, &found, 0))
         return false;
 
     for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
         const uint16_t offset = poisonPillProps[i];
-        id = NameToId(OFFSET_TO_NAME(cx->runtime, offset));
+        id = NameToId(OFFSET_TO_NAME(cx->runtime(), offset));
         if (!JSObject::hasProperty(cx, obj, id, &found, 0))
             return false;
     }
 
     return true;
 }
 
 static JSObject *
@@ -273,31 +273,31 @@ fun_resolve(JSContext *cx, HandleObject 
 
         RootedValue v(cx);
         if (JSID_IS_ATOM(id, cx->names().length)) {
             if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
                 return false;
             uint16_t ndefaults = fun->hasScript() ? fun->nonLazyScript()->ndefaults : 0;
             v.setInt32(fun->nargs - ndefaults - fun->hasRest());
         } else {
-            v.setString(fun->atom() == NULL ?  cx->runtime->emptyString : fun->atom());
+            v.setString(fun->atom() == NULL ?  cx->runtime()->emptyString : fun->atom());
         }
 
         if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
             return false;
         }
         objp.set(fun);
         return true;
     }
 
     for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
         const uint16_t offset = poisonPillProps[i];
 
-        if (JSID_IS_ATOM(id, OFFSET_TO_NAME(cx->runtime, offset))) {
+        if (JSID_IS_ATOM(id, OFFSET_TO_NAME(cx->runtime(), offset))) {
             JS_ASSERT(!IsInternalFunctionObject(fun));
 
             PropertyOp getter;
             StrictPropertyOp setter;
             unsigned attrs = JSPROP_PERMANENT;
             if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
                 return false;
             if (fun->isInterpreted() ? fun->strict() : fun->isBoundFunction()) {
@@ -513,17 +513,17 @@ JS_FRIEND_DATA(Class) js::FunctionClass 
 static bool
 FindBody(JSContext *cx, HandleFunction fun, StableCharPtr chars, size_t length,
          size_t *bodyStart, size_t *bodyEnd)
 {
     // We don't need principals, since those are only used for error reporting.
     CompileOptions options(cx);
     options.setFileAndLine("internal-findBody", 0)
            .setVersion(fun->nonLazyScript()->getVersion());
-    AutoKeepAtoms keepAtoms(cx->runtime);
+    AutoKeepAtoms keepAtoms(cx->runtime());
     TokenStream ts(cx, options, chars.get(), length, NULL, keepAtoms);
     int nest = 0;
     bool onward = true;
     // Skip arguments list.
     do {
         switch (ts.getToken()) {
           case TOK_NAME:
             if (nest == 0)
@@ -1102,17 +1102,17 @@ JSFunction::createScriptForLazilyInterpr
     }
 
     /* Lazily cloned self hosted script. */
     JSFunctionSpec *fs = static_cast<JSFunctionSpec *>(fun->getExtendedSlot(0).toPrivate());
     RootedAtom funAtom(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
     if (!funAtom)
         return false;
     Rooted<PropertyName *> funName(cx, funAtom->asPropertyName());
-    return cx->runtime->cloneSelfHostedFunctionScript(cx, funName, fun);
+    return cx->runtime()->cloneSelfHostedFunctionScript(cx, funName, fun);
 }
 
 /* ES5 15.3.4.5.1 and 15.3.4.5.2. */
 JSBool
 js::CallOrConstructBoundFunction(JSContext *cx, unsigned argc, Value *vp)
 {
     RootedFunction fun(cx, vp[0].toObject().toFunction());
     JS_ASSERT(fun->isBoundFunction());
@@ -1288,17 +1288,17 @@ js::Function(JSContext *cx, unsigned arg
 
     /* Block this call if security callbacks forbid it. */
     Rooted<GlobalObject*> global(cx, &args.callee().global());
     if (!GlobalObject::isRuntimeCodeGenEnabled(cx, global)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
         return false;
     }
 
-    AutoKeepAtoms keepAtoms(cx->runtime);
+    AutoKeepAtoms keepAtoms(cx->runtime());
     AutoNameVector formals(cx);
 
     bool hasRest = false;
 
     const char *filename;
     unsigned lineno;
     JSPrincipals *originPrincipals;
     CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals);
@@ -1438,17 +1438,17 @@ js::Function(JSContext *cx, unsigned arg
     for (unsigned i = 0; i < formals.length(); ++i) {
         JSString *str = formals[i];
         JS_ASSERT(str->asAtom().asPropertyName() == formals[i]);
     }
 #endif
 
     RootedString str(cx);
     if (!args.length())
-        str = cx->runtime->emptyString;
+        str = cx->runtime()->emptyString;
     else
         str = ToString<CanGC>(cx, args.handleAt(args.length() - 1));
     if (!str)
         return false;
     JSLinearString *linear = str->ensureLinear(cx);
     if (!linear)
         return false;
 
@@ -1532,17 +1532,17 @@ js::NewFunction(JSContext *cx, HandleObj
 
 JSFunction *
 js::CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent, gc::AllocKind allocKind,
                         NewObjectKind newKindArg /* = GenericObject */)
 {
     JS_ASSERT(parent);
     JS_ASSERT(!fun->isBoundFunction());
 
-    bool useSameScript = cx->compartment == fun->compartment() &&
+    bool useSameScript = cx->compartment() == fun->compartment() &&
                          !fun->hasSingletonType() &&
                          !types::UseNewTypeForClone(fun);
 
     if (!useSameScript && fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
         return NULL;
 
     NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
     JSObject *cloneobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent),
@@ -1562,17 +1562,17 @@ js::CloneFunctionObject(JSContext *cx, H
         clone->initEnvironment(parent);
     } else {
         clone->initNative(fun->native(), fun->jitInfo());
     }
     clone->initAtom(fun->displayAtom());
 
     if (allocKind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFunction::EXTENDED;
-        if (fun->isExtended() && fun->compartment() == cx->compartment) {
+        if (fun->isExtended() && fun->compartment() == cx->compartment()) {
             for (unsigned i = 0; i < FunctionExtended::NUM_EXTENDED_SLOTS; i++)
                 clone->initExtendedSlot(i, fun->getExtendedSlot(i));
         } else {
             clone->initializeExtended();
         }
     }
 
     if (useSameScript) {
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1026,17 +1026,17 @@ AddRoot(JSRuntime *rt, T *rp, const char
 
     return rt->gcRootsHash.put((void *)rp, RootInfo(name, rootType));
 }
 
 template <typename T>
 static bool
 AddRoot(JSContext *cx, T *rp, const char *name, JSGCRootType rootType)
 {
-    bool ok = AddRoot(cx->runtime, rp, name, rootType);
+    bool ok = AddRoot(cx->runtime(), rp, name, rootType);
     if (!ok)
         JS_ReportOutOfMemory(cx);
     return ok;
 }
 
 JSBool
 js::AddValueRoot(JSContext *cx, Value *vp, const char *name)
 {
@@ -1466,17 +1466,17 @@ RunLastDitchGC(JSContext *cx, JS::Zone *
     /*
      * In parallel sections, we do not attempt to refill the free list
      * and hence do not encounter last ditch GC.
      */
     JS_ASSERT(!InParallelSection());
 
     PrepareZoneForGC(zone);
 
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     /* The last ditch GC preserves all atoms. */
     AutoKeepAtoms keep(rt);
     GC(rt, GC_NORMAL, JS::gcreason::LAST_DITCH);
 
     /*
      * The JSGC_END callback can legitimately allocate new GC
      * things and populate the free list. If that happens, just
@@ -1953,17 +1953,17 @@ js::TriggerZoneGC(Zone *zone, JS::gcreas
 
     PrepareZoneForGC(zone);
     TriggerOperationCallback(rt, reason);
 }
 
 void
 js::MaybeGC(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->assertValidThread();
 
     if (rt->gcZeal() == ZealAllocValue || rt->gcZeal() == ZealPokeValue) {
         JS::PrepareForFullGC(rt);
         GC(rt, GC_NORMAL, JS::gcreason::MAYBEGC);
         return;
     }
 
@@ -4696,17 +4696,17 @@ AutoPrepareForTracing::AutoPrepareForTra
     copy(rt)
 {
     RecordNativeStackTopForGC(rt);
 }
 
 JSCompartment *
 js::NewCompartment(JSContext *cx, Zone *zone, JSPrincipals *principals)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     JS_AbortIfWrongThread(rt);
 
     ScopedJSDeletePtr<Zone> zoneHolder;
     if (!zone) {
         zone = cx->new_<Zone>(rt);
         if (!zone)
             return NULL;
 
@@ -4743,22 +4743,22 @@ js::NewCompartment(JSContext *cx, Zone *
     zoneHolder.forget();
     return compartment.forget();
 }
 
 void
 gc::RunDebugGC(JSContext *cx)
 {
 #ifdef JS_GC_ZEAL
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     if (rt->mainThread.suppressGC)
         return;
 
-    PrepareForDebugGC(cx->runtime);
+    PrepareForDebugGC(cx->runtime());
 
     int type = rt->gcZeal();
     if (type == ZealIncrementalRootsThenFinish ||
         type == ZealIncrementalMarkAllThenFinish ||
         type == ZealIncrementalMultipleSlices)
     {
         js::gc::State initialState = rt->gcIncrementalState;
         int64_t budget;
@@ -4785,44 +4785,44 @@ gc::RunDebugGC(JSContext *cx)
          * phase.
          */
         if (type == ZealIncrementalMultipleSlices &&
             initialState == MARK && rt->gcIncrementalState == SWEEP)
         {
             rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
         }
     } else if (type == ZealPurgeAnalysisValue) {
-        cx->compartment->types.maybePurgeAnalysis(cx, /* force = */ true);
+        cx->compartment()->types.maybePurgeAnalysis(cx, /* force = */ true);
     } else {
         Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, JS::gcreason::DEBUG_GC);
     }
 
 #endif
 }
 
 void
 gc::SetDeterministicGC(JSContext *cx, bool enabled)
 {
 #ifdef JS_GC_ZEAL
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->gcDeterministicOnly = enabled;
 #endif
 }
 
 void
 gc::SetValidateGC(JSContext *cx, bool enabled)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->gcValidate = enabled;
 }
 
 void
 gc::SetFullCompartmentChecks(JSContext *cx, bool enabled)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     rt->gcFullCompartmentChecks = enabled;
 }
 
 #ifdef DEBUG
 
 /* Should only be called manually under gdb */
 void PreventGCDuringInteractiveDebug()
 {
@@ -4901,33 +4901,33 @@ ReleaseScriptCounts(FreeOp *fop)
 
     fop->delete_(rt->scriptAndCountsVector);
     rt->scriptAndCountsVector = NULL;
 }
 
 JS_FRIEND_API(void)
 js::StartPCCountProfiling(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     if (rt->profilingScripts)
         return;
 
     if (rt->scriptAndCountsVector)
         ReleaseScriptCounts(rt->defaultFreeOp());
 
     ReleaseAllJITCode(rt->defaultFreeOp());
 
     rt->profilingScripts = true;
 }
 
 JS_FRIEND_API(void)
 js::StopPCCountProfiling(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     if (!rt->profilingScripts)
         return;
     JS_ASSERT(!rt->scriptAndCountsVector);
 
     ReleaseAllJITCode(rt->defaultFreeOp());
 
     ScriptAndCountsVector *vec = cx->new_<ScriptAndCountsVector>(SystemAllocPolicy());
@@ -4949,17 +4949,17 @@ js::StopPCCountProfiling(JSContext *cx)
 
     rt->profilingScripts = false;
     rt->scriptAndCountsVector = vec;
 }
 
 JS_FRIEND_API(void)
 js::PurgePCCounts(JSContext *cx)
 {
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
 
     if (!rt->scriptAndCountsVector)
         return;
     JS_ASSERT(!rt->profilingScripts);
 
     ReleaseScriptCounts(rt->defaultFreeOp());
 }
 
@@ -5031,17 +5031,17 @@ ArenaLists::containsArena(JSRuntime *rt,
         if (aheader == needle)
             return true;
     }
     return false;
 }
 
 
 AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSContext *cx)
-  : runtime(cx->runtime),
+  : runtime(cx->runtime()),
     markCount(runtime->gcObjectsMarkedInDeadZones),
     inIncremental(JS::IsIncrementalGCInProgress(runtime)),
     manipulatingDeadZones(runtime->gcManipulatingDeadZones)
 {
     runtime->gcManipulatingDeadZones = true;
 }
 
 AutoMaybeTouchDeadZones::AutoMaybeTouchDeadZones(JSObject *obj)
@@ -5059,17 +5059,17 @@ AutoMaybeTouchDeadZones::~AutoMaybeTouch
         JS::PrepareForFullGC(runtime);
         js::GC(runtime, GC_NORMAL, JS::gcreason::TRANSPLANT);
     }
 
     runtime->gcManipulatingDeadZones = manipulatingDeadZones;
 }
 
 AutoSuppressGC::AutoSuppressGC(JSContext *cx)
-  : suppressGC_(cx->runtime->mainThread.suppressGC)
+  : suppressGC_(cx->runtime()->mainThread.suppressGC)
 {
     suppressGC_++;
 }
 
 AutoSuppressGC::AutoSuppressGC(JSCompartment *comp)
   : suppressGC_(comp->rt->mainThread.suppressGC)
 {
     suppressGC_++;
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -499,36 +499,36 @@ TryNewNurseryGCThing(JSContext *cx, size
  * trigger GC. This will ensure that GC tracing never sees junk values stored
  * in the partially initialized thing.
  */
 template <typename T, AllowGC allowGC>
 inline T *
 NewGCThing(JSContext *cx, AllocKind kind, size_t thingSize, InitialHeap heap)
 {
     JS_ASSERT(thingSize == js::gc::Arena::thingSize(kind));
-    JS_ASSERT_IF(cx->compartment == cx->runtime->atomsCompartment,
+    JS_ASSERT_IF(cx->compartment() == cx->runtime()->atomsCompartment,
                  kind == FINALIZE_STRING ||
                  kind == FINALIZE_SHORT_STRING ||
                  kind == FINALIZE_IONCODE);
-    JS_ASSERT(!cx->runtime->isHeapBusy());
-    JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
+    JS_ASSERT(!cx->runtime()->isHeapBusy());
+    JS_ASSERT(!cx->runtime()->noGCOrAllocationCheck);
 
     /* For testing out of memory conditions */
     JS_OOM_POSSIBLY_FAIL_REPORT(cx);
 
 #ifdef JS_GC_ZEAL
-    if (cx->runtime->needZealousGC() && allowGC)
+    if (cx->runtime()->needZealousGC() && allowGC)
         js::gc::RunDebugGC(cx);
 #endif
 
     if (allowGC)
         MaybeCheckStackRoots(cx);
 
 #if defined(JSGC_GENERATIONAL)
-    if (ShouldNurseryAllocate(cx->runtime->gcNursery, kind, heap)) {
+    if (ShouldNurseryAllocate(cx->runtime()->gcNursery, kind, heap)) {
         T *t = TryNewNurseryGCThing<T, allowGC>(cx, thingSize);
         if (t)
             return t;
     }
 #endif
 
     JS::Zone *zone = cx->zone();
     T *t = static_cast<T *>(zone->allocator.arenas.allocateFromFreeList(kind, thingSize));
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -253,17 +253,17 @@ types::TypeHasProperty(JSContext *cx, Ty
         if (id == id___proto__(cx) || id == id_constructor(cx) || id == id_caller(cx))
             return true;
 
         /*
          * If we called in here while resolving a type constraint, we may be in the
          * middle of resolving a standard class and the type sets will not be updated
          * until the outer TypeSet::add finishes.
          */
-        if (cx->compartment->types.pendingCount)
+        if (cx->compartment()->types.pendingCount)
             return true;
 
         Type type = GetValueType(cx, value);
 
         AutoEnterAnalysis enter(cx);
 
         /*
          * We don't track types for properties inherited from prototypes which
@@ -301,17 +301,17 @@ types::TypeFailure(JSContext *cx, const 
     va_list ap;
     va_start(ap, fmt);
     JS_vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
     va_end(ap);
 
     JS_snprintf(msgbuf, sizeof(msgbuf), "[infer failure] %s", errbuf);
 
     /* Dump type state, even if INFERFLAGS is unset. */
-    cx->compartment->types.print(cx, true);
+    cx->compartment()->types.print(cx, true);
 
     MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
     MOZ_CRASH();
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeSet
 /////////////////////////////////////////////////////////////////////
@@ -421,58 +421,58 @@ TypeSet::addTypesToConstraint(JSContext 
      * Build all types in the set into a vector before triggering the
      * constraint, as doing so may modify this type set.
      */
     Vector<Type> types(cx);
 
     /* If any type is possible, there's no need to worry about specifics. */
     if (flags & TYPE_FLAG_UNKNOWN) {
         if (!types.append(Type::UnknownType()))
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
     } else {
         /* Enqueue type set members stored as bits. */
         for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
             if (flags & flag) {
                 Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
                 if (!types.append(type))
-                    cx->compartment->types.setPendingNukeTypes(cx);
+                    cx->compartment()->types.setPendingNukeTypes(cx);
             }
         }
 
         /* If any object is possible, skip specifics. */
         if (flags & TYPE_FLAG_ANYOBJECT) {
             if (!types.append(Type::AnyObjectType()))
-                cx->compartment->types.setPendingNukeTypes(cx);
+                cx->compartment()->types.setPendingNukeTypes(cx);
         } else {
             /* Enqueue specific object types. */
             unsigned count = getObjectCount();
             for (unsigned i = 0; i < count; i++) {
                 TypeObjectKey *object = getObject(i);
                 if (object) {
                     if (!types.append(Type::ObjectType(object)))
-                        cx->compartment->types.setPendingNukeTypes(cx);
+                        cx->compartment()->types.setPendingNukeTypes(cx);
                 }
             }
         }
     }
 
     for (unsigned i = 0; i < types.length(); i++)
         constraint->newType(cx, this, types[i]);
 }
 
 inline void
 TypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExisting)
 {
     if (!constraint) {
         /* OOM failure while constructing the constraint. */
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
 
     InferSpew(ISpewOps, "addConstraint: %sT%p%s %sC%p%s %s",
               InferSpewColor(this), this, InferSpewColorReset(),
               InferSpewColor(constraint), constraint, InferSpewColorReset(),
               constraint->kind());
 
     JS_ASSERT(constraint->next == NULL);
     constraint->next = constraintList;
@@ -529,21 +529,21 @@ TypeSet::print()
                 printf(" %s", TypeString(Type::ObjectType(object)));
         }
     }
 }
 
 StackTypeSet *
 StackTypeSet::make(JSContext *cx, const char *name)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
 
     StackTypeSet *res = cx->analysisLifoAlloc().new_<StackTypeSet>();
     if (!res) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return NULL;
     }
 
     InferSpew(ISpewOps, "typeSet: %sT%p%s intermediate %s",
               InferSpewColor(res), res, InferSpewColorReset(),
               name);
     res->setPurged();
 
@@ -1000,19 +1000,19 @@ ScriptAnalysis::pruneTypeBarriers(JSCont
  * :FIXME: this heuristic sucks, and doesn't handle calls.
  */
 static const uint32_t BARRIER_OBJECT_LIMIT = 10;
 
 void ScriptAnalysis::breakTypeBarriers(JSContext *cx, uint32_t offset, bool all)
 {
     pruneTypeBarriers(cx, offset);
 
-    bool resetResolving = !cx->compartment->types.resolving;
+    bool resetResolving = !cx->compartment()->types.resolving;
     if (resetResolving)
-        cx->compartment->types.resolving = true;
+        cx->compartment()->types.resolving = true;
 
     TypeBarrier **pbarrier = &getCode(offset).typeBarriers;
     while (*pbarrier) {
         TypeBarrier *barrier = *pbarrier;
         if (barrier->target->hasType(barrier->type) ) {
             /*
              * Barrier is now obsolete, it can be removed. This is not
              * redundant with the pruneTypeBarriers() call above, as breaking
@@ -1031,18 +1031,18 @@ void ScriptAnalysis::breakTypeBarriers(J
             barrier->target->addType(cx, barrier->type);
             *pbarrier = barrier->next;
         } else {
             pbarrier = &barrier->next;
         }
     }
 
     if (resetResolving) {
-        cx->compartment->types.resolving = false;
-        cx->compartment->types.resolvePending(cx);
+        cx->compartment()->types.resolving = false;
+        cx->compartment()->types.resolvePending(cx);
     }
 }
 
 void ScriptAnalysis::breakTypeBarriersSSA(JSContext *cx, const SSAValue &v)
 {
     if (v.kind() != SSAValue::PUSHED)
         return;
 
@@ -1129,17 +1129,17 @@ GetPropertyObject(JSContext *cx, HandleS
         break;
 
       default:
         /* undefined, null and lazy arguments do not have properties. */
         return NULL;
     }
 
     if (!object)
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
     return object;
 }
 
 static inline bool
 UsePropertyTypeBarrier(jsbytecode *pc)
 {
     /*
      * At call opcodes, type barriers can only be added for the call bindings,
@@ -1319,17 +1319,17 @@ TypeConstraintProp<access>::newType(JSCo
     RootedScript script(cx, script_);
 
     if (UnknownPropertyAccess(script, type)) {
         /*
          * Access on an unknown object. Reads produce an unknown result, writes
          * need to be monitored.
          */
         if (access == PROPERTY_WRITE)
-            cx->compartment->types.monitorBytecode(cx, script, pc - script->code);
+            cx->compartment()->types.monitorBytecode(cx, script, pc - script->code);
         else
             MarkPropertyAccessUnknown(cx, script, pc, target);
         return;
     }
 
     if (type.isPrimitive(JSVAL_TYPE_MAGIC)) {
         /* Ignore cases which will be accounted for by the followEscapingArguments analysis. */
         if (access == PROPERTY_WRITE || (id != JSID_VOID && id != id_length(cx)))
@@ -1356,24 +1356,24 @@ TypeConstraintCallProp<access>::newType(
     /*
      * For CALLPROP, we need to update not just the pushed types but also the
      * 'this' types of possible callees. If we can't figure out that set of
      * callees, monitor the call to make sure discovered callees get their
      * 'this' types updated.
      */
 
     if (UnknownPropertyAccess(script, type)) {
-        cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
+        cx->compartment()->types.monitorBytecode(cx, script, callpc - script->code);
         return;
     }
 
     TypeObject *object = GetPropertyObject(cx, script, type);
     if (object) {
         if (object->unknownProperties()) {
-            cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
+            cx->compartment()->types.monitorBytecode(cx, script, callpc - script->code);
         } else {
             TypeSet *types = object->getProperty(cx, id, false);
             if (!types)
                 return;
             if (!types->hasPropagatedProperty())
                 object->getFromPrototypes(cx, id, types);
             if (access == PROPERTY_READ) {
                 types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintPropagateThis>(
@@ -1420,17 +1420,17 @@ TypeConstraintCall::newType(JSContext *c
     RootedScript script(cx, callsite->script);
     jsbytecode *pc = callsite->pc;
 
     JS_ASSERT_IF(script->hasAnalysis(),
                  callsite->returnTypes == TypeScript::BytecodeTypes(script, pc));
 
     if (type.isUnknown() || type.isAnyObject()) {
         /* Monitor calls on unknown functions. */
-        cx->compartment->types.monitorBytecode(cx, script, pc - script->code);
+        cx->compartment()->types.monitorBytecode(cx, script, pc - script->code);
         return;
     }
 
     RootedFunction callee(cx);
 
     if (type.isSingleObject()) {
         RootedObject obj(cx, type.singleObject());
 
@@ -1441,17 +1441,17 @@ TypeConstraintCall::newType(JSContext *c
 
         if (obj->toFunction()->isNative()) {
             /*
              * The return value and all side effects within native calls should
              * be dynamically monitored, except when the compiler is generating
              * specialized inline code or stub calls for a specific natives and
              * knows about the behavior of that native.
              */
-            cx->compartment->types.monitorBytecode(cx, script, pc - script->code, true);
+            cx->compartment()->types.monitorBytecode(cx, script, pc - script->code, true);
 
             /*
              * Add type constraints capturing the possible behavior of
              * specialized natives which operate on properties. :XXX: use
              * better factoring for both this and the compiler code itself
              * which specializes particular natives.
              */
 
@@ -1579,17 +1579,17 @@ TypeConstraintPropagateThis::newType(JSC
     RootedScript script(cx, script_);
     if (type.isUnknown() || type.isAnyObject()) {
         /*
          * The callee is unknown, make sure the call is monitored so we pick up
          * possible this/callee correlations. This only comes into play for
          * CALLPROP, for other calls we are past the type barrier and a
          * TypeConstraintCall will also monitor the call.
          */
-        cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
+        cx->compartment()->types.monitorBytecode(cx, script, callpc - script->code);
         return;
     }
 
     /* Ignore calls to natives, these will be handled by TypeConstraintCall. */
     RootedFunction callee(cx);
 
     if (type.isSingleObject()) {
         RootedObject object(cx, type.singleObject());
@@ -1723,17 +1723,17 @@ TypeConstraintTransformThis::newType(JSC
       case JSVAL_TYPE_STRING:
         object = TypeScript::StandardType(cx, JSProto_String);
         break;
       default:
         return;
     }
 
     if (!object) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     target->addType(cx, Type::ObjectType(object));
 }
 
 /////////////////////////////////////////////////////////////////////
 // Freeze constraints
@@ -1755,25 +1755,25 @@ class TypeConstraintFreeze : public Type
     const char *kind() { return "freeze"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type)
     {
         if (typeAdded)
             return;
 
         typeAdded = true;
-        cx->compartment->types.addPendingRecompile(cx, info);
+        cx->compartment()->types.addPendingRecompile(cx, info);
     }
 };
 
 void
 HeapTypeSet::addFreeze(JSContext *cx)
 {
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreeze>(
-                cx->compartment->types.compiledInfo), false);
+                cx->compartment()->types.compiledInfo), false);
 }
 
 static inline JSValueType
 GetValueTypeFromTypeFlags(TypeFlags flags)
 {
     switch (flags) {
       case TYPE_FLAG_UNDEFINED:
         return JSVAL_TYPE_UNDEFINED;
@@ -1879,17 +1879,17 @@ class TypeConstraintFreezeObjectFlags : 
     const char *kind() { return "freezeObjectFlags"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type) {}
 
     void newObjectState(JSContext *cx, TypeObject *object, bool force)
     {
         if (!marked && (object->hasAnyFlags(flags) || (!flags && force))) {
             marked = true;
-            cx->compartment->types.addPendingRecompile(cx, info);
+            cx->compartment()->types.addPendingRecompile(cx, info);
         }
     }
 };
 
 bool
 StackTypeSet::hasObjectFlags(JSContext *cx, TypeObjectFlags flags)
 {
     if (unknownObject())
@@ -1918,33 +1918,33 @@ StackTypeSet::hasObjectFlags(JSContext *
         /*
          * Add a constraint on the the object to pick up changes in the
          * object's properties.
          */
         TypeSet *types = object->getProperty(cx, JSID_EMPTY, false);
         if (!types)
             return true;
         types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
-                          cx->compartment->types.compiledInfo, flags), false);
+                          cx->compartment()->types.compiledInfo, flags), false);
     }
 
     return false;
 }
 
 bool
 HeapTypeSet::HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags flags)
 {
     if (object->hasAnyFlags(flags))
         return true;
 
     HeapTypeSet *types = object->getProperty(cx, JSID_EMPTY, false);
     if (!types)
         return true;
     types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
-                      cx->compartment->types.compiledInfo, flags), false);
+                      cx->compartment()->types.compiledInfo, flags), false);
     return false;
 }
 
 static inline void
 ObjectStateChange(JSContext *cx, TypeObject *object, bool markingUnknown, bool force)
 {
     if (object->unknownProperties())
         return;
@@ -1973,17 +1973,17 @@ HeapTypeSet::WatchObjectStateChange(JSCo
     if (!types)
         return;
 
     /*
      * Use a constraint which triggers recompilation when markStateChange is
      * called, which will set 'force' to true.
      */
     types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
-                     cx->compartment->types.compiledInfo,
+                     cx->compartment()->types.compiledInfo,
                      0));
 }
 
 class TypeConstraintFreezeOwnProperty : public TypeConstraint
 {
   public:
     RecompileInfo info;
 
@@ -1999,17 +1999,17 @@ class TypeConstraintFreezeOwnProperty : 
     void newType(JSContext *cx, TypeSet *source, Type type) {}
 
     void newPropertyState(JSContext *cx, TypeSet *source)
     {
         if (updated)
             return;
         if (source->ownProperty(configurable)) {
             updated = true;
-            cx->compartment->types.addPendingRecompile(cx, info);
+            cx->compartment()->types.addPendingRecompile(cx, info);
         }
     }
 };
 
 static void
 CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, HandleFunction fun);
 
 bool
@@ -2031,17 +2031,17 @@ HeapTypeSet::isOwnProperty(JSContext *cx
             object->flags &= ~OBJECT_FLAG_NEW_SCRIPT_REGENERATE;
         }
     }
 
     if (ownProperty(configurable))
         return true;
 
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeOwnProperty>(
-                                                      cx->compartment->types.compiledInfo,
+                                                      cx->compartment()->types.compiledInfo,
                                                       configurable), false);
     return false;
 }
 
 bool
 HeapTypeSet::knownNonEmpty(JSContext *cx)
 {
     if (baseFlags() != 0 || baseObjectCount() != 0)
@@ -2361,28 +2361,28 @@ static inline void
 AddPendingRecompile(JSContext *cx, JSScript *script, jsbytecode *pc,
                     RecompileKind kind = RECOMPILE_NONE)
 {
     /*
      * Trigger recompilation of the script itself, if code was not previously
      * compiled with the specified information.
      */
     if (!JITCodeHasCheck(script, pc, kind))
-        cx->compartment->types.addPendingRecompile(cx, script, pc);
+        cx->compartment()->types.addPendingRecompile(cx, script, pc);
 
     /*
      * Remind Ion not to save the compile code if generating type
      * inference information mid-compilation causes an invalidation of the
      * script being compiled.
      */
-    RecompileInfo& info = cx->compartment->types.compiledInfo;
+    RecompileInfo& info = cx->compartment()->types.compiledInfo;
     if (info.outputIndex != RecompileInfo::NoCompilerRunning) {
         CompilerOutput *co = info.compilerOutput(cx);
         if (!co) {
-            if (script->compartment() != cx->compartment)
+            if (script->compartment() != cx->compartment())
                 MOZ_CRASH();
             return;
         }
         switch (co->kind()) {
           case CompilerOutput::Ion:
           case CompilerOutput::ParallelIon:
             if (co->script == script)
                 co->invalidate();
@@ -2436,28 +2436,28 @@ TypeCompartment::TypeCompartment()
     compiledInfo.outputIndex = RecompileInfo::NoCompilerRunning;
 }
 
 void
 TypeZone::init(JSContext *cx)
 {
     if (!cx ||
         !cx->hasOption(JSOPTION_TYPE_INFERENCE) ||
-        !cx->runtime->jitSupportsFloatingPoint)
+        !cx->runtime()->jitSupportsFloatingPoint)
     {
         return;
     }
 
     inferenceEnabled = true;
 }
 
 TypeObject *
 TypeCompartment::newTypeObject(JSContext *cx, Class *clasp, Handle<TaggedProto> proto, bool unknown)
 {
-    JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
+    JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
 
     TypeObject *object = gc::NewGCThing<TypeObject, CanGC>(cx, gc::FINALIZE_TYPE_OBJECT,
                                                            sizeof(TypeObject), gc::TenuredHeap);
     if (!object)
         return NULL;
     new(object) TypeObject(clasp, proto, clasp == &FunctionClass, unknown);
 
     if (!cx->typeInferenceEnabled())
@@ -2544,17 +2544,17 @@ FindPreviousInnerInitializer(HandleScrip
 TypeObject *
 TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key)
 {
     AutoEnterAnalysis enter(cx);
 
     if (!allocationSiteTable) {
         allocationSiteTable = cx->new_<AllocationSiteTable>();
         if (!allocationSiteTable || !allocationSiteTable->init()) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return NULL;
         }
     }
 
     AllocationSiteTable::AddPtr p = allocationSiteTable->lookupForAdd(key);
     JS_ASSERT(!p);
 
     TypeObject *res = NULL;
@@ -2568,30 +2568,30 @@ TypeCompartment::addAllocationSiteTypeOb
     RootedScript keyScript(cx, key.script);
     jsbytecode *prev = FindPreviousInnerInitializer(keyScript, pc);
     if (prev) {
         AllocationSiteKey nkey;
         nkey.script = key.script;
         nkey.offset = prev - key.script->code;
         nkey.kind = JSProto_Array;
 
-        AllocationSiteTable::Ptr p = cx->compartment->types.allocationSiteTable->lookup(nkey);
+        AllocationSiteTable::Ptr p = cx->compartment()->types.allocationSiteTable->lookup(nkey);
         if (p)
             res = p->value;
     }
 
     if (!res) {
         RootedObject proto(cx);
         if (!js_GetClassPrototype(cx, key.kind, &proto, NULL))
             return NULL;
 
         Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
         res = newTypeObject(cx, GetClassForProtoKey(key.kind), tagged);
         if (!res) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return NULL;
         }
         key.script = keyScript;
     }
 
     if (JSOp(*pc) == JSOP_NEWOBJECT) {
         /*
          * This object is always constructed the same way and will not be
@@ -2600,17 +2600,17 @@ TypeCompartment::addAllocationSiteTypeOb
          */
         RootedObject baseobj(cx, key.script->getObject(GET_UINT32_INDEX(pc)));
 
         if (!res->addDefiniteProperties(cx, baseobj))
             return NULL;
     }
 
     if (!allocationSiteTable->add(p, key, res)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return NULL;
     }
 
     return res;
 }
 
 static inline jsid
 GetAtomId(JSContext *cx, JSScript *script, const jsbytecode *pc, unsigned offset)
@@ -2762,17 +2762,17 @@ types::TypeCanHaveExtraIndexedProperties
 }
 
 bool
 TypeCompartment::growPendingArray(JSContext *cx)
 {
     unsigned newCapacity = js::Max(unsigned(100), pendingCapacity * 2);
     PendingWork *newArray = js_pod_calloc<PendingWork>(newCapacity);
     if (!newArray) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return false;
     }
 
     PodCopy(newArray, pendingArray, pendingCount);
     js_free(pendingArray);
 
     pendingArray = newArray;
     pendingCapacity = newCapacity;
@@ -2808,17 +2808,17 @@ TypeCompartment::processPendingRecompile
     fop->delete_(pending);
 }
 
 void
 TypeCompartment::setPendingNukeTypes(JSContext *cx)
 {
     TypeZone *zone = &compartment()->zone()->types;
     if (!zone->pendingNukeTypes) {
-        if (cx->compartment)
+        if (cx->compartment())
             js_ReportOutOfMemory(cx);
         zone->pendingNukeTypes = true;
     }
 }
 
 void
 TypeZone::setPendingNukeTypes()
 {
@@ -2870,64 +2870,64 @@ TypeCompartment::addPendingRecompile(JSC
     CompilerOutput *co = info.compilerOutput(cx);
     if (!co)
         return;
 
     if (co->pendingRecompilation)
         return;
 
     if (co->isValid())
-        CancelOffThreadIonCompile(cx->compartment, co->script);
+        CancelOffThreadIonCompile(cx->compartment(), co->script);
 
     if (!co->isValid()) {
         JS_ASSERT(co->script == NULL);
         return;
     }
 
 #if defined(JS_ION)
     if (!co->script->hasAnyIonScript()) {
         /* Scripts which haven't been compiled yet don't need to be recompiled. */
         return;
     }
 #endif
 
     if (!pendingRecompiles) {
         pendingRecompiles = cx->new_< Vector<RecompileInfo> >(cx);
         if (!pendingRecompiles) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
     }
 
 #if DEBUG
     for (size_t i = 0; i < pendingRecompiles->length(); i++) {
         RecompileInfo pr = (*pendingRecompiles)[i];
         JS_ASSERT(info.outputIndex != pr.outputIndex);
     }
 #endif
 
     if (!pendingRecompiles->append(info)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     InferSpew(ISpewOps, "addPendingRecompile: %p:%s:%d", co->script, co->script->filename(), co->script->lineno);
 
     co->setPendingRecompilation();
 }
 
 void
 TypeCompartment::addPendingRecompile(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     JS_ASSERT(script);
     if (!constrainedOutputs)
         return;
 
 #ifdef JS_ION
-    CancelOffThreadIonCompile(cx->compartment, script);
+    CancelOffThreadIonCompile(cx->compartment(), script);
 
     // Let the script warm up again before attempting another compile.
     if (ion::IsBaselineEnabled(cx))
         script->resetUseCount();
 
     if (script->hasIonScript())
         addPendingRecompile(cx, script->ionScript()->recompileInfo());
 
@@ -2966,17 +2966,17 @@ TypeCompartment::monitorBytecode(JSConte
     code.monitoredTypes = true;
 
     AddPendingRecompile(cx, script, pc, RECOMPILE_CHECK_MONITORED);
 }
 
 void
 TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
 {
-    JS_ASSERT(this == &cx->compartment->types);
+    JS_ASSERT(this == &cx->compartment()->types);
     JS_ASSERT(!(target->flags & OBJECT_FLAG_SETS_MARKED_UNKNOWN));
     JS_ASSERT(!target->singleton);
     JS_ASSERT(target->unknownProperties());
     target->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
 
     AutoEnterAnalysis enter(cx);
 
     /*
@@ -2992,17 +2992,17 @@ TypeCompartment::markSetsUnknown(JSConte
     Vector<TypeSet *> pending(cx);
     for (gc::CellIter i(cx->zone(), gc::FINALIZE_TYPE_OBJECT); !i.done(); i.next()) {
         TypeObject *object = i.get<TypeObject>();
         unsigned count = object->getPropertyCount();
         for (unsigned i = 0; i < count; i++) {
             Property *prop = object->getProperty(i);
             if (prop && prop->types.hasType(Type::ObjectType(target))) {
                 if (!pending.append(&prop->types))
-                    cx->compartment->types.setPendingNukeTypes(cx);
+                    cx->compartment()->types.setPendingNukeTypes(cx);
             }
         }
     }
 
     for (unsigned i = 0; i < pending.length(); i++)
         pending[i]->addType(cx, Type::AnyObjectType());
 
     for (gc::CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
@@ -3088,17 +3088,17 @@ ScriptAnalysis::addTypeBarrier(JSContext
     InferSpew(ISpewOps, "typeBarrier: #%u:%05u: %sT%p%s %s",
               script_->id(), pc - script_->code,
               InferSpewColor(target), target, InferSpewColorReset(),
               TypeString(type));
 
     barrier = cx->analysisLifoAlloc().new_<TypeBarrier>(target, type, (JSObject *) NULL, JSID_VOID);
 
     if (!barrier) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
@@ -3119,17 +3119,17 @@ ScriptAnalysis::addSingletonTypeBarrier(
               script_->id(), pc - script_->code,
               InferSpewColor(target), target, InferSpewColorReset(),
               (void *) singleton.get(), TypeIdString(singletonId));
 
     TypeBarrier *barrier = cx->analysisLifoAlloc().new_<TypeBarrier>(target, Type::UndefinedType(),
                               singleton, singletonId);
 
     if (!barrier) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
@@ -3227,17 +3227,17 @@ void
 TypeCompartment::fixArrayType(JSContext *cx, JSObject *obj)
 {
     AutoEnterAnalysis enter(cx);
 
     if (!arrayTypeTable) {
         arrayTypeTable = cx->new_<ArrayTypeTable>();
         if (!arrayTypeTable || !arrayTypeTable->init()) {
             arrayTypeTable = NULL;
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
     }
 
     /*
      * If the array is of homogenous type, pick a type object which will be
      * shared with all other singleton/JSON arrays of the same type.
      * If the array is heterogenous, keep the existing type object, which has
@@ -3269,17 +3269,17 @@ TypeCompartment::fixArrayType(JSContext 
     if (p) {
         obj->setType(p->value);
     } else {
         Rooted<Type> origType(cx, type);
         /* Make a new type to use for future arrays with the same elements. */
         RootedObject objProto(cx, obj->getProto());
         Rooted<TypeObject*> objType(cx, newTypeObject(cx, &ArrayClass, objProto));
         if (!objType) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
         obj->setType(objType);
 
         if (!objType->unknownProperties())
             objType->addPropertyType(cx, JSID_VOID, type);
 
         // The key's fields may have been moved by moving GC and therefore the
@@ -3288,17 +3288,17 @@ TypeCompartment::fixArrayType(JSContext 
         // can just conditionally update them here.
         if (type != origType || key.proto != obj->getProto()) {
             key.type = origType;
             key.proto = obj->getProto();
             p = arrayTypeTable->lookupForAdd(key);
         }
 
         if (!arrayTypeTable->relookupOrAdd(p, key, objType)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
     }
 }
 
 /*
  * N.B. We could also use the initial shape of the object (before its type is
  * fixed) as the key in the object table, but since all references in the table
@@ -3376,33 +3376,33 @@ void
 TypeCompartment::fixObjectType(JSContext *cx, JSObject *obj)
 {
     AutoEnterAnalysis enter(cx);
 
     if (!objectTypeTable) {
         objectTypeTable = cx->new_<ObjectTypeTable>();
         if (!objectTypeTable || !objectTypeTable->init()) {
             objectTypeTable = NULL;
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
     }
 
     /*
      * Use the same type object for all singleton/JSON objects with the same
      * base shape, i.e. the same fields written in the same order.
      */
     JS_ASSERT(obj->isObject());
 
     if (obj->slotSpan() == 0 || obj->inDictionaryMode() || !obj->hasEmptyElements())
         return;
 
     Vector<IdValuePair> properties(cx);
     if (!properties.resize(obj->slotSpan())) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     Shape *shape = obj->lastProperty();
     while (!shape->isEmptyShape()) {
         IdValuePair &entry = properties[shape->slot()];
         entry.id = shape->propid();
         entry.value = obj->getSlot(shape->slot());
@@ -3420,32 +3420,32 @@ TypeCompartment::fixObjectType(JSContext
         obj->setType(p->value.object);
         return;
     }
 
     /* Make a new type to use for the object and similar future ones. */
     Rooted<TaggedProto> objProto(cx, obj->getTaggedProto());
     TypeObject *objType = newTypeObject(cx, &ObjectClass, objProto);
     if (!objType || !objType->addDefiniteProperties(cx, obj)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     if (obj->isIndexed())
         objType->setFlags(cx, OBJECT_FLAG_SPARSE_INDEXES);
 
     jsid *ids = cx->pod_calloc<jsid>(properties.length());
     if (!ids) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     Type *types = cx->pod_calloc<Type>(properties.length());
     if (!types) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     for (size_t i = 0; i < properties.length(); i++) {
         ids[i] = properties[i].id;
         types[i] = GetValueTypeForTable(cx, obj->getSlot(i));
         if (!objType->unknownProperties())
             objType->addPropertyType(cx, IdToTypeId(ids[i]), types[i]);
@@ -3459,33 +3459,33 @@ TypeCompartment::fixObjectType(JSContext
 
     ObjectTableEntry entry;
     entry.object = objType;
     entry.shape = obj->lastProperty();
     entry.types = types;
 
     p = objectTypeTable->lookupForAdd(lookup);
     if (!objectTypeTable->add(p, key, entry)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     obj->setType(objType);
 }
 
 JSObject *
 TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t nproperties)
 {
     AutoEnterAnalysis enter(cx);
 
     if (!objectTypeTable) {
         objectTypeTable = cx->new_<ObjectTypeTable>();
         if (!objectTypeTable || !objectTypeTable->init()) {
             objectTypeTable = NULL;
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return NULL;
         }
     }
 
     /*
      * Use the object type table to allocate an object with the specified
      * properties, filling in its final type and shape and failing if no cache
      * entry could be found for the properties.
@@ -3594,17 +3594,17 @@ UpdatePropertyType(JSContext *cx, TypeSe
 }
 
 bool
 TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
 {
     JS_ASSERT(!*pprop);
     Property *base = cx->typeLifoAlloc().new_<Property>(id);
     if (!base) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return false;
     }
 
     if (singleton && singleton->isNative()) {
         /*
          * Fill the property in with any type the object already has in an own
          * property. We are only interested in plain native properties and
          * dense elements which don't go through a barrier when read by the VM
@@ -3739,17 +3739,17 @@ TypeObject::addPropertyType(JSContext *c
 void
 TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
 {
     jsid id = JSID_VOID;
     if (name) {
         JSAtom *atom = Atomize(cx, name, strlen(name));
         if (!atom) {
             AutoEnterAnalysis enter(cx);
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
         id = AtomToId(atom);
     }
     InlineAddTypeProperty(cx, this, id, type);
 }
 
 void
@@ -3808,17 +3808,17 @@ TypeObject::setFlags(JSContext *cx, Type
     ObjectStateChange(cx, this, false, false);
 }
 
 void
 TypeObject::markUnknown(JSContext *cx)
 {
     AutoEnterAnalysis enter(cx);
 
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
     JS_ASSERT(!unknownProperties());
 
     if (!(flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED))
         clearNewScript(cx);
 
     InferSpew(ISpewOps, "UnknownProperties: %s", TypeObjectString(this));
 
     ObjectStateChange(cx, this, true, true);
@@ -4272,17 +4272,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         PropertyAccess<PROPERTY_WRITE>(cx, script, pc, global, poppedTypes(pc, 0), id);
         poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
         break;
       }
 
       case JSOP_SETNAME:
       case JSOP_SETINTRINSIC:
       case JSOP_SETCONST:
-        cx->compartment->types.monitorBytecode(cx, script, offset);
+        cx->compartment()->types.monitorBytecode(cx, script, offset);
         poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
         break;
 
       case JSOP_GETXPROP: {
         StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
         addTypeBarrier(cx, pc, seen, Type::UnknownType());
         seen->addSubset(cx, &pushed[0]);
         break;
@@ -4477,17 +4477,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         if (script->compileAndGo && !script->treatAsRunOnce && !UseNewTypeForClone(obj->toFunction()))
             res->addType(cx, Type::ObjectType(obj));
         else
             res->addType(cx, Type::AnyObjectType());
         break;
       }
 
       case JSOP_DEFFUN:
-        cx->compartment->types.monitorBytecode(cx, script, offset);
+        cx->compartment()->types.monitorBytecode(cx, script, offset);
         break;
 
       case JSOP_DEFVAR:
         break;
 
       case JSOP_CALL:
       case JSOP_EVAL:
       case JSOP_FUNCALL:
@@ -4496,32 +4496,32 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
         seen->addSubset(cx, &pushed[0]);
 
         /* Construct the base call information about this site. */
         unsigned argCount = GetUseCount(script, offset) - 2;
         TypeCallsite *callsite = cx->analysisLifoAlloc().new_<TypeCallsite>(
                                                         cx, script, pc, op == JSOP_NEW, argCount);
         if (!callsite || (argCount && !callsite->argumentTypes)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             break;
         }
         callsite->thisTypes = poppedTypes(pc, argCount);
         callsite->returnTypes = seen;
 
         for (unsigned i = 0; i < argCount; i++)
             callsite->argumentTypes[i] = poppedTypes(pc, argCount - 1 - i);
 
         /*
          * Mark FUNCALL and FUNAPPLY sites as monitored. The method JIT may
          * lower these into normal calls, and we need to make sure the
          * callee's argument types are checked on entry.
          */
         if (op == JSOP_FUNCALL || op == JSOP_FUNAPPLY)
-            cx->compartment->types.monitorBytecode(cx, script, pc - script->code);
+            cx->compartment()->types.monitorBytecode(cx, script, pc - script->code);
 
         StackTypeSet *calleeTypes = poppedTypes(pc, argCount + 1);
 
         /*
          * Propagate possible 'this' types to the callee except when the call
          * came through JSOP_CALLPROP (which uses TypeConstraintCallProperty)
          * or for JSOP_NEW (where the callee will construct the 'this' object).
          */
@@ -4629,17 +4629,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         if (initializer) {
             pushed[0].addType(cx, Type::ObjectType(initializer));
             if (!initializer->unknownProperties()) {
                 jsid id = GetAtomId(cx, script, pc, 0);
                 TypeSet *types = initializer->getProperty(cx, id, true);
                 if (!types)
                     return false;
                 if (id == id___proto__(cx) || id == id_prototype(cx))
-                    cx->compartment->types.monitorBytecode(cx, script, offset);
+                    cx->compartment()->types.monitorBytecode(cx, script, offset);
                 else if (op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER)
                     types->addType(cx, Type::UnknownType());
                 else
                     poppedTypes(pc, 0)->addSubset(cx, types);
             }
         } else {
             pushed[0].addType(cx, Type::UnknownType());
         }
@@ -4695,17 +4695,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
 
       case JSOP_MOREITER:
         pushed[1].addType(cx, Type::BooleanType());
         break;
 
       case JSOP_ENUMELEM:
       case JSOP_ENUMCONSTELEM:
       case JSOP_ARRAYPUSH:
-        cx->compartment->types.monitorBytecode(cx, script, offset);
+        cx->compartment()->types.monitorBytecode(cx, script, offset);
         break;
 
       case JSOP_THROW:
         /* There will be a monitor on the bytecode catching the exception. */
         break;
 
       case JSOP_FINALLY:
         /* Pushes information about whether an exception was thrown. */
@@ -4755,17 +4755,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
 }
 
 void
 ScriptAnalysis::analyzeTypes(JSContext *cx)
 {
     JS_ASSERT(!ranInference());
 
     if (OOM()) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     if (!ranSSA()) {
         analyzeSSA(cx);
         if (failed())
             return;
     }
@@ -4789,46 +4789,46 @@ ScriptAnalysis::analyzeTypes(JSContext *
      * property type sets previously added.
      */
     if (script_->types->propertyReadTypes) {
         state.hasPropertyReadTypes = true;
     } else {
         HeapTypeSet *typeArray =
             (HeapTypeSet*) cx->typeLifoAlloc().alloc(sizeof(HeapTypeSet) * numPropertyReads());
         if (!typeArray) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
         script_->types->propertyReadTypes = typeArray;
         PodZero(typeArray, numPropertyReads());
 
 #ifdef DEBUG
         for (unsigned i = 0; i < numPropertyReads(); i++) {
             InferSpew(ISpewOps, "typeSet: %sT%p%s propertyRead%u #%u",
                       InferSpewColor(&typeArray[i]), &typeArray[i], InferSpewColorReset(),
                       i, script_->id());
         }
 #endif
     }
 
     undefinedTypeSet = cx->analysisLifoAlloc().new_<StackTypeSet>();
     if (!undefinedTypeSet) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
     undefinedTypeSet->addType(cx, Type::UndefinedType());
 
     unsigned offset = 0;
     while (offset < script_->length) {
         Bytecode *code = maybeCode(offset);
 
         jsbytecode *pc = script_->code + offset;
 
         if (code && !analyzeTypesBytecode(cx, offset, state)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
 
         offset += GetBytecodeLength(pc);
     }
 
     JS_ASSERT(state.propertyReadIndex == numPropertyReads());
 
@@ -4996,17 +4996,17 @@ AnalyzeNewScriptProperties(JSContext *cx
          * number of properties we can track), we may be recursing.
          */
         return false;
     }
 
     RootedScript script(cx, fun->nonLazyScript());
     if (!script->ensureRanAnalysis(cx) || !script->ensureRanInference(cx)) {
         state.baseobj = NULL;
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return false;
     }
 
     ScriptAnalysis *analysis = script->analysis();
 
     /*
      * Offset of the last bytecode which popped 'this' and which we have
      * processed. To support compound inline assignments to properties like
@@ -5118,34 +5118,34 @@ AnalyzePoppedThis(JSContext *cx, SSAUseC
         if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id))
             return false;
 
         unsigned slotSpan = state.baseobj->slotSpan();
         RootedValue value(cx, UndefinedValue());
         if (!DefineNativeProperty(cx, state.baseobj, id, value, NULL, NULL,
                                   JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE))
         {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             state.baseobj = NULL;
             return false;
         }
 
         if (state.baseobj->inDictionaryMode()) {
             state.baseobj = NULL;
             return false;
         }
 
         if (state.baseobj->slotSpan() == slotSpan) {
             /* Set a duplicate property. */
             return false;
         }
 
         TypeNewScript::Initializer setprop(TypeNewScript::Initializer::SETPROP, use->offset);
         if (!state.initializerList.append(setprop)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             state.baseobj = NULL;
             return false;
         }
 
         if (state.baseobj->slotSpan() >= (TYPE_FLAG_DEFINITE_MASK >> TYPE_FLAG_DEFINITE_SHIFT)) {
             /* Maximum number of definite properties added. */
             return false;
         }
@@ -5164,17 +5164,17 @@ AnalyzePoppedThis(JSContext *cx, SSAUseC
          *   is not later added as one. Since the definite properties are
          *   added to the object at the point of its creation, reading a
          *   definite property before it is assigned could incorrectly hit.
          */
         RootedId id(cx, NameToId(script->getName(GET_UINT32_INDEX(pc))));
         if (IdToTypeId(id) != id)
             return false;
         if (!state.baseobj->nativeLookup(cx, id) && !state.accessedProperties.append(id.get())) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             state.baseobj = NULL;
             return false;
         }
 
         if (!AddClearDefiniteGetterSetterForPrototypeChain(cx, type, id))
             return false;
 
         /*
@@ -5249,27 +5249,27 @@ AnalyzePoppedThis(JSContext *cx, SSAUseC
          */
         funcallTypes->add(cx,
             cx->analysisLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
         scriptTypes->add(cx,
             cx->analysisLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
 
         TypeNewScript::Initializer pushframe(TypeNewScript::Initializer::FRAME_PUSH, use->offset);
         if (!state.initializerList.append(pushframe)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             state.baseobj = NULL;
             return false;
         }
 
         if (!AnalyzeNewScriptProperties(cx, type, function, state))
             return false;
 
         TypeNewScript::Initializer popframe(TypeNewScript::Initializer::FRAME_POP, 0);
         if (!state.initializerList.append(popframe)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             state.baseobj = NULL;
             return false;
         }
 
         /*
          * The callee never lets the 'this' value escape, continue looking
          * for definite properties in the remainder of this script.
          */
@@ -5294,17 +5294,17 @@ CheckNewScriptProperties(JSContext *cx, 
     NewScriptPropertiesState state(cx);
     state.thisFunction = fun;
 
     /* Strawman object to add properties to and watch for duplicates. */
     state.baseobj = NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16);
     if (!state.baseobj) {
         if (type->newScript)
             type->clearNewScript(cx);
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     AnalyzeNewScriptProperties(cx, type, fun, state);
     if (!state.baseobj ||
         state.baseobj->slotSpan() == 0 ||
         !!(type->flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED))
     {
@@ -5336,17 +5336,17 @@ CheckNewScriptProperties(JSContext *cx, 
      * than we will use for subsequent new objects. Generate an object with the
      * appropriate final shape.
      */
     RootedShape shape(cx, state.baseobj->lastProperty());
     state.baseobj = NewReshapedObject(cx, type, state.baseobj->getParent(), kind, shape);
     if (!state.baseobj ||
         !type->addDefiniteProperties(cx, state.baseobj) ||
         !state.initializerList.append(done)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     size_t numBytes = sizeof(TypeNewScript)
                     + (state.initializerList.length() * sizeof(TypeNewScript::Initializer));
 #ifdef JSGC_ROOT_ANALYSIS
     // calloc can legitimately return a pointer that appears to be poisoned.
     void *p;
@@ -5354,17 +5354,17 @@ CheckNewScriptProperties(JSContext *cx, 
         p = cx->calloc_(numBytes);
     } while (IsPoisonedPtr(p));
     type->newScript = (TypeNewScript *) p;
 #else
     type->newScript = (TypeNewScript *) cx->calloc_(numBytes);
 #endif
 
     if (!type->newScript) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     type->newScript->fun = fun;
     type->newScript->allocKind = kind;
     type->newScript->shape = state.baseobj->lastProperty();
 
     type->newScript->initializerList = (TypeNewScript::Initializer *)
@@ -5538,17 +5538,17 @@ types::MarkIteratorUnknownSlow(JSContext
         }
         result = result->next;
     }
 
     InferSpew(ISpewOps, "externalType: customIterator #%u", script->id());
 
     result = cx->new_<TypeResult>(UINT32_MAX, Type::UnknownType());
     if (!result) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
     result->next = script->types->dynamicList;
     script->types->dynamicList = result;
 
     AddPendingRecompile(cx, script, NULL);
 
     if (!script->hasAnalysis() || !script->analysis()->ranInference())
@@ -5607,17 +5607,17 @@ types::TypeDynamicResult(JSContext *cx, 
     if (!script->types)
         return;
 
     AutoEnterAnalysis enter(cx);
 
     /* Directly update associated type sets for applicable bytecodes. */
     if (js_CodeSpec[*pc].format & JOF_TYPESET) {
         if (!script->ensureHasBytecodeTypeMap(cx)) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
         TypeSet *types = TypeScript::BytecodeTypes(script, pc);
         if (!types->hasType(type)) {
             InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
                       script->id(), pc - script->code, TypeString(type));
             types->addType(cx, type);
         }
@@ -5651,17 +5651,17 @@ types::TypeDynamicResult(JSContext *cx, 
         }
     }
 
     InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
               script->id(), pc - script->code, TypeString(type));
 
     TypeResult *result = cx->new_<TypeResult>(pc - script->code, type);
     if (!result) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
     result->next = script->types->dynamicList;
     script->types->dynamicList = result;
 
     /*
      * New type information normally requires all code in the entire script to
      * be recompiled, as changes to types can flow through variables etc. into
@@ -5713,17 +5713,17 @@ types::TypeMonitorResult(JSContext *cx, 
         return;
 
     if (!script->types)
         return;
 
     AutoEnterAnalysis enter(cx);
 
     if (!script->ensureHasBytecodeTypeMap(cx)) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return;
     }
 
     Type type = GetValueType(cx, rval);
     TypeSet *types = TypeScript::BytecodeTypes(script, pc);
     if (types->hasType(type))
         return;
 
@@ -5824,17 +5824,17 @@ JSScript::makeTypes(JSContext *cx)
     }
 
     AutoEnterAnalysis enter(cx);
 
     unsigned count = TypeScript::NumTypeSets(this);
 
     types = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(TypeSet) * count));
     if (!types) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return false;
     }
 
     new(types) TypeScript();
 
     TypeSet *typeArray = types->typeArray();
     TypeSet *returnTypes = TypeScript::ReturnTypes(this);
 
@@ -5947,17 +5947,17 @@ JSFunction::setTypeForScriptedFunction(J
     if (!cx->typeInferenceEnabled())
         return true;
 
     if (singleton) {
         if (!setSingletonType(cx, fun))
             return false;
     } else {
         RootedObject funProto(cx, fun->getProto());
-        TypeObject *type = cx->compartment->types.newTypeObject(cx, &FunctionClass, funProto);
+        TypeObject *type = cx->compartment()->types.newTypeObject(cx, &FunctionClass, funProto);
         if (!type)
             return false;
 
         fun->setType(type);
         type->interpretedFunction = fun;
     }
 
     return true;
@@ -5981,17 +5981,17 @@ JSObject::shouldSplicePrototype(JSContex
     if (getProto() != NULL)
         return false;
     return !cx->typeInferenceEnabled() || hasSingletonType();
 }
 
 bool
 JSObject::splicePrototype(JSContext *cx, Class *clasp, Handle<TaggedProto> proto)
 {
-    JS_ASSERT(cx->compartment == compartment());
+    JS_ASSERT(cx->compartment() == compartment());
 
     RootedObject self(cx, this);
 
     /*
      * For singleton types representing only a single JSObject, the proto
      * can be rearranged as needed without destroying type information for
      * the old or new types. Note that type constraints propagating properties
      * from the old prototype are not removed.
@@ -6011,17 +6011,17 @@ JSObject::splicePrototype(JSContext *cx,
     Rooted<TypeObject*> protoType(cx, NULL);
     if (proto.isObject()) {
         protoType = proto.toObject()->getType(cx);
         if (!protoType)
             return false;
     }
 
     if (!cx->typeInferenceEnabled()) {
-        TypeObject *type = cx->compartment->getNewType(cx, clasp, proto);
+        TypeObject *type = cx->compartment()->getNewType(cx, clasp, proto);
         if (!type)
             return false;
         self->type_ = type;
         return true;
     }
 
     type->clasp = clasp;
     type->proto = proto.raw();
@@ -6045,29 +6045,29 @@ JSObject::splicePrototype(JSContext *cx,
 
     return true;
 }
 
 /* static */ TypeObject *
 JSObject::makeLazyType(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->hasLazyType());
-    JS_ASSERT(cx->compartment == obj->compartment());
+    JS_ASSERT(cx->compartment() == obj->compartment());
 
     /* De-lazification of functions can GC, so we need to do it up here. */
     if (obj->isFunction() && obj->toFunction()->isInterpretedLazy()) {
         RootedFunction fun(cx, obj->toFunction());
         if (!fun->getOrCreateScript(cx))
             return NULL;
     }
     Rooted<TaggedProto> proto(cx, obj->getTaggedProto());
-    TypeObject *type = cx->compartment->types.newTypeObject(cx, obj->getClass(), proto);
+    TypeObject *type = cx->compartment()->types.newTypeObject(cx, obj->getClass(), proto);
     if (!type) {
         if (cx->typeInferenceEnabled())
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
         return obj->type_;
     }
 
     if (!cx->typeInferenceEnabled()) {
         /* This can only happen if types were previously nuked. */
         obj->type_ = type;
         return type;
     }
@@ -6139,30 +6139,30 @@ JSObject::setNewTypeUnknown(JSContext *c
     if (!obj->setFlag(cx, js::BaseShape::NEW_TYPE_UNKNOWN))
         return false;
 
     /*
      * If the object already has a new type, mark that type as unknown. It will
      * not have the SETS_MARKED_UNKNOWN bit set, so may require a type set
      * crawl if prototypes of the object change dynamically in the future.
      */
-    TypeObjectSet &table = cx->compartment->newTypeObjects;
+    TypeObjectSet &table = cx->compartment()->newTypeObjects;
     if (table.initialized()) {
         if (TypeObjectSet::Ptr p = table.lookup(TypeObjectSet::Lookup(clasp, obj.get())))
             MarkTypeObjectUnknownProperties(cx, *p);
     }
 
     return true;
 }
 
 TypeObject *
 JSCompartment::getNewType(JSContext *cx, Class *clasp, TaggedProto proto_, JSFunction *fun_)
 {
     JS_ASSERT_IF(fun_, proto_.isObject());
-    JS_ASSERT_IF(proto_.isObject(), cx->compartment == proto_.toObject()->compartment());
+    JS_ASSERT_IF(proto_.isObject(), cx->compartment() == proto_.toObject()->compartment());
 
     if (!newTypeObjects.initialized() && !newTypeObjects.init())
         return NULL;
 
     TypeObjectSet::AddPtr p = newTypeObjects.lookupForAdd(TypeObjectSet::Lookup(clasp, proto_));
     if (p) {
         TypeObject *type = *p;
 
@@ -6242,42 +6242,42 @@ JSCompartment::getNewType(JSContext *cx,
         type->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
 
     return type;
 }
 
 TypeObject *
 JSObject::getNewType(JSContext *cx, Class *clasp, JSFunction *fun)
 {
-    return cx->compartment->getNewType(cx, clasp, this, fun);
+    return cx->compartment()->getNewType(cx, clasp, this, fun);
 }
 
 TypeObject *
 JSCompartment::getLazyType(JSContext *cx, Class *clasp, TaggedProto proto)
 {
-    JS_ASSERT(cx->compartment == this);
-    JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
+    JS_ASSERT(cx->compartment() == this);
+    JS_ASSERT_IF(proto.isObject(), cx->compartment() == proto.toObject()->compartment());
 
     AutoEnterAnalysis enter(cx);
 
-    TypeObjectSet &table = cx->compartment->lazyTypeObjects;
+    TypeObjectSet &table = cx->compartment()->lazyTypeObjects;
 
     if (!table.initialized() && !table.init())
         return NULL;
 
     TypeObjectSet::AddPtr p = table.lookupForAdd(TypeObjectSet::Lookup(clasp, proto));
     if (p) {
         TypeObject *type = *p;
         JS_ASSERT(type->lazy());
 
         return type;
     }
 
     Rooted<TaggedProto> protoRoot(cx, proto);
-    TypeObject *type = cx->compartment->types.newTypeObject(cx, clasp, protoRoot, false);
+    TypeObject *type = cx->compartment()->types.newTypeObject(cx, clasp, protoRoot, false);
     if (!type)
         return NULL;
 
     if (!table.relookupOrAdd(p, TypeObjectSet::Lookup(clasp, protoRoot), type))
         return NULL;
 
     type->singleton = (JSObject *) TypeObject::LAZY_SINGLETON;
 
@@ -6751,64 +6751,64 @@ TypeScript::Purge(JSContext *cx, HandleS
 }
 
 void
 TypeCompartment::maybePurgeAnalysis(JSContext *cx, bool force)
 {
     // FIXME bug 781657
     return;
 
-    JS_ASSERT(this == &cx->compartment->types);
-    JS_ASSERT(!cx->compartment->activeAnalysis);
+    JS_ASSERT(this == &cx->compartment()->types);
+    JS_ASSERT(!cx->compartment()->activeAnalysis);
 
     if (!cx->typeInferenceEnabled())
         return;
 
-    size_t triggerBytes = cx->runtime->analysisPurgeTriggerBytes;
-    size_t beforeUsed = cx->compartment->analysisLifoAlloc.used();
+    size_t triggerBytes = cx->runtime()->analysisPurgeTriggerBytes;
+    size_t beforeUsed = cx->compartment()->analysisLifoAlloc.used();
 
     if (!force) {
         if (!triggerBytes || triggerBytes >= beforeUsed)
             return;
     }
 
     AutoEnterAnalysis enter(cx);
 
     /* Reset the analysis pool, making its memory available for reuse. */
-    cx->compartment->analysisLifoAlloc.releaseAll();
+    cx->compartment()->analysisLifoAlloc.releaseAll();
 
     uint64_t start = PRMJ_Now();
 
     for (gc::CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
         RootedScript script(cx, i.get<JSScript>());
-        if (script->compartment() == cx->compartment)
+        if (script->compartment() == cx->compartment())
             TypeScript::Purge(cx, script);
     }
 
     uint64_t done = PRMJ_Now();
 
-    if (cx->runtime->analysisPurgeCallback) {
-        size_t afterUsed = cx->compartment->analysisLifoAlloc.used();
+    if (cx->runtime()->analysisPurgeCallback) {
+        size_t afterUsed = cx->compartment()->analysisLifoAlloc.used();
         size_t typeUsed = cx->typeLifoAlloc().used();
 
         char buf[1000];
         JS_snprintf(buf, sizeof(buf),
                     "Total Time %.2f ms, %d bytes before, %d bytes after\n",
                     (done - start) / double(PRMJ_USEC_PER_MSEC),
                     (int) (beforeUsed + typeUsed),
                     (int) (afterUsed + typeUsed));
 
         JSString *desc = JS_NewStringCopyZ(cx, buf);
         if (!desc) {
             cx->clearPendingException();
             return;
         }
 
         JS::Rooted<JSFlatString*> flat(cx, &desc->asFlat());
-        cx->runtime->analysisPurgeCallback(cx->runtime, flat);
+        cx->runtime()->analysisPurgeCallback(cx->runtime(), flat);
     }
 }
 
 static void
 SizeOfScriptTypeInferenceData(JSScript *script, JS::TypeInferenceSizes *sizes,
                               JSMallocSizeOfFun mallocSizeOf)
 {
     TypeScript *typeScript = script->types;
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -155,17 +155,17 @@ RecompileInfo::compilerOutput(TypeCompar
     if (!types.constrainedOutputs || outputIndex >= types.constrainedOutputs->length())
         return NULL;
     return &(*types.constrainedOutputs)[outputIndex];
 }
 
 inline CompilerOutput*
 RecompileInfo::compilerOutput(JSContext *cx) const
 {
-    return compilerOutput(cx->compartment->types);
+    return compilerOutput(cx->compartment()->types);
 }
 
 /////////////////////////////////////////////////////////////////////
 // Types
 /////////////////////////////////////////////////////////////////////
 
 /* static */ inline Type
 Type::ObjectType(JSObject *obj)
@@ -333,17 +333,17 @@ struct AutoEnterAnalysis
 
     FreeOp *freeOp;
     JSCompartment *compartment;
     bool oldActiveAnalysis;
 
     AutoEnterAnalysis(JSContext *cx)
       : suppressGC(cx)
     {
-        init(cx->runtime->defaultFreeOp(), cx->compartment);
+        init(cx->runtime()->defaultFreeOp(), cx->compartment());
     }
 
     AutoEnterAnalysis(FreeOp *fop, JSCompartment *comp)
       : suppressGC(comp)
     {
         init(fop, comp);
     }
 
@@ -382,20 +382,20 @@ struct AutoEnterAnalysis
 struct AutoEnterCompilation
 {
     JSContext *cx;
     RecompileInfo &info;
     CompilerOutput::Kind kind;
 
     AutoEnterCompilation(JSContext *cx, CompilerOutput::Kind kind)
       : cx(cx),
-        info(cx->compartment->types.compiledInfo),
+        info(cx->compartment()->types.compiledInfo),
         kind(kind)
     {
-        JS_ASSERT(cx->compartment->activeAnalysis);
+        JS_ASSERT(cx->compartment()->activeAnalysis);
         JS_ASSERT(info.outputIndex == RecompileInfo::NoCompilerRunning);
     }
 
     bool init(JSScript *script, bool constructing, unsigned chunkIndex)
     {
         CompilerOutput co;
         co.script = script;
         co.setKind(kind);
@@ -406,17 +406,17 @@ struct AutoEnterCompilation
         // This flag is used to prevent adding the current compiled script in
         // the list of compiler output which should be invalided.  This is
         // necessary because we can run some analysis might discard the script
         // it-self, which can happen when the monitored value does not reflect
         // the types propagated by the type inference.
         co.pendingRecompilation = true;
 
         JS_ASSERT(!co.isValid());
-        TypeCompartment &types = cx->compartment->types;
+        TypeCompartment &types = cx->compartment()->types;
         if (!types.constrainedOutputs) {
             types.constrainedOutputs = cx->new_< Vector<CompilerOutput> >(cx);
             if (!types.constrainedOutputs) {
                 types.setPendingNukeTypes(cx);
                 return false;
             }
         }
 
@@ -440,17 +440,17 @@ struct AutoEnterCompilation
     }
 
     ~AutoEnterCompilation()
     {
         // Handle failure cases of init.
         if (info.outputIndex >= RecompileInfo::NoCompilerRunning)
             return;
 
-        JS_ASSERT(info.outputIndex < cx->compartment->types.constrainedOutputs->length());
+        JS_ASSERT(info.outputIndex < cx->compartment()->types.constrainedOutputs->length());
         CompilerOutput *co = info.compilerOutput(cx);
         co->pendingRecompilation = false;
         if (!co->isValid())
             co->invalidate();
 
         info.outputIndex = RecompileInfo::NoCompilerRunning;
     }
 };
@@ -646,17 +646,17 @@ MarkTypeObjectFlags(JSContext *cx, JSObj
 inline void
 MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj,
                                 bool markSetsUnknown = false)
 {
     if (cx->typeInferenceEnabled()) {
         if (!obj->unknownProperties())
             obj->markUnknown(cx);
         if (markSetsUnknown && !(obj->flags & OBJECT_FLAG_SETS_MARKED_UNKNOWN))
-            cx->compartment->types.markSetsUnknown(cx, obj);
+            cx->compartment()->types.markSetsUnknown(cx, obj);
     }
 }
 
 /*
  * Mark any property which has been deleted or configured to be non-writable or
  * have a getter/setter.
  */
 inline void
@@ -680,24 +680,24 @@ MarkObjectStateChange(JSContext *cx, JSO
  * For an array or object which has not yet escaped and been referenced elsewhere,
  * pick a new type based on the object's current contents.
  */
 
 inline void
 FixArrayType(JSContext *cx, HandleObject obj)
 {
     if (cx->typeInferenceEnabled())
-        cx->compartment->types.fixArrayType(cx, obj);
+        cx->compartment()->types.fixArrayType(cx, obj);
 }
 
 inline void
 FixObjectType(JSContext *cx, HandleObject obj)
 {
     if (cx->typeInferenceEnabled())
-        cx->compartment->types.fixObjectType(cx, obj);
+        cx->compartment()->types.fixObjectType(cx, obj);
 }
 
 /* Interface helpers for JSScript*. */
 extern void TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc,
                               const js::Value &rval);
 extern void TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc,
                               js::types::Type type);
 
@@ -911,24 +911,24 @@ TypeScript::InitObject(JSContext *cx, JS
     if (!cx->typeInferenceEnabled() || !script->compileAndGo || offset >= AllocationSiteKey::OFFSET_LIMIT)
         return GetTypeNewObject(cx, kind);
 
     AllocationSiteKey key;
     key.script = script;
     key.offset = offset;
     key.kind = kind;
 
-    if (!cx->compartment->types.allocationSiteTable)
-        return cx->compartment->types.addAllocationSiteTypeObject(cx, key);
+    if (!cx->compartment()->types.allocationSiteTable)
+        return cx->compartment()->types.addAllocationSiteTypeObject(cx, key);
 
-    AllocationSiteTable::Ptr p = cx->compartment->types.allocationSiteTable->lookup(key);
+    AllocationSiteTable::Ptr p = cx->compartment()->types.allocationSiteTable->lookup(key);
 
     if (p)
         return p->value;
-    return cx->compartment->types.addAllocationSiteTypeObject(cx, key);
+    return cx->compartment()->types.addAllocationSiteTypeObject(cx, key);
 }
 
 /* Set the type to use for obj according to the site it was allocated at. */
 static inline bool
 SetInitializerObjectType(JSContext *cx, HandleScript script, jsbytecode *pc, HandleObject obj, NewObjectKind kind)
 {
     if (!cx->typeInferenceEnabled())
         return true;
@@ -1106,18 +1106,18 @@ inline JSCompartment *
 TypeCompartment::compartment()
 {
     return (JSCompartment *)((char *)this - offsetof(JSCompartment, types));
 }
 
 inline void
 TypeCompartment::addPending(JSContext *cx, TypeConstraint *constraint, TypeSet *source, Type type)
 {
-    JS_ASSERT(this == &cx->compartment->types);
-    JS_ASSERT(!cx->runtime->isHeapBusy());
+    JS_ASSERT(this == &cx->compartment()->types);
+    JS_ASSERT(!cx->runtime()->isHeapBusy());
 
     InferSpew(ISpewOps, "pending: %sC%p%s %s",
               InferSpewColor(constraint), constraint, InferSpewColorReset(),
               TypeString(type));
 
     if ((pendingCount == pendingCapacity) && !growPendingArray(cx))
         return;
 
@@ -1125,17 +1125,17 @@ TypeCompartment::addPending(JSContext *c
     pending.constraint = constraint;
     pending.source = source;
     pending.type = type;
 }
 
 inline void
 TypeCompartment::resolvePending(JSContext *cx)
 {
-    JS_ASSERT(this == &cx->compartment->types);
+    JS_ASSERT(this == &cx->compartment()->types);
 
     if (resolving) {
         /* There is an active call further up resolving the worklist. */
         return;
     }
 
     resolving = true;
 
@@ -1380,17 +1380,17 @@ TypeSet::clearObjects()
 {
     setBaseObjectCount(0);
     objectSet = NULL;
 }
 
 inline void
 TypeSet::addType(JSContext *cx, Type type)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
 
     if (unknown())
         return;
 
     if (type.isUnknown()) {
         flags |= TYPE_FLAG_BASE_MASK;
         clearObjects();
         JS_ASSERT(unknown());
@@ -1406,24 +1406,24 @@ TypeSet::addType(JSContext *cx, Type typ
         flags |= flag;
     } else {
         if (flags & TYPE_FLAG_ANYOBJECT)
             return;
         if (type.isAnyObject())
             goto unknownObject;
 
         LifoAlloc &alloc =
-            purged() ? cx->compartment->analysisLifoAlloc : cx->typeLifoAlloc();
+            purged() ? cx->compartment()->analysisLifoAlloc : cx->typeLifoAlloc();
 
         uint32_t objectCount = baseObjectCount();
         TypeObjectKey *object = type.objectKey();
         TypeObjectKey **pentry = HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
                                      (alloc, objectSet, objectCount, object);
         if (!pentry) {
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
             return;
         }
         if (*pentry)
             return;
         *pentry = object;
 
         setBaseObjectCount(objectCount);
 
@@ -1455,21 +1455,21 @@ TypeSet::addType(JSContext *cx, Type typ
 
     InferSpew(ISpewOps, "addType: %sT%p%s %s",
               InferSpewColor(this), this, InferSpewColorReset(),
               TypeString(type));
 
     /* Propagate the type to all constraints. */
     TypeConstraint *constraint = constraintList;
     while (constraint) {
-        cx->compartment->types.addPending(cx, constraint, this, type);
+        cx->compartment()->types.addPending(cx, constraint, this, type);
         constraint = constraint->next;
     }
 
-    cx->compartment->types.resolvePending(cx);
+    cx->compartment()->types.resolvePending(cx);
 }
 
 inline void
 TypeSet::setOwnProperty(JSContext *cx, bool configured)
 {
     TypeFlags nflags = TYPE_FLAG_OWN_PROPERTY | (configured ? TYPE_FLAG_CONFIGURED_PROPERTY : 0);
 
     if ((flags & nflags) == nflags)
@@ -1518,25 +1518,25 @@ TypeSet::getTypeObject(unsigned i) const
 {
     TypeObjectKey *key = getObject(i);
     return (key && !(uintptr_t(key) & 1)) ? (TypeObject *) key : NULL;
 }
 
 inline TypeObject *
 TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i) const
 {
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
     TypeObject *type = getTypeObject(i);
     if (!type) {
         JSObject *singleton = getSingleObject(i);
         if (!singleton)
             return NULL;
         type = singleton->getType(cx);
         if (!type)
-            cx->compartment->types.setPendingNukeTypes(cx);
+            cx->compartment()->types.setPendingNukeTypes(cx);
     }
     return type;
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeCallsite
 /////////////////////////////////////////////////////////////////////
 
@@ -1584,27 +1584,27 @@ TypeObject::setBasePropertyCount(uint32_
     JS_ASSERT(count <= OBJECT_FLAG_PROPERTY_COUNT_LIMIT);
     flags = (flags & ~OBJECT_FLAG_PROPERTY_COUNT_MASK)
           | (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
 }
 
 inline HeapTypeSet *
 TypeObject::getProperty(JSContext *cx, jsid id, bool own)
 {
-    JS_ASSERT(cx->compartment->activeAnalysis);
+    JS_ASSERT(cx->compartment()->activeAnalysis);
 
     JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
     JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
     JS_ASSERT(!unknownProperties());
 
     uint32_t propertyCount = basePropertyCount();
     Property **pprop = HashSetInsert<jsid,Property,Property>
         (cx->typeLifoAlloc(), propertySet, propertyCount, id);
     if (!pprop) {
-        cx->compartment->types.setPendingNukeTypes(cx);
+        cx->compartment()->types.setPendingNukeTypes(cx);
         return NULL;
     }
 
     if (!*pprop) {
         setBasePropertyCount(propertyCount);
         if (!addProperty(cx, id, pprop)) {
             setBasePropertyCount(0);
             propertySet = NULL;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -368,17 +368,17 @@ Compare(T *a, T *b, size_t c)
     }
     return true;
 }
 
 static inline PropertyIteratorObject *
 NewPropertyIteratorObject(JSContext *cx, unsigned flags)
 {
     if (flags & JSITER_ENUMERATE) {
-        RootedTypeObject type(cx, cx->compartment->getNewType(cx, &PropertyIteratorObject::class_, NULL));
+        RootedTypeObject type(cx, cx->compartment()->getNewType(cx, &PropertyIteratorObject::class_, NULL));
         if (!type)
             return NULL;
 
         Class *clasp = &PropertyIteratorObject::class_;
         RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, NULL, NULL, NewObjectMetadata(cx),
                                                           ITERATOR_FINALIZE_KIND));
         if (!shape)
             return NULL;
@@ -446,17 +446,17 @@ NativeIterator::init(JSObject *obj, JSOb
     this->shapes_key = key;
 }
 
 static inline void
 RegisterEnumerator(JSContext *cx, PropertyIteratorObject *iterobj, NativeIterator *ni)
 {
     /* Register non-escaping native enumerators (for-in) with the current context. */
     if (ni->flags & JSITER_ENUMERATE) {
-        ni->link(cx->compartment->enumerators);
+        ni->link(cx->compartment()->enumerators);
 
         JS_ASSERT(!(ni->flags & JSITER_ACTIVE));
         ni->flags |= JSITER_ACTIVE;
     }
 }
 
 static inline bool
 VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVector &keys,
@@ -605,17 +605,17 @@ js::GetIterator(JSContext *cx, HandleObj
 
         if (keysOnly) {
             /*
              * Check to see if this is the same as the most recent object which
              * was iterated over.  We don't explicitly check for shapeless
              * objects here, as they are not inserted into the cache and
              * will result in a miss.
              */
-            PropertyIteratorObject *last = cx->runtime->nativeIterCache.last;
+            PropertyIteratorObject *last = cx->runtime()->nativeIterCache.last;
             if (last) {
                 NativeIterator *lastni = last->getNativeIterator();
                 if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     obj->isNative() &&
                     obj->hasEmptyElements() &&
                     obj->lastProperty() == lastni->shapes_array[0])
                 {
                     JSObject *proto = obj->getProto();
@@ -652,29 +652,29 @@ js::GetIterator(JSContext *cx, HandleObj
                     Shape *shape = pobj->lastProperty();
                     key = (key + (key << 16)) ^ (uintptr_t(shape) >> 3);
                     if (!shapes.append(shape))
                         return false;
                     pobj = pobj->getProto();
                 } while (pobj);
             }
 
-            PropertyIteratorObject *iterobj = cx->runtime->nativeIterCache.get(key);
+            PropertyIteratorObject *iterobj = cx->runtime()->nativeIterCache.get(key);
             if (iterobj) {
                 NativeIterator *ni = iterobj->getNativeIterator();
                 if (!(ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
                     ni->shapes_key == key &&
                     ni->shapes_length == shapes.length() &&
                     Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
                     vp.setObject(*iterobj);
 
                     UpdateNativeIterator(ni, obj);
                     RegisterEnumerator(cx, iterobj, ni);
                     if (shapes.length() == 2)
-                        cx->runtime->nativeIterCache.last = iterobj;
+                        cx->runtime()->nativeIterCache.last = iterobj;
                     return true;
                 }
             }
         }
 
       miss:
         if (obj->isProxy()) {
             types::MarkIteratorUnknown(cx);
@@ -703,20 +703,20 @@ js::GetIterator(JSContext *cx, HandleObj
         if (!VectorToKeyIterator(cx, obj, flags, keys, shapes.length(), key, vp))
             return false;
     }
 
     PropertyIteratorObject *iterobj = &vp.toObject().asPropertyIterator();
 
     /* Cache the iterator object if possible. */
     if (shapes.length())
-        cx->runtime->nativeIterCache.set(key, iterobj);
+        cx->runtime()->nativeIterCache.set(key, iterobj);
 
     if (shapes.length() == 2)
-        cx->runtime->nativeIterCache.last = iterobj;
+        cx->runtime()->nativeIterCache.last = iterobj;
     return true;
 }
 
 JSObject *
 js::GetIteratorObject(JSContext *cx, HandleObject obj, uint32_t flags)
 {
     RootedValue value(cx);
     if (!GetIterator(cx, obj, flags, &value))
@@ -908,17 +908,17 @@ ElementIteratorObject::next_impl(JSConte
     if (i >= length) {
         js_ThrowStopIteration(cx);
         goto close;
     }
 
     // Get target[i].
     JS_ASSERT(i + 1 > i);
     if (target.isString()) {
-        JSString *c = cx->runtime->staticStrings.getUnitStringForElement(cx, target.toString(), i);
+        JSString *c = cx->runtime()->staticStrings.getUnitStringForElement(cx, target.toString(), i);
         if (!c)
             goto close;
         args.rval().setString(c);
     } else {
         if (!JSObject::getElement(cx, obj, obj, i, args.rval()))
             goto close;
     }
 
@@ -1064,17 +1064,17 @@ js::UnwindIteratorForUncatchableExceptio
  * argument is an object which can be called on an id and returns true or
  * false. It also must have a method |matchesAtMostOne| which allows us to
  * stop searching after the first deletion if true.
  */
 template<typename StringPredicate>
 static bool
 SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate predicate)
 {
-    NativeIterator *enumeratorList = cx->compartment->enumerators;
+    NativeIterator *enumeratorList = cx->compartment()->enumerators;
     NativeIterator *ni = enumeratorList->next();
 
     while (ni != enumeratorList) {
       again:
         /* This only works for identified suppressed keys, not values. */
         if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
             /* Check whether id is still to come. */
             HeapPtr<JSFlatString> *props_cursor = ni->current();
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -144,17 +144,17 @@ js::math_acos(JSContext *cx, unsigned ar
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_acos_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 double
@@ -173,17 +173,17 @@ js::math_asin(JSContext *cx, unsigned ar
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_asin_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 double
@@ -198,17 +198,17 @@ js::math_atan(JSContext *cx, unsigned ar
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_atan_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 double
@@ -295,17 +295,17 @@ js::math_cos(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_cos_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 double
@@ -328,17 +328,17 @@ js::math_exp(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_exp_impl(mathCache, x);
     vp->setNumber(z);
     return JS_TRUE;
 }
 
 double
@@ -397,17 +397,17 @@ js::math_log(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_log_impl(mathCache, x);
     vp->setNumber(z);
     return JS_TRUE;
 }
 
 JSBool
@@ -622,17 +622,17 @@ random_next(uint64_t *rngState, int bits
     nextstate &= RNG_MASK;
     *rngState = nextstate;
     return nextstate >> (48 - bits);
 }
 
 static inline double
 random_nextDouble(JSContext *cx)
 {
-    uint64_t *rng = &cx->compartment->rngState;
+    uint64_t *rng = &cx->compartment()->rngState;
     return double((random_next(rng, 26) << 27) + random_next(rng, 27)) / RNG_DSCALE;
 }
 
 double
 math_random_no_outparam(JSContext *cx)
 {
     /* Calculate random without memory traffic, for use in the JITs. */
     return random_nextDouble(cx);
@@ -688,17 +688,17 @@ js::math_sin(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_sin_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 JSBool
@@ -707,17 +707,17 @@ js_math_sqrt(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = mathCache->lookup(sqrt, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 double
@@ -732,17 +732,17 @@ js::math_tan(JSContext *cx, unsigned arg
     double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
-    MathCache *mathCache = cx->runtime->getMathCache(cx);
+    MathCache *mathCache = cx->runtime()->getMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = math_tan_impl(mathCache, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 #if JS_HAS_TOSOURCE
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -70,17 +70,17 @@ ComputeAccurateDecimalInteger(JSContext 
         char c = char(start[i]);
         JS_ASSERT(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'));
         cstr[i] = c;
     }
     cstr[length] = 0;
 
     char *estr;
     int err = 0;
-    *dp = js_strtod_harder(cx->runtime->dtoaState, cstr, &estr, &err);
+    *dp = js_strtod_harder(cx->runtime()->dtoaState, cstr, &estr, &err);
     if (err == JS_DTOA_ENOMEM) {
         JS_ReportOutOfMemory(cx);
         js_free(cstr);
         return false;
     }
     if (err == JS_DTOA_ERANGE && *dp == HUGE_VAL)
         *dp = js_PositiveInfinity;
     js_free(cstr);
@@ -506,24 +506,24 @@ ToCStringBuf::~ToCStringBuf()
 
 template <AllowGC allowGC>
 JSFlatString *
 js::Int32ToString(JSContext *cx, int32_t si)
 {
     uint32_t ui;
     if (si >= 0) {
         if (StaticStrings::hasInt(si))
-            return cx->runtime->staticStrings.getInt(si);
+            return cx->runtime()->staticStrings.getInt(si);
         ui = si;
     } else {
         ui = uint32_t(-si);
         JS_ASSERT_IF(si == INT32_MIN, ui == uint32_t(INT32_MAX) + 1);
     }
 
-    JSCompartment *c = cx->compartment;
+    JSCompartment *c = cx->compartment();
     if (JSFlatString *str = c->dtoaCache.lookup(10, si))
         return str;
 
     JSShortString *str = js_NewGCShortString<allowGC>(cx);
     if (!str)
         return NULL;
 
     jschar buffer[JSShortString::MAX_SHORT_LENGTH + 1];
@@ -659,17 +659,17 @@ num_toLocaleString_impl(JSContext *cx, C
         nint++;
     int digits = nint - num;
     const char *end = num + digits;
     if (!digits) {
         args.rval().setString(str);
         return true;
     }
 
-    JSRuntime *rt = cx->runtime;
+    JSRuntime *rt = cx->runtime();
     size_t thousandsLength = strlen(rt->thousandsSeparator);
     size_t decimalLength = strlen(rt->decimalSeparator);
 
     /* Figure out how long resulting string will be. */
     int buflen = strlen(num);
     if (*nint == '.')
         buflen += decimalLength - 1; /* -1 to account for existing '.' */
 
@@ -727,19 +727,19 @@ num_toLocaleString_impl(JSContext *cx, C
         tmpDest += decimalLength;
         JS_ASSERT(tmpDest - buf + ptrdiff_t(strlen(nint + 1)) <= buflen);
         strcpy(tmpDest, nint + 1);
     } else {
         JS_ASSERT(tmpDest - buf + ptrdiff_t(strlen(nint)) <= buflen);
         strcpy(tmpDest, nint);
     }
 
-    if (cx->runtime->localeCallbacks && cx->runtime->localeCallbacks->localeToUnicode) {
+    if (cx->runtime()->localeCallbacks && cx->runtime()->localeCallbacks->localeToUnicode) {
         Rooted<Value> v(cx, StringValue(str));
-        bool ok = !!cx->runtime->localeCallbacks->localeToUnicode(cx, buf, &v);
+        bool ok = !!cx->runtime()->localeCallbacks->localeToUnicode(cx, buf, &v);
         if (ok)
             args.rval().set(v);
         js_free(buf);
         return ok;
     }
 
     str = js_NewStringCopyN<CanGC>(cx, buf, buflen);
     js_free(buf);
@@ -792,17 +792,17 @@ ComputePrecisionInRange(JSContext *cx, i
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr);
     return false;
 }
 
 static bool
 DToStrResult(JSContext *cx, double d, JSDToStrMode mode, int precision, CallArgs args)
 {
     char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION + 1)];
-    char *numStr = js_dtostr(cx->runtime->dtoaState, buf, sizeof buf, mode, precision, d);
+    char *numStr = js_dtostr(cx->runtime()->dtoaState, buf, sizeof buf, mode, precision, d);
     if (!numStr) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
     JSString *str = js_NewStringCopyZ<CanGC>(cx, numStr);
     if (!str)
         return false;
     args.rval().setString(str);
@@ -1156,18 +1156,18 @@ js_InitNumberClass(JSContext *cx, Handle
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, numberProto, NULL, number_methods))
         return NULL;
 
     if (!JS_DefineFunctions(cx, global, number_functions))
         return NULL;
 
-    RootedValue valueNaN(cx, cx->runtime->NaNValue);
-    RootedValue valueInfinity(cx, cx->runtime->positiveInfinityValue);
+    RootedValue valueNaN(cx, cx->runtime()->NaNValue);
+    RootedValue valueInfinity(cx, cx->runtime()->positiveInfinityValue);
 
     /* ES5 15.1.1.1, 15.1.1.2 */
     if (!DefineNativeProperty(cx, global, cx->names().NaN, valueNaN,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0) ||
         !DefineNativeProperty(cx, global, cx->names().Infinity, valueInfinity,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
@@ -1201,17 +1201,17 @@ FracNumberToCString(JSContext *cx, ToCSt
          *   Florian Loitsch, PLDI 2010.
          */
         const double_conversion::DoubleToStringConverter &converter
             = double_conversion::DoubleToStringConverter::EcmaScriptConverter();
         double_conversion::StringBuilder builder(cbuf->sbuf, cbuf->sbufSize);
         converter.ToShortest(d, &builder);
         numStr = builder.Finalize();
     } else {
-        numStr = cbuf->dbuf = js_dtobasestr(cx->runtime->dtoaState, base, d);
+        numStr = cbuf->dbuf = js_dtobasestr(cx->runtime()->dtoaState, base, d);
     }
     return numStr;
 }
 
 char *
 js::NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base/* = 10*/)
 {
     int32_t i;
@@ -1230,28 +1230,28 @@ js_NumberToStringWithBase(JSContext *cx,
     /*
      * Caller is responsible for error reporting. When called from trace,
      * returning NULL here will cause us to fall of trace and then retry
      * from the interpreter (which will report the error).
      */
     if (base < 2 || base > 36)
         return NULL;
 
-    JSCompartment *c = cx->compartment;
+    JSCompartment *c = cx->compartment();
 
     int32_t i;
     if (mozilla::DoubleIsInt32(d, &i)) {
         if (base == 10 && StaticStrings::hasInt(i))
-            return cx->runtime->staticStrings.getInt(i);
+            return cx->runtime()->staticStrings.getInt(i);
         if (unsigned(i) < unsigned(base)) {
             if (i < 10)
-                return cx->runtime->staticStrings.getInt(i);
+                return cx->runtime()->staticStrings.getInt(i);
             jschar c = 'a' + i - 10;
             JS_ASSERT(StaticStrings::hasUnit(c));
-            return cx->runtime->staticStrings.getUnit(c);
+            return cx->runtime()->staticStrings.getUnit(c);
         }
 
         if (JSFlatString *str = c->dtoaCache.lookup(base, d))
             return str;
 
         numStr = IntToCString(&cbuf, i, base);
         JS_ASSERT(!cbuf.dbuf && numStr >= cbuf.sbuf && numStr < cbuf.sbuf + cbuf.sbufSize);
     } else {
@@ -1294,19 +1294,19 @@ js::NumberToString(JSContext *cx, double
         return &str->asFlat();
     return NULL;
 }
 
 JSFlatString *
 js::IndexToString(JSContext *cx, uint32_t index)
 {
     if (StaticStrings::hasUint(index))
-        return cx->runtime->staticStrings.getUint(index);
+        return cx->runtime()->staticStrings.getUint(index);
 
-    JSCompartment *c = cx->compartment;
+    JSCompartment *c = cx->compartment();
     if (JSFlatString *str = c->dtoaCache.lookup(10, index))
         return str;
 
     JSShortString *str = js_NewGCShortString<CanGC>(cx);
     if (!str)
         return NULL;
 
     jschar buffer[JSShortString::MAX_SHORT_LENGTH + 1];
@@ -1608,17 +1608,17 @@ js_strtod(JSContext *cx, const jschar *s
     istr = cstr;
     if ((negative = (*istr == '-')) != 0 || *istr == '+')
         istr++;
     if (*istr == 'I' && !strncmp(istr, "Infinity", 8)) {
         d = negative ? js_NegativeInfinity : js_PositiveInfinity;
         estr = istr + 8;
     } else {
         int err;
-        d = js_strtod_harder(cx->runtime->dtoaState, cstr, &estr, &err);
+        d = js_strtod_harder(cx->runtime()->dtoaState, cstr, &estr, &err);
         if (d == HUGE_VAL)
             d = js_PositiveInfinity;
         else if (d == -HUGE_VAL)
             d = js_NegativeInfinity;
     }
 
     i = estr - cstr;
     if (cstr != cbuf)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1237,17 +1237,17 @@ NewObjectGCKind(js::Class *clasp)
 
 static inline JSObject *
 NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
           gc::AllocKind kind, NewObjectKind newKind)
 {
     JS_ASSERT(clasp != &ArrayClass);
     JS_ASSERT_IF(clasp == &FunctionClass,
                  kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
-    JS_ASSERT_IF(parent, &parent->global() == cx->compartment->maybeGlobal());
+    JS_ASSERT_IF(parent, &parent->global() == cx->compartment()->maybeGlobal());
 
     RootedTypeObject type(cx, type_);
 
     RootedShape shape(cx, EmptyShape::getInitialShape(cx, clasp, TaggedProto(type->proto),
                                                       parent, NewObjectMetadata(cx), kind));
     if (!shape)
         return NULL;
 
@@ -1263,49 +1263,49 @@ NewObject(JSContext *cx, Class *clasp, t
         obj = nobj;
     }
 
     /*
      * This will cancel an already-running incremental GC from doing any more
      * slices, and it will prevent any future incremental GCs.
      */
     if (clasp->trace && !(clasp->flags & JSCLASS_IMPLEMENTS_BARRIERS))
-        cx->runtime->gcIncrementalEnabled = false;
+        cx->runtime()->gcIncrementalEnabled = false;
 
     Probes::createObject(cx, obj);
     return obj;
 }
 
 JSObject *
 js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
                             js::TaggedProto proto_, JSObject *parent_,
                             gc::AllocKind allocKind, NewObjectKind newKind)
 {
     Rooted<TaggedProto> proto(cx, proto_);
     RootedObject parent(cx, parent_);
 
     if (CanBeFinalizedInBackground(allocKind, clasp))
         allocKind = GetBackgroundAllocKind(allocKind);
 
-    NewObjectCache &cache = cx->runtime->newObjectCache;
+    NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
     if (proto.isObject() &&
         newKind == GenericObject &&
-        !cx->compartment->objectMetadataCallback &&
+        !cx->compartment()->objectMetadataCallback &&
         (!parent || parent == proto.toObject()->getParent()) && !proto.toObject()->isGlobal())
     {
         if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
             if (obj)
                 return obj;
         }
     }
 
-    types::TypeObject *type = cx->compartment->getNewType(cx, clasp, proto, NULL);
+    types::TypeObject *type = cx->compartment()->getNewType(cx, clasp, proto, NULL);
     if (!type)
         return NULL;
 
     /*
      * Default parent to the parent of the prototype, which was set from
      * the parent of the prototype's constructor.
      */
     if (!parent && proto.isObject())
@@ -1340,23 +1340,23 @@ js::NewObjectWithClassProtoCommon(JSCont
      * global[className].prototype, where changes to either the className or
      * prototype property would render the cached lookup incorrect. For classes
      * with a proto key, the prototype created during class initialization is
      * stored in an immutable slot on the global (except for ClearScope, which
      * will flush the new object cache).
      */
     JSProtoKey protoKey = GetClassProtoKey(clasp);
 
-    NewObjectCache &cache = cx->runtime->newObjectCache;
+    NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
     if (parentArg->isGlobal() &&
         protoKey != JSProto_Null &&
         newKind == GenericObject &&
-        !cx->compartment->objectMetadataCallback)
+        !cx->compartment()->objectMetadataCallback)
     {
         if (cache.lookupGlobal(clasp, &parentArg->asGlobal(), allocKind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
             if (obj)
                 return obj;
         }
     }
 
@@ -1386,22 +1386,22 @@ js::NewObjectWithType(JSContext *cx, Han
 {
     JS_ASSERT(type->proto->hasNewType(&ObjectClass, type));
     JS_ASSERT(parent);
 
     JS_ASSERT(allocKind <= gc::FINALIZE_OBJECT_LAST);
     if (CanBeFinalizedInBackground(allocKind, &ObjectClass))
         allocKind = GetBackgroundAllocKind(allocKind);
 
-    NewObjectCache &cache = cx->runtime->newObjectCache;
+    NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
     if (parent == type->proto->getParent() &&
         newKind == GenericObject &&
-        !cx->compartment->objectMetadataCallback)
+        !cx->compartment()->objectMetadataCallback)
     {
         if (cache.lookupType(&ObjectClass, type, allocKind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, &ObjectClass));
             if (obj)
                 return obj;
         }
     }
 
@@ -1638,33 +1638,33 @@ js_InferFlags(JSContext *cx, unsigned de
     return flags;
 }
 
 /* static */ JSBool
 JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj,
                                HandleId id, MutableHandleValue vp, JSBool strict)
 {
     if (JS_UNLIKELY(obj->watched())) {
-        WatchpointMap *wpmap = cx->compartment->watchpointMap;
+        WatchpointMap *wpmap = cx->compartment()->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
             return false;
     }
     return obj->getOps()->setGeneric(cx, obj, id, vp, strict);
 }
 
 /* static */ JSBool
 JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj,
                               uint32_t index, MutableHandleValue vp, JSBool strict)
 {
     if (JS_UNLIKELY(obj->watched())) {
         RootedId id(cx);
         if (!IndexToId(cx, index, &id))
             return false;
 
-        WatchpointMap *wpmap = cx->compartment->watchpointMap;
+        WatchpointMap *wpmap = cx->compartment()->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
             return false;
     }
     return obj->getOps()->setElement(cx, obj, index, vp, strict);
 }
 
 /* static */ bool
 JSObject::deleteByValue(JSContext *cx, HandleObject obj, const Value &property, JSBool *succeeded)
@@ -1711,22 +1711,22 @@ JS_CopyPropertiesFrom(JSContext *cx, JSO
     RootedId id(cx);
     size_t n = shapes.length();
     while (n > 0) {
         shape = shapes[--n];
         unsigned attrs = shape->attributes();
         PropertyOp getter = shape->getter();
         StrictPropertyOp setter = shape->setter();
         AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
-        if ((attrs & JSPROP_GETTER) && !cx->compartment->wrap(cx, &getter))
+        if ((attrs & JSPROP_GETTER) && !cx->compartment()->wrap(cx, &getter))
             return false;
-        if ((attrs & JSPROP_SETTER) && !cx->compartment->wrap(cx, &setter))
+        if ((attrs & JSPROP_SETTER) && !cx->compartment()->wrap(cx, &setter))
             return false;
         v = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
-        if (!cx->compartment->wrap(cx, &v))
+        if (!cx->compartment()->wrap(cx, &v))
             return false;
         id = shape->propid();
         if (!JSObject::defineGeneric(cx, target, id, v, getter, setter, attrs))
             return false;
     }
     return true;
 }
 
@@ -1744,17 +1744,17 @@ CopySlots(JSContext *cx, HandleObject fr
         to->setSlot(1, from->getSlot(1));
         n = 2;
     }
 
     size_t span = JSCLASS_RESERVED_SLOTS(from->getClass());
     RootedValue v(cx);
     for (; n < span; ++n) {
         v = from->getSlot(n);
-        if (!cx->compartment->wrap(cx, &v))
+        if (!cx->compartment()->wrap(cx, &v))
             return false;
         to->setSlot(n, v);
     }
     return true;
 }
 
 JSObject *
 js::CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent)
@@ -1989,18 +1989,18 @@ JSObject::TradeGuts(JSContext *cx, JSObj
         js_memcpy(b, tmp, size);
 
 #ifdef JSGC_GENERATIONAL
         /*
          * Trigger post barriers for fixed slots. JSObject bits are barriered
          * below, in common with the other case.
          */
         for (size_t i = 0; i < a->numFixedSlots(); ++i) {
-            HeapSlot::writeBarrierPost(cx->runtime, a, HeapSlot::Slot, i);
-            HeapSlot::writeBarrierPost(cx->runtime, b, HeapSlot::Slot, i);
+            HeapSlot::writeBarrierPost(cx->runtime(), a, HeapSlot::Slot, i);
+            HeapSlot::writeBarrierPost(cx->runtime(), b, HeapSlot::Slot, i);
         }
 #endif
     } else {
         /*
          * If the objects are of differing sizes, use the space we reserved
          * earlier to save the slots from each object and then copy them into
          * the new layout for the other object.
          */
@@ -2431,28 +2431,28 @@ JSObject::setSlotSpan(JSContext *cx, Han
     obj->lastProperty()->base()->setSlotSpan(span);
     return true;
 }
 
 static HeapSlot *
 AllocateSlots(JSContext *cx, JSObject *obj, uint32_t nslots)
 {
 #ifdef JSGC_GENERATIONAL
-    return cx->runtime->gcNursery.allocateSlots(cx, obj, nslots);
+    return cx->runtime()->gcNursery.allocateSlots(cx, obj, nslots);
 #else
     return cx->pod_malloc<HeapSlot>(nslots);
 #endif
 }
 
 static HeapSlot *
 ReallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
                 uint32_t oldCount, uint32_t newCount)
 {
 #ifdef JSGC_GENERATIONAL
-    return cx->runtime->gcNursery.reallocateSlots(cx, obj, oldSlots, oldCount, newCount);
+    return cx->runtime()->gcNursery.reallocateSlots(cx, obj, oldSlots, oldCount, newCount);
 #else
     return (HeapSlot *)cx->realloc_(oldSlots, oldCount * sizeof(HeapSlot),
                                     newCount * sizeof(HeapSlot));
 #endif
 }
 
 /* static */ bool
 JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
@@ -2514,17 +2514,17 @@ JSObject::growSlots(JSContext *cx, Handl
 
     return true;
 }
 
 static void
 FreeSlots(JSContext *cx, HeapSlot *slots)
 {
 #ifdef JSGC_GENERATIONAL
-    if (!cx->runtime->gcNursery.isInside(slots))
+    if (!cx->runtime()->gcNursery.isInside(slots))
 #endif
         js_free(slots);
 }
 
 /* static */ void
 JSObject::shrinkSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
 {
     JS_ASSERT(newCount < oldCount);
@@ -2749,33 +2749,33 @@ JSObject::maybeDensifySparseElements(JSC
     return ED_OK;
 }
 
 ObjectElements *
 AllocateElements(JSObject::MaybeContext maybecx, JSObject *obj, uint32_t nelems)
 {
     if (JSContext *cx = maybecx.context) {
 #ifdef JSGC_GENERATIONAL
-        return cx->runtime->gcNursery.allocateElements(cx, obj, nelems);
+        return cx->runtime()->gcNursery.allocateElements(cx, obj, nelems);
 #else
         return static_cast<js::ObjectElements *>(cx->malloc_(nelems * sizeof(HeapValue)));
 #endif
     }
 
     Allocator *alloc = maybecx.allocator;
     return static_cast<js::ObjectElements *>(alloc->malloc_(nelems * sizeof(HeapValue)));
 }
 
 ObjectElements *
 ReallocateElements(JSObject::MaybeContext maybecx, JSObject *obj, ObjectElements *oldHeader,
                    uint32_t oldCount, uint32_t newCount)
 {
     if (JSContext *cx = maybecx.context) {
 #ifdef JSGC_GENERATIONAL
-        return cx->runtime->gcNursery.reallocateElements(cx, obj, oldHeader, oldCount, newCount);
+        return cx->runtime()->gcNursery.reallocateElements(cx, obj, oldHeader, oldCount, newCount);
 #else
         return static_cast<js::ObjectElements *>(cx->realloc_(oldHeader,
                                                               oldCount * sizeof(HeapValue),
                                                               newCount * sizeof(HeapSlot)));
 #endif