Bug 790349 - Convert all fooAtom uses to simply foo. r=jorendorff
☠☠ backed out by 7c6024089dc3 ☠ ☠
authorJeff Walden <jwalden@mit.edu>
Tue, 11 Sep 2012 10:32:33 -0700
changeset 107248 d3d8807c6c59c170a6bc1be9be37f6511ea15b25
parent 107247 cf239b55242a63ce52186cedbcfe6dcebda815ed
child 107249 c5e3744772c4a9c3735986b68b4675a41388efee
push id14930
push userjwalden@mit.edu
push dateMon, 17 Sep 2012 17:42:39 +0000
treeherdermozilla-inbound@d3d8807c6c59 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs790349
milestone18.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 790349 - Convert all fooAtom uses to simply foo. r=jorendorff
js/src/builtin/ParallelArray.cpp
js/src/builtin/RegExp.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/FoldConstants.cpp
js/src/frontend/Parser.cpp
js/src/frontend/TokenStream.cpp
js/src/ion/CodeGenerator.cpp
js/src/ion/IonBuilder.cpp
js/src/ion/VMFunctions.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsatominlines.h
js/src/jsbool.cpp
js/src/jscntxt.h
js/src/jsdate.cpp
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsopcode.cpp
js/src/jsopcodeinlines.h
js/src/jsproxy.cpp
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastOps.cpp
js/src/methodjit/LoopState.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/vm/ArgumentsObject.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/Stack.cpp
js/src/vm/StringBuffer.cpp
js/src/vm/StringObject-inl.h
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -842,29 +842,29 @@ ParallelArrayObject::initClass(JSContext
 
     Rooted<GlobalObject *> global(cx, &obj->asGlobal());
 
     RootedObject proto(cx, global->createBlankPrototype(cx, &protoClass));
     if (!proto)
         return NULL;
 
     JSProtoKey key = JSProto_ParallelArray;
-    Rooted<PropertyName*> name(cx, cx->runtime->atomState.ParallelArrayAtom);
-    RootedFunction ctor(cx, global->createConstructor(cx, construct, name, 0));
+    RootedFunction ctor(cx);
+    ctor = global->createConstructor(cx, construct, cx->names().ParallelArray, 0);
     if (!ctor ||
         !LinkConstructorAndPrototype(cx, ctor, proto) ||
         !DefinePropertiesAndBrand(cx, proto, NULL, methods) ||
         !DefineConstructorAndPrototype(cx, global, key, ctor, proto))
     {
         return NULL;
     }
 
     // Define the length and shape properties.
-    RootedId lengthId(cx, AtomToId(cx->runtime->atomState.lengthAtom));
-    RootedId shapeId(cx, AtomToId(cx->runtime->atomState.shapeAtom));
+    RootedId lengthId(cx, AtomToId(cx->names().length));
+    RootedId shapeId(cx, AtomToId(cx->names().shape));
     unsigned flags = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_GETTER;
 
     JSObject *scriptedLength = js_NewFunction(cx, NULL, NonGenericMethod<lengthGetter>,
                                               0, 0, global, NULL);
     JSObject *scriptedShape = js_NewFunction(cx, NULL, NonGenericMethod<dimensionsGetter>,
                                              0, 0, global, NULL);
 
     RootedValue value(cx, UndefinedValue());
@@ -1528,17 +1528,17 @@ ParallelArrayObject::toStringBufferImpl(
 
         if (!elem->isNullOrUndefined()) {
             if (useLocale) {
                 tmp = *elem;
                 JSObject *robj = ToObject(cx, tmp);
                 if (!robj)
                     return false;
 
-                id = NameToId(cx->runtime->atomState.toLocaleStringAtom);
+                id = NameToId(cx->names().toLocaleString);
                 if (!robj->callMethod(cx, id, 0, NULL, &localeElem) ||
                     !ValueToStringBuffer(cx, localeElem, sb))
                 {
                     return false;
                 }
             } else {
                 if (!ValueToStringBuffer(cx, *elem, sb))
                     return false;
@@ -1606,17 +1606,17 @@ ParallelArrayObject::mark(JSTracer *trc,
 JSBool
 ParallelArrayObject::lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                    MutableHandleObject objp, MutableHandleShape propp)
 {
     uint32_t i;
     if (js_IdIsIndex(id, &i))
         return lookupElement(cx, obj, i, objp, propp);
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().length)) {
         MarkNonNativePropertyFound(obj, propp);
         objp.set(obj);
         return true;
     }
 
     RootedObject proto(cx, obj->getProto());
     if (proto)
         return JSObject::lookupGeneric(cx, proto, id, objp, propp);
@@ -1713,17 +1713,17 @@ ParallelArrayObject::getGeneric(JSContex
     Rooted<PropertyName*> name(cx, atom->asPropertyName());
     return getProperty(cx, obj, receiver, name, vp);
 }
 
 JSBool
 ParallelArrayObject::getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
                                  HandlePropertyName name, MutableHandleValue vp)
 {
-    if (name == cx->runtime->atomState.lengthAtom) {
+    if (name == cx->names().length) {
         vp.setNumber(as(obj)->outermostDimension());
         return true;
     }
 
     RootedObject proto(cx, obj->getProto());
     if (proto)
         return JSObject::getProperty(cx, proto, receiver, name, vp);
 
@@ -1784,29 +1784,29 @@ ParallelArrayObject::setSpecial(JSContex
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PAR_ARRAY_IMMUTABLE);
     return false;
 }
 
 JSBool
 ParallelArrayObject::getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
                                           unsigned *attrsp)
 {
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
+    if (JSID_IS_ATOM(id, cx->names().length))
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
     else
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_ENUMERATE;
 
     return true;
 }
 
 JSBool
 ParallelArrayObject::getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                            unsigned *attrsp)
 {
-    if (name == cx->runtime->atomState.lengthAtom)
+    if (name == cx->names().length)
         *attrsp = JSPROP_PERMANENT | JSPROP_READONLY;
     return true;
 }
 
 JSBool
 ParallelArrayObject::getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
                                           unsigned *attrsp)
 {
@@ -1887,17 +1887,17 @@ ParallelArrayObject::deleteSpecial(JSCon
 }
 
 bool
 ParallelArrayObject::enumerate(JSContext *cx, HandleObject obj, unsigned flags,
                                AutoIdVector *props)
 {
     RootedParallelArrayObject source(cx, as(obj));
 
-    if (flags & JSITER_HIDDEN && !props->append(NameToId(cx->runtime->atomState.lengthAtom)))
+    if (flags & JSITER_HIDDEN && !props->append(NameToId(cx->names().length)))
         return false;
 
     // ParallelArray objects have no holes.
     if (source->outermostDimension() > 0) {
         for (uint32_t i = 0; i < source->outermostDimension(); i++)
             props->append(INT_TO_JSID(i));
     }
 
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -32,26 +32,24 @@ class RegExpMatchBuilder
 
     bool append(uint32_t index, HandleValue v) {
         JS_ASSERT(!array->getOps()->getElement);
         return !!baseops::DefineElement(cx, array, index, v, JS_PropertyStub, JS_StrictPropertyStub,
                                         JSPROP_ENUMERATE);
     }
 
     bool setIndex(int index) {
-        Rooted<PropertyName*> name(cx, cx->runtime->atomState.indexAtom);
         RootedValue value(cx, Int32Value(index));
-        return setProperty(name, value);
+        return setProperty(cx->names().index, value);
     }
 
     bool setInput(JSString *str) {
         JS_ASSERT(str);
-        Rooted<PropertyName*> name(cx, cx->runtime->atomState.inputAtom);
         RootedValue value(cx, StringValue(str));
-        return setProperty(name, value);
+        return setProperty(cx->names().input, value);
     }
 };
 
 static bool
 CreateRegExpMatchResult(JSContext *cx, JSString *input_, const jschar *chars, size_t length,
                         MatchPairs *matchPairs, Value *rval)
 {
     RootedString input(cx, input_);
@@ -239,17 +237,17 @@ CompileRegExpObject(JSContext *cx, RegEx
             flags = g->getFlags();
         }
 
         /*
          * 'toSource' is a permanent read-only property, so this is equivalent
          * to executing RegExpObject::getSource on the unwrapped object.
          */
         RootedValue v(cx);
-        if (!JSObject::getProperty(cx, sourceObj, sourceObj, cx->runtime->atomState.sourceAtom, &v))
+        if (!JSObject::getProperty(cx, sourceObj, sourceObj, cx->names().source, &v))
             return false;
 
         Rooted<JSAtom*> sourceAtom(cx, &v.toString()->asAtom());
         RegExpObject *reobj = builder.build(sourceAtom, flags);
         if (!reobj)
             return false;
 
         args.rval().setObject(*reobj);
@@ -488,26 +486,26 @@ js_InitRegExpClass(JSContext *cx, JSObje
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpClass));
     if (!proto)
         return NULL;
     proto->setPrivate(NULL);
 
+    HandlePropertyName empty = cx->names().empty;
     RegExpObjectBuilder builder(cx, &proto->asRegExp());
-    Rooted<JSAtom*> empty(cx, cx->runtime->emptyString);
     if (!builder.build(empty, RegExpFlag(0)))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods))
         return NULL;
 
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, regexp_construct, cx->runtime->atomState.RegExpAtom, 2);
+    ctor = global->createConstructor(cx, regexp_construct, cx->names().RegExp, 2);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     /* Add static properties to the RegExp constructor. */
     if (!JS_DefineProperties(cx, ctor, regexp_static_props))
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -219,17 +219,17 @@ frontend::CompileScript(JSContext *cx, H
     if (pn && onlyXML && !callerFrame) {
         parser.reportError(NULL, JSMSG_XML_WHOLE_PROGRAM);
         return NULL;
     }
 #endif
 
     // It's an error to use |arguments| in a function that has a rest parameter.
     if (callerFrame && callerFrame->isFunctionFrame() && callerFrame->fun()->hasRest()) {
-        PropertyName *arguments = cx->runtime->atomState.argumentsAtom;
+        HandlePropertyName arguments = cx->names().arguments;
         for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) {
             if (r.front().key() == arguments) {
                 parser.reportError(NULL, JSMSG_ARGUMENTS_AND_REST);
                 return NULL;
             }
         }
     }
 
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -767,17 +767,17 @@ EmitIndexOp(JSContext *cx, JSOp op, uint
     return true;
 }
 
 static bool
 EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
 {
     JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
 
-    if (op == JSOP_GETPROP && atom == cx->runtime->atomState.lengthAtom) {
+    if (op == JSOP_GETPROP && atom == cx->names().length) {
         /* Specialize length accesses for the interpreter. */
         op = JSOP_LENGTH;
     }
 
     jsatomid index;
     if (!bce->makeAtomIndex(atom, &index))
         return false;
 
@@ -2621,17 +2621,17 @@ frontend::EmitFunctionScript(JSContext *
         JS_ASSERT(bce->next() == bce->base());  /* See JSScript::argumentsBytecode. */
         bce->switchToProlog();
         if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
             return false;
         unsigned varIndex = bce->script->bindings.argumentsVarIndex(cx);
         if (bce->script->varIsAliased(varIndex)) {
             ScopeCoordinate sc;
             sc.hops = 0;
-            sc.slot = AliasedNameToSlot(bce->script, cx->runtime->atomState.argumentsAtom);
+            sc.slot = AliasedNameToSlot(bce->script, cx->names().arguments);
             if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, bce))
                 return false;
         } else {
             if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, varIndex, bce))
                 return false;
         }
         if (Emit1(cx, bce, JSOP_POP) < 0)
             return false;
@@ -3548,17 +3548,17 @@ EmitAssignment(JSContext *cx, BytecodeEm
                 JSOp op = lhs->isOp(JSOP_SETARG) ? JSOP_GETARG : JSOP_GETLOCAL;
                 if (!EmitVarOp(cx, lhs, op, bce))
                     return false;
             }
             break;
           case PNK_DOT: {
             if (Emit1(cx, bce, JSOP_DUP) < 0)
                 return false;
-            bool isLength = (lhs->pn_atom == cx->runtime->atomState.lengthAtom);
+            bool isLength = (lhs->pn_atom == cx->names().length);
             if (!EmitIndex32(cx, isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex, bce))
                 return false;
             break;
           }
           case PNK_ELEM:
           case PNK_CALL:
 #if JS_HAS_XML_SUPPORT
           case PNK_XMLUNARY:
@@ -3771,17 +3771,17 @@ ParseNode::getConstantValue(JSContext *c
                 if (idvalue.isInt32() && INT_FITS_IN_JSID(idvalue.toInt32()))
                     id = INT_TO_JSID(idvalue.toInt32());
                 else if (!InternNonIntElementId(cx, obj, idvalue, id.address()))
                     return false;
                 if (!JSObject::defineGeneric(cx, obj, id, value, NULL, NULL, JSPROP_ENUMERATE))
                     return false;
             } else {
                 JS_ASSERT(pnid->isKind(PNK_NAME) || pnid->isKind(PNK_STRING));
-                JS_ASSERT(pnid->pn_atom != cx->runtime->atomState.protoAtom);
+                JS_ASSERT(pnid->pn_atom != cx->names().proto);
                 RootedId id(cx, AtomToId(pnid->pn_atom));
                 if (!DefineNativeProperty(cx, obj, id, value, NULL, NULL,
                                           JSPROP_ENUMERATE, 0, 0)) {
                     return false;
                 }
             }
         }
 
