Bug 1461938 part 5 - Some atoms compartment/realm related changes. r=jonco
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 18 May 2018 15:18:23 +0200
changeset 473140 32fc25dec8920d79cd533c45c503e56a422ad7df
parent 473139 84a09a4a0dc2dac930cf8f531b010c403c07fd73
child 473141 9d9e1b118451d451c7a050e365d36f4dd17cfb97
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1461938
milestone62.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 1461938 part 5 - Some atoms compartment/realm related changes. r=jonco
dom/workers/WorkerPrivate.cpp
js/public/Realm.h
js/src/builtin/Object.cpp
js/src/gc/Allocator.cpp
js/src/gc/AtomMarking.cpp
js/src/gc/GC.cpp
js/src/jit/Ion.cpp
js/src/jsapi.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/vm/GlobalObject.cpp
js/src/vm/HelperThreads.cpp
js/src/vm/JSCompartment-inl.h
js/src/vm/JSCompartment.cpp
js/src/vm/JSCompartment.h
js/src/vm/JSContext-inl.h
js/src/vm/JSContext.cpp
js/src/vm/JSContext.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/SelfHosting.cpp
js/src/vm/StringType-inl.h
js/src/vm/SymbolType.cpp
js/src/vm/UbiNodeCensus.cpp
js/xpconnect/src/XPCJSRuntime.cpp
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1206,17 +1206,17 @@ public:
     // aRealmStats->extra is a xpc::RealmStatsExtras pointer.
     xpc::RealmStatsExtras* extras = new xpc::RealmStatsExtras;
 
     // This is the |jsPathPrefix|.  Each worker has exactly two realms:
     // one for atoms, and one for everything else.
     extras->jsPathPrefix.Assign(mRtPath);
     extras->jsPathPrefix += nsPrintfCString("zone(0x%p)/",
                                             (void *)js::GetCompartmentZone(aCompartment));
-    extras->jsPathPrefix += js::IsAtomsCompartment(aCompartment)
+    extras->jsPathPrefix += js::IsAtomsRealm(JS::GetRealmForCompartment(aCompartment))
                             ? NS_LITERAL_CSTRING("realm(web-worker-atoms)/")
                             : NS_LITERAL_CSTRING("realm(web-worker)/");
 
     // This should never be used when reporting with workers (hence the "?!").
     extras->domPathPrefix.AssignLiteral("explicit/workers/?!/");
 
     MOZ_ASSERT(StartsWithExplicit(extras->jsPathPrefix));
     MOZ_ASSERT(StartsWithExplicit(extras->domPathPrefix));
--- a/js/public/Realm.h
+++ b/js/public/Realm.h
@@ -93,17 +93,17 @@ typedef void
 (* RealmNameCallback)(JSContext* cx, Handle<Realm*> realm, char* buf, size_t bufsize);
 
 // Set the callback SpiderMonkey calls to get the name of a realm, for
 // diagnostic output.
 extern JS_PUBLIC_API(void)
 SetRealmNameCallback(JSContext* cx, RealmNameCallback callback);
 
 // Get the global object for the given realm. Returns null only if `realm` is
-// in the atoms compartment.
+// the atoms realm.
 extern JS_PUBLIC_API(JSObject*)
 GetRealmGlobalOrNull(Handle<Realm*> realm);
 
 extern JS_PUBLIC_API(JSObject*)
 GetRealmObjectPrototype(JSContext* cx);
 
 extern JS_PUBLIC_API(JSObject*)
 GetRealmFunctionPrototype(JSContext* cx);
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -1981,17 +1981,17 @@ CreateObjectConstructor(JSContext* cx, J
 
     fun->setJitInfo(&jit::JitInfo_Object);
     return fun;
 }
 
 static JSObject*
 CreateObjectPrototype(JSContext* cx, JSProtoKey key)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     MOZ_ASSERT(cx->global()->isNative());
 
     /*
      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
      * prototype of the created object.
      */
     RootedPlainObject objectProto(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr,
                                                                            SingletonObject));
--- a/js/src/gc/Allocator.cpp
+++ b/js/src/gc/Allocator.cpp
@@ -81,17 +81,17 @@ template JSObject* js::Allocate<JSObject
 template <AllowGC allowGC>
 JSObject*
 GCRuntime::tryNewNurseryObject(JSContext* cx, size_t thingSize, size_t nDynamicSlots, const Class* clasp)
 {
     MOZ_RELEASE_ASSERT(!cx->helperThread());
 
     MOZ_ASSERT(cx->isNurseryAllocAllowed());
     MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
-    MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     JSObject* obj = cx->nursery().allocateObject(cx, thingSize, nDynamicSlots, clasp);
     if (obj)
         return obj;
 
     if (allowGC && !cx->suppressGC) {
         cx->runtime()->gc.minorGC(JS::gcreason::OUT_OF_NURSERY);
 
@@ -135,17 +135,17 @@ GCRuntime::tryNewTenuredObject(JSContext
 template <AllowGC allowGC>
 JSString*
 GCRuntime::tryNewNurseryString(JSContext* cx, size_t thingSize, AllocKind kind)
 {
     MOZ_ASSERT(IsNurseryAllocable(kind));
     MOZ_ASSERT(cx->isNurseryAllocAllowed());
     MOZ_ASSERT(!cx->helperThread());
     MOZ_ASSERT(!cx->isNurseryAllocSuppressed());
-    MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     Cell* cell = cx->nursery().allocateString(cx->zone(), thingSize, kind);
     if (cell)
         return static_cast<JSString*>(cell);
 
     if (allowGC && !cx->suppressGC) {
         cx->runtime()->gc.minorGC(JS::gcreason::OUT_OF_NURSERY);
 
@@ -270,23 +270,23 @@ bool
 GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
 {
     if (allowGC) {
         if (!gcIfNeededAtAllocation(cx))
             return false;
     }
 
 #if defined(JS_GC_ZEAL) || defined(DEBUG)
-    MOZ_ASSERT_IF(cx->compartment()->isAtomsCompartment(),
+    MOZ_ASSERT_IF(cx->realm()->isAtomsRealm(),
                   kind == AllocKind::ATOM ||
                   kind == AllocKind::FAT_INLINE_ATOM ||
                   kind == AllocKind::SYMBOL ||
                   kind == AllocKind::JITCODE ||
                   kind == AllocKind::SCOPE);
-    MOZ_ASSERT_IF(!cx->compartment()->isAtomsCompartment(),
+    MOZ_ASSERT_IF(!cx->realm()->isAtomsRealm(),
                   kind != AllocKind::ATOM &&
                   kind != AllocKind::FAT_INLINE_ATOM);
     MOZ_ASSERT(!JS::CurrentThreadIsHeapBusy());
     MOZ_ASSERT(cx->isAllocAllowed());
 #endif
 
     // Crash if we perform a GC action when it is not safe.
     if (allowGC && !cx->suppressGC)
--- a/js/src/gc/AtomMarking.cpp
+++ b/js/src/gc/AtomMarking.cpp
@@ -78,17 +78,17 @@ bool
 AtomMarkingRuntime::computeBitmapFromChunkMarkBits(JSRuntime* runtime, DenseBitmap& bitmap)
 {
     MOZ_ASSERT(CurrentThreadIsPerformingGC());
     MOZ_ASSERT(!runtime->hasHelperThreadZones());
 
     if (!bitmap.ensureSpace(allocatedWords))
         return false;
 
-    Zone* atomsZone = runtime->unsafeAtomsCompartment()->zone();
+    Zone* atomsZone = runtime->unsafeAtomsRealm()->zone();
     for (auto thingKind : AllAllocKinds()) {
         for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
             Arena* arena = aiter.get();
             uintptr_t* chunkWords = arena->chunk()->bitmap.arenaBits(arena);
             bitmap.copyBitsFrom(arena->atomBitmapStart(), ArenaBitmapWords, chunkWords);
         }
     }
 
@@ -112,17 +112,17 @@ template <typename Bitmap>
 static void
 AddBitmapToChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap)
 {
     // Make sure that by copying the mark bits for one arena in word sizes we
     // do not affect the mark bits for other arenas.
     static_assert(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD,
                   "ArenaBitmapWords must evenly divide ArenaBitmapBits");
 
-    Zone* atomsZone = runtime->unsafeAtomsCompartment()->zone();
+    Zone* atomsZone = runtime->unsafeAtomsRealm()->zone();
     for (auto thingKind : AllAllocKinds()) {
         for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
             Arena* arena = aiter.get();
             uintptr_t* chunkWords = arena->chunk()->bitmap.arenaBits(arena);
             bitmap.bitwiseOrRangeInto(arena->atomBitmapStart(), ArenaBitmapWords, chunkWords);
         }
     }
 }
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -3383,17 +3383,17 @@ GCRuntime::triggerZoneGC(Zone* zone, JS:
 #ifdef JS_GC_ZEAL
     if (hasZealMode(ZealMode::Alloc)) {
         MOZ_RELEASE_ASSERT(triggerGC(reason));
         return true;
     }
 #endif
 
     if (zone->isAtomsZone()) {
-        /* We can't do a zone GC of the atoms compartment. */
+        /* We can't do a zone GC of the atoms zone. */
         if (rt->mainContextFromOwnThread()->keepAtoms || rt->hasHelperThreadZones()) {
             /* Skip GC and retrigger later, since atoms zone won't be collected
              * if keepAtoms is true. */
             fullGCForAtomsRequested_ = true;
             return false;
         }
         stats().recordTrigger(used, threshold);
         MOZ_RELEASE_ASSERT(triggerGC(reason));
@@ -3840,17 +3840,17 @@ Zone::sweepCompartments(FreeOp* fop, boo
     mozilla::DebugOnly<JSRuntime*> rt = runtimeFromMainThread();
 
     JSCompartment** read = compartments().begin();
     JSCompartment** end = compartments().end();
     JSCompartment** write = read;
     bool foundOne = false;
     while (read < end) {
         JSCompartment* comp = *read++;
-        MOZ_ASSERT(!rt->isAtomsCompartment(comp));
+        MOZ_ASSERT(!JS::GetRealmForCompartment(comp)->isAtomsRealm());
 
         /*
          * Don't delete the last compartment if all the ones before it were
          * deleted and keepAtleastOne is true.
          */
         bool dontDelete = read == end && !foundOne && keepAtleastOne;
         if ((!comp->marked && !dontDelete) || destroyingRuntime) {
             JS::GetRealmForCompartment(comp)->destroy(fop);
@@ -4485,17 +4485,17 @@ GCRuntime::markCompartments()
             }
         }
     }
 
     /* Set scheduleForDestruction based on maybeAlive. */
 
     for (GCCompartmentsIter comp(rt); !comp.done(); comp.next()) {
         MOZ_ASSERT(!comp->scheduledForDestruction);
-        if (!comp->maybeAlive && !rt->isAtomsCompartment(comp))
+        if (!comp->maybeAlive && !JS::GetRealmForCompartment(comp)->isAtomsRealm())
             comp->scheduledForDestruction = true;
     }
 }
 
 void
 GCRuntime::updateMallocCountersOnGCStart()
 {
     // Update the malloc counters for any zones we are collecting.
@@ -5329,19 +5329,19 @@ GCRuntime::endMarkingSweepGroup(FreeOp* 
      * whose referents are not marked. This can occur when gray cells become
      * black by the action of UnmarkGray.
      */
     MarkIncomingCrossCompartmentPointers(rt, MarkColor::Black);
     markWeakReferencesInCurrentGroup(gcstats::PhaseKind::SWEEP_MARK_WEAK);
 
     /*
      * Change state of current group to MarkGray to restrict marking to this
-     * group.  Note that there may be pointers to the atoms compartment, and
+     * group.  Note that there may be pointers to the atoms zone, and
      * these will be marked through, as they are not marked with
-     * MarkCrossCompartmentXXX.
+     * TraceCrossCompartmentEdge.
      */
     for (SweepGroupZonesIter zone(rt); !zone.done(); zone.next())
         zone->changeGCState(Zone::Mark, Zone::MarkGray);
     marker.setMarkColorGray();
 
     /* Mark incoming gray pointers from previously swept compartments. */
     MarkIncomingCrossCompartmentPointers(rt, MarkColor::Gray);
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -332,17 +332,17 @@ JitRuntime::initialize(JSContext* cx, Au
     return true;
 }
 
 JitCode*
 JitRuntime::debugTrapHandler(JSContext* cx)
 {
     if (!debugTrapHandler_) {
         // JitRuntime code stubs are shared across compartments and have to
-        // be allocated in the atoms compartment.
+        // be allocated in the atoms zone.
         AutoLockForExclusiveAccess lock(cx);
         AutoAtomsRealm ar(cx, lock);
         debugTrapHandler_ = generateDebugTrapHandler(cx);
     }
     return debugTrapHandler_;
 }
 
 JitRuntime::IonBuilderList&
@@ -582,22 +582,22 @@ jit::LazyLinkTopActivation(JSContext* cx
     return calleeScript->jitCodeRaw();
 }
 
 /* static */ void
 JitRuntime::Trace(JSTracer* trc, AutoLockForExclusiveAccess& lock)
 {
     MOZ_ASSERT(!JS::CurrentThreadIsHeapMinorCollecting());
 
-    // Shared stubs are allocated in the atoms compartment, so do not iterate
+    // Shared stubs are allocated in the atoms zone, so do not iterate
     // them after the atoms heap after it has been "finished."
     if (trc->runtime()->atomsAreFinished())
         return;
 
-    Zone* zone = trc->runtime()->atomsCompartment(lock)->zone();
+    Zone* zone = trc->runtime()->atomsRealm(lock)->zone();
     for (auto i = zone->cellIter<JitCode>(); !i.done(); i.next()) {
         JitCode* code = i;
         TraceRoot(trc, &code, "wrapper");
     }
 }
 
 /* static */ void
 JitRuntime::TraceJitcodeGlobalTableForMinorGC(JSTracer* trc)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -949,17 +949,17 @@ JS_PUBLIC_API(bool)
 JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj)
 {
     return RemapAllWrappersForObject(cx, obj, obj);
 }
 
 JS_PUBLIC_API(bool)
 JS_InitStandardClasses(JSContext* cx, HandleObject obj)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     assertSameCompartment(cx, obj);
 
     Rooted<GlobalObject*> global(cx, &obj->global());
     return GlobalObject::initStandardClasses(cx, global);
 }
@@ -1969,34 +1969,34 @@ JS_FireOnNewGlobalObject(JSContext* cx, 
     assertSameCompartment(cx, global);
     Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
     Debugger::onNewGlobalObject(cx, globalObject);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewObject(JSContext* cx, const JSClass* jsclasp)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     const Class* clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &PlainObject::class_;    /* default class is Object */
 
     MOZ_ASSERT(clasp != &JSFunction::class_);
     MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     return NewObjectWithClassProto(cx, clasp, nullptr);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject proto)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto);
 
     const Class* clasp = Valueify(jsclasp);
     if (!clasp)
         clasp = &PlainObject::class_;    /* default class is Object */
 
@@ -2004,17 +2004,17 @@ JS_NewObjectWithGivenProto(JSContext* cx
     MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     return NewObjectWithGivenProto(cx, clasp, proto);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewPlainObject(JSContext* cx)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     return NewBuiltinClassInstance<PlainObject>(cx);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const CallArgs& args)
@@ -2904,34 +2904,34 @@ JS::IsConstructor(JSObject* obj)
 {
     return obj->isConstructor();
 }
 
 JS_PUBLIC_API(bool)
 JS_CallFunctionValue(JSContext* cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
                      MutableHandleValue rval)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fval, args);
 
     InvokeArgs iargs(cx);
     if (!FillArgumentsFromArraylike(cx, iargs, args))
         return false;
 
     RootedValue thisv(cx, ObjectOrNullValue(obj));
     return Call(cx, fval, thisv, iargs, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS_CallFunction(JSContext* cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
                 MutableHandleValue rval)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fun, args);
 
     InvokeArgs iargs(cx);
     if (!FillArgumentsFromArraylike(cx, iargs, args))
         return false;
 
@@ -2939,17 +2939,17 @@ JS_CallFunction(JSContext* cx, HandleObj
     RootedValue thisv(cx, ObjectOrNullValue(obj));
     return Call(cx, fval, thisv, iargs, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS_CallFunctionName(JSContext* cx, HandleObject obj, const char* name, const HandleValueArray& args,
                     MutableHandleValue rval)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, args);
 
     JSAtom* atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return false;
 
@@ -3373,28 +3373,28 @@ JS_PUBLIC_API(void)
 JS_SetReservedSlot(JSObject* obj, uint32_t index, const Value& value)
 {
     obj->as<NativeObject>().setReservedSlot(index, value);
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     assertSameCompartment(cx, contents);
     return NewDenseCopiedArray(cx, contents.length(), contents.begin());
 }
 
 JS_PUBLIC_API(JSObject*)
 JS_NewArrayObject(JSContext* cx, size_t length)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     return NewDenseFullyAllocatedArray(cx, length);
 }
 
 inline bool
 IsGivenTypeObject(JSContext* cx, JS::HandleObject obj, const ESClass& typeClass, bool* isType)
@@ -3507,17 +3507,17 @@ JS_InitReadPrincipalsCallback(JSContext*
     MOZ_ASSERT(!cx->runtime()->readPrincipals);
     cx->runtime()->readPrincipals = read;
 }
 
 JS_PUBLIC_API(JSFunction*)
 JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
                const char* name)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
@@ -3527,17 +3527,17 @@ JS_NewFunction(JSContext* cx, JSNative n
     return (flags & JSFUN_CONSTRUCTOR)
            ? NewNativeConstructor(cx, native, nargs, atom)
            : NewNativeFunction(cx, native, nargs, atom);
 }
 
 JS_PUBLIC_API(JSFunction*)
 JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, id);
 
     RootedAtom name(cx, IdToFunctionName(cx, id));
     if (!name)
         return nullptr;
 
@@ -3783,60 +3783,60 @@ extern JS_PUBLIC_API(bool)
 JS_IsConstructor(JSFunction* fun)
 {
     return fun->isConstructor();
 }
 
 JS_PUBLIC_API(bool)
 JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     return DefineFunctions(cx, obj, fs, NotIntrinsic);
 }
 
 JS_PUBLIC_API(JSFunction*)
 JS_DefineFunction(JSContext* cx, HandleObject obj, const char* name, JSNative call,
                   unsigned nargs, unsigned attrs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom* atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return nullptr;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 JS_PUBLIC_API(JSFunction*)
 JS_DefineUCFunction(JSContext* cx, HandleObject obj,
                     const char16_t* name, size_t namelen, JSNative call,
                     unsigned nargs, unsigned attrs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
     if (!atom)
         return nullptr;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 extern JS_PUBLIC_API(JSFunction*)
 JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative call,
                       unsigned nargs, unsigned attrs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
     return DefineFunction(cx, obj, id, call, nargs, attrs);
 }
 
 /* Use the fastest available getc. */
 #if defined(HAVE_GETC_UNLOCKED)
@@ -4077,17 +4077,17 @@ JS::CompileOptions::CompileOptions(JSCon
 }
 
 static bool
 Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
         SourceBufferHolder& srcBuf, MutableHandleScript script)
 {
     ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
 
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
     return !!script;
 }
 
 static bool
@@ -4218,17 +4218,17 @@ JS::CompileForNonSyntacticScope(JSContex
 }
 
 #if defined(JS_BUILD_BINAST)
 
 JSScript*
 JS::DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options,
                  const uint8_t* buf, size_t length)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     return frontend::CompileGlobalBinASTScript(cx, cx->tempLifoAlloc(), options, buf, length);
 }
 
 JSScript*
 JS::DecodeBinAST(JSContext* cx, const ReadOnlyCompileOptions& options, FILE* file)