@@ -4351,19 +4351,19 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
 {
     JS_ASSERT(!bce->sc->inStrictMode());
 
     if (Emit1(cx, bce, JSOP_STARTXML) < 0)
         return false;
 
     {
         jsatomid index;
-        JSAtom *tagAtom = (pn->isKind(PNK_XMLETAGO))
-                          ? cx->runtime->atomState.etagoAtom
-                          : cx->runtime->atomState.stagoAtom;
+        HandlePropertyName tagAtom = (pn->isKind(PNK_XMLETAGO))
+                                     ? cx->names().etago
+                                     : cx->names().stago;
         if (!bce->makeAtomIndex(tagAtom, &index))
             return false;
         if (!EmitIndex32(cx, JSOP_STRING, index, bce))
             return false;
     }
 
     JS_ASSERT(pn->pn_count != 0);
     ParseNode *pn2 = pn->pn_head;
@@ -4385,18 +4385,19 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
                 return false;
         }
         if (Emit1(cx, bce, (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0)
             return false;
     }
 
     {
         jsatomid index;
-        JSAtom *tmp = (pn->isKind(PNK_XMLPTAGC)) ? cx->runtime->atomState.ptagcAtom
-                                                 : cx->runtime->atomState.tagcAtom;
+        HandlePropertyName tmp = pn->isKind(PNK_XMLPTAGC)
+                                 ? cx->names().ptagc
+                                 : cx->names().tagc;
         if (!bce->makeAtomIndex(tmp, &index))
             return false;
         if (!EmitIndex32(cx, JSOP_STRING, index, bce))
             return false;
     }
     if (Emit1(cx, bce, JSOP_ADD) < 0)
         return false;
 
@@ -5346,17 +5347,17 @@ EmitCallOrNew(JSContext *cx, BytecodeEmi
     bool emitArgs = true;
     ParseNode *pn2 = pn->pn_head;
     switch (pn2->getKind()) {
       case PNK_NAME:
         if (!EmitNameOp(cx, bce, pn2, callop))
             return false;
         break;
       case PNK_INTRINSICNAME:
-        if (pn2->name() == cx->runtime->atomState._CallFunctionAtom)
+        if (pn2->name() == cx->names()._CallFunction)
         {
             /*
              * Special-casing of %_CallFunction to emit bytecode that directly
              * invokes the callee with the correct |this| object and arguments.
              * The call %_CallFunction(receiver, ...args, fun) thus becomes:
              * - emit lookup for fun
              * - emit lookup for receiver
              * - emit lookups for ...args
@@ -5795,17 +5796,17 @@ EmitObject(JSContext *cx, BytecodeEmitte
             jsatomid index;
             if (!bce->makeAtomIndex(pn3->pn_atom, &index))
                 return false;
 
             /*
              * Disable NEWOBJECT on initializers that set __proto__, which has
              * a non-standard setter on objects.
              */
-            if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
+            if (pn3->pn_atom == cx->names().proto)
                 obj = NULL;
             op = JSOP_INITPROP;
 
             if (obj) {
                 JS_ASSERT(!obj->inDictionaryMode());
                 Rooted<jsid> id(cx, AtomToId(pn3->pn_atom));
                 RootedValue undefinedValue(cx, UndefinedValue());
                 if (!DefineNativeProperty(cx, obj, id, undefinedValue, NULL, NULL,
@@ -6540,19 +6541,18 @@ frontend::EmitTree(JSContext *cx, Byteco
                 return false;
             if (pn2 != pn->pn_head && Emit1(cx, bce, JSOP_ADD) < 0)
                 return false;
         }
 
         if (pn->pn_xflags & PNX_XMLROOT) {
             if (pn->pn_count == 0) {
                 JS_ASSERT(pn->isKind(PNK_XMLLIST));
-                JSAtom *atom = cx->runtime->atomState.emptyAtom;
                 jsatomid index;
-                if (!bce->makeAtomIndex(atom, &index))
+                if (!bce->makeAtomIndex(cx->names().empty, &index))
                     return false;
                 if (!EmitIndex32(cx, JSOP_STRING, index, bce))
                     return false;
             }
             if (Emit1(cx, bce, pn->getOp()) < 0)
                 return false;
         }
 #ifdef DEBUG
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -196,19 +196,19 @@ FoldXMLConstants(JSContext *cx, ParseNod
     JS_ASSERT(pn->isArity(PN_LIST));
     ParseNodeKind kind = pn->getKind();
     ParseNode **pnp = &pn->pn_head;
     ParseNode *pn1 = *pnp;
     RootedString accum(cx);
     RootedString str(cx);
     if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
         if (kind == PNK_XMLETAGO)
-            accum = cx->runtime->atomState.etagoAtom;
+            accum = cx->names().etago;
         else if (kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC)
-            accum = cx->runtime->atomState.stagoAtom;
+            accum = cx->names().stago;
     }
 
     /*
      * GC Rooting here is tricky: for most of the loop, |accum| is safe via
      * the newborn string root. However, when |pn2->getKind()| is PNK_XMLCDATA,
      * PNK_XMLCOMMENT, or PNK_XMLPI it is knocked out of the newborn root.
      * Therefore, we have to add additonal protection from GC nesting under
      * js_ConcatStrings.
@@ -302,19 +302,19 @@ FoldXMLConstants(JSContext *cx, ParseNod
         }
         accum = str;
     }
 
     if (accum) {
         str = NULL;
         if ((pn->pn_xflags & PNX_CANTFOLD) == 0) {
             if (kind == PNK_XMLPTAGC)
-                str = cx->runtime->atomState.ptagcAtom;
+                str = cx->names().ptagc;
             else if (kind == PNK_XMLSTAGO || kind == PNK_XMLETAGO)
-                str = cx->runtime->atomState.tagcAtom;
+                str = cx->names().tagc;
         }
         if (str) {
             accum = js_ConcatStrings(cx, accum, str);
             if (!accum)
                 return false;
         }
 
         JS_ASSERT(*pnp == pn1);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -169,17 +169,17 @@ ParseContext::define(JSContext *cx, Prop
       case Definition::ARG:
         JS_ASSERT(sc->isFunction);
         dn->setOp(JSOP_GETARG);
         dn->pn_dflags |= PND_BOUND;
         if (!dn->pn_cookie.set(cx, staticLevel, args_.length()))
             return false;
         if (!args_.append(dn))
             return false;
-        if (name == cx->runtime->atomState.emptyAtom)
+        if (name == cx->names().empty)
             break;
         if (!decls_.addUnique(name, dn))
             return false;
         break;
 
       case Definition::CONST:
       case Definition::VAR:
         if (sc->isFunction) {
@@ -691,18 +691,17 @@ CheckFinalReturn(JSContext *cx, Parser *
  * Check that it is permitted to assign to lhs.  Strict mode code may not
  * assign to 'eval' or 'arguments'.
  */
 static bool
 CheckStrictAssignment(JSContext *cx, Parser *parser, ParseNode *lhs)
 {
     if (parser->pc->sc->needStrictChecks() && lhs->isKind(PNK_NAME)) {
         JSAtom *atom = lhs->pn_atom;
-        JSAtomState *atomState = &cx->runtime->atomState;
-        if (atom == atomState->evalAtom || atom == atomState->argumentsAtom) {
+        if (atom == cx->names().eval || atom == cx->names().arguments) {
             JSAutoByteString name;
             if (!js_AtomToPrintableString(cx, atom, &name) ||
                 !parser->reportStrictModeError(lhs, JSMSG_DEPRECATED_ASSIGN, name.ptr()))
             {
                 return false;
             }
         }
     }
@@ -716,19 +715,18 @@ CheckStrictAssignment(JSContext *cx, Par
  * pc's token stream if pn is NULL.
  */
 bool
 CheckStrictBinding(JSContext *cx, Parser *parser, HandlePropertyName name, ParseNode *pn)
 {
     if (!parser->pc->sc->needStrictChecks())
         return true;
 
-    JSAtomState *atomState = &cx->runtime->atomState;
-    if (name == atomState->evalAtom ||
-        name == atomState->argumentsAtom ||
+    if (name == cx->names().eval ||
+        name == cx->names().arguments ||
         FindKeyword(name->charsZ(), name->length()))
     {
         JSAutoByteString bytes;
         if (!js_AtomToPrintableString(cx, name, &bytes))
             return false;
         return parser->reportStrictModeError(pn, JSMSG_BAD_BINDING, bytes.ptr());
     }
 
@@ -785,17 +783,17 @@ Parser::functionBody(FunctionBodyType ty
     /* Check for falling off the end of a function that returns a value. */
     if (context->hasStrictOption() && pc->funHasReturnExpr &&
         !CheckFinalReturn(context, this, pn))
     {
         pn = NULL;
     }
 
     /* Time to implement the odd semantics of 'arguments'. */
-    Rooted<PropertyName*> arguments(context, context->runtime->atomState.argumentsAtom);
+    Handle<PropertyName*> arguments = context->names().arguments;
 
     /*
      * Non-top-level functions use JSOP_DEFFUN which is a dynamic scope
      * operation which means it aliases any bindings with the same name.
      * Due to the implicit declaration mechanism (below), 'arguments' will not
      * have decls and, even if it did, they will not be noted as closed in the
      * emitter. Thus, in the corner case of function-statement-overridding-
      * arguments, flag the whole scope as dynamic.
@@ -1420,17 +1418,17 @@ Parser::functionArguments(ParseNode **li
                 if (!lhs)
                     return false;
 
                 /*
                  * Synthesize a destructuring assignment from the single
                  * anonymous positional parameter into the destructuring
                  * left-hand-side expression and accumulate it in list.
                  */
-                PropertyName *name = context->runtime->atomState.emptyAtom;
+                HandlePropertyName name = context->names().empty;
                 ParseNode *rhs = NameNode::create(PNK_NAME, name, this, this->pc);
                 if (!rhs)
                     return false;
 
                 if (!pc->define(context, name, rhs, Definition::ARG))
                     return false;
 
                 ParseNode *item = new_<BinaryNode>(PNK_ASSIGN, JSOP_NOP, lhs->pn_pos, lhs, rhs);
@@ -1907,17 +1905,17 @@ Parser::processDirectives(ParseNode *stm
             freeTree(stringNode);
             if (next == TOK_ERROR)
                 return false;
             break;
         }
         tokenStream.matchToken(TOK_SEMI);
         if (isDirective) {
             // It's a directive. Is it one we know?
-            if (atom == context->runtime->atomState.useStrictAtom && !gotStrictMode) {
+            if (atom == context->names().useStrict && !gotStrictMode) {
                 pc->sc->setExplicitUseStrict();
                 if (!setStrictMode(true))
                     return false;
                 gotStrictMode = true;
             }
         }
         ParseNode *stmt = UnaryNode::create(PNK_SEMI, this);
         if (!stmt) {
@@ -2948,17 +2946,17 @@ Parser::switchStatement()
 bool
 Parser::matchInOrOf(bool *isForOfp)
 {
     if (tokenStream.matchToken(TOK_IN)) {
         *isForOfp = false;
         return true;
     }
     if (tokenStream.matchToken(TOK_NAME)) {
-        if (tokenStream.currentToken().name() == context->runtime->atomState.ofAtom) {
+        if (tokenStream.currentToken().name() == context->names().of) {
             *isForOfp = true;
             return true;
         }
         tokenStream.ungetToken();
     }
     return false;
 }
 
@@ -2973,17 +2971,17 @@ Parser::forStatement()
         return NULL;
 
     StmtInfoPC forStmt(context);
     PushStatementPC(pc, &forStmt, STMT_FOR_LOOP);
 
     pn->setOp(JSOP_ITER);
     pn->pn_iflags = 0;
     if (tokenStream.matchToken(TOK_NAME)) {
-        if (tokenStream.currentToken().name() == context->runtime->atomState.eachAtom)
+        if (tokenStream.currentToken().name() == context->names().each)
             pn->pn_iflags = JSITER_FOREACH;
         else
             tokenStream.ungetToken();
     }
 
     TokenPos lp_pos = tokenStream.currentToken().pos;
     MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
 
@@ -5156,17 +5154,17 @@ Parser::comprehensionTail(ParseNode *kid
          */
         pn2 = BinaryNode::create(PNK_FOR, this);
         if (!pn2)
             return NULL;
 
         pn2->setOp(JSOP_ITER);
         pn2->pn_iflags = JSITER_ENUMERATE;
         if (tokenStream.matchToken(TOK_NAME)) {
-            if (tokenStream.currentToken().name() == context->runtime->atomState.eachAtom)
+            if (tokenStream.currentToken().name() == context->names().each)
                 pn2->pn_iflags |= JSITER_FOREACH;
             else
                 tokenStream.ungetToken();
         }
         MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
 
         GenexpGuard guard(this);
 
@@ -5387,18 +5385,17 @@ Parser::generatorExpr(ParseNode *kid)
         ParseNode *body = comprehensionTail(pn, outerpc->blockid(), true);
         if (!body)
             return NULL;
         JS_ASSERT(!genfn->pn_body);
         genfn->pn_body = body;
         genfn->pn_pos.begin = body->pn_pos.begin = kid->pn_pos.begin;
         genfn->pn_pos.end = body->pn_pos.end = tokenStream.currentToken().pos.end;
 
-        JSAtom *arguments = context->runtime->atomState.argumentsAtom;
-        if (AtomDefnPtr p = genpc.lexdeps->lookup(arguments)) {
+        if (AtomDefnPtr p = genpc.lexdeps->lookup(context->names().arguments)) {
             Definition *dn = p.value();
             ParseNode *errorNode = dn->dn_uses ? dn->dn_uses : body;
             reportError(errorNode, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
             return NULL;
         }
 
         if (!LeaveFunction(genfn, this))
             return NULL;
@@ -5690,33 +5687,33 @@ Parser::memberExpr(bool allowCallSyntax)
                 return NULL;
         } else if (allowCallSyntax && tt == TOK_LP) {
             nextMember = ListNode::create(PNK_CALL, this);
             if (!nextMember)
                 return NULL;
             nextMember->setOp(JSOP_CALL);
 
             if (lhs->isOp(JSOP_NAME)) {
-                if (lhs->pn_atom == context->runtime->atomState.evalAtom) {
+                if (lhs->pn_atom == context->names().eval) {
                     /* Select JSOP_EVAL and flag pc as heavyweight. */
                     nextMember->setOp(JSOP_EVAL);
                     pc->sc->setBindingsAccessedDynamically();
 
                     /*
                      * In non-strict mode code, direct calls to eval can add
                      * variables to the call object.
                      */
                     if (pc->sc->isFunction && pc->sc->strictModeState != StrictMode::STRICT)
                         pc->sc->asFunbox()->setHasExtensibleScope();
                 }
             } else if (lhs->isOp(JSOP_GETPROP)) {
                 /* Select JSOP_FUNAPPLY given foo.apply(...). */
-                if (lhs->pn_atom == context->runtime->atomState.applyAtom)
+                if (lhs->pn_atom == context->names().apply)
                     nextMember->setOp(JSOP_FUNAPPLY);
-                else if (lhs->pn_atom == context->runtime->atomState.callAtom)
+                else if (lhs->pn_atom == context->names().call)
                     nextMember->setOp(JSOP_FUNCALL);
             }
 
             nextMember->initList(lhs);
             nextMember->pn_pos.begin = lhs->pn_pos.begin;
 
             if (!argumentList(nextMember))
                 return NULL;
@@ -5825,17 +5822,17 @@ Parser::propertySelector()
     JS_ASSERT(allowsXML());
 
     ParseNode *selector;
     if (tokenStream.isCurrentTokenType(TOK_STAR)) {
         selector = NullaryNode::create(PNK_ANYNAME, this);
         if (!selector)
             return NULL;
         selector->setOp(JSOP_ANYNAME);
-        selector->pn_atom = context->runtime->atomState.starAtom;
+        selector->pn_atom = context->names().star;
     } else {
         JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME));
         selector = NullaryNode::create(PNK_NAME, this);
         if (!selector)
             return NULL;
         selector->setOp(JSOP_QNAMEPART);
         selector->setArity(PN_NAME);
         selector->pn_atom = tokenStream.currentToken().name();
@@ -5861,17 +5858,17 @@ Parser::qualifiedSuffix(ParseNode *pn)
         pn->setOp(JSOP_NAME);
 
     TokenKind tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
     if (tt == TOK_STAR || tt == TOK_NAME) {
         /* Inline and specialize propertySelector for JSOP_QNAMECONST. */
         pn2->setOp(JSOP_QNAMECONST);
         pn2->pn_pos.begin = pn->pn_pos.begin;
         pn2->pn_atom = (tt == TOK_STAR)
-                       ? context->runtime->atomState.starAtom
+                       ? context->names().star
                        : tokenStream.currentToken().name();
         pn2->pn_expr = pn;
         pn2->pn_cookie.makeFree();
         return pn2;
     }
 
     if (tt != TOK_LB) {
         reportError(NULL, JSMSG_SYNTAX_ERROR);
@@ -6460,17 +6457,17 @@ Parser::intrinsicName()
 {
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_MOD));
     if (tokenStream.getToken() != TOK_NAME) {
         reportError(NULL, JSMSG_SYNTAX_ERROR);
         return NULL;
     }
 
     PropertyName *name = tokenStream.currentToken().name();
-    if (!(name == context->runtime->atomState._CallFunctionAtom ||
+    if (!(name == context->names()._CallFunction ||
           context->global()->hasIntrinsicFunction(context, name)))
     {
         reportError(NULL, JSMSG_INTRINSIC_NOT_DEFINED, JS_EncodeString(context, name));
         return NULL;
     }
     ParseNode *node = NameNode::create(PNK_INTRINSICNAME, name, this, this->pc);
     if (!node)
         return NULL;
@@ -6715,19 +6712,19 @@ Parser::primaryExpr(TokenKind tt, bool a
                 pn3->pn_dval = tokenStream.currentToken().number();
                 atom = ToAtom(context, DoubleValue(pn3->pn_dval));
                 if (!atom)
                     return NULL;
                 break;
               case TOK_NAME:
                 {
                     atom = tokenStream.currentToken().name();
-                    if (atom == context->runtime->atomState.getAtom) {
+                    if (atom == context->names().get) {
                         op = JSOP_GETTER;
-                    } else if (atom == context->runtime->atomState.setAtom) {
+                    } else if (atom == context->names().set) {
                         op = JSOP_SETTER;
                     } else {
                         pn3 = NullaryNode::create(PNK_NAME, this);
                         if (!pn3)
                             return NULL;
                         pn3->pn_atom = atom;
                         break;
                     }
@@ -6816,17 +6813,17 @@ Parser::primaryExpr(TokenKind tt, bool a
                 if (foldConstants && !FoldConstants(context, pnval, this))
                     return NULL;
 
                 /*
                  * Treat initializers which mutate __proto__ as non-constant,
                  * so that we can later assume singleton objects delegate to
                  * the default Object.prototype.
                  */
-                if (!pnval->isConstant() || atom == context->runtime->atomState.protoAtom)
+                if (!pnval->isConstant() || atom == context->names().proto)
                     pn->pn_xflags |= PNX_NONCONST;
             }
 #if JS_HAS_DESTRUCTURING_SHORTHAND
             else if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
                 /*
                  * Support, e.g., |var {x, y} = o| as destructuring shorthand
                  * for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
                  */
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1036,17 +1036,17 @@ TokenStream::getXMLMarkup(TokenKind *ttp
             if (!tokenbuf.append(c))
                 goto error;
         }
         if (targetLength == 0)
             goto bad_xml_markup;
 
         JSAtom *data;
         if (contentIndex < 0) {
-            data = cx->runtime->atomState.emptyAtom;
+            data = cx->names().empty;
         } else {
             data = AtomizeChars(cx, tokenbuf.begin() + contentIndex,
                                 tokenbuf.length() - contentIndex);
             if (!data)
                 goto error;
         }
         tokenbuf.shrinkBy(tokenbuf.length() - targetLength);
         consumeKnownChar('>');
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -3163,17 +3163,17 @@ CodeGenerator::visitOutOfLineCacheGetPro
     // Define the input and output registers each opcode wants,
     // and which atom property it should get
     // Note: because all registers are saved, the output register should be
     //       a def register, else the result will be overriden by restoreLive(ins)
     PropertyName *name = NULL;
     switch (ins->op()) {
       case LInstruction::LOp_InstanceOfO:
       case LInstruction::LOp_InstanceOfV:
-        name = gen->compartment->rt->atomState.classPrototypeAtom;
+        name = gen->compartment->rt->atomState.classPrototype;
         objReg = ToRegister(ins->getTemp(1));
         output = TypedOrValueRegister(MIRType_Object, ToAnyRegister(ins->getDef(0)));
         break;
       case LInstruction::LOp_GetPropertyCacheT:
         name = ((LGetPropertyCacheT *) ins)->mir()->name();
         objReg = ToRegister(ins->getOperand(0));
         output = TypedOrValueRegister(mir->type(), ToAnyRegister(ins->getDef(0)));
         break;
@@ -3470,39 +3470,39 @@ CodeGenerator::visitTypeOfV(LTypeOfV *li
     // Jump to the OOL path if the value is an object. Objects are complicated
     // since they may have a typeof hook.
     masm.branchTestObject(Assembler::Equal, tag, ool->entry());
 
     Label done;
 
     Label notNumber;
     masm.branchTestNumber(Assembler::NotEqual, tag, &notNumber);
-    masm.movePtr(ImmGCPtr(rt->atomState.numberAtom), output);
+    masm.movePtr(ImmGCPtr(rt->atomState.number), output);
     masm.jump(&done);
     masm.bind(&notNumber);
 
     Label notUndefined;
     masm.branchTestUndefined(Assembler::NotEqual, tag, &notUndefined);
-    masm.movePtr(ImmGCPtr(rt->atomState.undefinedAtom), output);
+    masm.movePtr(ImmGCPtr(rt->atomState.undefined), output);
     masm.jump(&done);
     masm.bind(&notUndefined);
 
     Label notNull;
     masm.branchTestNull(Assembler::NotEqual, tag, &notNull);
-    masm.movePtr(ImmGCPtr(rt->atomState.objectAtom), output);
+    masm.movePtr(ImmGCPtr(rt->atomState.object), output);
     masm.jump(&done);
     masm.bind(&notNull);
 
     Label notBoolean;
     masm.branchTestBoolean(Assembler::NotEqual, tag, &notBoolean);
-    masm.movePtr(ImmGCPtr(rt->atomState.booleanAtom), output);
+    masm.movePtr(ImmGCPtr(rt->atomState.boolean), output);
     masm.jump(&done);
     masm.bind(&notBoolean);
 
-    masm.movePtr(ImmGCPtr(rt->atomState.stringAtom), output);
+    masm.movePtr(ImmGCPtr(rt->atomState.string), output);
 
     masm.bind(&done);
     masm.bind(ool->rejoin());
     return true;
 }
 
 bool
 CodeGenerator::visitOutOfLineTypeOfV(OutOfLineTypeOfV *ool)
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3460,18 +3460,17 @@ IonBuilder::createThisNative()
 
 MDefinition *
 IonBuilder::createThisScripted(MDefinition *callee)
 {
     // Get callee.prototype.
     // This instruction MUST be idempotent: since it does not correspond to an
     // explicit operation in the bytecode, we cannot use resumeAfter(). But
     // calling GetProperty can trigger a GC, and thus invalidation.
-    RootedPropertyName name(cx, cx->runtime->atomState.classPrototypeAtom);
-    MCallGetProperty *getProto = MCallGetProperty::New(callee, name);
+    MCallGetProperty *getProto = MCallGetProperty::New(callee, cx->names().classPrototype);
 
     // Getters may not override |prototype| fetching, so this is repeatable.
     getProto->markUneffectful();
     current->add(getProto);
 
     MCreateThis *createThis = MCreateThis::New(callee, getProto, NULL);
     current->add(createThis);
 
@@ -3481,17 +3480,17 @@ IonBuilder::createThisScripted(MDefiniti
 JSObject *
 IonBuilder::getSingletonPrototype(JSFunction *target)
 {
     if (!target->hasSingletonType())
         return NULL;
     if (target->getType(cx)->unknownProperties())
         return NULL;
 
-    jsid protoid = AtomToId(cx->runtime->atomState.classPrototypeAtom);
+    jsid protoid = NameToId(cx->names().classPrototype);
     types::HeapTypeSet *protoTypes = target->getType(cx)->getProperty(cx, protoid, false);
     if (!protoTypes)
         return NULL;
 
     return protoTypes->getSingleton(cx);
 }
 
 MDefinition *
@@ -3674,17 +3673,17 @@ GetBuiltinRegExpTest(JSContext *cx, JSSc
     RootedObject proto(cx, script->global().getOrCreateRegExpPrototype(cx));
     if (!proto)
         return false;
 
     // Get the |test| property. Note that we use lookupProperty, not getProperty,
     // to avoid calling a getter.
     RootedShape shape(cx);
     RootedObject holder(cx);
-    if (!JSObject::lookupProperty(cx, proto, cx->runtime->atomState.testAtom, &holder, &shape))
+    if (!JSObject::lookupProperty(cx, proto, cx->names().test, &holder, &shape))
         return false;
 
     if (proto != holder || !shape || !shape->hasDefaultGetter() || !shape->hasSlot())
         return true;
 
     // The RegExp.prototype.test property is writable, so we have to ensure
     // we got the builtin function.
     Value val = holder->getSlot(shape->slot());
@@ -4607,21 +4606,21 @@ IonBuilder::monitorResult(MInstruction *
     MInstruction *monitor = MMonitorTypes::New(ins, types);
     current->add(monitor);
 }
 
 bool
 IonBuilder::jsop_getgname(HandlePropertyName name)
 {
     // Optimize undefined, NaN, and Infinity.
-    if (name == cx->runtime->atomState.undefinedAtom)
+    if (name == cx->names().undefined)
         return pushConstant(UndefinedValue());
-    if (name == cx->runtime->atomState.NaNAtom)
+    if (name == cx->names().NaN)
         return pushConstant(cx->runtime->NaNValue);
-    if (name == cx->runtime->atomState.InfinityAtom)
+    if (name == cx->names().Infinity)
         return pushConstant(cx->runtime->positiveInfinityValue);
 
     RootedObject globalObj(cx, &script->global());
     JS_ASSERT(globalObj->isNative());
 
     RootedId id(cx, NameToId(name));
 
     // For the fastest path, the property must be found, and it must be found
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -126,17 +126,17 @@ DefVarOrConst(JSContext *cx, HandlePrope
 
 bool
 InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value)
 {
     // Copy the incoming value. This may be overwritten; the return value is discarded.
     RootedValue rval(cx, value);
     RootedId id(cx, NameToId(name));
 
-    if (name == cx->runtime->atomState.protoAtom)
+    if (name == cx->names().proto)
         return baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, false);
     return !!DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, 0);
 }
 
 template<bool Equal>
 bool
 LooselyEqual(JSContext *cx, HandleValue lhs, HandleValue rhs, JSBool *res)
 {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1800,17 +1800,17 @@ JS_InitStandardClasses(JSContext *cx, JS
 #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
 
 typedef struct JSStdName {
     JSClassInitializerOp init;
     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
     Class       *clasp;
 } JSStdName;
 
-static PropertyName *
+static Handle<PropertyName*>
 StdNameToPropertyName(JSContext *cx, JSStdName *stdn)
 {
     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.
@@ -1950,17 +1950,17 @@ JS_ResolveStandardClass(JSContext *cx, J
 
     rt = cx->runtime;
     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
         return true;
 
     idstr = JSID_TO_STRING(id);
 
     /* Check whether we're resolving 'undefined', and define it if so. */
-    atom = rt->atomState.undefinedAtom;
+    atom = rt->atomState.undefined;
     if (idstr == atom) {
         *resolved = true;
         RootedValue undefinedValue(cx, UndefinedValue());
         return JSObject::defineProperty(cx, obj, atom->asPropertyName(), undefinedValue,
                                         JS_PropertyStub, JS_StrictPropertyStub,
                                         JSPROP_PERMANENT | JSPROP_READONLY);
     }
 
@@ -2043,17 +2043,17 @@ JS_EnumerateStandardClasses(JSContext *c
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     /*
      * Check whether we need to bind 'undefined' and define it if so.
      * Since ES5 15.1.1.3 undefined can't be deleted.
      */
-    RootedPropertyName undefinedName(cx, cx->runtime->atomState.undefinedAtom);
+    HandlePropertyName undefinedName = cx->names().undefined;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!obj->nativeContains(cx, undefinedName) &&
         !JSObject::defineProperty(cx, obj, undefinedName, undefinedValue,
                                   JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY)) {
         return false;
     }
 
@@ -2152,22 +2152,22 @@ JS_EnumerateResolvedStandardClasses(JSCo
     } else {
         ida = NewIdArray(cx, 8);
         if (!ida)
             return NULL;
         i = 0;
     }
 
     /* Check whether 'undefined' has been resolved and enumerate it if so. */
-    Rooted<PropertyName*> name(cx, rt->atomState.undefinedAtom);
-    ida = EnumerateIfResolved(cx, obj, name, ida, &i, &found);
+    ida = EnumerateIfResolved(cx, obj, cx->names().undefined, ida, &i, &found);
     if (!ida)
         return NULL;
 
     /* Enumerate only classes that *have* been resolved. */
+    Rooted<PropertyName*> name(cx);
     for (j = 0; standard_class_atoms[j].init; j++) {
         name = OFFSET_TO_NAME(rt, standard_class_atoms[j].atomOffset);
         ida = EnumerateIfResolved(cx, obj, name, ida, &i, &found);
         if (!ida)
             return NULL;
 
         if (found) {
             init = standard_class_atoms[j].init;
@@ -3368,17 +3368,17 @@ JS_GetConstructor(JSContext *cx, JSObjec
     RootedValue cval(cx);
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto);
     {
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
-        if (!JSObject::getProperty(cx, proto, proto, cx->runtime->atomState.constructorAtom, &cval))
+        if (!JSObject::getProperty(cx, proto, proto, cx->names().constructor, &cval))
             return NULL;
     }
     if (!IsFunctionObject(cval)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
                              proto->getClass()->name);
         return NULL;
     }
     return &cval.toObject();
@@ -6387,18 +6387,18 @@ JS_Stringify(JSContext *cx, jsval *vp, J
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, replacer, space);
     StringBuffer sb(cx);
     if (!js_Stringify(cx, &value, replacer, space, sb))
         return false;
     *vp = value;
     if (sb.empty()) {
-        JSAtom *nullAtom = cx->runtime->atomState.nullAtom;
-        return callback(nullAtom->chars(), nullAtom->length(), data);
+        HandlePropertyName null = cx->names().null;
+        return callback(null->chars(), null->length(), data);
     }
     return callback(sb.begin(), sb.length(), data);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, jsval *vp)
 {
     AssertHeapIsIdle(cx);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -130,17 +130,17 @@ GetLengthProperty(JSContext *cx, HandleO
         ArgumentsObject &argsobj = obj->asArguments();
         if (!argsobj.hasOverriddenLength()) {
             *lengthp = argsobj.initialLength();
             return true;
         }
     }
 
     RootedValue value(cx);
-    if (!JSObject::getProperty(cx, obj, obj, cx->runtime->atomState.lengthAtom, &value))
+    if (!JSObject::getProperty(cx, obj, obj, cx->names().length, &value))
         return false;
 
     if (value.isInt32()) {
         *lengthp = uint32_t(value.toInt32()); /* uint32_t cast does ToUint32_t */
         return true;
     }
 
     return ToUint32(cx, value, (uint32_t *)lengthp);
@@ -486,17 +486,17 @@ SetOrDeleteArrayElement(JSContext *cx, H
 }
 
 JSBool
 js::SetLengthProperty(JSContext *cx, HandleObject obj, double length)
 {
     RootedValue v(cx, NumberValue(length));
 
     /* We don't support read-only array length yet. */
-    return JSObject::setProperty(cx, obj, obj, cx->runtime->atomState.lengthAtom, &v, false);
+    return JSObject::setProperty(cx, obj, obj, cx->names().length, &v, false);
 }
 
 /*
  * Since SpiderMonkey supports cross-class prototype-based delegation, we have
  * to be careful about the length getter and setter being called on an object
  * not of Array class. For the getter, we search obj's prototype chain for the
  * array that caused this getter to be invoked. In the setter case to overcome
  * the JSPROP_SHARED attribute, we must define a shadowing length property.
@@ -513,17 +513,17 @@ array_length_getter(JSContext *cx, Handl
     } while ((obj = obj->getProto()) != NULL);
     return JS_TRUE;
 }
 
 static JSBool
 array_length_setter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
 {
     if (!obj->isArray()) {
-        return JSObject::defineProperty(cx, obj, cx->runtime->atomState.lengthAtom, vp,
+        return JSObject::defineProperty(cx, obj, cx->names().length, vp,
                                         NULL, NULL, JSPROP_ENUMERATE);
     }
 
     uint32_t newlen;
     if (!ToUint32(cx, vp, &newlen))
         return false;
 
     double d;
@@ -618,17 +618,17 @@ IsDenseArrayIndex(JSObject *obj, uint32_
  * length property. For all else, we delegate to the prototype.
  */
 static inline bool
 IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t i;
-    return JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
+    return JSID_IS_ATOM(id, cx->names().length) ||
            (js_IdIsIndex(id, &i) && IsDenseArrayIndex(obj, i));
 }
 
 static JSBool
 array_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                     MutableHandleObject objp, MutableHandleShape propp)
 {
     if (!obj->isDenseArray())
@@ -689,29 +689,29 @@ array_lookupSpecial(JSContext *cx, Handl
 
 JSBool
 js_GetDenseArrayElementValue(JSContext *cx, HandleObject obj, jsid id, Value *vp)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t i;
     if (!js_IdIsIndex(id, &i)) {
-        JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
+        JS_ASSERT(JSID_IS_ATOM(id, cx->names().length));
         vp->setNumber(obj->getArrayLength());
         return JS_TRUE;
     }
     *vp = obj->getDenseArrayElement(i);
     return JS_TRUE;
 }
 
 static JSBool
 array_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
                   MutableHandleValue vp)
 {
-    if (name == cx->runtime->atomState.lengthAtom) {
+    if (name == cx->names().length) {
         vp.setNumber(obj->getArrayLength());
         return true;
     }
 
     if (!obj->isDenseArray()) {
         Rooted<jsid> id(cx, NameToId(name));
         return baseops::GetProperty(cx, obj, receiver, id, vp);
     }
@@ -803,17 +803,17 @@ slowarray_addProperty(JSContext *cx, Han
         obj->setArrayLength(cx, index + 1);
     return JS_TRUE;
 }
 
 static JSBool
 array_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                  MutableHandleValue vp, JSBool strict)
 {
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
+    if (JSID_IS_ATOM(id, cx->names().length))
         return array_length_setter(cx, obj, id, strict, vp);
 
     if (!obj->isDenseArray())
         return baseops::SetPropertyHelper(cx, obj, obj, id, 0, vp, strict);
 
     do {
         uint32_t i;
         if (!js_IdIsIndex(id, &i))
@@ -917,17 +917,17 @@ js_PrototypeHasIndexedProperties(JSConte
     }
     return JS_FALSE;
 }
 
 static JSBool
 array_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                     JSPropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
+    if (JSID_IS_ATOM(id, cx->names().length))
         return JS_TRUE;
 
     if (!obj->isDenseArray())
         return baseops::DefineGeneric(cx, obj, id, value, getter, setter, attrs);
 
     do {
         uint32_t i = 0;       // init to shut GCC up
         bool isIndex = js_IdIsIndex(id, &i);
@@ -1010,25 +1010,25 @@ array_defineSpecial(JSContext *cx, Handl
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return array_defineGeneric(cx, obj, id, value, getter, setter, attrs);
 }
 
 static JSBool
 array_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
-    *attrsp = JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)
+    *attrsp = JSID_IS_ATOM(id, cx->names().length)
         ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
 array_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
 {
-    *attrsp = (name == cx->runtime->atomState.lengthAtom)
+    *attrsp = (name == cx->names().length)
               ? JSPROP_PERMANENT
               : JSPROP_ENUMERATE;
     return true;
 }
 
 static JSBool
 array_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
 {
@@ -1073,17 +1073,17 @@ array_setSpecialAttributes(JSContext *cx
 
 static JSBool
 array_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                      MutableHandleValue rval, JSBool strict)
 {
     if (!obj->isDenseArray())
         return baseops::DeleteProperty(cx, obj, name, rval, strict);
 
-    if (name == cx->runtime->atomState.lengthAtom) {
+    if (name == cx->names().length) {
         rval.setBoolean(false);
         return true;
     }
 
     rval.setBoolean(true);
     return true;
 }
 
@@ -1236,17 +1236,17 @@ AddLengthProperty(JSContext *cx, HandleO
 {
     /*
      * Add the 'length' property for a newly created or converted slow array,
      * and update the elements to be an empty array owned by the object.
      * The shared emptyObjectElements singleton cannot be used for slow arrays,
      * as accesses to 'length' will use the elements header.
      */
 
-    RootedId lengthId(cx, NameToId(cx->runtime->atomState.lengthAtom));
+    RootedId lengthId(cx, NameToId(cx->names().length));
     JS_ASSERT(!obj->nativeLookup(cx, lengthId));
 
     if (!obj->allocateSlowArrayElements(cx))
         return false;
 
     return obj->addProperty(cx, lengthId, array_length_getter, array_length_setter,
                             SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0);
 }
@@ -1454,17 +1454,17 @@ array_join_sub(JSContext *cx, CallArgs &
     if (!obj)
         return false;
 
     AutoCycleDetector detector(cx, obj);
     if (!detector.init())
         return false;
 
     if (detector.foundCycle()) {
-        args.rval().setString(cx->runtime->atomState.emptyAtom);
+        args.rval().setString(cx->names().empty);
         return true;
     }
 
     // Steps 2 and 3
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
 
@@ -1535,17 +1535,17 @@ array_join_sub(JSContext *cx, CallArgs &
             if (!GetElement(cx, obj, index, &hole, &elt))
                 return false;
 
             if (!hole && !elt.isNullOrUndefined()) {
                 if (locale) {
                     JSObject *robj = ToObject(cx, elt);
                     if (!robj)
                         return false;
-                    RootedId id(cx, NameToId(cx->runtime->atomState.toLocaleStringAtom));
+                    RootedId id(cx, NameToId(cx->names().toLocaleString));
                     if (!robj->callMethod(cx, id, 0, NULL, &elt))
                         return false;
                 }
                 if (!ValueToStringBuffer(cx, elt, sb))
                     return false;
             }
 
             if (index + 1 != length) {
@@ -1571,17 +1571,17 @@ array_toString(JSContext *cx, unsigned a
     JS_CHECK_RECURSION(cx, return false);
 
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     RootedValue join(cx, args.calleev());
-    if (!JSObject::getProperty(cx, obj, obj, cx->runtime->atomState.joinAtom, &join))
+    if (!JSObject::getProperty(cx, obj, obj, cx->names().join, &join))
         return false;
 
     if (!js_IsCallable(join)) {
         JSString *str = obj_toStringHelper(cx, obj);
         if (!str)
             return false;
         args.rval().setString(str);
         return true;
@@ -3547,17 +3547,17 @@ js_InitArrayClass(JSContext *cx, JSObjec
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject arrayProto(cx, global->createBlankPrototype(cx, &SlowArrayClass));
     if (!arrayProto || !AddLengthProperty(cx, arrayProto))
         return NULL;
     arrayProto->setArrayLength(cx, 0);
 
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_Array, cx->runtime->atomState.ArrayAtom, 1);
+    ctor = global->createConstructor(cx, js_Array, cx->names().Array, 1);
     if (!ctor)
         return NULL;
 
     /*
      * The default 'new' type of Array.prototype is required by type inference
      * to have unknown properties, to simplify handling of e.g. heterogenous
      * arrays in JSON and script literals and allows setDenseArrayElement to
      * be used without updating the indexed type set for such default arrays.
--- a/js/src/jsatominlines.h
+++ b/js/src/jsatominlines.h
@@ -151,35 +151,35 @@ AtomHasher::match(const AtomStateEntry &
         return false;
     return PodEqual(key->chars(), lookup.chars, lookup.length);
 }
 
 inline Handle<PropertyName*>
 TypeName(JSType type, JSRuntime *rt)
 {
     JS_ASSERT(type < JSTYPE_LIMIT);
-    JS_STATIC_ASSERT(offsetof(JSAtomState, undefinedAtom) +
+    JS_STATIC_ASSERT(offsetof(JSAtomState, undefined) +
                      JSTYPE_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <=
                      sizeof(JSAtomState));
     JS_STATIC_ASSERT(JSTYPE_VOID == 0);
-    return (&rt->atomState.undefinedAtom)[type];
+    return (&rt->atomState.undefined)[type];
 }
 
 inline Handle<PropertyName*>
 TypeName(JSType type, JSContext *cx)
 {
     return TypeName(type, cx->runtime);
 }
 
 inline Handle<PropertyName*>
 ClassName(JSProtoKey key, JSContext *cx)
 {
     JS_ASSERT(key < JSProto_LIMIT);
-    JS_STATIC_ASSERT(offsetof(JSAtomState, NullAtom) +
+    JS_STATIC_ASSERT(offsetof(JSAtomState, Null) +
                      JSProto_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <=
                      sizeof(JSAtomState));
     JS_STATIC_ASSERT(JSProto_Null == 0);
-    return (&cx->runtime->atomState.NullAtom)[key];
+    return (&cx->runtime->atomState.Null)[key];
 }
 
 } // namespace js
 
 #endif /* jsatominlines_h___ */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -149,28 +149,27 @@ js_InitBooleanClass(JSContext *cx, JSObj
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanClass));
     if (!booleanProto)
         return NULL;
     booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
 
-    RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Boolean, cx->runtime->atomState.BooleanAtom, 1);
+    RootedFunction ctor(cx, global->createConstructor(cx, Boolean, cx->names().Boolean, 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, booleanProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods))
         return NULL;
 
-    Rooted<PropertyName*> valueOfName(cx, cx->runtime->atomState.valueOfAtom);
+    Handle<PropertyName*> valueOfName = cx->names().valueOf;
     Rooted<JSFunction*> valueOf(cx,
                                 js_NewFunction(cx, NULL, bool_valueOf, 0, 0, global, valueOfName));
     if (!valueOf)
         return NULL;
     RootedValue value(cx, ObjectValue(*valueOf));
     if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
                                   JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -377,35 +377,25 @@ class FreeOp : public JSFreeOp {
 
 namespace JS {
 struct RuntimeSizes;
 }
 
 /* Various built-in or commonly-used names pinned on first context. */
 struct JSAtomState
 {
-#define PROPERTYNAME_FIELD(idpart, id, text) \
-    union { \
-        js::FixedHeapPtr<js::PropertyName> idpart##Atom; \
-        js::FixedHeapPtr<js::PropertyName> id; \
-    };
+#define PROPERTYNAME_FIELD(idpart, id, text) js::FixedHeapPtr<js::PropertyName> id;
     FOR_EACH_COMMON_PROPERTYNAME(PROPERTYNAME_FIELD)
 #undef PROPERTYNAME_FIELD
-#define PROPERTYNAME_FIELD(name, code, init) \
-    union { \
-        js::FixedHeapPtr<js::PropertyName> name##Atom; \
-        js::FixedHeapPtr<js::PropertyName> name; \
-    };
+#define PROPERTYNAME_FIELD(name, code, init) js::FixedHeapPtr<js::PropertyName> name;
     JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD)
 #undef PROPERTYNAME_FIELD
 };
 
-#define ATOM(name) (cx->names().name)
-
-#define NAME_OFFSET(name)       offsetof(JSAtomState, name##Atom)
+#define NAME_OFFSET(name)       offsetof(JSAtomState, name)
 #define OFFSET_TO_NAME(rt,off)  (*(js::FixedHeapPtr<js::PropertyName>*)((char*)&(rt)->atomState + (off)))
 
 struct JSRuntime : js::RuntimeFriendFields
 {
     /* Default compartment. */
     JSCompartment       *atomsCompartment;
 
     /* List of compartments (protected by the GC lock). */
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -2604,17 +2604,17 @@ date_toJSON(JSContext *cx, unsigned argc
     /* Step 3. */
     if (tv.isDouble() && !MOZ_DOUBLE_IS_FINITE(tv.toDouble())) {
         args.rval().setNull();
         return true;
     }
 
     /* Step 4. */
     RootedValue toISO(cx);
-    if (!JSObject::getProperty(cx, obj, obj, cx->runtime->atomState.toISOStringAtom, &toISO))
+    if (!JSObject::getProperty(cx, obj, obj, cx->names().toISOString, &toISO))
         return false;
 
     /* Step 5. */
     if (!js_IsCallable(toISO)) {
         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                      JSMSG_BAD_TOISOSTRING_PROP);
         return false;
     }
@@ -3156,17 +3156,17 @@ js_InitDateClass(JSContext *cx, JSObject
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject dateProto(cx, global->createBlankPrototype(cx, &DateClass));
     if (!dateProto)
         return NULL;
     SetDateToNaN(cx, dateProto);
 
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_Date, cx->runtime->atomState.DateAtom, MAXARGS);
+    ctor = global->createConstructor(cx, js_Date, cx->names().Date, MAXARGS);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, dateProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, ctor, NULL, date_static_methods))
         return NULL;
@@ -3174,18 +3174,18 @@ js_InitDateClass(JSContext *cx, JSObject
     /*
      * Define all Date.prototype.* functions, then brand for trace-jitted code.
      * Date.prototype.toGMTString has the same initial value as
      * Date.prototype.toUTCString.
      */
     if (!JS_DefineFunctions(cx, dateProto, date_methods))
         return NULL;
     RootedValue toUTCStringFun(cx);
-    RootedId toUTCStringId(cx, NameToId(cx->runtime->atomState.toUTCStringAtom));
-    RootedId toGMTStringId(cx, NameToId(cx->runtime->atomState.toGMTStringAtom));
+    RootedId toUTCStringId(cx, NameToId(cx->names().toUTCString));
+    RootedId toGMTStringId(cx, NameToId(cx->names().toGMTString));
     if (!baseops::GetProperty(cx, dateProto, toUTCStringId, &toUTCStringFun) ||
         !baseops::DefineGeneric(cx, dateProto, toGMTStringId, toUTCStringFun,
                                 JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Date, ctor, dateProto))
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -34,17 +34,17 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, J
     rt->gcGrayRootsTraceOp = traceOp;
     rt->gcGrayRootsData = data;
 }
 
 JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
-    return rt->atomState.anonymousAtom;
+    return rt->atomState.anonymous;
 }
 
 JS_FRIEND_API(JSObject *)
 JS_FindCompilationScope(JSContext *cx, RawObject objArg)
 {
     RootedObject obj(cx, objArg);
 
     /*
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -103,17 +103,17 @@ fun_getProperty(JSContext *cx, HandleObj
         if (iter.callee() == fun)
             break;
     }
     if (iter.done())
         return true;
 
     StackFrame *fp = iter.fp();
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.argumentsAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().arguments)) {
         if (fun->hasRest()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_FUNCTION_ARGUMENTS_AND_REST);
             return false;
         }
         /* Warn if strict about f.arguments or equivalent unqualified uses. */
         if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage,
                                           NULL, JSMSG_DEPRECATED_USAGE, js_arguments_str)) {
             return false;
@@ -136,34 +136,34 @@ fun_getProperty(JSContext *cx, HandleObj
         vp.setObject(*argsobj);
         return true;
     }
 
 #ifdef JS_METHODJIT
     if (iter.isScript() && iter.isIon())
         fp = NULL;
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
+    if (JSID_IS_ATOM(id, cx->names().caller) && fp && fp->prev()) {
         /*
          * If the frame was called from within an inlined frame, mark the
          * innermost function as uninlineable to expand its frame and allow us
          * to recover its callee object.
          */
         InlinedSite *inlined;
         jsbytecode *prevpc = fp->prevpc(&inlined);
         if (inlined) {
             mjit::JITChunk *chunk = fp->prev()->jit()->chunk(prevpc);
             JSFunction *fun = chunk->inlineFrames()[inlined->inlineIndex].fun;
             fun->script()->uninlineable = true;
             MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
         }
     }
 #endif
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().caller)) {
         ++iter;
         if (iter.done() || !iter.isFunctionFrame()) {
             JS_ASSERT(vp.isNull());
             return true;
         }
 
         vp.set(iter.calleev());
 
@@ -200,26 +200,26 @@ static JSBool
 fun_enumerate(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isFunction());
 
     RootedId id(cx);
     bool found;
 
     if (!obj->isBoundFunction()) {
-        id = NameToId(cx->runtime->atomState.classPrototypeAtom);
+        id = NameToId(cx->names().classPrototype);
         if (!JSObject::hasProperty(cx, obj, id, &found, JSRESOLVE_QUALIFIED))
             return false;
     }
 
-    id = NameToId(cx->runtime->atomState.lengthAtom);
+    id = NameToId(cx->names().length);
     if (!JSObject::hasProperty(cx, obj, id, &found, JSRESOLVE_QUALIFIED))
         return false;
 
-    id = NameToId(cx->runtime->atomState.nameAtom);
+    id = NameToId(cx->names().name);
     if (!JSObject::hasProperty(cx, obj, id, &found, JSRESOLVE_QUALIFIED))
         return false;
 
     for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
         const uint16_t offset = poisonPillProps[i];
         id = NameToId(OFFSET_TO_NAME(cx->runtime, offset));
         if (!JSObject::hasProperty(cx, obj, id, &found, JSRESOLVE_QUALIFIED))
             return false;
@@ -259,20 +259,20 @@ ResolveInterpretedFunctionPrototype(JSCo
     /*
      * Per ES5 15.3.5.2 a user-defined function's .prototype property is
      * initially non-configurable, non-enumerable, and writable.  Per ES5 13.2
      * the prototype's .constructor property is configurable, non-enumerable,
      * and writable.
      */
     RootedValue protoVal(cx, ObjectValue(*proto));
     RootedValue objVal(cx, ObjectValue(*obj));
-    if (!JSObject::defineProperty(cx, obj, cx->runtime->atomState.classPrototypeAtom,
+    if (!JSObject::defineProperty(cx, obj, cx->names().classPrototype,
                                   protoVal, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT) ||
-        !JSObject::defineProperty(cx, proto, cx->runtime->atomState.constructorAtom,
+        !JSObject::defineProperty(cx, proto, cx->names().constructor,
                                   objVal, JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
        return NULL;
     }
 
     return proto;
 }
 
@@ -280,17 +280,17 @@ static JSBool
 fun_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             MutableHandleObject objp)
 {
     if (!JSID_IS_ATOM(id))
         return true;
 
     RootedFunction fun(cx, obj->toFunction());
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.classPrototypeAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().classPrototype)) {
         /*
          * Built-in functions do not have a .prototype property per ECMA-262,
          * or (Object.prototype, Function.prototype, etc.) have that property
          * created eagerly.
          *
          * ES5 15.3.4: the non-native function object named Function.prototype
          * does not have a .prototype property.
          *
@@ -302,22 +302,21 @@ fun_resolve(JSContext *cx, HandleObject 
             return true;
 
         if (!ResolveInterpretedFunctionPrototype(cx, fun))
             return false;
         objp.set(fun);
         return true;
     }
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
-        JSID_IS_ATOM(id, cx->runtime->atomState.nameAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().name)) {
         JS_ASSERT(!IsInternalFunctionObject(obj));
 
         RootedValue v(cx);
-        if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
+        if (JSID_IS_ATOM(id, cx->names().length))
             v.setInt32(fun->nargs - fun->hasRest());
         else
             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;
         }
@@ -475,17 +474,17 @@ fun_hasInstance(JSContext *cx, HandleObj
 
     while (obj->isFunction()) {
         if (!obj->isBoundFunction())
             break;
         obj = obj->toFunction()->getBoundFunctionTarget();
     }
 
     RootedValue pval(cx);
-    if (!JSObject::getProperty(cx, obj, obj, cx->runtime->atomState.classPrototypeAtom, &pval))
+    if (!JSObject::getProperty(cx, obj, obj, cx->names().classPrototype, &pval))
         return JS_FALSE;
 
     if (pval.isPrimitive()) {
         /*
          * Throw a runtime error if instanceof is called on a function that
          * has a non-object as its .prototype value.
          */
         RootedValue val(cx, ObjectValue(*obj));
@@ -1381,17 +1380,17 @@ Function(JSContext *cx, unsigned argc, V
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      */
     RootedFunction fun(cx, js_NewFunction(cx, NULL, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
-                                          global, cx->runtime->atomState.anonymousAtom));
+                                          global, cx->names().anonymous));
     if (!fun)
         return false;
 
     if (hasRest)
         fun->setHasRest();
 
     bool ok = frontend::CompileFunctionBody(cx, fun, options, formals, chars, length);
     args.rval().setObject(*fun);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -49,54 +49,54 @@
 #endif
 
 using namespace js;
 using namespace js::types;
 using namespace js::analyze;
 
 static inline jsid
 id_prototype(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.classPrototypeAtom);
+    return NameToId(cx->names().classPrototype);
 }
 
 static inline jsid
 id_arguments(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.argumentsAtom);
+    return NameToId(cx->names().arguments);
 }
 
 static inline jsid
 id_length(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.lengthAtom);
+    return NameToId(cx->names().length);
 }
 
 static inline jsid
 id___proto__(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.protoAtom);
+    return NameToId(cx->names().proto);
 }
 
 static inline jsid
 id_constructor(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.constructorAtom);
+    return NameToId(cx->names().constructor);
 }
 
 static inline jsid
 id_caller(JSContext *cx) {
-    return NameToId(cx->runtime->atomState.callerAtom);
+    return NameToId(cx->names().caller);
 }
 
 static inline jsid
 id_toString(JSContext *cx)
 {
-    return NameToId(cx->runtime->atomState.toStringAtom);
+    return NameToId(cx->names().toString);
 }
 
 static inline jsid
 id_toSource(JSContext *cx)
 {
-    return NameToId(cx->runtime->atomState.toSourceAtom);
+    return NameToId(cx->names().toSource);
 }
 
 #ifdef DEBUG
 const char *
 types::TypeIdStringImpl(jsid id)
 {
     if (JSID_IS_VOID(id))
         return "(index)";
@@ -3733,21 +3733,21 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         seen->addSubset(cx, &pushed[0]);
 
         /*
          * Normally we rely on lazy standard class initialization to fill in
          * the types of global properties the script can access. In a few cases
          * the method JIT will bypass this, and we need to add the types
          * directly.
          */
-        if (id == NameToId(cx->runtime->atomState.undefinedAtom))
+        if (id == NameToId(cx->names().undefined))
             seen->addType(cx, Type::UndefinedType());
-        if (id == NameToId(cx->runtime->atomState.NaNAtom))
+        if (id == NameToId(cx->names().NaN))
             seen->addType(cx, Type::DoubleType());
-        if (id == NameToId(cx->runtime->atomState.InfinityAtom))
+        if (id == NameToId(cx->names().Infinity))
             seen->addType(cx, Type::DoubleType());
 
         TypeObject *global = script->global().getType(cx);
 
         /* Handle as a property access. */
         if (state.hasPropertyReadTypes)
             PropertyAccess<PROPERTY_READ_EXISTING>(cx, script, pc, global, seen, id);
         else
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -167,17 +167,17 @@ Class js_NoSuchMethodClass = {
  * call by name, and args is an Array containing this invocation's actual
  * parameters.
  */
 bool
 js::OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval_, MutableHandleValue vp)
 {
     RootedValue idval(cx, idval_);
 
-    RootedId id(cx, NameToId(cx->runtime->atomState.noSuchMethodAtom));
+    RootedId id(cx, NameToId(cx->names().noSuchMethod));
     RootedValue value(cx);
     if (!GetMethod(cx, obj, id, 0, &value))
         return false;
     TypeScript::MonitorUnknown(cx);
 
     if (value.get().isPrimitive()) {
         vp.set(value);
     } else {
@@ -3158,17 +3158,17 @@ BEGIN_CASE(JSOP_INITPROP)
     obj = &regs.sp[-2].toObject();
     JS_ASSERT(obj->isObject());
 
     PropertyName *name = script->getName(regs.pc);
 
     RootedId &id = rootId0;
     id = NameToId(name);
 
-    if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
+    if (JS_UNLIKELY(name == cx->names().proto)
         ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, script->strictModeCode)
         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
                                 JSPROP_ENUMERATE, 0, 0, 0)) {
         goto error;
     }
 
     regs.sp--;
 }
@@ -3976,17 +3976,17 @@ js::Throw(JSContext *cx, HandleValue v)
     JS_ASSERT(!cx->isExceptionPending());
     cx->setPendingException(v);
     return false;
 }
 
 bool
 js::GetProperty(JSContext *cx, HandleValue v, PropertyName *name, MutableHandleValue vp)
 {
-    if (name == cx->runtime->atomState.lengthAtom) {
+    if (name == cx->names().length) {
         // Fast path for strings, arrays and arguments.
         if (GetLengthProperty(v, vp))
             return true;
     }
 
     RootedObject obj(cx, ToObjectFromStack(cx, v));
     if (!obj)
         return false;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -99,17 +99,17 @@ Enumerate(JSContext *cx, JSObject *obj, 
     /*
      * We implement __proto__ using a property on |Object.prototype|, but
      * because __proto__ is highly deserving of removal, we don't want it to
      * show up in property enumeration, even if only for |Object.prototype|
      * (think introspection by Prototype-like frameworks that add methods to
      * the built-in prototypes).  So exclude __proto__ if the object where the
      * property was found has no [[Prototype]] and might be |Object.prototype|.
      */
-    if (JS_UNLIKELY(!pobj->getProto() && JSID_IS_ATOM(id, cx->runtime->atomState.protoAtom)))
+    if (JS_UNLIKELY(!pobj->getProto() && JSID_IS_ATOM(id, cx->names().proto)))
         return true;
 
     if (!(flags & JSITER_OWNONLY) || pobj->isProxy() || pobj->getOps()->enumerate) {
         /* If we've already seen this, we definitely won't add it. */
         IdSet::AddPtr p = ht.lookupForAdd(id);
         if (JS_UNLIKELY(!!p))
             return true;
 
@@ -152,20 +152,18 @@ EnumerateNativeProperties(JSContext *cx,
     ::Reverse(props->begin() + initialLength, props->end());
     return true;
 }
 
 static bool
 EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, unsigned flags,
                               IdSet &ht, AutoIdVector *props)
 {
-    if (!Enumerate(cx, obj, pobj, NameToId(cx->runtime->atomState.lengthAtom), false,
-                   flags, ht, props)) {
+    if (!Enumerate(cx, obj, pobj, NameToId(cx->names().length), false, flags, ht, props))
         return false;
-    }
 
     if (pobj->getArrayLength() > 0) {
         size_t initlen = pobj->getDenseArrayInitializedLength();
         const Value *vp = pobj->getDenseArrayElements();
         for (size_t i = 0; i < initlen; ++i, ++vp) {
             if (!vp->isMagic(JS_ARRAY_HOLE)) {
                 /* Dense arrays never get so large that i would not fit into an integer id. */
                 if (!Enumerate(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, props))
@@ -350,17 +348,17 @@ js::GetPropertyNames(JSContext *cx, JSOb
 size_t sCustomIteratorCount = 0;
 
 static inline bool
 GetCustomIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     /* Check whether we have a valid __iterator__ method. */
-    RootedPropertyName name(cx, cx->runtime->atomState.iteratorIntrinsicAtom);
+    HandlePropertyName name = cx->names().iteratorIntrinsic;
     if (!GetMethod(cx, obj, name, 0, vp))
         return false;
 
     /* If there is no custom __iterator__ method, we are done here. */
     if (!vp.isObject()) {
         vp.setUndefined();
         return true;
     }
@@ -579,17 +577,17 @@ UpdateNativeIterator(NativeIterator *ni,
 }
 
 bool
 GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
 {
     if (flags == JSITER_FOR_OF) {
         // for-of loop. The iterator is simply |obj.iterator()|.
         RootedValue method(cx);
-        if (!JSObject::getProperty(cx, obj, obj, cx->runtime->atomState.iteratorAtom, &method))
+        if (!JSObject::getProperty(cx, obj, obj, cx->names().iterator, &method))
             return false;
 
         // Throw if obj.iterator isn't callable. js::Invoke is about to check
         // for this kind of error anyway, but it would throw an inscrutable
         // error message about |method| rather than this nice one about |obj|.
         if (!method.isObject() || !method.toObject().isCallable()) {
             RootedValue val(cx, ObjectOrNullValue(obj));
             char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, NullPtr());
@@ -1238,17 +1236,17 @@ js_IteratorMore(JSContext *cx, HandleObj
         ni->incCursor();
         RootedObject obj(cx, ni->obj);
         if (!JSObject::getGeneric(cx, obj, obj, id, rval))
             return false;
         if ((ni->flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, rval, rval))
             return false;
     } else {
         /* Call the iterator object's .next method. */
-        if (!GetMethod(cx, iterobj, cx->runtime->atomState.nextAtom, 0, rval))
+        if (!GetMethod(cx, iterobj, cx->names().next, 0, rval))
             return false;
         if (!Invoke(cx, ObjectValue(*iterobj), rval, 0, NULL, rval.address())) {
             /* Check for StopIteration. */
             if (!cx->isExceptionPending() || !IsStopIteration(cx->getPendingException()))
                 return false;
 
             cx->clearPendingException();
             cx->iterValue.setMagic(JS_NO_ITER_VALUE);
@@ -1773,17 +1771,17 @@ GlobalObject::initIteratorClasses(JSCont
         NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, blank);
         if (!ni)
             return false;
         ni->init(NULL, 0 /* flags */, 0, 0);
 
         iteratorProto->asPropertyIterator().setNativeIterator(ni);
 
         Rooted<JSFunction*> ctor(cx);
-        ctor = global->createConstructor(cx, IteratorConstructor, cx->runtime->atomState.IteratorAtom, 2);
+        ctor = global->createConstructor(cx, IteratorConstructor, cx->names().Iterator, 2);
         if (!ctor)
             return false;
         if (!LinkConstructorAndPrototype(cx, ctor, iteratorProto))
             return false;
         if (!DefinePropertiesAndBrand(cx, iteratorProto, NULL, iterator_methods))
             return false;
         if (!DefineConstructorAndPrototype(cx, global, JSProto_Iterator, ctor, iteratorProto))
             return false;
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -651,17 +651,17 @@ js::math_tan(JSContext *cx, unsigned arg
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 #if JS_HAS_TOSOURCE
 static JSBool
 math_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
-    vp->setString(cx->runtime->atomState.MathAtom);
+    vp->setString(cx->names().Math);
     return JS_TRUE;
 }
 #endif
 
 static JSFunctionSpec math_static_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,  math_toSource,        0, 0),
 #endif
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1132,17 +1132,17 @@ js_InitNumberClass(JSContext *cx, JSObje
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject numberProto(cx, global->createBlankPrototype(cx, &NumberClass));
     if (!numberProto)
         return NULL;
     numberProto->asNumber().setPrimitiveValue(0);
 
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Number, cx->runtime->atomState.NumberAtom, 1);
+    ctor = global->createConstructor(cx, Number, cx->names().Number, 1);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, numberProto))
         return NULL;
 
     /* Add numeric constants (MAX_VALUE, NaN, &c.) to the Number constructor. */
     if (!JS_DefineConstDoubles(cx, ctor, number_constants))
@@ -1156,20 +1156,20 @@ js_InitNumberClass(JSContext *cx, JSObje
 
     if (!JS_DefineFunctions(cx, global, number_functions))
         return NULL;
 
     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->runtime->atomState.NaNAtom, valueNaN,
+    if (!DefineNativeProperty(cx, global, cx->names().NaN, valueNaN,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0) ||
-        !DefineNativeProperty(cx, global, cx->runtime->atomState.InfinityAtom, valueInfinity,
+        !DefineNativeProperty(cx, global, cx->names().Infinity, valueInfinity,
                               JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Number, ctor, numberProto))
         return NULL;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -157,23 +157,23 @@ obj_toSource(JSContext *cx, unsigned arg
         int valcnt = 0;
         if (shape) {
             bool doGet = true;
             if (obj2->isNative()) {
                 unsigned attrs = shape->attributes();
                 if (attrs & JSPROP_GETTER) {
                     doGet = false;
                     val[valcnt] = shape->getterValue();
-                    gsop[valcnt] = cx->runtime->atomState.getAtom;
+                    gsop[valcnt] = cx->names().get;
                     valcnt++;
                 }
                 if (attrs & JSPROP_SETTER) {
                     doGet = false;
                     val[valcnt] = shape->setterValue();
-                    gsop[valcnt] = cx->runtime->atomState.setAtom;
+                    gsop[valcnt] = cx->names().set;
                     valcnt++;
                 }
             }
             if (doGet) {
                 valcnt = 1;
                 gsop[0] = NULL;
                 MutableHandleValue vp = MutableHandleValue::fromMarkedLocation(&val[0]);
                 if (!JSObject::getGeneric(cx, obj, obj, id, vp))
@@ -336,23 +336,23 @@ InformalValueTypeName(const Value &v)
 /* ES5 15.2.4.2.  Note steps 1 and 2 are errata. */
 static JSBool
 obj_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     if (args.thisv().isUndefined()) {
-        args.rval().setString(cx->runtime->atomState.objectUndefinedAtom);
+        args.rval().setString(cx->names().objectUndefined);
         return true;
     }
 
     /* Step 2. */
     if (args.thisv().isNull()) {
-        args.rval().setString(cx->runtime->atomState.objectNullAtom);
+        args.rval().setString(cx->names().objectNull);
         return true;
     }
 
     /* Step 3. */
     JSObject *obj = ToObject(cx, args.thisv());
     if (!obj)
         return false;
 
@@ -373,17 +373,17 @@ obj_toLocaleString(JSContext *cx, unsign
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     JSObject *obj = ToObject(cx, args.thisv());
     if (!obj)
         return false;
 
     /* Steps 2-4. */
-    RootedId id(cx, NameToId(cx->runtime->atomState.toStringAtom));
+    RootedId id(cx, NameToId(cx->names().toString));
     return obj->callMethod(cx, id, 0, NULL, args.rval());
 }
 
 static JSBool
 obj_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JSObject *obj = ToObject(cx, args.thisv());
@@ -638,29 +638,29 @@ DefineAccessor(JSContext *cx, unsigned a
     RootedId id(cx);
     if (!ValueToId(cx, args[0], id.address()))
         return false;
 
     RootedObject descObj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!descObj)
         return false;
 
-    JSAtomState &state = cx->runtime->atomState;
+    JSAtomState &names = cx->names();
     RootedValue trueVal(cx, BooleanValue(true));
 
     /* enumerable: true */
-    if (!JSObject::defineProperty(cx, descObj, state.enumerableAtom, trueVal))
+    if (!JSObject::defineProperty(cx, descObj, names.enumerable, trueVal))
         return false;
 
     /* configurable: true */
-    if (!JSObject::defineProperty(cx, descObj, state.configurableAtom, trueVal))
+    if (!JSObject::defineProperty(cx, descObj, names.configurable, trueVal))
         return false;
 
     /* enumerable: true */
-    PropertyName *acc = (Type == Getter) ? state.getAtom : state.setAtom;
+    PropertyName *acc = (Type == Getter) ? names.get : names.set;
     RootedValue accessorVal(cx, args[1]);
     if (!JSObject::defineProperty(cx, descObj, acc, accessorVal))
         return false;
 
     RootedObject thisObj(cx, &args.thisv().toObject());
 
     JSBool dummy;
     if (!js_DefineOwnProperty(cx, thisObj, id, ObjectValue(*descObj), &dummy)) {
@@ -852,32 +852,32 @@ bool
 PropDesc::makeObject(JSContext *cx)
 {
     MOZ_ASSERT(!isUndefined());
 
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!obj)
         return false;
 
-    const JSAtomState &atomState = cx->runtime->atomState;
+    const JSAtomState &names = cx->names();
     RootedValue configurableVal(cx, BooleanValue((attrs & JSPROP_PERMANENT) == 0));
     RootedValue enumerableVal(cx, BooleanValue((attrs & JSPROP_ENUMERATE) != 0));
     RootedValue writableVal(cx, BooleanValue((attrs & JSPROP_READONLY) == 0));
     if ((hasConfigurable() &&
-         !JSObject::defineProperty(cx, obj, atomState.configurableAtom, configurableVal)) ||
+         !JSObject::defineProperty(cx, obj, names.configurable, configurableVal)) ||
         (hasEnumerable() &&
-         !JSObject::defineProperty(cx, obj, atomState.enumerableAtom, enumerableVal)) ||
+         !JSObject::defineProperty(cx, obj, names.enumerable, enumerableVal)) ||
         (hasGet() &&
-         !JSObject::defineProperty(cx, obj, atomState.getAtom, getterValue())) ||
+         !JSObject::defineProperty(cx, obj, names.get, getterValue())) ||
         (hasSet() &&
-         !JSObject::defineProperty(cx, obj, atomState.setAtom, setterValue())) ||
+         !JSObject::defineProperty(cx, obj, names.set, setterValue())) ||
         (hasValue() &&
-         !JSObject::defineProperty(cx, obj, atomState.valueAtom, value())) ||
+         !JSObject::defineProperty(cx, obj, names.value, value())) ||
         (hasWritable() &&
-         !JSObject::defineProperty(cx, obj, atomState.writableAtom, writableVal)))
+         !JSObject::defineProperty(cx, obj, names.writable, writableVal)))
     {
         return false;
     }
 
     pd_.setObject(*obj);
     return true;
 }
 
@@ -1046,69 +1046,69 @@ PropDesc::initialize(JSContext *cx, cons
      * rid of PropDesc::attributes()
      */
     attrs = JSPROP_PERMANENT | JSPROP_READONLY;
 
     bool found = false;
     RootedId id(cx);
 
     /* 8.10.5 step 3 */
-    id = NameToId(cx->runtime->atomState.enumerableAtom);
+    id = NameToId(cx->names().enumerable);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasEnumerable_ = true;
         if (ToBoolean(v))
             attrs |= JSPROP_ENUMERATE;
     }
 
     /* 8.10.5 step 4 */
-    id = NameToId(cx->runtime->atomState.configurableAtom);
+    id = NameToId(cx->names().configurable);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasConfigurable_ = true;
         if (ToBoolean(v))
             attrs &= ~JSPROP_PERMANENT;
     }
 
     /* 8.10.5 step 5 */
-    id = NameToId(cx->runtime->atomState.valueAtom);
+    id = NameToId(cx->names().value);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasValue_ = true;
         value_ = v;
     }
 
     /* 8.10.6 step 6 */
-    id = NameToId(cx->runtime->atomState.writableAtom);
+    id = NameToId(cx->names().writable);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasWritable_ = true;
         if (ToBoolean(v))
             attrs &= ~JSPROP_READONLY;
     }
 
     /* 8.10.7 step 7 */
-    id = NameToId(cx->runtime->atomState.getAtom);
+    id = NameToId(cx->names().get);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasGet_ = true;
         get_ = v;
         attrs |= JSPROP_GETTER | JSPROP_SHARED;
         attrs &= ~JSPROP_READONLY;
         if (checkAccessors && !checkGetter(cx))
             return false;
     }
 
     /* 8.10.7 step 8 */
-    id = NameToId(cx->runtime->atomState.setAtom);
+    id = NameToId(cx->names().set);
     if (!HasProperty(cx, desc, id, &v, &found))
         return false;
     if (found) {
         hasSet_ = true;
         set_ = v;
         attrs |= JSPROP_SETTER | JSPROP_SHARED;
         attrs &= ~JSPROP_READONLY;
         if (checkAccessors && !checkSetter(cx))
@@ -1560,17 +1560,17 @@ DefinePropertyOnArray(JSContext *cx, Han
      * attributes).  Such definitions are probably unlikely, so we don't bother
      * for now.
      */
     if (obj->isDenseArray() && !JSObject::makeDenseArraySlow(cx, obj))
         return JS_FALSE;
 
     uint32_t oldLen = obj->getArrayLength();
 
-    if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    if (JSID_IS_ATOM(id, cx->names().length)) {
         /*
          * Our optimization of storage of the length property of arrays makes
          * it very difficult to properly implement defining the property.  For
          * now simply throw an exception (NB: not merely Reject) on any attempt
          * to define the "length" property, rather than attempting to implement
          * some difficult-for-authors-to-grasp subset of that functionality.
          */
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_DEFINE_ARRAY_LENGTH);
@@ -2308,17 +2308,17 @@ js::NewReshapedObject(JSContext *cx, Han
 
     return res;
 }
 
 JSObject*
 js_CreateThis(JSContext *cx, Class *newclasp, HandleObject callee)
 {
     RootedValue protov(cx);
-    if (!JSObject::getProperty(cx, callee, callee, cx->runtime->atomState.classPrototypeAtom, &protov))
+    if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
         return NULL;
 
     JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : NULL;
     JSObject *parent = callee->getParent();
     gc::AllocKind kind = NewObjectGCKind(cx, newclasp);
     return NewObjectWithClassProto(cx, newclasp, proto, parent, kind);
 }
 
@@ -2362,17 +2362,17 @@ js_CreateThisForFunctionWithProto(JSCont
 
     return res;
 }
 
 JSObject *
 js_CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
 {
     RootedValue protov(cx);
-    if (!JSObject::getProperty(cx, callee, callee, cx->runtime->atomState.classPrototypeAtom, &protov))
+    if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &protov))
         return NULL;
     JSObject *proto;
     if (protov.isObject())
         proto = &protov.toObject();
     else
         proto = NULL;
     JSObject *obj = js_CreateThisForFunctionWithProto(cx, callee, proto);
 
@@ -2429,17 +2429,17 @@ Detecting(JSContext *cx, jsbytecode *pc)
 
     if (op == JSOP_GETGNAME || op == JSOP_NAME) {
         /*
          * Special case #2: handle (document.all == undefined).  Don't worry
          * about a local variable named |undefined| shadowing the immutable
          * global binding...because, really?
          */
         atom = script->getAtom(GET_UINT32_INDEX(pc));
-        if (atom == cx->runtime->atomState.undefinedAtom &&
+        if (atom == cx->names().undefined &&
             (pc += js_CodeSpec[op].length) < endpc) {
             op = JSOp(*pc);
             return op == JSOP_EQ || op == JSOP_NE || op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
         }
     }
 
     return false;
 }
@@ -4318,17 +4318,17 @@ js_GetPropertyHelperInline(JSContext *cx
             JSScript *script = cx->stack.currentScript();
             if (!script || script->warnedAboutUndefinedProp)
                 return true;
 
             /*
              * XXX do not warn about missing __iterator__ as the function
              * may be called from JS_GetMethodById. See bug 355145.
              */
-            if (JSID_IS_ATOM(id, cx->runtime->atomState.iteratorIntrinsicAtom))
+            if (JSID_IS_ATOM(id, cx->names().iteratorIntrinsic))
                 return JS_TRUE;
 
             /* Do not warn about tests like (obj[prop] == undefined). */
             if (cx->resolveFlags == RESOLVE_INFER) {
                 pc += js_CodeSpec[op].length;
                 if (Detecting(cx, pc))
                     return JS_TRUE;
             } else if (cx->resolveFlags & JSRESOLVE_DETECTING) {
@@ -4850,63 +4850,63 @@ DefaultValue(JSContext *cx, HandleObject
 #if JS_HAS_XML_SUPPORT
     JS_ASSERT(!obj->isXML());
 #endif
 
     Rooted<jsid> id(cx);
 
     Class *clasp = obj->getClass();
     if (hint == JSTYPE_STRING) {
-        id = NameToId(cx->runtime->atomState.toStringAtom);
+        id = NameToId(cx->names().toString);
 
         /* Optimize (new String(...)).toString(). */
         if (clasp == &StringClass) {
             if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) {
                 vp.setString(obj->asString().unbox());
                 return true;
             }
         }
 
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
         if (vp.isPrimitive())
             return true;
 
-        id = NameToId(cx->runtime->atomState.valueOfAtom);
+        id = NameToId(cx->names().valueOf);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
         if (vp.isPrimitive())
             return true;
     } else {
 
         /* Optimize new String(...).valueOf(). */
         if (clasp == &StringClass) {
-            id = NameToId(cx->runtime->atomState.valueOfAtom);
+            id = NameToId(cx->names().valueOf);
             if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) {
                 vp.setString(obj->asString().unbox());
                 return true;
             }
         }
 
         /* Optimize new Number(...).valueOf(). */
         if (clasp == &NumberClass) {
-            id = NameToId(cx->runtime->atomState.valueOfAtom);
+            id = NameToId(cx->names().valueOf);
             if (ClassMethodIsNative(cx, obj, &NumberClass, id, js_num_valueOf)) {
                 vp.setNumber(obj->asNumber().unbox());
                 return true;
             }
         }
 
-        id = NameToId(cx->runtime->atomState.valueOfAtom);
+        id = NameToId(cx->names().valueOf);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
         if (vp.isPrimitive())
             return true;
 
-        id = NameToId(cx->runtime->atomState.toStringAtom);
+        id = NameToId(cx->names().toString);
         if (!MaybeCallMethod(cx, obj, id, vp))
             return false;
         if (vp.isPrimitive())
             return true;
     }
 
     /* Avoid recursive death when decompiling in js_ReportValueError. */
     RootedString str(cx);
@@ -5057,17 +5057,17 @@ js_GetClassPrototype(JSContext *cx, JSPr
     }
 
     RootedValue v(cx);
     if (!js_FindClassObject(cx, protoKey, &v, clasp))
         return false;
 
     if (IsFunctionObject(v)) {
         RootedObject ctor(cx, &v.get().toObject());
-        if (!JSObject::getProperty(cx, ctor, ctor, cx->runtime->atomState.classPrototypeAtom, &v))
+        if (!JSObject::getProperty(cx, ctor, ctor, cx->names().classPrototype, &v))
             return false;
     }
 
     protop.set(v.get().isObject() ? &v.get().toObject() : NULL);
     return true;
 }
 
 JSObject *
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -369,17 +369,17 @@ JSObject::setArrayLength(JSContext *cx, 
     if (length > INT32_MAX) {
         /*
          * Mark the type of this object as possibly not a dense array, per the
          * requirements of OBJECT_FLAG_NON_DENSE_ARRAY.
          */
         js::types::MarkTypeObjectFlags(cx, this,
                                        js::types::OBJECT_FLAG_NON_PACKED_ARRAY |
                                        js::types::OBJECT_FLAG_NON_DENSE_ARRAY);
-        jsid lengthId = js::NameToId(cx->runtime->atomState.lengthAtom);
+        jsid lengthId = js::NameToId(cx->names().length);
         js::types::AddTypePropertyId(cx, this, lengthId,
                                      js::types::Type::DoubleType());
     }
 
     getElementsHeader()->length = length;
 }
 
 inline void
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -63,17 +63,17 @@ js_json_parse(JSContext *cx, unsigned ar
     if (argc >= 1) {
         JSString *str = ToString(cx, args[0]);
         if (!str)
             return false;
         linear = str->ensureLinear(cx);
         if (!linear)
             return false;
     } else {
-        linear = cx->runtime->atomState.undefinedAtom;
+        linear = cx->names().undefined;
     }
     JS::Anchor<JSString *> anchor(linear);
 
     RootedValue reviver(cx, (argc >= 2) ? args[1] : UndefinedValue());
 
     /* Steps 2-5. */
     return ParseJSONWithReviver(cx, linear->chars(), linear->length(), reviver, args.rval());
 }
@@ -276,17 +276,17 @@ template<typename KeyType>
 static bool
 PreprocessValue(JSContext *cx, HandleObject holder, KeyType key, MutableHandleValue vp, StringifyContext *scx)
 {
     RootedString keyStr(cx);
 
     /* Step 2. */
     if (vp.get().isObject()) {
         RootedValue toJSON(cx);
-        RootedId id(cx, NameToId(cx->runtime->atomState.toJSONAtom));
+        RootedId id(cx, NameToId(cx->names().toJSON));
         Rooted<JSObject*> obj(cx, &vp.get().toObject());
         if (!GetMethod(cx, obj, id, 0, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = KeyStringifier<KeyType>::toString(cx, key);
             if (!keyStr)
                 return false;
@@ -720,17 +720,17 @@ js_Stringify(JSContext *cx, MutableHandl
     }
 
     /* Step 9. */
     RootedObject wrapper(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!wrapper)
         return false;
 
     /* Step 10. */
-    RootedId emptyId(cx, NameToId(cx->runtime->atomState.emptyAtom));
+    RootedId emptyId(cx, NameToId(cx->names().empty));
     if (!DefineNativeProperty(cx, wrapper, emptyId, vp, JS_PropertyStub, JS_StrictPropertyStub,
                               JSPROP_ENUMERATE, 0, 0))
     {
         return false;
     }
 
     /* Step 11. */
     StringifyContext scx(cx, sb, gap, replacer, propertyList);
@@ -851,20 +851,20 @@ Walk(JSContext *cx, HandleObject holder,
 
 static bool
 Revive(JSContext *cx, HandleValue reviver, MutableHandleValue vp)
 {
     RootedObject obj(cx, NewBuiltinClassInstance(cx, &ObjectClass));
     if (!obj)
         return false;
 
-    if (!JSObject::defineProperty(cx, obj, cx->runtime->atomState.emptyAtom, vp))
+    if (!JSObject::defineProperty(cx, obj, cx->names().empty, vp))
         return false;
 
-    Rooted<jsid> id(cx, NameToId(cx->runtime->atomState.emptyAtom));
+    Rooted<jsid> id(cx, NameToId(cx->names().empty));
     return Walk(cx, obj, id, reviver, vp);
 }
 
 namespace js {
 
 JSBool
 ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, HandleValue reviver,
                      MutableHandleValue vp, DecodingMode decodingMode /* = STRICT */)
@@ -882,17 +882,17 @@ ParseJSONWithReviver(JSContext *cx, cons
 }
 
 } /* namespace js */
 
 #if JS_HAS_TOSOURCE
 static JSBool
 json_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
-    vp->setString(cx->runtime->atomState.JSONAtom);
+    vp->setString(cx->names().JSON);
     return JS_TRUE;
 }
 #endif
 
 static JSFunctionSpec json_static_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,  json_toSource,      0, 0),
 #endif
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -424,17 +424,17 @@ ToDisassemblySource(JSContext *cx, jsval
                 return false;
 
             Shape::Range r = obj->lastProperty()->all();
             Shape::Range::AutoRooter root(cx, &r);
 
             while (!r.empty()) {
                 Rooted<Shape*> shape(cx, &r.front());
                 JSAtom *atom = JSID_IS_INT(shape->propid())
-                               ? cx->runtime->atomState.emptyAtom
+                               ? cx->names().empty
                                : JSID_TO_ATOM(shape->propid());
 
                 JSAutoByteString bytes;
                 if (!js_AtomToPrintableString(cx, atom, &bytes))
                     return false;
 
                 r.popFront();
                 source = JS_sprintf_append(source, "%s: %d%s",
@@ -2337,17 +2337,17 @@ GetBlockNames(JSContext *cx, StaticBlock
 
     unsigned i = numAtoms;
     for (Shape::Range r = blockObj.lastProperty()->all(); !r.empty(); r.popFront()) {
         Shape &shape = r.front();
         LOCAL_ASSERT(shape.hasShortID());
         --i;
         LOCAL_ASSERT((unsigned)shape.shortid() == i);
         (*atoms)[i] = JSID_IS_INT(shape.propid())
-                      ? cx->runtime->atomState.emptyAtom
+                      ? cx->names().empty
                       : JSID_TO_ATOM(shape.propid());
     }
 
     LOCAL_ASSERT(i == 0);
     return true;
 }
 
 static bool
@@ -3462,17 +3462,17 @@ Decompile(SprintStack *ss, jsbytecode *p
 
                     if (groupAssign) {
                         if (ss->sprinter.put(rhs) < 0)
                             return NULL;
                     } else if (!strncmp(rhs, DestructuredString, DestructuredStringLength)) {
                         if (ss->sprinter.put(rhs + DestructuredStringLength) < 0)
                             return NULL;
                     } else {
-                        JS_ASSERT(atoms[i] != cx->runtime->atomState.emptyAtom);
+                        JS_ASSERT(atoms[i] != cx->names().empty);
                         if (!QuoteString(&ss->sprinter, atoms[i], 0))
                             return NULL;
                         if (*rhs) {
                             uint8_t prec = js_CodeSpec[ss->opcodes[letDepth + i]].prec;
                             const char *fmt = prec && prec < js_CodeSpec[JSOP_SETLOCAL].prec
                                               ? " = (%s)"
                                               : " = %s";
                             if (Sprint(&ss->sprinter, fmt, rhs) < 0)
@@ -5955,17 +5955,17 @@ ExpressionDecompiler::decompilePC(jsbyte
       case JSOP_GETALIASEDVAR: {
         JSAtom *atom = ScopeCoordinateName(cx->runtime, script, pc);
         JS_ASSERT(atom);
         return write(atom);
       }
       case JSOP_LENGTH:
       case JSOP_GETPROP:
       case JSOP_CALLPROP: {
-        JSAtom *prop = (op == JSOP_LENGTH) ? cx->runtime->atomState.lengthAtom : loadAtom(pc);
+        JSAtom *prop = (op == JSOP_LENGTH) ? cx->names().length : loadAtom(pc);
         if (!decompilePC(pcstack[-1]))
             return false;
         if (IsIdentifier(prop))
             return write(".") &&
                    quote(prop, '\0');
         else
             return write("[") &&
                    quote(prop, '\'') &&
--- a/js/src/jsopcodeinlines.h
+++ b/js/src/jsopcodeinlines.h
@@ -12,22 +12,22 @@
 #include "frontend/BytecodeEmitter.h"
 
 namespace js {
 
 static inline PropertyName *
 GetNameFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc, JSOp op)
 {
     if (op == JSOP_LENGTH)
-        return cx->runtime->atomState.lengthAtom;
+        return cx->names().length;
 
     // The method JIT's implementation of instanceof contains an internal lookup
     // of the prototype property.
     if (op == JSOP_INSTANCEOF)
-        return cx->runtime->atomState.classPrototypeAtom;
+        return cx->names().classPrototype;
 
     PropertyName *name;
     GET_NAME_FROM_BYTECODE(script, pc, 0, name);
     return name;
 }
 
 class BytecodeRange {
   public:
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -633,22 +633,22 @@ GetFundamentalTrap(JSContext *cx, Handle
 
     return JSObject::getProperty(cx, handler, handler, name, fvalp);
 }
 
 static bool
 GetDerivedTrap(JSContext *cx, HandleObject handler, HandlePropertyName name,
                MutableHandleValue fvalp)
 {
-    JS_ASSERT(name == ATOM(has) ||
-              name == ATOM(hasOwn) ||
-              name == ATOM(get) ||
-              name == ATOM(set) ||
-              name == ATOM(keys) ||
-              name == ATOM(iterate));
+    JS_ASSERT(name == cx->names().has ||
+              name == cx->names().hasOwn ||
+              name == cx->names().get ||
+              name == cx->names().set ||
+              name == cx->names().keys ||
+              name == cx->names().iterate);
 
     return JSObject::getProperty(cx, handler, handler, name, fvalp);
 }
 
 static bool
 Trap(JSContext *cx, HandleObject handler, HandleValue fval, unsigned argc, Value* argv, Value *rval)
 {
     return Invoke(cx, ObjectValue(*handler), fval, argc, argv, rval);
@@ -811,105 +811,105 @@ GetIndirectProxyHandlerObject(JSContext 
 bool
 ScriptedIndirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, bool set,
                                                     PropertyDescriptor *desc)
 {
     RootedId id(cx, id_);
     RootedObject proxy(cx, proxy_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, ATOM(getPropertyDescriptor), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().getPropertyDescriptor, &fval) &&
            Trap1(cx, handler, fval, id, value.address()) &&
            ((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) ||
-            (ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) &&
+            (ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().getPropertyDescriptor, value) &&
              ParsePropertyDescriptorObject(cx, proxy, value, desc)));
 }
 
 bool
 ScriptedIndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy_, jsid id_, bool set,
                                                        PropertyDescriptor *desc)
 {
     RootedId id(cx, id_);
     RootedObject proxy(cx, proxy_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyDescriptor), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().getOwnPropertyDescriptor, &fval) &&
            Trap1(cx, handler, fval, id, value.address()) &&
            ((value.get().isUndefined() && IndicatePropertyNotFound(cx, desc)) ||
-            (ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(getPropertyDescriptor), value) &&
+            (ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().getPropertyDescriptor, value) &&
              ParsePropertyDescriptorObject(cx, proxy, value, desc)));
 }
 
 bool
 ScriptedIndirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_,
                                              PropertyDescriptor *desc)
 {
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
     RootedId id(cx, id_);
-    return GetFundamentalTrap(cx, handler, ATOM(defineProperty), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().defineProperty, &fval) &&
            NewPropertyDescriptorObject(cx, desc, value.address()) &&
            Trap2(cx, handler, fval, id, value, value.address());
 }
 
 bool
 ScriptedIndirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy,
                                                   AutoIdVector &props)
 {
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, ATOM(getOwnPropertyNames), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().getOwnPropertyNames, &fval) &&
            Trap(cx, handler, fval, 0, NULL, value.address()) &&
            ArrayToIdVector(cx, value, props);
 }
 
 bool
 ScriptedIndirectProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id_, bool *bp)
 {
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedId id(cx, id_);
     RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, ATOM(delete_), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().delete_, &fval) &&
            Trap1(cx, handler, fval, id, value.address()) &&
            ValueToBool(cx, value, bp);
 }
 
 bool
 ScriptedIndirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props)
 {
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    return GetFundamentalTrap(cx, handler, ATOM(enumerate), &fval) &&
+    return GetFundamentalTrap(cx, handler, cx->names().enumerate, &fval) &&
            Trap(cx, handler, fval, 0, NULL, value.address()) &&
            ArrayToIdVector(cx, value, props);
 }
 
 bool
 ScriptedIndirectProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
 {
     RootedObject proxy(cx, proxy_);
     RootedId id(cx, id_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(has), &fval))
+    if (!GetDerivedTrap(cx, handler, cx->names().has, &fval))
         return false;
     if (!js_IsCallable(fval))
         return BaseProxyHandler::has(cx, proxy, id, bp);
     return Trap1(cx, handler, fval, id, value.address()) &&
            ValueToBool(cx, value, bp);
 }
 
 bool
 ScriptedIndirectProxyHandler::hasOwn(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
 {
     RootedObject proxy(cx, proxy_);
     RootedId id(cx, id_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue fval(cx), value(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(hasOwn), &fval))
+    if (!GetDerivedTrap(cx, handler, cx->names().hasOwn, &fval))
         return false;
     if (!js_IsCallable(fval))
         return BaseProxyHandler::hasOwn(cx, proxy, id, bp);
     return Trap1(cx, handler, fval, id, value.address()) &&
            ValueToBool(cx, value, bp);
 }
 
 bool
@@ -921,17 +921,17 @@ ScriptedIndirectProxyHandler::get(JSCont
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     JSString *str = ToString(cx, IdToValue(id));
     if (!str)
         return false;
     RootedValue value(cx, StringValue(str));
     Value argv[] = { ObjectOrNullValue(receiver), value };
     AutoValueArray ava(cx, argv, 2);
     RootedValue fval(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(get), &fval))
+    if (!GetDerivedTrap(cx, handler, cx->names().get, &fval))
         return false;
     if (!js_IsCallable(fval))
         return BaseProxyHandler::get(cx, proxy, receiver, id, vp);
     return Trap(cx, handler, fval, 2, argv, vp);
 }
 
 bool
 ScriptedIndirectProxyHandler::set(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid id_, bool strict,
@@ -942,49 +942,49 @@ ScriptedIndirectProxyHandler::set(JSCont
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     JSString *str = ToString(cx, IdToValue(id));
     if (!str)
         return false;
     RootedValue value(cx, StringValue(str));
     Value argv[] = { ObjectOrNullValue(receiver), value, *vp };
     AutoValueArray ava(cx, argv, 3);
     RootedValue fval(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(set), &fval))
+    if (!GetDerivedTrap(cx, handler, cx->names().set, &fval))
         return false;
     if (!js_IsCallable(fval))
         return BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp);
     return Trap(cx, handler, fval, 3, argv, value.address());
 }
 
 bool
 ScriptedIndirectProxyHandler::keys(JSContext *cx, JSObject *proxy_, AutoIdVector &props)
 {
     RootedObject proxy(cx, proxy_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue value(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(keys), &value))
+    if (!GetDerivedTrap(cx, handler, cx->names().keys, &value))
         return false;
     if (!js_IsCallable(value))
         return BaseProxyHandler::keys(cx, proxy, props);
     return Trap(cx, handler, value, 0, NULL, value.address()) &&
            ArrayToIdVector(cx, value, props);
 }
 
 bool
 ScriptedIndirectProxyHandler::iterate(JSContext *cx, JSObject *proxy_, unsigned flags, Value *vp)
 {
     RootedObject proxy(cx, proxy_);
     RootedObject handler(cx, GetIndirectProxyHandlerObject(cx, proxy));
     RootedValue value(cx);
-    if (!GetDerivedTrap(cx, handler, ATOM(iterate), &value))
+    if (!GetDerivedTrap(cx, handler, cx->names().iterate, &value))
         return false;
     if (!js_IsCallable(value))
         return BaseProxyHandler::iterate(cx, proxy, flags, vp);
     return Trap(cx, handler, value, 0, NULL, vp) &&
-           ReturnedValueMustNotBePrimitive(cx, proxy, ATOM(iterate), *vp);
+           ReturnedValueMustNotBePrimitive(cx, proxy, cx->names().iterate, *vp);
 }
 
 bool
 ScriptedIndirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
                                          CallArgs args)
 {
     return BaseProxyHandler::nativeCall(cx, test, impl, args);
 }
@@ -1116,19 +1116,19 @@ NormalizePropertyDescriptor(JSContext *c
     if (!GetPropertyNames(cx, attributes, 0, &props))
         return false;
     size_t n = props.length();
     for (size_t i = 0; i < n; ++i) {
         RootedId id(cx, props[i]);
         if (JSID_IS_ATOM(id)) {
             JSAtom *atom = JSID_TO_ATOM(id);
             const JSAtomState &atomState = cx->runtime->atomState;
-            if (atom == atomState.valueAtom || atom == atomState.writableAtom ||
-                atom == atomState.getAtom || atom == atomState.setAtom ||
-                atom == atomState.enumerableAtom || atom == atomState.configurableAtom)
+            if (atom == atomState.value || atom == atomState.writable ||
+                atom == atomState.get || atom == atomState.set ||
+                atom == atomState.enumerable || atom == atomState.configurable)
             {
                 continue;
             }
         }
 
         RootedValue v(cx);
         if (!JSObject::getGeneric(cx, descObj, attributes, id, &v))
             return false;
@@ -1301,17 +1301,17 @@ TrapGetOwnProperty(JSContext *cx, Handle
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(getOwnPropertyDescriptor), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().getOwnPropertyDescriptor, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined()) {
         AutoPropertyDescriptorRooter desc(cx);
         if (!GetOwnPropertyDescriptor(cx, target, id, &desc))
             return false;
         return NewPropertyDescriptorObject(cx, &desc, rval.address());
@@ -1403,17 +1403,17 @@ TrapDefineOwnProperty(JSContext *cx, Han
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(defineProperty), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().defineProperty, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined()) {
         AutoPropertyDescriptorRooter desc(cx);
         if (!ParsePropertyDescriptorObject(cx, proxy, vp, &desc))
             return false;
         return JS_DefinePropertyById(cx, target, id, desc.value, desc.getter, desc.setter,
@@ -1662,40 +1662,40 @@ ScriptedDirectProxyHandler::getOwnProper
     // step a
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step b
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step c
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(getOwnPropertyNames), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().getOwnPropertyNames, &trap))
         return false;
 
     // step d
     if (trap.isUndefined())
         return DirectProxyHandler::getOwnPropertyNames(cx, proxy_, props);
 
     // step e
     Value argv[] = {
         ObjectValue(*target)
     };
     RootedValue trapResult(cx);
     if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address()))
         return false;
 
     // step f
     if (trapResult.isPrimitive()) {
-        ReportInvalidTrapResult(cx, proxy, ATOM(getOwnPropertyNames));
+        ReportInvalidTrapResult(cx, proxy, cx->names().getOwnPropertyNames);
         return false;
     }
 
     // steps g to n are shared
     return ArrayToIdVector(cx, proxy, target, trapResult, props, JSITER_OWNONLY | JSITER_HIDDEN,
-                           ATOM(getOwnPropertyNames));
+                           cx->names().getOwnPropertyNames);
 }
 
 // Proxy.[[Delete]](P, Throw)
 bool
 ScriptedDirectProxyHandler::delete_(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
 {
     RootedObject proxy(cx, proxy_);
     RootedId id(cx, id_);
@@ -1703,17 +1703,17 @@ ScriptedDirectProxyHandler::delete_(JSCo
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(deleteProperty), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().deleteProperty, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined())
         return DirectProxyHandler::delete_(cx, proxy_, id_, bp);
 
     // step 5
     RootedValue value(cx);
@@ -1757,17 +1757,17 @@ ScriptedDirectProxyHandler::enumerate(JS
     // step a
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step b
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step c
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(enumerate), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().enumerate, &trap))
         return false;
 
     // step d
     if (trap.isUndefined())
         return DirectProxyHandler::enumerate(cx, proxy_, props);
 
     // step e
     Value argv[] = {
@@ -1775,27 +1775,27 @@ ScriptedDirectProxyHandler::enumerate(JS
     };
     RootedValue trapResult(cx);
     if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address()))
         return false;
 
     // step f
     if (trapResult.isPrimitive()) {
         JSAutoByteString bytes;
-        if (!js_AtomToPrintableString(cx, ATOM(enumerate), &bytes))
+        if (!js_AtomToPrintableString(cx, cx->names().enumerate, &bytes))
             return false;
         RootedValue v(cx, ObjectOrNullValue(proxy));
         js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_SEARCH_STACK,
                              v, NullPtr(), bytes.ptr());
         return false;
     }
 
     // steps g-m are shared
     // FIXME: the trap should return an iterator object, see bug 783826
-    return ArrayToIdVector(cx, proxy, target, trapResult, props, 0, ATOM(enumerate));
+    return ArrayToIdVector(cx, proxy, target, trapResult, props, 0, cx->names().enumerate);
 }
 
 // Proxy.[[HasProperty]](P)
 bool
 ScriptedDirectProxyHandler::has(JSContext *cx, JSObject *proxy_, jsid id_, bool *bp)
 {
     RootedObject proxy(cx, proxy_);
     RootedId id(cx, id_);
@@ -1803,17 +1803,17 @@ ScriptedDirectProxyHandler::has(JSContex
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(has), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().has, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined())
         return DirectProxyHandler::has(cx, proxy_, id_, bp);
 
     // step 5
     RootedValue value(cx);
@@ -1866,17 +1866,17 @@ ScriptedDirectProxyHandler::hasOwn(JSCon
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(hasOwn), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().hasOwn, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined())
         return DirectProxyHandler::hasOwn(cx, proxy_, id_, bp);
 
     // step 5
     RootedValue value(cx);
@@ -1939,17 +1939,17 @@ ScriptedDirectProxyHandler::get(JSContex
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(get), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().get, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined())
         return DirectProxyHandler::get(cx, proxy_, receiver_, id_, vp);
 
     // step 5
     RootedValue value(cx);
@@ -2012,17 +2012,17 @@ ScriptedDirectProxyHandler::set(JSContex
     // step 1
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 2
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step 3
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(set), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().set, &trap))
         return false;
 
     // step 4
     if (trap.isUndefined())
         return DirectProxyHandler::set(cx, proxy_, receiver_, id_, strict, vp);
 
     // step 5
     RootedValue value(cx);
@@ -2082,17 +2082,17 @@ ScriptedDirectProxyHandler::keys(JSConte
     // step a
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step b
     RootedObject target(cx, GetProxyTargetObject(proxy));
 
     // step c
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(keys), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().keys, &trap))
         return false;
 
     // step d
     if (trap.isUndefined())
         return DirectProxyHandler::keys(cx, proxy_, props);
 
     // step e
     Value argv[] = {
@@ -2100,26 +2100,26 @@ ScriptedDirectProxyHandler::keys(JSConte
     };
     RootedValue trapResult(cx);
     if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address()))
         return false;
 
     // step f
     if (trapResult.isPrimitive()) {
         JSAutoByteString bytes;
-        if (!js_AtomToPrintableString(cx, ATOM(keys), &bytes))
+        if (!js_AtomToPrintableString(cx, cx->names().keys, &bytes))
             return false;
         RootedValue v(cx, ObjectOrNullValue(proxy));
         js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_IGNORE_STACK,
                              v, NullPtr(), bytes.ptr());
         return false;
     }
 
     // steps g-n are shared
-    return ArrayToIdVector(cx, proxy, target, trapResult, props, JSITER_OWNONLY, ATOM(keys));
+    return ArrayToIdVector(cx, proxy, target, trapResult, props, JSITER_OWNONLY, cx->names().keys);
 }
 
 bool
 ScriptedDirectProxyHandler::iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp)
 {
     // FIXME: Provide a proper implementation for this trap, see bug 787004
     return DirectProxyHandler::iterate(cx, proxy, flags, vp);
 }
@@ -2142,17 +2142,17 @@ ScriptedDirectProxyHandler::call(JSConte
 
     // step 3
     RootedObject args(cx, NewDenseCopiedArray(cx, argc, vp + 2));
     if (!args)
         return false;
 
     // step 4
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(apply), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().apply, &trap))
         return false;
 
     // step 5
     if (trap.isUndefined())
         return DirectProxyHandler::call(cx, proxy_, argc, vp);
 
     // step 6
     Value argv[] = {
@@ -2183,17 +2183,17 @@ ScriptedDirectProxyHandler::construct(JS
 
     // step 3
     RootedObject args(cx, NewDenseCopiedArray(cx, argc, argv));
     if (!args)
         return false;
 
     // step 4
     RootedValue trap(cx);
-    if (!JSObject::getProperty(cx, handler, handler, ATOM(construct), &trap))
+    if (!JSObject::getProperty(cx, handler, handler, cx->names().construct, &trap))
         return false;
 
     // step 5
     if (trap.isUndefined())
         return DirectProxyHandler::construct(cx, proxy_, argc, argv, rval);
 
     // step 6
     Value constructArgv[] = {
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -1691,17 +1691,17 @@ NodeBuilder::xmlPI(HandleValue target, H
 class ASTSerializer
 {
     JSContext           *cx;
     Parser              *parser;
     NodeBuilder         builder;
     DebugOnly<uint32_t> lineno;
 
     RawValue unrootedAtomContents(RawAtom atom) {
-        return StringValue(atom ? atom : cx->runtime->atomState.emptyAtom);
+        return StringValue(atom ? atom : cx->names().empty);
     }
 
     BinaryOperator binop(ParseNodeKind kind, JSOp op);
     UnaryOperator unop(ParseNodeKind kind, JSOp op);
     AssignmentOperator aop(JSOp op);
 
     bool statements(ParseNode *pn, NodeVector &elts);
     bool expressions(ParseNode *pn, NodeVector &elts);
@@ -3413,26 +3413,26 @@ reflect_parse(JSContext *cx, uint32_t ar
             return JS_FALSE;
         }
 
         RootedObject config(cx, &arg.toObject());
 
         RootedValue prop(cx);
 
         /* config.loc */
-        RootedId locId(cx, NameToId(cx->runtime->atomState.locAtom));
+        RootedId locId(cx, NameToId(cx->names().loc));
         RootedValue trueVal(cx, BooleanValue(true));
         if (!baseops::GetPropertyDefault(cx, config, locId, trueVal, &prop))
             return JS_FALSE;
 
         loc = ToBoolean(prop);
 
         if (loc) {
             /* config.source */
-            RootedId sourceId(cx, NameToId(cx->runtime->atomState.sourceAtom));
+            RootedId sourceId(cx, NameToId(cx->names().source));
             RootedValue nullVal(cx, NullValue());
             if (!baseops::GetPropertyDefault(cx, config, sourceId, nullVal, &prop))
                 return JS_FALSE;
 
             if (!prop.isNullOrUndefined()) {
                 RootedString str(cx, ToString(cx, prop));
                 if (!str)
                     return JS_FALSE;
@@ -3444,26 +3444,26 @@ reflect_parse(JSContext *cx, uint32_t ar
 
                 filename = DeflateString(cx, chars, length);
                 if (!filename)
                     return JS_FALSE;
                 filenamep.reset(filename);
             }
 
             /* config.line */
-            RootedId lineId(cx, NameToId(cx->runtime->atomState.lineAtom));
+            RootedId lineId(cx, NameToId(cx->names().line));
             RootedValue oneValue(cx, Int32Value(1));
             if (!baseops::GetPropertyDefault(cx, config, lineId, oneValue, &prop) ||
                 !ToUint32(cx, prop, &lineno)) {
                 return JS_FALSE;
             }
         }
 
         /* config.builder */
-        RootedId builderId(cx, NameToId(cx->runtime->atomState.builderAtom));
+        RootedId builderId(cx, NameToId(cx->names().builder));
         RootedValue nullVal(cx, NullValue());
         if (!baseops::GetPropertyDefault(cx, config, builderId, nullVal, &prop))
             return JS_FALSE;
 
         if (!prop.isNullOrUndefined()) {
             if (!prop.isObject()) {
                 js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
                                          JSDVG_SEARCH_STACK, prop, NullPtr(), "not an object", NULL);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -48,17 +48,17 @@
 
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 unsigned
 Bindings::argumentsVarIndex(JSContext *cx) const
 {
-    PropertyName *arguments = cx->runtime->atomState.argumentsAtom;
+    HandlePropertyName arguments = cx->names().arguments;
     BindingIter bi(*this);
     while (bi->name() != arguments)
         bi++;
     return bi.frameIndex();
 }
 
 bool
 Bindings::initWithTemporaryStorage(JSContext *cx, InternalHandle<Bindings*> self,
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -61,17 +61,17 @@ using namespace js;
 using namespace js::gc;
 using namespace js::types;
 using namespace js::unicode;
 
 static JSLinearString *
 ArgToRootedString(JSContext *cx, CallArgs &args, unsigned argno)
 {
     if (argno >= args.length())
-        return cx->runtime->atomState.undefinedAtom;
+        return cx->names().undefined;
 
     Value &arg = args[argno];
     JSString *str = ToString(cx, arg);
     if (!str)
         return NULL;
 
     arg = StringValue(str);
     return str->ensureLinear(cx);
@@ -434,17 +434,17 @@ ThisToStringForStringProto(JSContext *cx
     JS_CHECK_RECURSION(cx, return NULL);
 
     if (call.thisv().isString())
         return call.thisv().toString();
 
     if (call.thisv().isObject()) {
         RootedObject obj(cx, &call.thisv().toObject());
         if (obj->isString()) {
-            Rooted<jsid> id(cx, NameToId(cx->runtime->atomState.toStringAtom));
+            Rooted<jsid> id(cx, NameToId(cx->names().toString));
             if (ClassMethodIsNative(cx, obj, &StringClass, id, js_str_toString)) {
                 JSString *str = obj->asString().unbox();
                 call.setThis(StringValue(str));
                 return str;
             }
         }
     } else if (call.thisv().isNullOrUndefined()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
@@ -1722,18 +1722,18 @@ BuildFlatMatchArray(JSContext *cx, Handl
     if (!obj)
         return false;
 
     RootedValue patternVal(cx, StringValue(fm.pattern()));
     RootedValue matchVal(cx, Int32Value(fm.match()));
     RootedValue textVal(cx, StringValue(textstr));
 
     if (!JSObject::defineElement(cx, obj, 0, patternVal) ||
-        !JSObject::defineProperty(cx, obj, cx->runtime->atomState.indexAtom, matchVal) ||
-        !JSObject::defineProperty(cx, obj, cx->runtime->atomState.inputAtom, textVal))
+        !JSObject::defineProperty(cx, obj, cx->names().index, matchVal) ||
+        !JSObject::defineProperty(cx, obj, cx->names().input, textVal))
     {
         return false;
     }
 
     args->rval().setObject(*obj);
     return true;
 }
 
@@ -3215,17 +3215,17 @@ static JSFunctionSpec string_static_meth
     JS_FS_END
 };
 
 Shape *
 StringObject::assignInitialShape(JSContext *cx)
 {
     JS_ASSERT(nativeEmpty());
 
-    return addDataProperty(cx, NameToId(cx->runtime->atomState.lengthAtom),
+    return addDataProperty(cx, NameToId(cx->names().length),
                            LENGTH_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 JSObject *
 js_InitStringClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isNative());
 
@@ -3233,17 +3233,17 @@ js_InitStringClass(JSContext *cx, JSObje
 
     Rooted<JSString*> empty(cx, cx->runtime->emptyString);
     RootedObject proto(cx, global->createBlankPrototype(cx, &StringClass));
     if (!proto || !proto->asString().init(cx, empty))
         return NULL;
 
     /* Now create the String function. */
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, js_String, cx->runtime->atomState.StringAtom, 1);
+    ctor = global->createConstructor(cx, js_String, cx->names().String, 1);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, proto, NULL, string_methods) ||
         !DefinePropertiesAndBrand(cx, ctor, NULL, string_static_methods))
@@ -3418,46 +3418,46 @@ js::ToStringSlow(JSContext *cx, const Va
         str = v.toString();
     } else if (v.isInt32()) {
         str = Int32ToString(cx, v.toInt32());
     } else if (v.isDouble()) {
         str = js_NumberToString(cx, v.toDouble());
     } else if (v.isBoolean()) {
         str = js_BooleanToString(cx, v.toBoolean());
     } else if (v.isNull()) {
-        str = cx->runtime->atomState.nullAtom;
+        str = cx->names().null;
     } else {
-        str = cx->runtime->atomState.undefinedAtom;
+        str = cx->names().undefined;
     }
     return str;
 }
 
 JS_FRIEND_API(JSString *)
 js_ValueToSource(JSContext *cx, const Value &v)
 {
     JS_CHECK_RECURSION(cx, return NULL);
 
     if (v.isUndefined())
-        return cx->runtime->atomState.void0Atom;
+        return cx->names().void0;
     if (v.isString())
         return js_QuoteString(cx, v.toString(), '"');
     if (v.isPrimitive()) {
         /* Special case to preserve negative zero, _contra_ toString. */
         if (v.isDouble() && MOZ_DOUBLE_IS_NEGATIVE_ZERO(v.toDouble())) {
             /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
             static const jschar js_negzero_ucNstr[] = {'-', '0'};
 
             return js_NewStringCopyN(cx, js_negzero_ucNstr, 2);
         }
         return ToString(cx, v);
     }
 
     Value rval = NullValue();
     RootedValue fval(cx);
-    RootedId id(cx, NameToId(cx->runtime->atomState.toSourceAtom));
+    RootedId id(cx, NameToId(cx->names().toSource));
     Rooted<JSObject*> obj(cx, &v.toObject());
     if (!GetMethod(cx, obj, id, 0, &fval))
         return NULL;
     if (js_IsCallable(fval)) {
         if (!Invoke(cx, ObjectValue(*obj), fval, 0, NULL, &rval))
             return NULL;
     }
 
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1591,26 +1591,26 @@ class TypedArrayTemplate
         return DefineNativeProperty(cx, proto, id, value,
                                     JS_DATA_TO_FUNC_PTR(PropertyOp, getter), NULL,
                                     flags, 0, 0);
     }
 
     static
     bool defineGetters(JSContext *cx, HandleObject proto)
     {
-        if (!DefineGetter<lengthValue>(cx, cx->runtime->atomState.lengthAtom, proto))
+        if (!DefineGetter<lengthValue>(cx, cx->names().length, proto))
             return false;
 
-        if (!DefineGetter<bufferValue>(cx, cx->runtime->atomState.bufferAtom, proto))
+        if (!DefineGetter<bufferValue>(cx, cx->names().buffer, proto))
             return false;
 
-        if (!DefineGetter<byteLengthValue>(cx, cx->runtime->atomState.byteLengthAtom, proto))
+        if (!DefineGetter<byteLengthValue>(cx, cx->names().byteLength, proto))
             return false;
 
-        if (!DefineGetter<byteOffsetValue>(cx, cx->runtime->atomState.byteOffsetAtom, proto))
+        if (!DefineGetter<byteOffsetValue>(cx, cx->names().byteOffset, proto))
             return false;
 
         return true;
     }
 
     /* subarray(start[, end]) */
     static bool
     fun_subarray_impl(JSContext *cx, CallArgs args)
@@ -3210,21 +3210,21 @@ InitTypedArrayClass(JSContext *cx)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     RootedValue bytesValue(cx, Int32Value(ArrayType::BYTES_PER_ELEMENT));
 
     if (!JSObject::defineProperty(cx, ctor,
-                                  cx->runtime->atomState.BYTES_PER_ELEMENTAtom, bytesValue,
+                                  cx->names().BYTES_PER_ELEMENT, bytesValue,
                                   JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY) ||
         !JSObject::defineProperty(cx, proto,
-                                  cx->runtime->atomState.BYTES_PER_ELEMENTAtom, bytesValue,
+                                  cx->names().BYTES_PER_ELEMENT, bytesValue,
                                   JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return NULL;
     }
 
     if (!ArrayType::defineGetters(cx, proto))
         return NULL;
@@ -3286,24 +3286,24 @@ static JSObject *
 InitArrayBufferClass(JSContext *cx)
 {
     Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
     RootedObject arrayBufferProto(cx, global->createBlankPrototype(cx, &ArrayBufferObject::protoClass));
     if (!arrayBufferProto)
         return NULL;
 
     RootedFunction ctor(cx, global->createConstructor(cx, ArrayBufferObject::class_constructor,
-                                                      cx->runtime->atomState.ArrayBufferAtom, 1));
+                                                      cx->names().ArrayBuffer, 1));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, arrayBufferProto))
         return NULL;
 
-    RootedId byteLengthId(cx, NameToId(cx->runtime->atomState.byteLengthAtom));
+    RootedId byteLengthId(cx, NameToId(cx->names().byteLength));
     unsigned flags = JSPROP_SHARED | JSPROP_GETTER | JSPROP_PERMANENT;
     JSObject *getter = js_NewFunction(cx, NULL, ArrayBufferObject::byteLengthGetter, 0, 0, global, NULL);
     if (!getter)
         return NULL;
 
     RootedValue value(cx, UndefinedValue());
     if (!DefineNativeProperty(cx, arrayBufferProto, byteLengthId, value,
                               JS_DATA_TO_FUNC_PTR(PropertyOp, getter), NULL, flags, 0, 0))
@@ -3415,30 +3415,30 @@ JSObject *
 DataViewObject::initClass(JSContext *cx)
 {
     Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
     RootedObject proto(cx, global->createBlankPrototype(cx, &DataViewObject::protoClass));
     if (!proto)
         return NULL;
 
     RootedFunction ctor(cx, global->createConstructor(cx, DataViewObject::class_constructor,
-                                                      cx->runtime->atomState.DataViewAtom, 3));
+                                                      cx->names().DataView, 3));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
-    if (!defineGetter<bufferValue>(cx, cx->runtime->atomState.bufferAtom, proto))
+    if (!defineGetter<bufferValue>(cx, cx->names().buffer, proto))
         return NULL;
 
-    if (!defineGetter<byteLengthValue>(cx, cx->runtime->atomState.byteLengthAtom, proto))
+    if (!defineGetter<byteLengthValue>(cx, cx->names().byteLength, proto))
         return NULL;
 
-    if (!defineGetter<byteOffsetValue>(cx, cx->runtime->atomState.byteOffsetAtom, proto))
+    if (!defineGetter<byteOffsetValue>(cx, cx->names().byteOffset, proto))
         return NULL;
 
     if (!JS_DefineFunctions(cx, proto, DataViewObject::jsfuncs))
         return NULL;
 
     /*
      * Create a helper function to implement the craziness of
      * |new DataView(new otherWindow.ArrayBuffer())|, and install it in the
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -368,17 +368,17 @@ js_InitWeakMapClass(JSContext *cx, JSObj
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
     RootedObject weakMapProto(cx, global->createBlankPrototype(cx, &WeakMapClass));
     if (!weakMapProto)
         return NULL;
 
     RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
-                                                      cx->runtime->atomState.WeakMapAtom, 0));
+                                                      cx->names().WeakMap, 0));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, weakMapProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, weakMapProto, NULL, weak_map_methods))
         return NULL;
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -349,22 +349,22 @@ static JSPropertySpec qname_props[] = {
 static JSString *
 ConvertQNameToString(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isQName());
     RootedString uri(cx, obj->getNameURI());
     RootedString str(cx);
     if (!uri) {
         /* No uri means wildcard qualifier. */
-        str = cx->runtime->atomState.starQualifierAtom;
+        str = cx->names().starQualifier;
     } else if (uri->empty()) {
         /* Empty string for uri means localName is in no namespace. */
         str = cx->runtime->emptyString;
     } else {
-        RootedString qualstr(cx, cx->runtime->atomState.qualifierAtom);
+        RootedString qualstr(cx, cx->names().qualifier);
         str = js_ConcatStrings(cx, uri, qualstr);
         if (!str)
             return NULL;
     }
     Rooted<JSString*> localName(cx, obj->getQNameLocalName());
     str = js_ConcatStrings(cx, str, localName);
     if (!str)
         return NULL;
@@ -732,17 +732,17 @@ QNameHelper(JSContext *cx, int argc, jsv
 
         /* Namespace and qname were passed -- use the qname's localName. */
         nameval = qn->getQNameLocalNameVal();
     }
 
     if (argc == 0) {
         name = cx->runtime->emptyString;
     } else if (argc < 0) {
-        name = cx->runtime->atomState.undefinedAtom;
+        name = cx->names().undefined;
     } else {
         name = ToAtom(cx, nameval);
         if (!name)
             return false;
     }
 
     if (argc > 1 && !JSVAL_IS_VOID(argv[0])) {
         nsval = argv[0];
@@ -2800,17 +2800,17 @@ ToAttributeName(JSContext *cx, jsval v)
 
         if (clasp == &QNameClass) {
             qn = obj;
             uri = qn->getNameURI();
             prefix = qn->getNamePrefix();
             name = qn->getQNameLocalName();
         } else {
             if (clasp == &AnyNameClass) {
-                name = cx->runtime->atomState.starAtom;
+                name = cx->names().star;
             } else {
                 name = ToAtom(cx, v);
                 if (!name)
                     return NULL;
             }
             uri = prefix = cx->runtime->emptyString;
         }
     }
@@ -2828,17 +2828,17 @@ ReportBadXMLName(JSContext *cx, const Va
     js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, val, NullPtr());
 }
 
 namespace js {
 
 bool
 GetLocalNameFromFunctionQName(JSObject *qn, JSAtom **namep, JSContext *cx)
 {
-    JSAtom *atom = cx->runtime->atomState.functionNamespaceURIAtom;
+    JSAtom *atom = cx->names().functionNamespaceURI;
     JSLinearString *uri = qn->getNameURI();
     if (uri && (uri == atom || EqualStrings(uri, atom))) {
         *namep = qn->getQNameLocalName();
         return true;
     }
     return false;
 }
 
@@ -2874,17 +2874,17 @@ ToXMLName(JSContext *cx, jsval v, jsid *
             return NULL;
         }
 
         obj = JSVAL_TO_OBJECT(v);
         clasp = obj->getClass();
         if (clasp == &AttributeNameClass || clasp == &QNameClass)
             goto out;
         if (clasp == &AnyNameClass) {
-            name = cx->runtime->atomState.starAtom;
+            name = cx->names().star;
             goto construct;
         }
         name = ToStringSlow(cx, v);
         if (!name)
             return NULL;
     }
 
     atomizedName = AtomizeString(cx, name);
@@ -4155,17 +4155,17 @@ PutProperty(JSContext *cx, HandleObject 
             XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
         }
 
         /* 2(h). */
         else {
             kidobj = js_GetXMLObject(cx, kid);
             if (!kidobj)
                 goto bad;
-            id = NameToId(cx->runtime->atomState.starAtom);
+            id = NameToId(cx->names().star);
             ok = PutProperty(cx, kidobj, id, strict, vp);
             if (!ok)
                 goto out;
         }
     } else {
         /*
          * ECMA-357 9.2.1.2/9.1.1.2 qname case.
          */
@@ -4253,17 +4253,17 @@ PutProperty(JSContext *cx, HandleObject 
                 n = vxml->xml_kids.length;
                 if (n == 0) {
                     vp.set(STRING_TO_JSVAL(cx->runtime->emptyString));
                 } else {
                     RootedString left(cx, KidToString(cx, vxml, 0));
                     if (!left)
                         goto bad;
 
-                    RootedString space(cx, cx->runtime->atomState.spaceAtom);
+                    RootedString space(cx, cx->names().space);
                     for (i = 1; i < n; i++) {
                         left = js_ConcatStrings(cx, left, space);
                         if (!left)
                             goto bad;
                         RootedString right(cx, KidToString(cx, vxml, i));
                         if (!right)
                             goto bad;
                         left = js_ConcatStrings(cx, left, right);
@@ -5500,17 +5500,17 @@ xml_attribute(JSContext *cx, unsigned ar
         return JS_FALSE;
     return GetProperty(cx, obj, id, MutableHandleValue::fromMarkedLocation(vp));
 }
 
 /* XML and XMLList */
 static JSBool
 xml_attributes(JSContext *cx, unsigned argc, jsval *vp)
 {
-    jsval name = STRING_TO_JSVAL(cx->runtime->atomState.starAtom);
+    jsval name = STRING_TO_JSVAL(cx->names().star);
     JSObject *qn = ToAttributeName(cx, name);
     if (!qn)
         return JS_FALSE;
 
     RootedId id(cx, OBJECT_TO_JSID(qn));
     RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])));
     if (!obj)
         return JS_FALSE;
@@ -5669,17 +5669,17 @@ xml_childIndex(JSContext *cx, unsigned a
 
 /* XML and XMLList */
 static JSBool
 xml_children(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject obj(cx, ToObject(cx, HandleValue::fromMarkedLocation(&vp[1])));
     if (!obj)
         return false;
-    RootedId name(cx, NameToId(cx->runtime->atomState.starAtom));
+    RootedId name(cx, NameToId(cx->names().star));
     return GetProperty(cx, obj, name, MutableHandleValue::fromMarkedLocation(vp));
 }
 
 /* XML and XMLList */
 static JSBool
 xml_comments_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp)
 {
     JSXML *list, *kid, *vxml;
@@ -5783,17 +5783,17 @@ xml_copy(JSContext *cx, unsigned argc, j
 /* XML and XMLList */
 static JSBool
 xml_descendants(JSContext *cx, unsigned argc, jsval *vp)
 {
     jsval name;
     JSXML *list;
 
     XML_METHOD_PROLOG;
-    name = argc == 0 ? STRING_TO_JSVAL(cx->runtime->atomState.starAtom) : vp[2];
+    name = argc == 0 ? STRING_TO_JSVAL(cx->names().star) : vp[2];
     list = Descendants(cx, xml, name);
     if (!list)
         return JS_FALSE;
     *vp = OBJECT_TO_JSVAL(list->object);
     return JS_TRUE;
 }
 
 /* XML and XMLList */
@@ -5855,17 +5855,17 @@ static JSBool
 xml_elements(JSContext *cx, unsigned argc, jsval *vp)
 {
     jsval name;
     JSObject *nameqn;
     jsid funid;
 
     XML_METHOD_PROLOG;
 
-    name = (argc == 0) ? STRING_TO_JSVAL(cx->runtime->atomState.starAtom) : vp[2];
+    name = (argc == 0) ? STRING_TO_JSVAL(cx->names().star) : vp[2];
     nameqn = ToXMLName(cx, name, &funid);
     if (!nameqn)
         return JS_FALSE;
 
     if (!JSID_IS_VOID(funid))
         return xml_list_helper(cx, xml, vp) != NULL;
 
     return xml_elements_helper(cx, obj, xml, nameqn, vp);
@@ -6408,17 +6408,17 @@ static JSBool
 xml_processingInstructions(JSContext *cx, unsigned argc, jsval *vp)
 {
     jsval name;
     JSObject *nameqn;
     jsid funid;
 
     XML_METHOD_PROLOG;
 
-    name = (argc == 0) ? STRING_TO_JSVAL(cx->runtime->atomState.starAtom) : vp[2];
+    name = (argc == 0) ? STRING_TO_JSVAL(cx->names().star) : vp[2];
     nameqn = ToXMLName(cx, name, &funid);
     if (!nameqn)
         return JS_FALSE;
     vp[2] = OBJECT_TO_JSVAL(nameqn);
 
     if (!JSID_IS_VOID(funid))
         return xml_list_helper(cx, xml, vp) != NULL;
 
@@ -6545,17 +6545,17 @@ xml_replace(JSContext *cx, unsigned argc
     uint32_t index, i;
     JSObject *nameqn;
 
     NON_LIST_XML_METHOD_PROLOG;
     if (xml->xml_class != JSXML_CLASS_ELEMENT)
         goto done;
 
     if (argc <= 1) {
-        value = STRING_TO_JSVAL(cx->runtime->atomState.undefinedAtom);
+        value = STRING_TO_JSVAL(cx->names().undefined);
     } else {
         value = vp[3];
         vxml = VALUE_IS_XML(value)
                ? (JSXML *) JSVAL_TO_OBJECT(value)->getPrivate()
                : NULL;
         if (!vxml) {
             if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &vp[3]))
                 return JS_FALSE;
@@ -6617,17 +6617,17 @@ xml_replace(JSContext *cx, unsigned argc
 static JSBool
 xml_setChildren(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject obj(cx);
 
     if (!StartNonListXMLMethod(cx, vp, &obj))
         return JS_FALSE;
 
-    Rooted<jsid> id(cx, NameToId(cx->runtime->atomState.starAtom));
+    Rooted<jsid> id(cx, NameToId(cx->names().star));
     *vp = argc != 0 ? vp[2] : JSVAL_VOID;     /* local root */
     if (!PutProperty(cx, obj, id, false, MutableHandleValue::fromMarkedLocation(vp)))
         return JS_FALSE;
 
     *vp = OBJECT_TO_JSVAL(obj);
     return JS_TRUE;
 }
 
@@ -6637,17 +6637,17 @@ xml_setLocalName(JSContext *cx, unsigned
     NON_LIST_XML_METHOD_PROLOG;
     if (!JSXML_HAS_NAME(xml)) {
         vp[0] = JSVAL_VOID;
         return JS_TRUE;
     }
 
     JSAtom *namestr;
     if (argc == 0) {
-        namestr = cx->runtime->atomState.undefinedAtom;
+        namestr = cx->names().undefined;
     } else {
         jsval name = vp[2];
         if (!JSVAL_IS_PRIMITIVE(name) && JSVAL_TO_OBJECT(name)->isQName()) {
             namestr = JSVAL_TO_OBJECT(name)->getQNameLocalName();
         } else {
             namestr = ToAtom(cx, name);
             if (!namestr)
                 return false;
@@ -6673,17 +6673,17 @@ xml_setName(JSContext *cx, unsigned argc
     uint32_t i, n;
     JSObject *ns;
 
     NON_LIST_XML_METHOD_PROLOG;
     if (!JSXML_HAS_NAME(xml))
         return JS_TRUE;
 
     if (argc == 0) {
-        name = STRING_TO_JSVAL(cx->runtime->atomState.undefinedAtom);
+        name = STRING_TO_JSVAL(cx->names().undefined);
     } else {
         name = vp[2];
         if (!JSVAL_IS_PRIMITIVE(name) &&
             JSVAL_TO_OBJECT(name)->getClass() == &QNameClass &&
             !(nameqn = JSVAL_TO_OBJECT(name))->getNameURI()) {
             name = vp[2] = nameqn->getQNameLocalNameVal();
         }
     }
@@ -7335,17 +7335,17 @@ js_InitNamespaceClass(JSContext *cx, JSO
     if (!namespaceProto)
         return NULL;
     JSFlatString *empty = cx->runtime->emptyString;
     namespaceProto->setNamePrefix(empty);
     namespaceProto->setNameURI(empty);
 
     const unsigned NAMESPACE_CTOR_LENGTH = 2;
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, Namespace, cx->runtime->atomState.NamespaceAtom,
+    ctor = global->createConstructor(cx, Namespace, cx->names().Namespace,
                                      NAMESPACE_CTOR_LENGTH);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, namespaceProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, namespaceProto, namespace_props, namespace_methods))
@@ -7368,17 +7368,17 @@ js_InitQNameClass(JSContext *cx, JSObjec
     RootedObject qnameProto(cx, global->createBlankPrototype(cx, &QNameClass));
     if (!qnameProto)
         return NULL;
     JSAtom *empty = cx->runtime->emptyString;
     if (!InitXMLQName(cx, qnameProto, empty, empty, empty))
         return NULL;
 
     const unsigned QNAME_CTOR_LENGTH = 2;
-    RootedFunction ctor(cx, global->createConstructor(cx, QName, cx->runtime->atomState.QNameAtom,
+    RootedFunction ctor(cx, global->createConstructor(cx, QName, cx->names().QName,
                                                       QNAME_CTOR_LENGTH));
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, qnameProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, qnameProto, NULL, qname_methods))
@@ -7409,17 +7409,17 @@ js_InitXMLClass(JSContext *cx, JSObject 
     /* Don't count this as a real content-created XML object. */
     if (!cx->runningWithTrustedPrincipals()) {
         JS_ASSERT(sE4XObjectsCreated > 0);
         --sE4XObjectsCreated;
     }
 
     const unsigned XML_CTOR_LENGTH = 1;
     RootedFunction ctor(cx);
-    ctor = global->createConstructor(cx, XML, cx->runtime->atomState.XMLAtom, XML_CTOR_LENGTH);
+    ctor = global->createConstructor(cx, XML, cx->names().XML, XML_CTOR_LENGTH);
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, xmlProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, xmlProto, NULL, xml_methods) ||
         !DefinePropertiesAndBrand(cx, ctor, xml_static_props, xml_static_methods))
@@ -7430,17 +7430,17 @@ js_InitXMLClass(JSContext *cx, JSObject 
     if (!SetDefaultXMLSettings(cx, ctor))
         return NULL;
 
     /* Define the XMLList function, and give it the same .prototype as XML. */
     RootedFunction xmllist(cx, JS_DefineFunction(cx, global, js_XMLList_str, XMLList, 1, JSFUN_CONSTRUCTOR));
     if (!xmllist)
         return NULL;
     RootedValue value(cx, ObjectValue(*xmlProto));
-    if (!JSObject::defineProperty(cx, xmllist, cx->runtime->atomState.classPrototypeAtom,
+    if (!JSObject::defineProperty(cx, xmllist, cx->names().classPrototype,
                                   value, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_XML, ctor, xmlProto))
         return NULL;
@@ -7464,19 +7464,18 @@ js_InitXMLClasses(JSContext *cx, JSObjec
 
 namespace js {
 
 bool
 GlobalObject::getFunctionNamespace(JSContext *cx, Value *vp)
 {
     Value v = getSlot(FUNCTION_NS);
     if (v.isUndefined()) {
-        JSRuntime *rt = cx->runtime;
-        JSLinearString *prefix = rt->atomState.functionAtom;
-        JSLinearString *uri = rt->atomState.functionNamespaceURIAtom;
+        HandlePropertyName prefix = cx->names().function;
+        HandlePropertyName uri = cx->names().functionNamespaceURI;
         RootedObject obj(cx, NewXMLNamespace(cx, prefix, uri, JS_FALSE));
         if (!obj)
             return false;
 
         /*
          * Avoid entraining any in-scope Object.prototype.  The loss of
          * Namespace.prototype is not detectable, as there is no way to
          * refer to this instance in scripts.  When used to qualify method
@@ -7643,17 +7642,17 @@ js_GetAnyName(JSContext *cx, jsid *idp)
     if (v.isUndefined()) {
         RootedObject obj(cx, NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global));
         if (!obj)
             return false;
 
         JS_ASSERT(!obj->getProto());
 
         JSRuntime *rt = cx->runtime;
-        if (!InitXMLQName(cx, obj, rt->emptyString, rt->emptyString, rt->atomState.starAtom))
+        if (!InitXMLQName(cx, obj, rt->emptyString, rt->emptyString, rt->atomState.star))
             return false;
 
         v.setObject(*obj);
         SetReservedSlot(global, JSProto_AnyName, v);
     }
     *idp = OBJECT_TO_JSID(&v.toObject());
     return true;
 }
@@ -7668,17 +7667,17 @@ js_FindXMLProperty(JSContext *cx, const 
     RootedObject target(cx);
     JSObject *obj, *proto;
     JSXML *xml;
     JSBool found;
 
     JS_ASSERT(nameval.isObject());
     nameobj = &nameval.toObject();
     if (nameobj->getClass() == &AnyNameClass) {
-        v = STRING_TO_JSVAL(cx->runtime->atomState.starAtom);
+        v = STRING_TO_JSVAL(cx->names().star);
         nameobj = ConstructObjectWithArguments(cx, &QNameClass, 1, &v);
         if (!nameobj)
             return JS_FALSE;
     } else {
         JS_ASSERT(nameobj->getClass() == &AttributeNameClass ||
                   nameobj->getClass() == &QNameClass);
     }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -5021,23 +5021,22 @@ mjit::Compiler::jsop_getprop(PropertyNam
 
     /*
      * Use a different rejoin for GETPROP computing the 'this' object, as we
      * can't use the current bytecode within InternalInterpret to tell this is
      * fetching the 'this' value.
      */
     RejoinState rejoin = REJOIN_GETTER;
     if (forPrototype) {
-        JS_ASSERT(top->isType(JSVAL_TYPE_OBJECT) &&
-                  name == cx->runtime->atomState.classPrototypeAtom);
+        JS_ASSERT(top->isType(JSVAL_TYPE_OBJECT) && name == cx->names().classPrototype);
         rejoin = REJOIN_THIS_PROTOTYPE;
     }
 
     /* Handle length accesses on known strings without using a PIC. */
-    if (name == cx->runtime->atomState.lengthAtom &&
+    if (name == cx->names().length &&
         top->isType(JSVAL_TYPE_STRING) &&
         (!cx->typeInferenceEnabled() || knownPushedType(0) == JSVAL_TYPE_INT32)) {
         if (top->isConstant()) {
             JSString *str = top->getValue().toString();
             Value v;
             v.setNumber(uint32_t(str->length()));
             frame.pop();
             frame.push(v);
@@ -5047,17 +5046,17 @@ mjit::Compiler::jsop_getprop(PropertyNam
             masm.urshift32(Imm32(JSString::LENGTH_SHIFT), str);
             frame.pop();
             frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
         }
         return true;
     }
 
     /* Handle lenth accesses of optimize 'arguments'. */
-    if (name == cx->runtime->atomState.lengthAtom &&
+    if (name == cx->names().length &&
         cx->typeInferenceEnabled() &&
         analysis->poppedTypes(PC, 0)->isMagicArguments() &&
         knownPushedType(0) == JSVAL_TYPE_INT32)
     {
         frame.pop();
         RegisterID reg = frame.allocReg();
         masm.load32(Address(JSFrameReg, StackFrame::offsetOfNumActual()), reg);
         frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
@@ -6455,25 +6454,25 @@ mjit::Compiler::jsop_bindgname()
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
 }
 
 bool
 mjit::Compiler::jsop_getgname(uint32_t index)
 {
     /* Optimize undefined, NaN and Infinity. */
     PropertyName *name = script->getName(index);
-    if (name == cx->runtime->atomState.undefinedAtom) {
+    if (name == cx->names().undefined) {
         frame.push(UndefinedValue());
         return true;
     }
-    if (name == cx->runtime->atomState.NaNAtom) {
+    if (name == cx->names().NaN) {
         frame.push(cx->runtime->NaNValue);
         return true;
     }
-    if (name == cx->runtime->atomState.InfinityAtom) {
+    if (name == cx->names().Infinity) {
         frame.push(cx->runtime->positiveInfinityValue);
         return true;
     }
 
     /* Optimize singletons like Math for JSOP_CALLPROP. */
     JSObject *obj = pushedSingleton(0);
     if (obj && !hasTypeBarriers(PC)) {
         Rooted<jsid> id(cx, NameToId(name));
@@ -6791,17 +6790,17 @@ mjit::Compiler::jsop_instanceof()
         firstSlow = stubcc.masm.jump();
     }
 
     frame.freeReg(tmp);
 
     /* This is sadly necessary because the error case needs the object. */
     frame.dup();
 
-    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN))
+    if (!jsop_getprop(cx->names().classPrototype, JSVAL_TYPE_UNKNOWN))
         return false;
 
     /* Primitive prototypes are invalid. */
     rhs = frame.peek(-1);
     Jump j = frame.testPrimitive(Assembler::Equal, rhs);
     stubcc.linkExit(j, Uses(3));
 
     /* Allocate registers up front, because of branchiness. */
@@ -7373,17 +7372,17 @@ mjit::Compiler::constructThis()
     do {
         if (!cx->typeInferenceEnabled() ||
             !fun->hasSingletonType() ||
             fun->getType(cx)->unknownProperties())
         {
             break;
         }
 
-        jsid id = NameToId(cx->runtime->atomState.classPrototypeAtom);
+        Rooted<jsid> id(cx, NameToId(cx->names().classPrototype));
         types::HeapTypeSet *protoTypes = fun->getType(cx)->getProperty(cx, id, false);
 
         JSObject *proto = protoTypes->getSingleton(cx);
         if (!proto)
             break;
 
         /*
          * Generate an inline path to create a 'this' object with the given
@@ -7422,17 +7421,17 @@ mjit::Compiler::constructThis()
         stubcc.rejoin(Changes(1));
         return true;
     } while (false);
 
     // Load the callee.
     frame.pushCallee();
 
     // Get callee.prototype.
-    if (!jsop_getprop(cx->runtime->atomState.classPrototypeAtom, JSVAL_TYPE_UNKNOWN, false, /* forPrototype = */ true))
+    if (!jsop_getprop(cx->names().classPrototype, JSVAL_TYPE_UNKNOWN, false, /* forPrototype = */ true))
         return false;
 
     // Reach into the proto Value and grab a register for its data.
     FrameEntry *protoFe = frame.peek(-1);
     RegisterID protoReg = frame.ownRegForData(protoFe);
 
     // Now, get the type. If it's not an object, set protoReg to NULL.
     JS_ASSERT_IF(protoFe->isTypeKnown(), protoFe->isType(JSVAL_TYPE_OBJECT));
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -687,32 +687,32 @@ mjit::Compiler::jsop_typeof()
     FrameEntry *fe = frame.peek(-1);
 
     if (fe->isTypeKnown()) {
         JSRuntime *rt = cx->runtime;
 
         JSAtom *atom = NULL;
         switch (fe->getKnownType()) {
           case JSVAL_TYPE_STRING:
-            atom = rt->atomState.stringAtom;
+            atom = rt->atomState.string;
             break;
           case JSVAL_TYPE_UNDEFINED:
-            atom = rt->atomState.undefinedAtom;
+            atom = rt->atomState.undefined;
             break;
           case JSVAL_TYPE_NULL:
-            atom = rt->atomState.objectAtom;
+            atom = rt->atomState.object;
             break;
           case JSVAL_TYPE_OBJECT:
             atom = NULL;
             break;
           case JSVAL_TYPE_BOOLEAN:
-            atom = rt->atomState.booleanAtom;
+            atom = rt->atomState.boolean;
             break;
           default:
-            atom = rt->atomState.numberAtom;
+            atom = rt->atomState.number;
             break;
         }
 
         if (atom) {
             frame.pop();
             frame.push(StringValue(atom));
             return;
         }
@@ -725,23 +725,23 @@ mjit::Compiler::jsop_typeof()
         if (op == JSOP_STRICTEQ || op == JSOP_EQ || op == JSOP_STRICTNE || op == JSOP_NE) {
             JSAtom *atom = script->getAtom(GET_UINT32_INDEX(PC + JSOP_TYPEOF_LENGTH));
             JSRuntime *rt = cx->runtime;
             JSValueType type = JSVAL_TYPE_UNKNOWN;
             Assembler::Condition cond = (op == JSOP_STRICTEQ || op == JSOP_EQ)
                                         ? Assembler::Equal
                                         : Assembler::NotEqual;
 
-            if (atom == rt->atomState.undefinedAtom) {
+            if (atom == rt->atomState.undefined) {
                 type = JSVAL_TYPE_UNDEFINED;
-            } else if (atom == rt->atomState.stringAtom) {
+            } else if (atom == rt->atomState.string) {
                 type = JSVAL_TYPE_STRING;
-            } else if (atom == rt->atomState.booleanAtom) {
+            } else if (atom == rt->atomState.boolean) {
                 type = JSVAL_TYPE_BOOLEAN;
-            } else if (atom == rt->atomState.numberAtom) {
+            } else if (atom == rt->atomState.number) {
                 type = JSVAL_TYPE_INT32;
 
                 /* JSVAL_TYPE_DOUBLE is 0x0 and JSVAL_TYPE_INT32 is 0x1, use <= or > to match both */
                 cond = (cond == Assembler::Equal) ? Assembler::BelowOrEqual : Assembler::Above;
             }
 
             jsbytecode *afterPC = PC + JSOP_STRING_LENGTH + JSOP_EQ_LENGTH;
 
--- a/js/src/methodjit/LoopState.cpp
+++ b/js/src/methodjit/LoopState.cpp
@@ -844,17 +844,17 @@ LoopState::invariantLength(const CrossSS
 }
 
 FrameEntry *
 LoopState::invariantProperty(const CrossSSAValue &obj, jsid id)
 {
     if (skipAnalysis)
         return NULL;
 
-    if (id == NameToId(cx->runtime->atomState.lengthAtom))
+    if (id == NameToId(cx->names().length))
         return NULL;
 
     uint32_t objSlot;
     int32_t objConstant;
     if (!getEntryValue(obj, &objSlot, &objConstant) || objSlot == UNASSIGNED || objConstant != 0)
         return NULL;
 
     for (unsigned i = 0; i < invariantEntries.length(); i++) {
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -1979,17 +1979,17 @@ DisabledGetPropNoCacheIC(VMFrame &f, ic:
 
 void JS_FASTCALL
 ic::GetProp(VMFrame &f, ic::PICInfo *pic)
 {
     bool cached = pic->cached;
     VoidStubPIC stub = cached ? DisabledGetPropIC : DisabledGetPropNoCacheIC;
 
     RootedPropertyName name(f.cx, pic->name);
-    if (name == f.cx->runtime->atomState.lengthAtom) {
+    if (name == f.cx->names().length) {
         if (IsOptimizedArguments(f.fp(), &f.regs.sp[-1])) {
             f.regs.sp[-1].setInt32(f.regs.fp()->numActualArgs());
             return;
         }
         if (!f.regs.sp[-1].isPrimitive()) {
             JSObject *obj = &f.regs.sp[-1].toObject();
             if (obj->isArray() || obj->isString()) {
                 GetPropCompiler cc(f, obj, *pic, NULL, stub);
@@ -2009,17 +2009,17 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
             }
         }
     }
 
     RootedValue objval(f.cx, f.regs.sp[-1]);
 
     if (f.regs.sp[-1].isString()) {
         GetPropCompiler cc(f, NULL, *pic, name, stub);
-        if (name == f.cx->runtime->atomState.lengthAtom) {
+        if (name == f.cx->names().length) {
             LookupStatus status = cc.generateStringLengthStub();
             if (status == Lookup_Error)
                 THROW();
             JSString *str = f.regs.sp[-1].toString();
             f.regs.sp[-1].setInt32(str->length());
         } else {
             LookupStatus status = cc.generateStringPropertyStub();
             if (status == Lookup_Error)
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1028,17 +1028,17 @@ stubs::GetPropNoCache(VMFrame &f, Proper
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     const Value &lval = f.regs.sp[-1];
 
     // Uncached lookups are only used for .prototype accesses at the start of constructors.
     JS_ASSERT(lval.isObject());
-    JS_ASSERT(name == cx->runtime->atomState.classPrototypeAtom);
+    JS_ASSERT(name == cx->names().classPrototype);
 
     RootedObject obj(cx, &lval.toObject());
     RootedValue rval(cx);
     if (!JSObject::getProperty(cx, obj, obj, name, &rval))
         THROW();
 
     regs.sp[-1] = rval;
 }
@@ -1076,17 +1076,17 @@ InitPropOrMethod(VMFrame &f, PropertyNam
 
     /* Load the object being initialized into lval/obj. */
     RootedObject obj(cx, &regs.sp[-2].toObject());
     JS_ASSERT(obj->isNative());
 
     /* Get the immediate property name into id. */
     RootedId id(cx, NameToId(name));
 
-    if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
+    if (JS_UNLIKELY(name == cx->names().proto)
         ? !baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, false)
         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
                                 JSPROP_ENUMERATE, 0, 0, 0)) {
         THROW();
     }
 }
 
 void JS_FASTCALL
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -117,19 +117,19 @@ ArgumentsObject::createUnexpected(JSCont
 static JSBool
 args_delProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
     ArgumentsObject &argsobj = obj->asArguments();
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
             argsobj.markElementDeleted(arg);
-    } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    } else if (JSID_IS_ATOM(id, cx->names().length)) {
         argsobj.markLengthOverridden();
-    } else if (JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)) {
+    } else if (JSID_IS_ATOM(id, cx->names().callee)) {
         argsobj.asNormalArguments().clearCallee();
     }
     return true;
 }
 
 static JSBool
 ArgGetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
 {
@@ -140,21 +140,21 @@ ArgGetter(JSContext *cx, HandleObject ob
     if (JSID_IS_INT(id)) {
         /*
          * arg can exceed the number of arguments if a script changed the
          * prototype to point to another Arguments object with a bigger argc.
          */
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
             vp.set(argsobj.element(arg));
-    } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    } else if (JSID_IS_ATOM(id, cx->names().length)) {
         if (!argsobj.hasOverriddenLength())
             vp.setInt32(argsobj.initialLength());
     } else {
-        JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
+        JS_ASSERT(JSID_IS_ATOM(id, cx->names().callee));
         if (!argsobj.callee().isMagic(JS_OVERWRITTEN_CALLEE))
             vp.set(argsobj.callee());
     }
     return true;
 }
 
 static JSBool
 ArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
@@ -178,18 +178,17 @@ ArgSetter(JSContext *cx, HandleObject ob
             if (arg < script->function()->nargs) {
                 if (!script->ensureHasTypes(cx))
                     return false;
                 types::TypeScript::SetArgument(cx, script, arg, vp);
             }
             return true;
         }
     } else {
-        JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
-                  JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
+        JS_ASSERT(JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().callee));
     }
 
     /*
      * For simplicity we use delete/define to replace the property with one
      * backed by the default Object getter and setter. Note that we rely on
      * args_delProperty to clear the corresponding reserved slot so the GC can
      * collect its value. Note also that we must define the property instead
      * of setting it in case the user has changed the prototype to an object
@@ -210,21 +209,21 @@ args_resolve(JSContext *cx, HandleObject
 
     unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
     if (JSID_IS_INT(id)) {
         uint32_t arg = uint32_t(JSID_TO_INT(id));
         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
             return true;
 
         attrs |= JSPROP_ENUMERATE;
-    } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    } else if (JSID_IS_ATOM(id, cx->names().length)) {
         if (argsobj->hasOverriddenLength())
             return true;
     } else {
-        if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom))
+        if (!JSID_IS_ATOM(id, cx->names().callee))
             return true;
 
         if (argsobj->callee().isMagic(JS_OVERWRITTEN_CALLEE))
             return true;
     }
 
     RootedValue undef(cx, UndefinedValue());
     if (!baseops::DefineGeneric(cx, argsobj, id, undef, ArgGetter, ArgSetter, attrs))
@@ -242,19 +241,19 @@ args_enumerate(JSContext *cx, HandleObje
 
     /*
      * Trigger reflection in args_resolve using a series of js_LookupProperty
      * calls.
      */
     int argc = int(argsobj->initialLength());
     for (int i = -2; i != argc; i++) {
         id = (i == -2)
-             ? NameToId(cx->runtime->atomState.lengthAtom)
+             ? NameToId(cx->names().length)
              : (i == -1)
-             ? NameToId(cx->runtime->atomState.calleeAtom)
+             ? NameToId(cx->names().callee)
              : INT_TO_JSID(i);
 
         RootedObject pobj(cx);
         RootedShape prop(cx);
         if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
             return false;
     }
     return true;
@@ -272,17 +271,17 @@ StrictArgGetter(JSContext *cx, HandleObj
         /*
          * arg can exceed the number of arguments if a script changed the
          * prototype to point to another Arguments object with a bigger argc.
          */
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
             vp.set(argsobj.element(arg));
     } else {
-        JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
+        JS_ASSERT(JSID_IS_ATOM(id, cx->names().length));
         if (!argsobj.hasOverriddenLength())
             vp.setInt32(argsobj.initialLength());
     }
     return true;
 }
 
 static JSBool
 StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp)
@@ -300,17 +299,17 @@ StrictArgSetter(JSContext *cx, HandleObj
 
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj->initialLength()) {
             argsobj->setElement(arg, vp);
             return true;
         }
     } else {
-        JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
+        JS_ASSERT(JSID_IS_ATOM(id, cx->names().length));
     }
 
     /*
      * For simplicity we use delete/define to replace the property with one
      * backed by the default Object getter and setter. Note that we rely on
      * args_delProperty to clear the corresponding reserved slot so the GC can
      * collect its value.
      */
@@ -332,24 +331,22 @@ strictargs_resolve(JSContext *cx, Handle
     StrictPropertyOp setter = StrictArgSetter;
 
     if (JSID_IS_INT(id)) {
         uint32_t arg = uint32_t(JSID_TO_INT(id));
         if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
             return true;
 
         attrs |= JSPROP_ENUMERATE;
-    } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
+    } else if (JSID_IS_ATOM(id, cx->names().length)) {
         if (argsobj->hasOverriddenLength())
             return true;
     } else {
-        if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom) &&
-            !JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
+        if (!JSID_IS_ATOM(id, cx->names().callee) && !JSID_IS_ATOM(id, cx->names().caller))
             return true;
-        }
 
         attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
         getter = CastAsPropertyOp(argsobj->global().getThrowTypeError());
         setter = CastAsStrictPropertyOp(argsobj->global().getThrowTypeError());
     }
 
     RootedValue undef(cx, UndefinedValue());
     if (!baseops::DefineGeneric(cx, argsobj, id, undef, getter, setter, attrs))
@@ -368,27 +365,27 @@ strictargs_enumerate(JSContext *cx, Hand
      * Trigger reflection in strictargs_resolve using a series of
      * js_LookupProperty calls.
      */
     RootedObject pobj(cx);
     RootedShape prop(cx);
     RootedId id(cx);
 
     // length
-    id = NameToId(cx->runtime->atomState.lengthAtom);
+    id = NameToId(cx->names().length);
     if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
         return false;
 
     // callee
-    id = NameToId(cx->runtime->atomState.calleeAtom);
+    id = NameToId(cx->names().callee);
     if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
         return false;
 
     // caller
-    id = NameToId(cx->runtime->atomState.callerAtom);
+    id = NameToId(cx->names().caller);
     if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
         return false;
 
     for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) {
         id = INT_TO_JSID(i);
         if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop))
             return false;
     }
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1793,17 +1793,17 @@ Debugger::construct(JSContext *cx, unsig
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CCW_REQUIRED, "Debugger");
             return false;
         }
     }
 
     /* Get Debugger.prototype. */
     RootedValue v(cx);
     RootedObject callee(cx, &args.callee());
-    if (!JSObject::getProperty(cx, callee, callee, cx->runtime->atomState.classPrototypeAtom, &v))
+    if (!JSObject::getProperty(cx, callee, callee, cx->names().classPrototype, &v))
         return false;
     RootedObject proto(cx, &v.toObject());
     JS_ASSERT(proto->getClass() == &Debugger::jsclass);
 
     /*
      * Make the new Debugger object. Each one has a reference to
      * Debugger.{Frame,Object,Script}.prototype in reserved slots. The rest of
      * the reserved slots are for hooks; they default to undefined.
@@ -1995,17 +1995,17 @@ class Debugger::ScriptQuery {
      * it specifies.
      */
     bool parseQuery(HandleObject query) {
         /*
          * Check for a 'global' property, which limits the results to those
          * scripts scoped to a particular global object.
          */
         RootedValue global(cx);
-        if (!JSObject::getProperty(cx, query, query, cx->runtime->atomState.globalAtom, &global))
+        if (!JSObject::getProperty(cx, query, query, cx->names().global, &global))
             return false;
         if (global.isUndefined()) {
             matchAllDebuggeeGlobals();
         } else {
             JSObject *referent = debugger->unwrapDebuggeeArgument(cx, global);
             if (!referent)
                 return false;
             GlobalObject *globalObject = &referent->global();
@@ -2016,27 +2016,27 @@ class Debugger::ScriptQuery {
              */
             if (debugger->debuggees.has(globalObject)) {
                 if (!matchSingleGlobal(globalObject))
                     return false;
             }
         }
 
         /* Check for a 'url' property. */
-        if (!JSObject::getProperty(cx, query, query, cx->runtime->atomState.urlAtom, &url))
+        if (!JSObject::getProperty(cx, query, query, cx->names().url, &url))
             return false;
         if (!url.isUndefined() && !url.isString()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                  "query object's 'url' property", "neither undefined nor a string");
             return false;
         }
 
         /* Check for a 'line' property. */
         RootedValue lineProperty(cx);
-        if (!JSObject::getProperty(cx, query, query, cx->runtime->atomState.lineAtom, &lineProperty))
+        if (!JSObject::getProperty(cx, query, query, cx->names().line, &lineProperty))
             return false;
         if (lineProperty.isUndefined()) {
             hasLine = false;
         } else if (lineProperty.isNumber()) {
             if (url.isUndefined()) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_QUERY_LINE_WITHOUT_URL);
                 return false;
             }
@@ -2050,17 +2050,17 @@ class Debugger::ScriptQuery {
         } else {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                                  "query object's 'line' property",
                                  "neither undefined nor an integer");
             return false;
         }
 
         /* Check for an 'innermost' property. */
-        PropertyName *innermostName = cx->runtime->atomState.innermostAtom;
+        PropertyName *innermostName = cx->names().innermost;
         RootedValue innermostProperty(cx);
         if (!JSObject::getProperty(cx, query, query, innermostName, &innermostProperty))
             return false;
         innermost = ToBoolean(innermostProperty);
         if (innermost) {
             /* Technically, we need only check hasLine, but this is clearer. */
             if (url.isUndefined() || !hasLine) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@@ -3060,20 +3060,20 @@ DebuggerFrame_getType(JSContext *cx, uns
 {
     THIS_FRAME(cx, argc, vp, "get type", args, thisobj, fp);
 
     /*
      * Indirect eval frames are both isGlobalFrame() and isEvalFrame(), so the
      * order of checks here is significant.
      */
     args.rval().setString(fp->isEvalFrame()
-                          ? cx->runtime->atomState.evalAtom
+                          ? cx->names().eval
                           : fp->isGlobalFrame()
-                          ? cx->runtime->atomState.globalAtom
-                          : cx->runtime->atomState.callAtom);
+                          ? cx->names().global
+                          : cx->names().call);
     return true;
 }
 
 static JSBool
 DebuggerFrame_getEnvironment(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME_OWNER(cx, argc, vp, "get environment", args, thisobj, fp, dbg);
 
@@ -3229,17 +3229,17 @@ DebuggerFrame_getArguments(JSContext *cx
         argsobj = NewObjectWithGivenProto(cx, &DebuggerArguments_class, proto, global);
         if (!argsobj)
             return false;
         SetReservedSlot(argsobj, JSSLOT_DEBUGARGUMENTS_FRAME, ObjectValue(*thisobj));
 
         JS_ASSERT(fp->numActualArgs() <= 0x7fffffff);
         unsigned fargc = fp->numActualArgs();
         RootedValue fargcVal(cx, Int32Value(fargc));
-        if (!DefineNativeProperty(cx, argsobj, cx->runtime->atomState.lengthAtom,
+        if (!DefineNativeProperty(cx, argsobj, cx->names().length,
                                   fargcVal, NULL, NULL,
                                   JSPROP_PERMANENT | JSPROP_READONLY, 0, 0))
         {
             return false;
         }
 
         Rooted<jsid> id(cx);
         RootedValue undefinedValue(cx, UndefinedValue());
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -70,17 +70,17 @@ ProtoGetterImpl(JSContext *cx, CallArgs 
     JS_ASSERT(TestProtoGetterThis(args.thisv()));
 
     const Value &thisv = args.thisv();
     if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args))
         return false;
 
     unsigned dummy;
     RootedObject obj(cx, &args.thisv().toObject());
-    RootedId nid(cx, NameToId(cx->runtime->atomState.protoAtom));
+    RootedId nid(cx, NameToId(cx->names().proto));
     RootedValue v(cx);
     if (!CheckAccess(cx, obj, nid, JSACC_PROTO, &v, &dummy))
         return false;
 
     args.rval().set(v);
     return true;
 }
 
@@ -149,17 +149,17 @@ ProtoSetterImpl(JSContext *cx, CallArgs 
     if (args.length() == 0 || !args[0].isObjectOrNull()) {
         args.rval().setUndefined();
         return true;
     }
 
     Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull());
 
     unsigned dummy;
-    RootedId nid(cx, NameToId(cx->runtime->atomState.protoAtom));
+    RootedId nid(cx, NameToId(cx->names().proto));
     RootedValue v(cx);
     if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy))
         return false;
 
     if (!SetProto(cx, obj, newProto, true))
         return false;
 
     args.rval().setUndefined();
@@ -343,17 +343,17 @@ GlobalObject::initFunctionAndObjectClass
 
     /* Create the Object function now that we have a [[Prototype]] for it. */
     RootedFunction objectCtor(cx);
     {
         JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
         if (!ctor)
             return NULL;
         objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self,
-                                    cx->runtime->atomState.ObjectAtom);
+                                    cx->names().Object);
         if (!objectCtor)
             return NULL;
     }
 
     /*
      * Install |Object| and |Object.prototype| for the benefit of subsequent
      * code that looks for them.
      */
@@ -362,17 +362,17 @@ GlobalObject::initFunctionAndObjectClass
     /* Create |Function| so it and |Function.prototype| can be installed. */
     RootedFunction functionCtor(cx);
     {
         // Note that ctor is rooted purely for the JS_ASSERT at the end
         RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self));
         if (!ctor)
             return NULL;
         functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
-                                      cx->runtime->atomState.FunctionAtom);
+                                      cx->names().Function);
         if (!functionCtor)
             return NULL;
         JS_ASSERT(ctor == functionCtor);
     }
 
     /*
      * Install |Function| and |Function.prototype| so that we can freely create
      * functions and objects without special effort.
@@ -399,17 +399,17 @@ GlobalObject::initFunctionAndObjectClass
     if (!getter)
         return NULL;
 #if JS_HAS_OBJ_PROTO_PROP
     Rooted<JSFunction*> setter(cx, js_NewFunction(cx, NULL, ProtoSetter, 0, 0, self, NULL));
     if (!setter)
         return NULL;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!JSObject::defineProperty(cx, objectProto,
-                                  cx->runtime->atomState.protoAtom, undefinedValue,
+                                  cx->names().proto, undefinedValue,
                                   JS_DATA_TO_FUNC_PTR(PropertyOp, getter.get()),
                                   JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setter.get()),
                                   JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED))
     {
         return NULL;
     }
 #endif /* JS_HAS_OBJ_PROTO_PROP */
     self->setProtoGetter(getter);
@@ -419,27 +419,27 @@ GlobalObject::initFunctionAndObjectClass
         !LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
         !DefinePropertiesAndBrand(cx, functionProto, NULL, function_methods) ||
         !DefinePropertiesAndBrand(cx, functionCtor, NULL, NULL))
     {
         return NULL;
     }
 
     /* Add the global Function and Object properties now. */
-    jsid objectId = NameToId(cx->runtime->atomState.ObjectAtom);
+    jsid objectId = NameToId(cx->names().Object);
     if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
         return NULL;
-    jsid functionId = NameToId(cx->runtime->atomState.FunctionAtom);
+    jsid functionId = NameToId(cx->names().Function);
     if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
         return NULL;
 
     /* Heavy lifting done, but lingering tasks remain. */
 
     /* ES5 15.1.2.1. */
-    RootedId id(cx, NameToId(cx->runtime->atomState.evalAtom));
+    RootedId id(cx, NameToId(cx->names().eval));
     JSObject *evalobj = js_DefineFunction(cx, self, id, IndirectEval, 1, JSFUN_STUB_GSOPS);
     if (!evalobj)
         return NULL;
     self->setOriginalEval(evalobj);
 
     /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
     RootedFunction throwTypeError(cx, js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL));
     if (!throwTypeError)
@@ -499,21 +499,19 @@ GlobalObject::create(JSContext *cx, Clas
 
     global->initSlot(REGEXP_STATICS, ObjectValue(*res));
     return global;
 }
 
 /* static */ bool
 GlobalObject::initStandardClasses(JSContext *cx, Handle<GlobalObject*> global)
 {
-    JSAtomState &state = cx->runtime->atomState;
-
     /* Define a top-level property 'undefined' with the undefined value. */
     RootedValue undefinedValue(cx, UndefinedValue());
-    if (!JSObject::defineProperty(cx, global, state.undefinedAtom, undefinedValue,
+    if (!JSObject::defineProperty(cx, global, cx->names().undefined, undefinedValue,
                                   JS_PropertyStub, JS_StrictPropertyStub, JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return false;
     }
 
     if (!global->initFunctionAndObjectClasses(cx))
         return false;
 
@@ -596,20 +594,20 @@ GlobalObject::createBlankPrototypeInheri
 bool
 LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor_, JSObject *proto_)
 {
     RootedObject ctor(cx, ctor_), proto(cx, proto_);
 
     RootedValue protoVal(cx, ObjectValue(*proto));
     RootedValue ctorVal(cx, ObjectValue(*ctor));
 
-    return JSObject::defineProperty(cx, ctor, cx->runtime->atomState.classPrototypeAtom,
+    return JSObject::defineProperty(cx, ctor, cx->names().classPrototype,
                                     protoVal, JS_PropertyStub, JS_StrictPropertyStub,
                                     JSPROP_PERMANENT | JSPROP_READONLY) &&
-           JSObject::defineProperty(cx, proto, cx->runtime->atomState.constructorAtom,
+           JSObject::defineProperty(cx, proto, cx->names().constructor,
                                     ctorVal, JS_PropertyStub, JS_StrictPropertyStub, 0);
 }
 
 bool
 DefinePropertiesAndBrand(JSContext *cx, JSObject *obj_,
                          const JSPropertySpec *ps, const JSFunctionSpec *fs)
 {
     RootedObject obj(cx, obj_);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -328,36 +328,36 @@ RegExpObject::assignInitialShape(JSConte
     JS_STATIC_ASSERT(GLOBAL_FLAG_SLOT == SOURCE_SLOT + 1);
     JS_STATIC_ASSERT(IGNORE_CASE_FLAG_SLOT == GLOBAL_FLAG_SLOT + 1);
     JS_STATIC_ASSERT(MULTILINE_FLAG_SLOT == IGNORE_CASE_FLAG_SLOT + 1);
     JS_STATIC_ASSERT(STICKY_FLAG_SLOT == MULTILINE_FLAG_SLOT + 1);
 
     RootedObject self(cx, this);
 
     /* The lastIndex property alone is writable but non-configurable. */
-    if (!addDataProperty(cx, NameToId(cx->runtime->atomState.lastIndexAtom),
+    if (!addDataProperty(cx, NameToId(cx->names().lastIndex),
                          LAST_INDEX_SLOT, JSPROP_PERMANENT))
     {
         return NULL;
     }
 
     /* Remaining instance properties are non-writable and non-configurable. */
-    if (!self->addDataProperty(cx, NameToId(cx->runtime->atomState.sourceAtom),
+    if (!self->addDataProperty(cx, NameToId(cx->names().source),
                                SOURCE_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
-        !self->addDataProperty(cx, NameToId(cx->runtime->atomState.globalAtom),
+        !self->addDataProperty(cx, NameToId(cx->names().global),
                                GLOBAL_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
-        !self->addDataProperty(cx, NameToId(cx->runtime->atomState.ignoreCaseAtom),
+        !self->addDataProperty(cx, NameToId(cx->names().ignoreCase),
                                IGNORE_CASE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
-        !self->addDataProperty(cx, NameToId(cx->runtime->atomState.multilineAtom),
+        !self->addDataProperty(cx, NameToId(cx->names().multiline),
                                MULTILINE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return NULL;
     }
 
-    return self->addDataProperty(cx, NameToId(cx->runtime->atomState.stickyAtom),
+    return self->addDataProperty(cx, NameToId(cx->names().sticky),
                                  STICKY_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 inline bool
 RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
 {
     Rooted<RegExpObject *> self(cx, this);
 
@@ -369,28 +369,27 @@ RegExpObject::init(JSContext *cx, Handle
             Shape *shape = assignInitialShape(cx);
             if (!shape)
                 return false;
             EmptyShape::insertInitialShape(cx, shape, self->getProto());
         }
         JS_ASSERT(!self->nativeEmpty());
     }
 
-    DebugOnly<JSAtomState *> atomState = &cx->runtime->atomState;
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->lastIndexAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().lastIndex))->slot() ==
               LAST_INDEX_SLOT);
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->sourceAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().source))->slot() ==
               SOURCE_SLOT);
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->globalAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().global))->slot() ==
               GLOBAL_FLAG_SLOT);
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->ignoreCaseAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().ignoreCase))->slot() ==
               IGNORE_CASE_FLAG_SLOT);
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->multilineAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().multiline))->slot() ==
               MULTILINE_FLAG_SLOT);
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(atomState->stickyAtom))->slot() ==
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().sticky))->slot() ==
               STICKY_FLAG_SLOT);
 
     /*
      * If this is a re-initialization with an existing RegExpShared, 'flags'
      * may not match getShared()->flags, so forget the RegExpShared.
      */
     self->JSObject::setPrivate(NULL);
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -122,17 +122,17 @@ js::ScopeCoordinateName(JSRuntime *rt, J
     Shape::Range r = ScopeCoordinateToStaticScope(script, pc).scopeShape()->all();
     ScopeCoordinate sc(pc);
     while (r.front().slot() != sc.slot)
         r.popFront();
     jsid id = r.front().propid();
 
     /* Beware nameless destructuring formal. */
     if (!JSID_IS_ATOM(id))
-        return rt->atomState.emptyAtom;
+        return rt->atomState.empty;
     return JSID_TO_ATOM(id)->asPropertyName();
 }
 
 /*****************************************************************************/
 
 /*
  * Construct a bare-bones call object given a shape, type, and slots pointer.
  * The call object must be further initialized to be usable.
@@ -1221,17 +1221,17 @@ class DebugScopeProxy : public BaseProxy
 
         /* The rest of the internal scopes do not have unaliased vars. */
         JS_ASSERT(scope->isDeclEnv() || scope->isWith() || scope->asCall().isForEval());
         return false;
     }
 
     static bool isArguments(JSContext *cx, jsid id)
     {
-        return id == NameToId(cx->runtime->atomState.argumentsAtom);
+        return id == NameToId(cx->names().arguments);
     }
 
     static bool isFunctionScope(ScopeObject &scope)
     {
         return scope.isCall() && !scope.asCall().isForEval();
     }
 
     /*
@@ -1376,20 +1376,19 @@ class DebugScopeProxy : public BaseProxy
         return JS_DefinePropertyById(cx, scope, id, desc->value, desc->getter, desc->setter,
                                      desc->attrs);
     }
 
     bool getScopePropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props, unsigned flags)
     {
         ScopeObject &scope = proxy->asDebugScope().scope();
 
-        if (isMissingArgumentsBinding(scope) &&
-            !props.append(NameToId(cx->runtime->atomState.argumentsAtom)))
-        {
-            return false;
+        if (isMissingArgumentsBinding(scope)) {
+            if (!props.append(NameToId(cx->names().arguments)))
+                return false;
         }
 
         RootedObject rootedScope(cx, &scope);
         if (!GetPropertyNames(cx, rootedScope, flags, &props))
             return false;
 
         /*
          * Function scopes are optimized to not contain unaliased variables so
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -683,17 +683,17 @@ StackSpace::markAndClobberFrame(JSTracer
                 JSValueType type = vp->extractNonDoubleType();
                 if (type == JSVAL_TYPE_INT32)
                     *vp = Int32Value(0);
                 else if (type == JSVAL_TYPE_UNDEFINED)
                     *vp = UndefinedValue();
                 else if (type == JSVAL_TYPE_BOOLEAN)
                     *vp = BooleanValue(false);
                 else if (type == JSVAL_TYPE_STRING)
-                    *vp = StringValue(rt->atomState.nullAtom);
+                    *vp = StringValue(rt->atomState.null);
                 else if (type == JSVAL_TYPE_NULL)
                     *vp = NullValue();
                 else if (type == JSVAL_TYPE_OBJECT)
                     *vp = ObjectValue(fp->scopeChain()->global());
             }
         }
     }
 
--- a/js/src/vm/StringBuffer.cpp
+++ b/js/src/vm/StringBuffer.cpp
@@ -38,17 +38,17 @@ StringBuffer::extractWellSized()
     return buf;
 }
 
 JSFixedString *
 StringBuffer::finishString()
 {
     JSContext *cx = context();
     if (cb.empty())
-        return cx->runtime->atomState.emptyAtom;
+        return cx->names().empty;
 
     size_t length = cb.length();
     if (!JSString::validateLength(cx, length))
         return NULL;
 
     JS_STATIC_ASSERT(JSShortString::MAX_SHORT_LENGTH < CharBuffer::InlineLength);
     if (JSShortString::lengthFits(length))
         return NewShortString(cx, cb.begin(), length);
@@ -68,17 +68,17 @@ StringBuffer::finishString()
 
 JSAtom *
 StringBuffer::finishAtom()
 {
     JSContext *cx = context();
 
     size_t length = cb.length();
     if (length == 0)
-        return cx->runtime->atomState.emptyAtom;
+        return cx->names().empty;
 
     JSAtom *atom = AtomizeChars(cx, cb.begin(), length);
     cb.clear();
     return atom;
 }
 
 bool
 js::ValueToStringBufferSlow(JSContext *cx, const Value &arg, StringBuffer &sb)
@@ -89,12 +89,12 @@ js::ValueToStringBufferSlow(JSContext *c
 
     if (v.isString())
         return sb.append(v.toString());
     if (v.isNumber())
         return NumberValueToStringBuffer(cx, v, sb);
     if (v.isBoolean())
         return BooleanToStringBuffer(cx, v.toBoolean(), sb);
     if (v.isNull())
-        return sb.append(cx->runtime->atomState.nullAtom);
+        return sb.append(cx->names().null);
     JS_ASSERT(v.isUndefined());
-    return sb.append(cx->runtime->atomState.undefinedAtom);
+    return sb.append(cx->names().undefined);
 }
--- a/js/src/vm/StringObject-inl.h
+++ b/js/src/vm/StringObject-inl.h
@@ -33,18 +33,17 @@ StringObject::init(JSContext *cx, Handle
         } else {
             Shape *shape = assignInitialShape(cx);
             if (!shape)
                 return false;
             EmptyShape::insertInitialShape(cx, shape, self->getProto());
         }
     }
 
-    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->runtime->atomState.lengthAtom))->slot()
-              == LENGTH_SLOT);
+    JS_ASSERT(self->nativeLookupNoAllocation(NameToId(cx->names().length))->slot() == LENGTH_SLOT);
 
     self->setStringThis(str);
 
     return true;
 }
 
 inline StringObject *
 StringObject::create(JSContext *cx, HandleString str)