@@ -4541,17 +4541,17 @@ JS_GetFunctionScript(JSContext* cx, Hand
  */
 static bool
 CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
                 HandleAtom name, bool isInvalidName,
                 SourceBufferHolder& srcBuf, uint32_t parameterListEnd,
                 HandleObject enclosingEnv, HandleScope enclosingScope,
                 MutableHandleFunction fun)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, enclosingEnv);
     RootedAtom funAtom(cx);
 
     fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL,
                                 isInvalidName ? nullptr : name,
                                 /* proto = */ nullptr,
@@ -4710,17 +4710,17 @@ JS::ExposeScriptToDebugger(JSContext* cx
     MOZ_ASSERT(script->hideScriptFromDebugger());
     script->clearHideScriptFromDebugger();
     Debugger::onNewScript(cx, script);
 }
 
 JS_PUBLIC_API(JSString*)
 JS_DecompileScript(JSContext* cx, HandleScript script)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     script->ensureNonLazyCanonicalFunction();
     RootedFunction fun(cx, script->functionNonDelazifying());
     if (fun)
         return JS_DecompileFunction(cx, fun);
     bool haveSource = script->scriptSource()->hasSourceData();
@@ -4728,27 +4728,27 @@ JS_DecompileScript(JSContext* cx, Handle
         return nullptr;
     return haveSource ? JSScript::sourceData(cx, script)
                       : NewStringCopyZ<CanGC>(cx, "[no source]");
 }
 
 JS_PUBLIC_API(JSString*)
 JS_DecompileFunction(JSContext* cx, HandleFunction fun)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, fun);
     return FunctionToString(cx, fun, /* isToSource = */ false);
 }
 
 MOZ_NEVER_INLINE static bool
 ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, scope, script);
     MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope());
     return Execute(cx, script, *scope, rval);
 }
 
 static bool
@@ -4832,17 +4832,17 @@ JS::CloneAndExecuteScript(JSContext* cx,
 }
 
 static bool
 Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
          const ReadOnlyCompileOptions& optionsArg,
          SourceBufferHolder& srcBuf, MutableHandleValue rval)
 {
     CompileOptions options(cx, optionsArg);
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, env);
     MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
 
     options.setIsRunOnce(true);
     RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
                                                           scopeKind, options, srcBuf));
@@ -4959,17 +4959,17 @@ JS::SetModuleResolveHook(JSRuntime* rt, 
     AssertHeapIsIdle();
     rt->moduleResolveHook = func;
 }
 
 JS_PUBLIC_API(bool)
 JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
                   SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     module.set(frontend::CompileModule(cx, options, srcBuf));
     return !!module;
 }
 
 JS_PUBLIC_API(void)
@@ -5117,17 +5117,17 @@ JS::SetPromiseRejectionTrackerCallback(J
 {
     cx->promiseRejectionTrackerCallback = callback;
     cx->promiseRejectionTrackerCallbackData = data;
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, executor, proto);
 
     if (!executor)
         return PromiseObject::createSkippingExecutor(cx);
 
     MOZ_ASSERT(IsCallable(executor));
@@ -5371,17 +5371,17 @@ JS::GetWaitForAllPromise(JSContext* cx, 
 
 JS_PUBLIC_API(JSObject*)
 JS::NewReadableDefaultStreamObject(JSContext* cx,
                                    JS::HandleObject underlyingSource /* = nullptr */,
                                    JS::HandleFunction size /* = nullptr */,
                                    double highWaterMark /* = 1 */,
                                    JS::HandleObject proto /* = nullptr */)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     RootedObject source(cx, underlyingSource);
     if (!source) {
         source = NewBuiltinClassInstance<PlainObject>(cx);
         if (!source)
             return nullptr;
@@ -5393,17 +5393,17 @@ JS::NewReadableDefaultStreamObject(JSCon
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::NewReadableByteStreamObject(JSContext* cx,
                                 JS::HandleObject underlyingSource /* = nullptr */,
                                 double highWaterMark /* = 1 */,
                                 JS::HandleObject proto /* = nullptr */)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
     RootedObject source(cx, underlyingSource);
     if (!source) {
         source = NewBuiltinClassInstance<PlainObject>(cx);
         if (!source)
             return nullptr;
@@ -5452,17 +5452,17 @@ JS::HasReadableStreamCallbacks(JSContext
     return cx->runtime()->readableStreamDataRequestCallback;
 }
 
 JS_PUBLIC_API(JSObject*)
 JS::NewReadableExternalSourceStreamObject(JSContext* cx, void* underlyingSource,
                                           uint8_t flags /* = 0 */,
                                           HandleObject proto /* = nullptr */)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
 
 #ifdef DEBUG
     JSRuntime* rt = cx->runtime();
     MOZ_ASSERT(rt->readableStreamDataRequestCallback);
     MOZ_ASSERT(rt->readableStreamWriteIntoReadRequestCallback);
     MOZ_ASSERT(rt->readableStreamCancelCallback);
@@ -7583,17 +7583,17 @@ GetScriptedCallerGlobal(JSContext* cx)
 
     // If the caller is hidden, the embedding wants us to return null here so
     // that it can check its own stack (see HideScriptedCaller).
     if (activation->scriptedCallerIsHidden())
         return nullptr;
 
     GlobalObject* global = activation->compartment()->maybeGlobal();
 
-    // Noone should be running code in the atoms compartment or running code in
+    // No one should be running code in the atoms realm or running code in
     // a compartment without any live objects, so there should definitely be a
     // live global.
     MOZ_ASSERT(global);
 
     return global;
 }
 
 JS_PUBLIC_API(void)
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -236,17 +236,17 @@ DefineHelpProperty(JSContext* cx, Handle
     if (!atom)
         return false;
     return JS_DefineProperty(cx, obj, prop, atom, JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
 JS_FRIEND_API(bool)
 JS_DefineFunctionsWithHelp(JSContext* cx, HandleObject obj, const JSFunctionSpecWithHelp* fs)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     for (; fs->name; fs++) {
         JSAtom* atom = Atomize(cx, fs->name, strlen(fs->name));
         if (!atom)
             return false;
 
@@ -338,19 +338,19 @@ js::IsSystemCompartment(JSCompartment* c
 
 JS_FRIEND_API(bool)
 js::IsSystemZone(Zone* zone)
 {
     return zone->isSystem;
 }
 
 JS_FRIEND_API(bool)
-js::IsAtomsCompartment(JSCompartment* comp)
+js::IsAtomsRealm(JS::Realm* realm)
 {
-    return comp->runtimeFromAnyThread()->isAtomsCompartment(comp);
+    return realm->isAtomsRealm();
 }
 
 JS_FRIEND_API(bool)
 js::IsAtomsZone(JS::Zone* zone)
 {
     return zone->runtimeFromAnyThread()->isAtomsZone(zone);
 }
 
@@ -419,31 +419,31 @@ js::RunningWithTrustedPrincipals(JSConte
     return cx->runningWithTrustedPrincipals();
 }
 
 JS_FRIEND_API(JSFunction*)
 js::DefineFunctionWithReserved(JSContext* cx, JSObject* objArg, const char* name, JSNative call,
                                unsigned nargs, unsigned attrs)
 {
     RootedObject obj(cx, objArg);
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom* atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return nullptr;
     Rooted<jsid> id(cx, AtomToId(atom));
     return DefineFunction(cx, obj, id, call, nargs, attrs, gc::AllocKind::FUNCTION_EXTENDED);
 }
 
 JS_FRIEND_API(JSFunction*)
 js::NewFunctionWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
                             const char* name)
 {
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     CHECK_REQUEST(cx);
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
             return nullptr;
@@ -454,17 +454,17 @@ js::NewFunctionWithReserved(JSContext* c
         NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
 }
 
 JS_FRIEND_API(JSFunction*)
 js::NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
                                 jsid id)
 {
     MOZ_ASSERT(JSID_IS_STRING(id));
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, id);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
     return (flags & JSFUN_CONSTRUCTOR) ?
         NewNativeConstructor(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED) :
         NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
 }
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -479,17 +479,17 @@ JS_FRIEND_API(bool) obj_defineSetter(JSC
 
 extern JS_FRIEND_API(bool)
 IsSystemCompartment(JSCompartment* comp);
 
 extern JS_FRIEND_API(bool)
 IsSystemZone(JS::Zone* zone);
 
 extern JS_FRIEND_API(bool)
-IsAtomsCompartment(JSCompartment* comp);
+IsAtomsRealm(JS::Realm* realm);
 
 extern JS_FRIEND_API(bool)
 IsAtomsZone(JS::Zone* zone);
 
 struct WeakMapTracer
 {
     JSRuntime* runtime;
 
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -496,17 +496,17 @@ GlobalObject::createInternal(JSContext* 
 }
 
 /* static */ GlobalObject*
 GlobalObject::new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
                    JS::OnNewGlobalHookOption hookOption,
                    const JS::RealmOptions& options)
 {
     MOZ_ASSERT(!cx->isExceptionPending());
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT_IF(cx->realm(), !cx->realm()->isAtomsRealm());
 
     JSCompartment* compartment = NewCompartment(cx, principals, options);
     if (!compartment)
         return nullptr;
 
     Rooted<GlobalObject*> global(cx);
     {
         AutoRealmUnchecked ar(cx, compartment);
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -342,17 +342,17 @@ js::CancelOffThreadIonCompile(const Comp
 }
 
 #ifdef DEBUG
 bool
 js::HasOffThreadIonCompile(JSCompartment* comp)
 {
     AutoLockHelperThreadState lock;
 
-    if (!HelperThreadState().threads || comp->isAtomsCompartment())
+    if (!HelperThreadState().threads || JS::GetRealmForCompartment(comp)->isAtomsRealm())
         return false;
 
     GlobalHelperThreadState::IonBuilderVector& worklist = HelperThreadState().ionWorklist(lock);
     for (size_t i = 0; i < worklist.length(); i++) {
         jit::IonBuilder* builder = worklist[i];
         if (builder->script()->compartment() == comp)
             return true;
     }
@@ -660,21 +660,20 @@ js::CancelOffThreadParses(JSRuntime* rt)
     }
 #endif
 }
 
 bool
 js::OffThreadParsingMustWaitForGC(JSRuntime* rt)
 {
     // Off thread parsing can't occur during incremental collections on the
-    // atoms compartment, to avoid triggering barriers. (Outside the atoms
-    // compartment, the compilation will use a new zone that is never
-    // collected.) If an atoms-zone GC is in progress, hold off on executing the
-    // parse task until the atoms-zone GC completes (see
-    // EnqueuePendingParseTasksAfterGC).
+    // atoms zone, to avoid triggering barriers. (Outside the atoms zone, the
+    // compilation will use a new zone that is never collected.) If an
+    // atoms-zone GC is in progress, hold off on executing the parse task until
+    // the atoms-zone GC completes (see EnqueuePendingParseTasksAfterGC).
     return rt->activeGCInAtomsZone();
 }
 
 static bool
 EnsureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
 {
     if (!GlobalObject::ensureConstructor(cx, global, key))
         return false;
@@ -780,17 +779,17 @@ QueueOffThreadParseTask(JSContext* cx, P
 
     return true;
 }
 
 bool
 StartOffThreadParseTask(JSContext* cx, ParseTask* task, const ReadOnlyCompileOptions& options)
 {
     // Suppress GC so that calls below do not trigger a new incremental GC
-    // which could require barriers on the atoms compartment.
+    // which could require barriers on the atoms zone.
     gc::AutoSuppressGC nogc(cx);
     gc::AutoSuppressNurseryCellAlloc noNurseryAlloc(cx);
     AutoSuppressAllocationMetadataBuilder suppressMetadata(cx);
 
     JSObject* global = CreateGlobalForOffThreadParse(cx, nogc);
     if (!global)
         return false;
 
--- a/js/src/vm/JSCompartment-inl.h
+++ b/js/src/vm/JSCompartment-inl.h
@@ -48,63 +48,63 @@ js::AutoRealm::AutoRealm(JSContext* cx, 
   : cx_(cx),
     origin_(cx->realm()),
     maybeLock_(nullptr)
 {
     cx_->enterRealmOf(target);
 }
 
 // Protected constructor that bypasses assertions in enterCompartmentOf. Used
-// only for entering the atoms compartment.
+// only for entering the atoms realm.
 js::AutoRealm::AutoRealm(JSContext* cx, JS::Realm* target,
                          js::AutoLockForExclusiveAccess& lock)
   : cx_(cx),
     origin_(cx->realm()),
     maybeLock_(&lock)
 {
-    MOZ_ASSERT(target->isAtomsCompartment());
+    MOZ_ASSERT(target->isAtomsRealm());
     cx_->enterAtomsRealm(target, lock);
 }
 
 // Protected constructor that bypasses assertions in enterCompartmentOf. Should
-// not be used to enter the atoms compartment.
+// not be used to enter the atoms realm.
 js::AutoRealm::AutoRealm(JSContext* cx, JS::Realm* target)
   : cx_(cx),
     origin_(cx->realm()),
     maybeLock_(nullptr)
 {
-    MOZ_ASSERT(!target->isAtomsCompartment());
+    MOZ_ASSERT(!target->isAtomsRealm());
     cx_->enterNonAtomsRealm(target);
 }
 
 js::AutoRealm::~AutoRealm()
 {
     cx_->leaveRealm(origin_, maybeLock_);
 }
 
 js::AutoAtomsRealm::AutoAtomsRealm(JSContext* cx,
                                    js::AutoLockForExclusiveAccess& lock)
-  : AutoRealm(cx, JS::GetRealmForCompartment(cx->atomsCompartment(lock)), lock)
+  : AutoRealm(cx, cx->atomsRealm(lock), lock)
 {}
 
 js::AutoRealmUnchecked::AutoRealmUnchecked(JSContext* cx, JSCompartment* target)
   : AutoRealm(cx, JS::GetRealmForCompartment(target))
 {}
 
 inline bool
 JSCompartment::wrap(JSContext* cx, JS::MutableHandleValue vp)
 {
     /* Only GC things have to be wrapped or copied. */
     if (!vp.isGCThing())
         return true;
 
     /*
      * Symbols are GC things, but never need to be wrapped or copied because
-     * they are always allocated in the atoms compartment. They still need to
-     * be marked in the new compartment's zone, however.
+     * they are always allocated in the atoms zone. They still need to be
+     * marked in the new compartment's zone, however.
      */
     if (vp.isSymbol()) {
         cx->markAtomValue(vp);
         return true;
     }
 
     /* Handle strings. */
     if (vp.isString()) {
--- a/js/src/vm/JSCompartment.cpp
+++ b/js/src/vm/JSCompartment.cpp
@@ -41,17 +41,16 @@ using namespace js::jit;
 
 using mozilla::PodArrayZero;
 
 JSCompartment::JSCompartment(Zone* zone)
   : zone_(zone),
     runtime_(zone->runtimeFromAnyThread()),
     principals_(nullptr),
     isSystem_(false),
-    isAtomsCompartment_(false),
     isSelfHosting(false),
     marked(true),
     warnedAboutStringGenericsMethods(0),
 #ifdef DEBUG
     firedOnNewGlobalObject(false),
 #endif
     global_(nullptr),
     enterCompartmentDepth(0),
@@ -162,17 +161,17 @@ JSCompartment::init(JSContext* maybecx)
     }
 
     return true;
 }
 
 jit::JitRuntime*
 JSRuntime::createJitRuntime(JSContext* cx)
 {
-    // The shared stubs are created in the atoms compartment, which may be
+    // The shared stubs are created in the atoms zone, which may be
     // accessed by other threads with an exclusive context.
     AutoLockForExclusiveAccess atomsLock(cx);
 
     MOZ_ASSERT(!jitRuntime_);
 
     if (!CanLikelyAllocateMoreExecutableMemory()) {
         // Report OOM instead of potentially hitting the MOZ_CRASH below.
         ReportOutOfMemory(cx);
@@ -601,17 +600,17 @@ JSCompartment::getNonSyntacticLexicalEnv
         return nullptr;
     return &lexicalEnv->as<LexicalEnvironmentObject>();
 }
 
 bool
 JSCompartment::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name)
 {
     MOZ_ASSERT(name);
-    MOZ_ASSERT(!isAtomsCompartment());
+    MOZ_ASSERT(!JS::GetRealmForCompartment(this)->isAtomsRealm());
 
     if (varNames_.put(name))
         return true;
 
     ReportOutOfMemory(cx);
     return false;
 }
 
--- a/js/src/vm/JSCompartment.h
+++ b/js/src/vm/JSCompartment.h
@@ -591,31 +591,23 @@ struct JSCompartment
         // to a group to which we do not belong anymore. For another thing,
         // we use `isSystem()` as part of the key to map compartments
         // to a `PerformanceGroup`, so if we do not unlink now, this will
         // be too late once we have updated `isSystem_`.
         performanceMonitoring.unlink();
         isSystem_ = isSystem;
     }
 
-    bool isAtomsCompartment() const {
-        return isAtomsCompartment_;
-    }
-    void setIsAtomsCompartment() {
-        isAtomsCompartment_ = true;
-    }
-
     // Used to approximate non-content code when reporting telemetry.
     inline bool isProbablySystemCode() const {
         return isSystem_;
     }
   private:
     JSPrincipals*                principals_;
     bool                         isSystem_;
-    bool                         isAtomsCompartment_;
 
   public:
     bool                         isSelfHosting;
     bool                         marked;
     uint32_t                     warnedAboutStringGenericsMethods;
 
 #ifdef DEBUG
     bool                         firedOnNewGlobalObject;
@@ -654,17 +646,17 @@ struct JSCompartment
     // Note: Unrestricted access to the zone's runtime from an arbitrary
     // thread can easily lead to races. Use this method very carefully.
     JSRuntime* runtimeFromAnyThread() const {
         return runtime_;
     }
 
     /* The global object for this compartment.
      *
-     * This returns nullptr if this is the atoms compartment.  (The global_
+     * This returns nullptr if this is the atoms realm.  (The global_
      * field is also null briefly during GC, after the global object is
      * collected; but when that happens the JSCompartment is destroyed during
      * the same GC.)
      *
      * In contrast, JSObject::global() is infallible because marking a JSObject
      * always marks its global as well.
      * TODO: add infallible JSScript::global()
      */
@@ -1209,16 +1201,26 @@ class JS::Realm : public JSCompartment
     void destroy(js::FreeOp* fop);
 
     const JS::RealmCreationOptions& creationOptions() const { return creationOptions_; }
     JS::RealmBehaviors& behaviors() { return behaviors_; }
     const JS::RealmBehaviors& behaviors() const { return behaviors_; }
 
     /* Whether to preserve JIT code on non-shrinking GCs. */
     bool preserveJitCode() { return creationOptions_.preserveJitCode(); }
+
+  private:
+    bool isAtomsRealm_ = false;
+  public:
+    bool isAtomsRealm() const {
+        return isAtomsRealm_;
+    }
+    void setIsAtomsRealm() {
+        isAtomsRealm_ = true;
+    }
 };
 
 namespace js {
 
 // We only set the maybeAlive flag for objects and scripts. It's assumed that,
 // if a compartment is alive, then it will have at least some live object or
 // script it in. Even if we get this wrong, the worst that will happen is that
 // scheduledForDestruction will be set on the compartment, which will cause
@@ -1277,17 +1279,17 @@ class AutoRealm
     inline ~AutoRealm();
 
     JSContext* context() const { return cx_; }
     JS::Realm* origin() const { return origin_; }
 
   protected:
     inline AutoRealm(JSContext* cx, JS::Realm* target);
 
-    // Used only for entering the atoms compartment.
+    // Used only for entering the atoms realm.
     inline AutoRealm(JSContext* cx, JS::Realm* target,
                      AutoLockForExclusiveAccess& lock);
 
   private:
     AutoRealm(const AutoRealm&) = delete;
     AutoRealm& operator=(const AutoRealm&) = delete;
 };
 
--- a/js/src/vm/JSContext-inl.h
+++ b/js/src/vm/JSContext-inl.h
@@ -515,22 +515,22 @@ JSContext::leaveRealm(JS::Realm* oldReal
         startingRealm->leave();
 }
 
 inline void
 JSContext::setRealm(JS::Realm* realm,
                     const js::AutoLockForExclusiveAccess* maybeLock /* = nullptr */)
 {
     // Only one thread can be in the atoms realm at a time.
-    MOZ_ASSERT_IF(runtime_->isAtomsCompartment(realm), maybeLock != nullptr);
-    MOZ_ASSERT_IF(runtime_->isAtomsCompartment(realm) || runtime_->isAtomsCompartment(realm_),
+    MOZ_ASSERT_IF(realm && realm->isAtomsRealm(), maybeLock != nullptr);
+    MOZ_ASSERT_IF((realm && realm->isAtomsRealm()) || (realm_ && realm_->isAtomsRealm()),
                   runtime_->currentThreadHasExclusiveAccess());
 
     // Make sure that the atoms realm has its own zone.
-    MOZ_ASSERT_IF(realm && !runtime_->isAtomsCompartment(realm),
+    MOZ_ASSERT_IF(realm && !realm->isAtomsRealm(),
                   !realm->zone()->isAtomsZone());
 
     // Both the current and the new realm should be properly marked as
     // entered at this point.
     MOZ_ASSERT_IF(realm_, realm_->hasBeenEntered());
     MOZ_ASSERT_IF(realm, realm->hasBeenEntered());
 
     // This thread must have exclusive access to the zone.
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -1350,17 +1350,17 @@ JSContext::setRuntime(JSRuntime* rt)
     runtime_ = rt;
 }
 
 bool
 JSContext::getPendingException(MutableHandleValue rval)
 {
     MOZ_ASSERT(throwing);
     rval.set(unwrappedException());
-    if (IsAtomsCompartment(compartment()))
+    if (realm()->isAtomsRealm())
         return true;
     bool wasOverRecursed = overRecursed_;
     clearPendingException();
     if (!compartment()->wrap(this, rval))
         return false;
     assertSameCompartment(this, rval);
     setPendingException(rval);
     overRecursed_ = wasOverRecursed;
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -270,18 +270,18 @@ struct JSContext : public JS::RootingCon
     // Current global. This is only safe to use within the scope of the
     // AutoRealm from which it's called.
     inline js::Handle<js::GlobalObject*> global() const;
 
     // Methods to access runtime data that must be protected by locks.
     js::AtomSet& atoms(js::AutoLockForExclusiveAccess& lock) {
         return runtime_->atoms(lock);
     }
-    JSCompartment* atomsCompartment(js::AutoLockForExclusiveAccess& lock) {
-        return runtime_->atomsCompartment(lock);
+    JS::Realm* atomsRealm(js::AutoLockForExclusiveAccess& lock) {
+        return runtime_->atomsRealm(lock);
     }
     js::SymbolRegistry& symbolRegistry(js::AutoLockForExclusiveAccess& lock) {
         return runtime_->symbolRegistry(lock);
     }
     js::ScriptDataTable& scriptDataTable(js::AutoLockScriptData& lock) {
         return runtime_->scriptDataTable(lock);
     }
 
@@ -552,17 +552,17 @@ struct JSContext : public JS::RootingCon
 
     // Count of AutoKeepAtoms instances on the current thread's stack. When any
     // instances exist, atoms in the runtime will not be collected. Threads
     // parsing off the main thread do not increment this value, but the presence
     // of any such threads also inhibits collection of atoms. We don't scan the
     // stacks of exclusive threads, so we need to avoid collecting their
     // objects in another way. The only GC thing pointers they have are to
     // their exclusive compartment (which is not collected) or to the atoms
-    // compartment. Therefore, we avoid collecting the atoms compartment when
+    // compartment. Therefore, we avoid collecting the atoms zone when
     // exclusive threads are running.
     js::ThreadData<unsigned> keepAtoms;
 
     bool canCollectAtoms() const {
         return !keepAtoms && !runtime()->hasHelperThreadZones();
     }
 
   private:
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -152,17 +152,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     thousandsSeparator(nullptr),
     decimalSeparator(nullptr),
     numGrouping(nullptr),
 #endif
     beingDestroyed_(false),
     allowContentJS_(true),
     atoms_(nullptr),
     atomsAddedWhileSweeping_(nullptr),
-    atomsCompartment_(nullptr),
+    atomsRealm_(nullptr),
     staticStrings(nullptr),
     commonNames(nullptr),
     permanentAtoms(nullptr),
     wellKnownSymbols(nullptr),
     jitSupportsFloatingPoint(false),
     jitSupportsUnalignedAccesses(false),
     jitSupportsSimd(false),
     offthreadIonCompilationEnabled_(true),
@@ -217,29 +217,29 @@ JSRuntime::init(JSContext* cx, uint32_t 
     if (!gc.init(maxbytes, maxNurseryBytes))
         return false;
 
     ScopedJSDeletePtr<Zone> atomsZone(js_new<Zone>(this));
     if (!atomsZone || !atomsZone->init(true))
         return false;
 
     JS::RealmOptions options;
-    ScopedJSDeletePtr<Realm> atomsCompartment(js_new<Realm>(atomsZone.get(), options));
-    if (!atomsCompartment || !atomsCompartment->init(nullptr))
+    ScopedJSDeletePtr<Realm> atomsRealm(js_new<Realm>(atomsZone.get(), options));
+    if (!atomsRealm || !atomsRealm->init(nullptr))
         return false;
 
     gc.atomsZone = atomsZone.get();
-    if (!atomsZone->compartments().append(atomsCompartment.get()))
+    if (!atomsZone->compartments().append(atomsRealm.get()))
         return false;
 
-    atomsCompartment->setIsSystem(true);
-    atomsCompartment->setIsAtomsCompartment();
+    atomsRealm->setIsSystem(true);
+    atomsRealm->setIsAtomsRealm();
 
     atomsZone.forget();
-    this->atomsCompartment_ = atomsCompartment.forget();
+    this->atomsRealm_ = atomsRealm.forget();
 
     if (!symbolRegistry_.ref().init())
         return false;
 
     if (!scriptDataTable_.ref().init())
         return false;
 
     /* The garbage collector depends on everything before this point being initialized. */
@@ -326,17 +326,17 @@ JSRuntime::destroyRuntime()
      */
     FreeScriptData(this);
 
 #if !EXPOSE_INTL_API
     FinishRuntimeNumberState(this);
 #endif
 
     gc.finish();
-    atomsCompartment_ = nullptr;
+    atomsRealm_ = nullptr;
 
     js_delete(defaultFreeOp_.ref());
 
     js_free(defaultLocale);
     js_delete(jitRuntime_.ref());
 
 #ifdef DEBUG
     initialized_ = false;
@@ -430,17 +430,17 @@ JSRuntime::addSizeOfIncludingThis(mozill
 
     rtSizes->wasmRuntime += wasmInstances.lock()->sizeOfExcludingThis(mallocSizeOf);
 }
 
 static bool
 HandleInterrupt(JSContext* cx, bool invokeCallback)
 {
     MOZ_ASSERT(cx->requestDepth >= 1);
-    MOZ_ASSERT(!cx->compartment()->isAtomsCompartment());
+    MOZ_ASSERT(!cx->realm()->isAtomsRealm());
 
     cx->runtime()->gc.gcIfRequested();
 
     // A worker thread may have requested an interrupt after finishing an Ion
     // compilation.
     jit::AttachFinishedCompilations(cx);
 
     // Don't call the interrupt callback if we only interrupted for GC or Ion.
@@ -763,17 +763,17 @@ JSRuntime::onOutOfMemoryCanGC(AllocFunct
     if (OnLargeAllocationFailure && bytes >= LARGE_ALLOCATION)
         OnLargeAllocationFailure();
     return onOutOfMemory(allocFunc, bytes, reallocPtr);
 }
 
 bool
 JSRuntime::activeGCInAtomsZone()
 {
-    Zone* zone = atomsCompartment_->zone();
+    Zone* zone = atomsRealm_->zone();
     return (zone->needsIncrementalBarrier() && !gc.isVerifyPreBarriersEnabled()) ||
            zone->wasGCStarted();
 }
 
 bool
 JSRuntime::createAtomsAddedWhileSweepingTable()
 {
     MOZ_ASSERT(JS::CurrentThreadIsHeapCollecting());
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -695,24 +695,24 @@ struct JSRuntime : public js::MallocProv
     // Set of all atoms other than those in permanentAtoms and staticStrings.
     // Reading or writing this set requires the calling thread to use
     // AutoLockForExclusiveAccess.
     js::ExclusiveAccessLockOrGCTaskData<js::AtomSet*> atoms_;
 
     // Set of all atoms added while the main atoms table is being swept.
     js::ExclusiveAccessLockData<js::AtomSet*> atomsAddedWhileSweeping_;
 
-    // Compartment and associated zone containing all atoms in the runtime, as
+    // Realm and associated zone containing all atoms in the runtime, as
     // well as runtime wide IonCode stubs. Modifying the contents of this
-    // compartment requires the calling thread to use AutoLockForExclusiveAccess.
-    js::WriteOnceData<JSCompartment*> atomsCompartment_;
+    // zone requires the calling thread to use AutoLockForExclusiveAccess.
+    js::WriteOnceData<JS::Realm*> atomsRealm_;
 
     // Set of all live symbols produced by Symbol.for(). All such symbols are
-    // allocated in the atomsCompartment. Reading or writing the symbol
-    // registry requires the calling thread to use AutoLockForExclusiveAccess.
+    // allocated in the atomsZone. Reading or writing the symbol registry
+    // requires the calling thread to use AutoLockForExclusiveAccess.
     js::ExclusiveAccessLockOrGCTaskData<js::SymbolRegistry> symbolRegistry_;
 
   public:
     bool initializeAtoms(JSContext* cx);
     void finishAtoms();
     bool atomsAreFinished() const { return !atoms_; }
 
     js::AtomSet* atomsForSweeping() {
@@ -730,32 +730,35 @@ struct JSRuntime : public js::MallocProv
     }
 
     bool createAtomsAddedWhileSweepingTable();
     void destroyAtomsAddedWhileSweepingTable();
     js::AtomSet* atomsAddedWhileSweeping() {
         return atomsAddedWhileSweeping_;
     }
 
-    JSCompartment* atomsCompartment(js::AutoLockForExclusiveAccess& lock) {
-        return atomsCompartment_;
+    JS::Realm* atomsRealm(js::AutoLockForExclusiveAccess& lock) {
+        return atomsRealm_;
     }
-    JSCompartment* unsafeAtomsCompartment() {
-        return atomsCompartment_;
+    JS::Realm* unsafeAtomsRealm() {
+        return atomsRealm_;
     }
 
+    // Note: once JS::Realm and JSCompartment are completely unrelated, the
+    // atoms realm probably won't have a compartment so we can remove this
+    // then.
     bool isAtomsCompartment(JSCompartment* comp) {
-        return comp == atomsCompartment_;
+        return JS::GetRealmForCompartment(comp) == atomsRealm_;
     }
 
     const JS::Zone* atomsZone(js::AutoLockForExclusiveAccess& lock) const {
         return gc.atomsZone;
     }
 
-    // The atoms compartment is the only one in its zone.
+    // The atoms realm is the only one in its zone.
     bool isAtomsZone(const JS::Zone* zone) const {
         return zone == gc.atomsZone;
     }
 
     bool activeGCInAtomsZone();
 
     js::SymbolRegistry& symbolRegistry(js::AutoLockForExclusiveAccess& lock) {
         return symbolRegistry_.ref();
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2780,17 +2780,17 @@ js::FillSelfHostingCompileOptions(Compil
     options.extraWarningsOption = true;
 #endif
 }
 
 GlobalObject*
 JSRuntime::createSelfHostingGlobal(JSContext* cx)
 {
     MOZ_ASSERT(!cx->isExceptionPending());
-    MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
+    MOZ_ASSERT(!cx->realm());
 
     JS::RealmOptions options;
     options.creationOptions().setNewZone();
     options.behaviors().setDiscardSource(true);
 
     JSCompartment* compartment = NewCompartment(cx, nullptr, options);
     if (!compartment)
         return nullptr;
--- a/js/src/vm/StringType-inl.h
+++ b/js/src/vm/StringType-inl.h
@@ -224,17 +224,17 @@ MOZ_ALWAYS_INLINE JSFlatString*
 JSFlatString::new_(JSContext* cx, const CharT* chars, size_t length)
 {
     MOZ_ASSERT(chars[length] == CharT(0));
 
     if (!validateLength(cx, length))
         return nullptr;
 
     JSFlatString* str;
-    if (cx->compartment()->isAtomsCompartment())
+    if (cx->realm()->isAtomsRealm())
         str = js::Allocate<js::NormalAtom, allowGC>(cx);
     else
         str = js::Allocate<JSFlatString, allowGC>(cx, js::gc::DefaultHeap);
     if (!str)
         return nullptr;
 
     if (!str->isTenured()) {
         // The chars pointer is only considered to be handed over to this
@@ -268,27 +268,27 @@ JSFlatString::toPropertyName(JSContext* 
         return nullptr;
     return atom->asPropertyName();
 }
 
 template <js::AllowGC allowGC>
 MOZ_ALWAYS_INLINE JSThinInlineString*
 JSThinInlineString::new_(JSContext* cx)
 {
-    if (cx->compartment()->isAtomsCompartment())
+    if (cx->realm()->isAtomsRealm())
         return (JSThinInlineString*)(js::Allocate<js::NormalAtom, allowGC>(cx));
 
     return js::Allocate<JSThinInlineString, allowGC>(cx, js::gc::DefaultHeap);
 }
 
 template <js::AllowGC allowGC>
 MOZ_ALWAYS_INLINE JSFatInlineString*
 JSFatInlineString::new_(JSContext* cx)
 {
-    if (cx->compartment()->isAtomsCompartment())
+    if (cx->realm()->isAtomsRealm())
         return (JSFatInlineString*)(js::Allocate<js::FatInlineAtom, allowGC>(cx));
 
     return js::Allocate<JSFatInlineString, allowGC>(cx, js::gc::DefaultHeap);
 }
 
 template<>
 MOZ_ALWAYS_INLINE JS::Latin1Char*
 JSThinInlineString::init<JS::Latin1Char>(size_t length)
--- a/js/src/vm/SymbolType.cpp
+++ b/js/src/vm/SymbolType.cpp
@@ -17,17 +17,17 @@
 
 using JS::Symbol;
 using namespace js;
 
 Symbol*
 Symbol::newInternal(JSContext* cx, JS::SymbolCode code, uint32_t hash, JSAtom* description,
                     AutoLockForExclusiveAccess& lock)
 {
-    MOZ_ASSERT(cx->compartment() == cx->atomsCompartment(lock));
+    MOZ_ASSERT(cx->realm() == cx->atomsRealm(lock));
 
     // Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
     Symbol* p = Allocate<JS::Symbol, NoGC>(cx);
     if (!p) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
     return new (p) Symbol(code, hash, description);
--- a/js/src/vm/UbiNodeCensus.cpp
+++ b/js/src/vm/UbiNodeCensus.cpp
@@ -28,17 +28,17 @@ CountDeleter::operator()(CountBase* ptr)
     // pointer.
     ptr->destruct();
     js_free(ptr);
 }
 
 JS_PUBLIC_API(bool)
 Census::init() {
     AutoLockForExclusiveAccess lock(cx);
-    atomsZone = cx->runtime()->atomsCompartment(lock)->zone();
+    atomsZone = cx->runtime()->atomsRealm(lock)->zone();
     return targetZones.init();
 }
 
 
 /*** Count Types ***********************************************************************************/
 
 // The simplest type: just count everything.
 class SimpleCount : public CountType {
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1073,17 +1073,17 @@ XPCJSRuntime::~XPCJSRuntime()
 }
 
 // If |*anonymizeID| is non-zero and this is a user compartment, the name will
 // be anonymized.
 static void
 GetCompartmentName(JSCompartment* c, nsCString& name, int* anonymizeID,
                    bool replaceSlashes)
 {
-    if (js::IsAtomsCompartment(c)) {
+    if (js::IsAtomsRealm(JS::GetRealmForCompartment(c))) {
         name.AssignLiteral("atoms");
     } else if (*anonymizeID && !js::IsSystemCompartment(c)) {
         name.AppendPrintf("<anonymized-%d>", *anonymizeID);
         *anonymizeID += 1;
     } else if (JSPrincipals* principals = JS_GetCompartmentPrincipals(c)) {
         nsresult rv = nsJSPrincipals::get(principals)->GetScriptLocation(name);
         if (NS_FAILED(rv)) {
             name.AssignLiteral("(unknown)");