Bug 713183 - Make JSOP_*PROP and JSOP_*NAME store a PropertyName immediate, not a JSAtom immediate, and take advantage of this fact. r=bhackett
authorJeff Walden <jwalden@mit.edu>
Tue, 27 Dec 2011 02:27:02 -0600
changeset 84948 d0e3133d19e21dac315651c7d34c43b90bab1d6b
parent 84947 a45349a7d74a40dca1e6152aaad1a8424f76ac2c
child 84949 e2b6064a04ff508b622b587d0994021f001d36d7
push idunknown
push userunknown
push dateunknown
reviewersbhackett
bugs713183
milestone12.0a1
Bug 713183 - Make JSOP_*PROP and JSOP_*NAME store a PropertyName immediate, not a JSAtom immediate, and take advantage of this fact. r=bhackett
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsopcode.h
js/src/jspropertycache.cpp
js/src/jspropertycache.h
js/src/jspropertycacheinlines.h
js/src/jsscript.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/MethodJIT.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1279,29 +1279,29 @@ inline InterpreterFrames::~InterpreterFr
 static bool
 AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, FrameRegs& regs,
                             JSObject *start, JSObject *found,
                             PropertyCacheEntry *entry)
 {
     uint32_t sample = cx->runtime->gcNumber;
     PropertyCacheEntry savedEntry = *entry;
 
-    JSAtom *atom;
-    GET_ATOM_FROM_BYTECODE(script, regs.pc, 0, atom);
+    PropertyName *name;
+    GET_NAME_FROM_BYTECODE(script, regs.pc, 0, name);
 
     JSObject *obj, *pobj;
     JSProperty *prop;
     JSBool ok;
 
     if (JOF_OPMODE(*regs.pc) == JOF_NAME) {
         bool global = js_CodeSpec[*regs.pc].format & JOF_GNAME;
-        ok = js_FindProperty(cx, ATOM_TO_JSID(atom), global, &obj, &pobj, &prop);
+        ok = FindProperty(cx, name, global, &obj, &pobj, &prop);
     } else {
         obj = start;
-        ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop);
+        ok = LookupProperty(cx, obj, name, &pobj, &prop);
     }
     if (!ok)
         return false;
     if (cx->runtime->gcNumber != sample)
         JS_PROPERTY_CACHE(cx).restore(&savedEntry);
     JS_ASSERT(prop);
     JS_ASSERT(pobj == found);
 
@@ -1492,16 +1492,23 @@ js::Interpret(JSContext *cx, StackFrame 
 
 #define LOAD_ATOM(PCOFF, atom)                                                \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT((size_t)(atoms - script->atoms) <                           \
                   (size_t)(script->natoms - GET_INDEX(regs.pc + PCOFF)));     \
         atom = atoms[GET_INDEX(regs.pc + PCOFF)];                             \
     JS_END_MACRO
 
+#define LOAD_NAME(PCOFF, name)                                                \
+    JS_BEGIN_MACRO                                                            \
+        JSAtom *atom;                                                         \
+        LOAD_ATOM((PCOFF), atom);                                             \
+        name = atom->asPropertyName();                                        \
+    JS_END_MACRO
+
 #define GET_FULL_INDEX(PCOFF)                                                 \
     (atoms - script->atoms + GET_INDEX(regs.pc + (PCOFF)))
 
 #define LOAD_OBJECT(PCOFF, obj)                                               \
     (obj = script->getObject(GET_FULL_INDEX(PCOFF)))
 
 #define LOAD_FUNCTION(PCOFF)                                                  \
     (fun = script->getFunction(GET_FULL_INDEX(PCOFF)))
@@ -1639,17 +1646,16 @@ js::Interpret(JSContext *cx, StackFrame 
          */
         if (cx->isExceptionPending())
             goto error;
     }
 #endif
 
     /* State communicated between non-local jumps: */
     JSBool interpReturnOK;
-    JSAtom *atomNotDefined;
 
     /* Don't call the script prologue if executing between Method and Trace JIT. */
     if (interpMode == JSINTERP_NORMAL) {
         StackFrame *fp = regs.fp();
         JS_ASSERT_IF(!fp->isGeneratorFrame(), regs.pc == script->code);
         if (!ScriptPrologueOrGeneratorResume(cx, fp, UseNewTypeAtEntry(cx, fp)))
             goto error;
         if (cx->compartment->debugMode()) {
@@ -2255,21 +2261,21 @@ END_CASE(JSOP_PICK)
         } else {                                                              \
             if (!js_NativeSet(cx, obj, shape, false, strict, vp))             \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 BEGIN_CASE(JSOP_SETCONST)
 {
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
+    PropertyName *name;
+    LOAD_NAME(0, name);
     JSObject &obj = regs.fp()->varObj();
     const Value &ref = regs.sp[-1];
-    if (!obj.defineProperty(cx, atom->asPropertyName(), ref,
+    if (!obj.defineProperty(cx, name, ref,
                             JS_PropertyStub, JS_StrictPropertyStub,
                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
         goto error;
     }
 }
 END_CASE(JSOP_SETCONST);
 
 #if JS_HAS_DESTRUCTURING
@@ -2315,25 +2321,24 @@ BEGIN_CASE(JSOP_BINDNAME)
          * forms.
          */
         obj = &regs.fp()->scopeChain();
         if (obj->isGlobal())
             break;
 
         PropertyCacheEntry *entry;
         JSObject *obj2;
-        JSAtom *atom;
-        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, atom);
-        if (!atom) {
+        PropertyName *name;
+        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, name);
+        if (!name) {
             ASSERT_VALID_PROPERTY_CACHE_HIT(obj, obj2, entry);
             break;
         }
 
-        jsid id = ATOM_TO_JSID(atom);
-        obj = js_FindIdentifierBase(cx, &regs.fp()->scopeChain(), id);
+        obj = FindIdentifierBase(cx, &regs.fp()->scopeChain(), name);
         if (!obj)
             goto error;
     } while (0);
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_BINDNAME)
 
 #define BITWISE_OP(OP)                                                        \
@@ -2716,47 +2721,45 @@ BEGIN_CASE(JSOP_POS)
     if (!ToNumber(cx, &regs.sp[-1]))
         goto error;
     if (!regs.sp[-1].isInt32())
         TypeScript::MonitorOverflow(cx, script, regs.pc);
 END_CASE(JSOP_POS)
 
 BEGIN_CASE(JSOP_DELNAME)
 {
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
-    jsid id = ATOM_TO_JSID(atom);
+    PropertyName *name;
+    LOAD_NAME(0, name);
     JSObject *obj, *obj2;
     JSProperty *prop;
-    if (!js_FindProperty(cx, id, false, &obj, &obj2, &prop))
+    if (!FindProperty(cx, name, false, &obj, &obj2, &prop))
         goto error;
 
     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
     JS_ASSERT(!script->strictModeCode);
 
     /* ECMA says to return true if name is undefined or inherited. */
     PUSH_BOOLEAN(true);
     if (prop) {
-        if (!obj->deleteProperty(cx, atom->asPropertyName(), &regs.sp[-1], false))
+        if (!obj->deleteProperty(cx, name, &regs.sp[-1], false))
             goto error;
     }
 }
 END_CASE(JSOP_DELNAME)
 
 BEGIN_CASE(JSOP_DELPROP)
 {
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
-    jsid id = ATOM_TO_JSID(atom);
+    PropertyName *name;
+    LOAD_NAME(0, name);
 
     JSObject *obj;
     FETCH_OBJECT(cx, -1, obj);
 
     Value rval;
-    if (!obj->deleteGeneric(cx, id, &rval, script->strictModeCode))
+    if (!obj->deleteProperty(cx, name, &rval, script->strictModeCode))
         goto error;
 
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_DELPROP)
 
 BEGIN_CASE(JSOP_DELELEM)
 {
@@ -2799,18 +2802,17 @@ BEGIN_CASE(JSOP_TOID)
 }
 END_CASE(JSOP_TOID)
 
 BEGIN_CASE(JSOP_TYPEOFEXPR)
 BEGIN_CASE(JSOP_TYPEOF)
 {
     const Value &ref = regs.sp[-1];
     JSType type = JS_TypeOfValue(cx, ref);
-    JSAtom *atom = rt->atomState.typeAtoms[type];
-    regs.sp[-1].setString(atom);
+    regs.sp[-1].setString(rt->atomState.typeAtoms[type]);
 }
 END_CASE(JSOP_TYPEOF)
 
 BEGIN_CASE(JSOP_VOID)
     regs.sp[-1].setUndefined();
 END_CASE(JSOP_VOID)
 
 BEGIN_CASE(JSOP_INCELEM)
@@ -2943,32 +2945,31 @@ BEGIN_CASE(JSOP_LENGTH)
         }
 
         JSObject *obj;
         VALUE_TO_OBJECT(cx, vp, obj);
         JSObject *aobj = js_GetProtoIfDenseArray(obj);
 
         PropertyCacheEntry *entry;
         JSObject *obj2;
-        JSAtom *atom;
-        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
-        if (!atom) {
+        PropertyName *name;
+        JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, name);
+        if (!name) {
             ASSERT_VALID_PROPERTY_CACHE_HIT(aobj, obj2, entry);
             NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval);
             break;
         }
 
-        jsid id = ATOM_TO_JSID(atom);
         if (JS_LIKELY(!aobj->getOps()->getProperty)
-            ? !js_GetPropertyHelper(cx, obj, id,
-                                    (regs.pc[JSOP_GETPROP_LENGTH] == JSOP_IFEQ)
-                                    ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                                    : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
-                                    &rval)
-            : !obj->getGeneric(cx, id, &rval))
+            ? !GetPropertyHelper(cx, obj, name,
+                                 (regs.pc[JSOP_GETPROP_LENGTH] == JSOP_IFEQ)
+                                 ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
+                                 : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
+                                 &rval)
+            : !obj->getProperty(cx, name, &rval))
         {
             goto error;
         }
     } while (0);
 
     TypeScript::Monitor(cx, script, regs.pc, rval);
 
     regs.sp[-1] = rval;
@@ -3002,60 +3003,54 @@ BEGIN_CASE(JSOP_CALLPROP)
         objv.setObject(*pobj);
     }
 
     JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
     Value rval;
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
-    if (!atom) {
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, name);
+    if (!name) {
         ASSERT_VALID_PROPERTY_CACHE_HIT(aobj, obj2, entry);
         NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval);
         regs.sp[-1] = rval;
         assertSameCompartment(cx, regs.sp[-1]);
         PUSH_COPY(lval);
     } else {
-        /*
-         * Cache miss: use the immediate atom that was loaded for us under
-         * PropertyCache::test.
-         */
-        jsid id;
-        id = ATOM_TO_JSID(atom);
-
+        /* Cache miss: use the name loaded for us under PropertyCache::test. */
         PUSH_NULL();
         if (lval.isObject()) {
-            if (!js_GetMethod(cx, &objv.toObject(), id,
-                              JS_LIKELY(!aobj->getOps()->getProperty)
-                              ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                              : JSGET_NO_METHOD_BARRIER,
-                              &rval)) {
+            if (!GetMethod(cx, &objv.toObject(), name,
+                           JS_LIKELY(!aobj->getOps()->getProperty)
+                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
+                           : JSGET_NO_METHOD_BARRIER,
+                           &rval))
+            {
                 goto error;
             }
             regs.sp[-1] = objv;
             regs.sp[-2] = rval;
-            assertSameCompartment(cx, regs.sp[-1], regs.sp[-2]);
         } else {
             JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
-                                      JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
-                                      &rval)) {
+            if (!GetPropertyHelper(cx, &objv.toObject(), name,
+                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER, &rval))
+            {
                 goto error;
             }
             regs.sp[-1] = lval;
             regs.sp[-2] = rval;
-            assertSameCompartment(cx, regs.sp[-1], regs.sp[-2]);
         }
+        assertSameCompartment(cx, regs.sp[-1], regs.sp[-2]);
     }
 #if JS_HAS_NO_SUCH_METHOD
     if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        LOAD_ATOM(0, atom);
-        regs.sp[-2].setString(atom);
+        LOAD_NAME(0, name);
+        regs.sp[-2].setString(name);
         if (!OnUnknownMethod(cx, regs.sp - 2))
             goto error;
     }
 #endif
     TypeScript::Monitor(cx, script, regs.pc, rval);
 }
 END_CASE(JSOP_CALLPROP)
 
@@ -3092,18 +3087,18 @@ BEGIN_CASE(JSOP_SETMETHOD)
          *   o.p = x;
          *
          * in a frequently executed method or loop body, where p will
          * (possibly after the first iteration) always exist in native
          * object o.
          */
         PropertyCacheEntry *entry;
         JSObject *obj2;
-        JSAtom *atom;
-        if (cache->testForSet(cx, regs.pc, obj, &entry, &obj2, &atom)) {
+        PropertyName *name;
+        if (cache->testForSet(cx, regs.pc, obj, &entry, &obj2, &name)) {
             /*
              * Property cache hit, only partially confirmed by testForSet. We
              * know that the entry applies to regs.pc and that obj's shape
              * matches.
              *
              * The entry predicts a set either an existing "own" property, or
              * on a prototype property that has a setter.
              */
@@ -3128,34 +3123,33 @@ BEGIN_CASE(JSOP_SETMETHOD)
 
                 PCMETER(cache->pchits++);
                 PCMETER(cache->setpchits++);
                 NATIVE_SET(cx, obj, shape, entry, script->strictModeCode, &rval);
                 break;
             }
             PCMETER(cache->setpcmisses++);
 
-            LOAD_ATOM(0, atom);
+            LOAD_NAME(0, name);
         } else {
-            JS_ASSERT(atom);
+            JS_ASSERT(name);
         }
 
-        jsid id = ATOM_TO_JSID(atom);
         if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
             uintN defineHow;
             if (op == JSOP_SETMETHOD)
                 defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
             else if (op == JSOP_SETNAME)
                 defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
             else
                 defineHow = DNP_CACHE_RESULT;
-            if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode))
+            if (!SetPropertyHelper(cx, obj, name, defineHow, &rval, script->strictModeCode))
                 goto error;
         } else {
-            if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
+            if (!obj->setProperty(cx, name, &rval, script->strictModeCode))
                 goto error;
         }
     } while (0);
 
     regs.sp[-2] = regs.sp[-1];
     regs.sp--;
 }
 END_CASE(JSOP_SETPROP)
@@ -3453,52 +3447,54 @@ BEGIN_CASE(JSOP_CALLNAME)
     bool global = js_CodeSpec[op].format & JOF_GNAME;
     if (global)
         obj = &obj->global();
 
     Value rval;
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, atom);
-    if (!atom) {
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, name);
+    if (!name) {
         ASSERT_VALID_PROPERTY_CACHE_HIT(obj, obj2, entry);
         NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval);
         PUSH_COPY(rval);
 
         TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 
         JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
         if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
             PUSH_IMPLICIT_THIS(cx, obj, regs.sp[-1]);
         len = JSOP_NAME_LENGTH;
         DO_NEXT_OP(len);
     }
 
-    jsid id = ATOM_TO_JSID(atom);
     JSProperty *prop;
-    if (!js_FindPropertyHelper(cx, id, true, global, &obj, &obj2, &prop))
+    if (!FindPropertyHelper(cx, name, true, global, &obj, &obj2, &prop))
         goto error;
     if (!prop) {
         /* Kludge to allow (typeof foo == "undefined") tests. */
         JSOp op2 = JSOp(regs.pc[JSOP_NAME_LENGTH]);
         if (op2 == JSOP_TYPEOF) {
             PUSH_UNDEFINED();
             TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
             len = JSOP_NAME_LENGTH;
             DO_NEXT_OP(len);
         }
-        atomNotDefined = atom;
-        goto atom_not_defined;
+
+        JSAutoByteString bytes;
+        if (js_AtomToPrintableString(cx, name, &bytes))
+            js_ReportIsNotDefined(cx, bytes.ptr());
+        goto error;
     }
 
     /* Take the slow path if prop was not found in a native object. */
     if (!obj->isNative() || !obj2->isNative()) {
-        if (!obj->getGeneric(cx, id, &rval))
+        if (!obj->getProperty(cx, name, &rval))
             goto error;
     } else {
         Shape *shape = (Shape *)prop;
         JSObject *normalized = obj;
         if (normalized->isWith() && !shape->hasDefaultGetter())
             normalized = &normalized->asWith().object();
         NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval);
     }
@@ -3856,45 +3852,45 @@ BEGIN_CASE(JSOP_DEFVAR)
 
     JSObject *obj = &regs.fp()->varObj();
     JS_ASSERT(!obj->getOps()->defineProperty);
     uintN attrs = JSPROP_ENUMERATE;
     if (!regs.fp()->isEvalFrame())
         attrs |= JSPROP_PERMANENT;
 
     /* Lookup id in order to check for redeclaration problems. */
-    jsid id = ATOM_TO_JSID(name);
     bool shouldDefine;
     if (op == JSOP_DEFVAR) {
         /*
          * Redundant declaration of a |var|, even one for a non-writable
          * property like |undefined| in ES5, does nothing.
          */
         JSProperty *prop;
         JSObject *obj2;
         if (!obj->lookupProperty(cx, name, &obj2, &prop))
             goto error;
         shouldDefine = (!prop || obj2 != obj);
     } else {
         JS_ASSERT(op == JSOP_DEFCONST);
         attrs |= JSPROP_READONLY;
-        if (!CheckRedeclaration(cx, obj, id, attrs))
+        if (!CheckRedeclaration(cx, obj, name, attrs))
             goto error;
 
         /*
          * As attrs includes readonly, CheckRedeclaration can succeed only
          * if prop does not exist.
          */
         shouldDefine = true;
     }
 
     /* Bind a variable only if it's not yet defined. */
     if (shouldDefine &&
-        !DefineNativeProperty(cx, obj, id, UndefinedValue(), JS_PropertyStub, JS_StrictPropertyStub,
-                              attrs, 0, 0)) {
+        !DefineNativeProperty(cx, obj, name, UndefinedValue(),
+                              JS_PropertyStub, JS_StrictPropertyStub, attrs, 0, 0))
+    {
         goto error;
     }
 }
 END_CASE(JSOP_DEFVAR)
 
 BEGIN_CASE(JSOP_DEFFUN)
 {
     /*
@@ -3951,17 +3947,16 @@ BEGIN_CASE(JSOP_DEFFUN)
      * We define the function as a property of the variable object and not the
      * current scope chain even for the case of function expression statements
      * and functions defined by eval inside let or with blocks.
      */
     JSObject *parent = &regs.fp()->varObj();
 
     /* ES5 10.5 (NB: with subsequent errata). */
     PropertyName *name = fun->atom->asPropertyName();
-    jsid id = ATOM_TO_JSID(name);
     JSProperty *prop = NULL;
     JSObject *pobj;
     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         goto error;
 
     Value rval = ObjectValue(*obj);
 
     do {
@@ -3985,19 +3980,19 @@ BEGIN_CASE(JSOP_DEFFUN)
                 {
                     goto error;
                 }
                 break;
             }
 
             if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
                 JSAutoByteString bytes;
-                if (const char *name = js_ValueToPrintable(cx, IdToValue(id), &bytes)) {
+                if (js_AtomToPrintableString(cx, name, &bytes)) {
                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                         JSMSG_CANT_REDEFINE_PROP, name);
+                                         JSMSG_CANT_REDEFINE_PROP, bytes.ptr());
                 }
                 goto error;
             }
         }
 
         /*
          * Non-global properties, and global properties which we aren't simply
          * redefining, must be set.  First, this preserves their attributes.
@@ -4024,21 +4019,20 @@ BEGIN_CASE(JSOP_DEFFUN_FC)
     Value rval = ObjectValue(*obj);
 
     uintN attrs = regs.fp()->isEvalFrame()
                   ? JSPROP_ENUMERATE
                   : JSPROP_ENUMERATE | JSPROP_PERMANENT;
 
     JSObject &parent = regs.fp()->varObj();
 
-    jsid id = ATOM_TO_JSID(fun->atom);
-    if (!CheckRedeclaration(cx, &parent, id, attrs))
+    PropertyName *name = fun->atom->asPropertyName();
+    if (!CheckRedeclaration(cx, &parent, name, attrs))
         goto error;
 
-    PropertyName *name = fun->atom->asPropertyName();
     if ((attrs == JSPROP_ENUMERATE)
         ? !parent.setProperty(cx, name, &rval, script->strictModeCode)
         : !parent.defineProperty(cx, name, rval, JS_PropertyStub, JS_StrictPropertyStub, attrs))
     {
         goto error;
     }
 }
 END_CASE(JSOP_DEFFUN_FC)
@@ -4222,19 +4216,19 @@ BEGIN_CASE(JSOP_SETTER)
       case JSOP_INDEXBASE2:
       case JSOP_INDEXBASE3:
         atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;
         goto do_getter_setter;
 
       case JSOP_SETNAME:
       case JSOP_SETPROP:
       {
-        JSAtom *atom;
-        LOAD_ATOM(0, atom);
-        id = ATOM_TO_JSID(atom);
+        PropertyName *name;
+        LOAD_NAME(0, name);
+        id = ATOM_TO_JSID(name);
         rval = regs.sp[-1];
         i = -1;
         goto gs_pop_lval;
       }
       case JSOP_SETELEM:
         rval = regs.sp[-1];
         id = JSID_VOID;
         i = -2;
@@ -4242,19 +4236,19 @@ BEGIN_CASE(JSOP_SETTER)
         FETCH_OBJECT(cx, i - 1, obj);
         break;
 
       case JSOP_INITPROP:
       {
         JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
         rval = regs.sp[-1];
         i = -1;
-        JSAtom *atom;
-        LOAD_ATOM(0, atom);
-        id = ATOM_TO_JSID(atom);
+        PropertyName *name;
+        LOAD_NAME(0, name);
+        id = ATOM_TO_JSID(name);
         goto gs_get_lval;
       }
       default:
         JS_ASSERT(op2 == JSOP_INITELEM);
 
         JS_ASSERT(regs.sp - regs.fp()->base() >= 3);
         rval = regs.sp[-1];
         id = JSID_VOID;
@@ -4268,21 +4262,18 @@ BEGIN_CASE(JSOP_SETTER)
       }
     }
 
     /* Ensure that id has a type suitable for use with obj. */
     if (JSID_IS_VOID(id))
         FETCH_ELEMENT_ID(obj, i, id);
 
     if (!js_IsCallable(rval)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             JSMSG_BAD_GETTER_OR_SETTER,
-                             (op == JSOP_GETTER)
-                             ? js_getter_str
-                             : js_setter_str);
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_GETTER_OR_SETTER,
+                             (op == JSOP_GETTER) ? js_getter_str : js_setter_str);
         goto error;
     }
 
     /*
      * Getters and setters are just like watchpoints from an access control
      * point of view.
      */
     Value rtmp;
@@ -4407,37 +4398,34 @@ BEGIN_CASE(JSOP_INITMETHOD)
 
     /*
      * Probe the property cache to see if this is a set on an existing property
      * added by a NEWOBJECT or a previous INITPROP. If the cached shape has a
      * non-default setter, it must be __proto__, so don't handle this.
      */
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    if (JS_PROPERTY_CACHE(cx).testForSet(cx, regs.pc, obj, &entry, &obj2, &atom) &&
+    PropertyName *name;
+    if (JS_PROPERTY_CACHE(cx).testForSet(cx, regs.pc, obj, &entry, &obj2, &name) &&
         entry->prop->hasDefaultSetter() &&
         entry->isOwnPropertyHit())
     {
         JS_ASSERT(obj == obj2);
         /* Fast path. Property cache hit. */
         obj->nativeSetSlotWithType(cx, entry->prop, rval);
     } else {
         PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
-        LOAD_ATOM(0, atom);
-
-        /* Get the immediate property name into id. */
-        jsid id = ATOM_TO_JSID(atom);
+        LOAD_NAME(0, name);
 
         uintN defineHow = (op == JSOP_INITMETHOD)
                           ? DNP_CACHE_RESULT | DNP_SET_METHOD
                           : DNP_CACHE_RESULT;
-        if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
-            ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)
-            : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
+        if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
+            ? !SetPropertyHelper(cx, obj, name, defineHow, &rval, script->strictModeCode)
+            : !DefineNativeProperty(cx, obj, name, rval, NULL, NULL,
                                     JSPROP_ENUMERATE, 0, 0, defineHow)) {
             goto error;
         }
     }
 
     /* Common tail for property cache hit and miss cases. */
     regs.sp--;
 }
@@ -5433,17 +5421,9 @@ END_CASE(JSOP_ARRAYPUSH)
      * This path is used when it's guaranteed the method can be finished
      * inside the JIT.
      */
   leave_on_safe_point:
 #endif
 
     gc::VerifyBarriers(cx, true);
     return interpReturnOK;
-
-  atom_not_defined:
-    {
-        JSAutoByteString printable;
-        if (js_AtomToPrintableString(cx, atomNotDefined, &printable))
-            js_ReportIsNotDefined(cx, printable.ptr());
-    }
-    goto error;
 }
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -229,16 +229,22 @@ extern JS_NEVER_INLINE bool
 Interpret(JSContext *cx, StackFrame *stopFp, InterpMode mode = JSINTERP_NORMAL);
 
 extern bool
 RunScript(JSContext *cx, JSScript *script, StackFrame *fp);
 
 extern bool
 CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs);
 
+inline bool
+CheckRedeclaration(JSContext *cx, JSObject *obj, PropertyName *name, uintN attrs)
+{
+    return CheckRedeclaration(cx, obj, ATOM_TO_JSID(name), attrs);
+}
+
 extern bool
 StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *equal);
 
 extern bool
 LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, JSBool *equal);
 
 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
 extern bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5025,34 +5025,31 @@ js_LookupElement(JSContext *cx, JSObject
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
 
     return LookupPropertyWithFlagsInline(cx, obj, id, cx->resolveFlags, objp, propp);
 }
 
-namespace js {
-
 bool
-LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
-                        JSObject **objp, JSProperty **propp)
+js::LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+                            JSObject **objp, JSProperty **propp)
 {
     /* Convert string indices to integers if appropriate. */
     id = js_CheckForStringIndex(id);
 
     return LookupPropertyWithFlagsInline(cx, obj, id, flags, objp, propp);
 }
 
-} /* namespace js */
-
 PropertyCacheEntry *
-js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
-                      JSObject **objp, JSObject **pobjp, JSProperty **propp)
-{
+js::FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, bool global,
+                       JSObject **objp, JSObject **pobjp, JSProperty **propp)
+{
+    jsid id = ATOM_TO_JSID(name);
     JSObject *scopeChain, *obj, *parent, *pobj;
     PropertyCacheEntry *entry;
     int scopeIndex;
     JSProperty *prop;
 
     scopeChain = cx->stack.currentScriptedScopeChain();
 
     if (global) {
@@ -5147,25 +5144,25 @@ js_FindPropertyHelper(JSContext *cx, jsi
     *propp = prop;
     return entry;
 }
 
 /*
  * On return, if |*pobjp| is a native object, then |*propp| is a |Shape *|.
  * Otherwise, its type and meaning depends on the host object's implementation.
  */
-JS_FRIEND_API(JSBool)
-js_FindProperty(JSContext *cx, jsid id, bool global,
-                JSObject **objp, JSObject **pobjp, JSProperty **propp)
-{
-    return !!js_FindPropertyHelper(cx, id, false, global, objp, pobjp, propp);
+bool
+js::FindProperty(JSContext *cx, PropertyName *name, bool global,
+                 JSObject **objp, JSObject **pobjp, JSProperty **propp)
+{
+    return !!FindPropertyHelper(cx, name, false, global, objp, pobjp, propp);
 }
 
 JSObject *
-js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
+js::FindIdentifierBase(JSContext *cx, JSObject *scopeChain, PropertyName *name)
 {
     /*
      * This function should not be called for a global object or from the
      * trace and should have a valid cache entry for native scopeChain.
      */
     JS_ASSERT(scopeChain->enclosingScope() != NULL);
 
     JSObject *obj = scopeChain;
@@ -5179,17 +5176,17 @@ js_FindIdentifierBase(JSContext *cx, JSO
      * The test order here matters because IsCacheableNonGlobalScope
      * must not be passed a global object (i.e. one with null parent).
      */
     for (int scopeIndex = 0;
          obj->isGlobal() || IsCacheableNonGlobalScope(obj);
          scopeIndex++) {
         JSObject *pobj;
         JSProperty *prop;
-        if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop))
+        if (!LookupPropertyWithFlags(cx, obj, name, cx->resolveFlags, &pobj, &prop))
             return NULL;
         if (prop) {
             if (!pobj->isNative()) {
                 JS_ASSERT(obj->isGlobal());
                 return obj;
             }
             JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
             DebugOnly<PropertyCacheEntry*> entry =
@@ -5203,17 +5200,17 @@ js_FindIdentifierBase(JSContext *cx, JSO
             return obj;
         obj = parent;
     }
 
     /* Loop until we find a property or reach the global object. */
     do {
         JSObject *pobj;
         JSProperty *prop;
-        if (!obj->lookupGeneric(cx, id, &pobj, &prop))
+        if (!obj->lookupProperty(cx, name, &pobj, &prop))
             return NULL;
         if (prop)
             break;
 
         /*
          * We conservatively assume that a resolve hook could mutate the scope
          * chain during JSObject::lookupGeneric. So we must check if parent is
          * not null here even if it wasn't before the lookup.
@@ -5414,20 +5411,20 @@ js_GetPropertyHelperInline(JSContext *cx
 
     /* This call site is hot -- use the always-inlined variant of js_NativeGet(). */
     if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp))
         return JS_FALSE;
 
     return JS_TRUE;
 }
 
-JSBool
-js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp)
-{
-    return js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
+bool
+js::GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp)
+{
+    return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
 }
 
 JSBool
 js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
     return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp);
 }
@@ -5464,17 +5461,17 @@ js_GetMethod(JSContext *cx, JSObject *ob
 {
     JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
 
     GenericIdOp op = obj->getOps()->getGeneric;
     if (!op) {
 #if JS_HAS_XML_SUPPORT
         JS_ASSERT(!obj->isXML());
 #endif
-        return js_GetPropertyHelper(cx, obj, id, getHow, vp);
+        return GetPropertyHelper(cx, obj, id, getHow, vp);
     }
     JS_ASSERT_IF(getHow & JSGET_CACHE_RESULT, obj->isDenseArray());
 #if JS_HAS_XML_SUPPORT
     if (obj->isXML())
         return js_GetXMLMethod(cx, obj, id, vp);
 #endif
     return op(cx, obj, obj, id, vp);
 }
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -45,16 +45,17 @@
  * JS object definitions.
  *
  * A JS object consists of a possibly-shared object descriptor containing
  * ordered property names, called the map; and a dense vector of property
  * values, called slots.  The map/slot pointer pair is GC'ed, while the map
  * is reference counted and the slot vector is malloc'ed.
  */
 #include "jsapi.h"
+#include "jsatom.h"
 #include "jsclass.h"
 #include "jsfriendapi.h"
 #include "jsinfer.h"
 #include "jshash.h"
 #include "jspubtd.h"
 #include "jsprvtd.h"
 #include "jslock.h"
 #include "jscell.h"
@@ -241,16 +242,27 @@ typedef Vector<PropDesc, 1> PropDescArra
  * On success, and if id was found, return true with *objp non-null and with a
  * property of *objp stored in *propp. If successful but id was not found,
  * return true with both *objp and *propp null.
  */
 extern JS_FRIEND_API(JSBool)
 js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
                   JSProperty **propp);
 
+namespace js {
+
+inline bool
+LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
+               JSObject **objp, JSProperty **propp)
+{
+    return js_LookupProperty(cx, obj, ATOM_TO_JSID(name), objp, propp);
+}
+
+}
+
 extern JS_FRIEND_API(JSBool)
 js_LookupElement(JSContext *cx, JSObject *obj, uint32_t index,
                  JSObject **objp, JSProperty **propp);
 
 extern JSBool
 js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
                   JSPropertyOp getter, JSStrictPropertyOp setter, uintN attrs);
 
@@ -282,16 +294,27 @@ extern JSBool
 GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def, Value *vp);
 
 } /* namespace js */
 
 extern JSBool
 js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
                      js::Value *vp, JSBool strict);
 
+namespace js {
+
+inline bool
+SetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, uintN defineHow,
+                  Value *vp, JSBool strict)
+{
+    return !!js_SetPropertyHelper(cx, obj, ATOM_TO_JSID(name), defineHow, vp, strict);
+}
+
+} /* namespace js */
+
 extern JSBool
 js_SetElementHelper(JSContext *cx, JSObject *obj, uint32_t index, uintN defineHow,
                     js::Value *vp, JSBool strict);
 
 extern JSBool
 js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
 extern JSBool
@@ -1226,16 +1249,22 @@ struct JSObject : js::gc::Cell
         return addProperty(cx, id, NULL, NULL, slot, attrs, 0, 0);
     }
 
     /* Add or overwrite a property for id in this scope. */
     js::Shape *putProperty(JSContext *cx, jsid id,
                            JSPropertyOp getter, JSStrictPropertyOp setter,
                            uint32_t slot, uintN attrs,
                            uintN flags, intN shortid);
+    inline js::Shape *
+    putProperty(JSContext *cx, js::PropertyName *name,
+                JSPropertyOp getter, JSStrictPropertyOp setter,
+                uint32_t slot, uintN attrs, uintN flags, intN shortid) {
+        return putProperty(cx, js_CheckForStringIndex(ATOM_TO_JSID(name)), getter, setter, slot, attrs, flags, shortid);
+    }
 
     /* Change the given property into a sibling with the same id in this scope. */
     js::Shape *changeProperty(JSContext *cx, js::Shape *shape, uintN attrs, uintN mask,
                               JSPropertyOp getter, JSStrictPropertyOp setter);
 
     /* Remove the property named by id from this object. */
     bool removeProperty(JSContext *cx, jsid id);
 
@@ -1725,27 +1754,42 @@ const uintN DNP_UNQUALIFIED  = 8;   /* U
                                        the defineHow argument of
                                        js_SetPropertyHelper. */
 const uintN DNP_SKIP_TYPE = 0x10;   /* Don't update type information */
 
 /*
  * Return successfully added or changed shape or NULL on error.
  */
 extern const Shape *
-DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value,
+DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
                      PropertyOp getter, StrictPropertyOp setter, uintN attrs,
                      uintN flags, intN shortid, uintN defineHow = 0);
 
+inline const Shape *
+DefineNativeProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value &value,
+                     PropertyOp getter, StrictPropertyOp setter, uintN attrs,
+                     uintN flags, intN shortid, uintN defineHow = 0)
+{
+    return DefineNativeProperty(cx, obj, ATOM_TO_JSID(name), value, getter, setter, attrs, flags,
+                                shortid, defineHow);
+}
+
 /*
  * Specialized subroutine that allows caller to preset JSRESOLVE_* flags.
  */
 extern bool
 LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
                         JSObject **objp, JSProperty **propp);
 
+inline bool
+LookupPropertyWithFlags(JSContext *cx, JSObject *obj, PropertyName *name, uintN flags,
+                        JSObject **objp, JSProperty **propp)
+{
+    return LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(name), flags, objp, propp);
+}
 
 /*
  * Call the [[DefineOwnProperty]] internal method of obj.
  *
  * If obj is an array, this follows ES5 15.4.5.1.
  * If obj is any other native object, this follows ES5 8.12.9.
  * If obj is a proxy, this calls the proxy handler's defineProperty method.
  * Otherwise, this reports an error and returns false.
@@ -1763,35 +1807,35 @@ ReadPropertyDescriptors(JSContext *cx, J
                         AutoIdVector *ids, AutoPropDescArrayRooter *descs);
 
 /*
  * Constant to pass to js_LookupPropertyWithFlags to infer bits from current
  * bytecode.
  */
 static const uintN RESOLVE_INFER = 0xffff;
 
-}
-
 /*
  * If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
  */
-extern js::PropertyCacheEntry *
-js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
-                      JSObject **objp, JSObject **pobjp, JSProperty **propp);
+extern PropertyCacheEntry *
+FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, bool global,
+                   JSObject **objp, JSObject **pobjp, JSProperty **propp);
 
 /*
- * Search for id either on the current scope chain or on the scope chain's
+ * Search for name either on the current scope chain or on the scope chain's
  * global object, per the global parameter.
  */
-extern JS_FRIEND_API(JSBool)
-js_FindProperty(JSContext *cx, jsid id, bool global,
-                JSObject **objp, JSObject **pobjp, JSProperty **propp);
+extern bool
+FindProperty(JSContext *cx, PropertyName *name, bool global,
+             JSObject **objp, JSObject **pobjp, JSProperty **propp);
 
 extern JSObject *
-js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id);
+FindIdentifierBase(JSContext *cx, JSObject *scopeChain, PropertyName *name);
+
+}
 
 extern JSObject *
 js_FindVariableScope(JSContext *cx, JSFunction **funp);
 
 /*
  * JSGET_CACHE_RESULT is the analogue of JSDNP_CACHE_RESULT for js_GetMethod.
  *
  * JSGET_METHOD_BARRIER (the default, hence 0 but provided for documentation)
@@ -1817,35 +1861,51 @@ const uintN JSGET_NO_METHOD_BARRIER = 2;
 extern JSBool
 js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const js::Shape *shape, uintN getHow,
              js::Value *vp);
 
 extern JSBool
 js_NativeSet(JSContext *cx, JSObject *obj, const js::Shape *shape, bool added,
              bool strict, js::Value *vp);
 
-extern JSBool
-js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, js::Value *vp);
+namespace js {
+
+bool
+GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp);
 
-namespace js {
+inline bool
+GetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, uint32_t getHow, Value *vp)
+{
+    return GetPropertyHelper(cx, obj, ATOM_TO_JSID(name), getHow, vp);
+}
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescriptor *desc);
 
 bool
 GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 
 bool
 NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp);
 
 } /* namespace js */
 
 extern JSBool
 js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js::Value *vp);
 
+namespace js {
+
+inline bool
+GetMethod(JSContext *cx, JSObject *obj, PropertyName *name, uintN getHow, Value *vp)
+{
+    return js_GetMethod(cx, obj, ATOM_TO_JSID(name), getHow, vp);
+}
+
+} /* namespace js */
+
 /*
  * Change attributes for the given native property. The caller must ensure
  * that obj is locked and this function always unlocks obj on return.
  */
 extern JSBool
 js_SetNativeAttributes(JSContext *cx, JSObject *obj, js::Shape *shape,
                        uintN attrs);
 
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -336,20 +336,29 @@ js_GetIndexFromBytecode(JSScript *script
 
 /*
  * A slower version of GET_ATOM when the caller does not want to maintain
  * the index segment register itself.
  */
 #define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom)                       \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT(*(pc) != JSOP_DOUBLE);                                      \
+        JS_ASSERT(js_CodeSpec[*(pc)].format & JOF_ATOM);                      \
         uintN index_ = js_GetIndexFromBytecode((script), (pc), (pcoff));      \
         (atom) = (script)->getAtom(index_);                                   \
     JS_END_MACRO
 
+#define GET_NAME_FROM_BYTECODE(script, pc, pcoff, name)                       \
+    JS_BEGIN_MACRO                                                            \
+        JSAtom *atom_;                                                        \
+        GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom_);                     \
+        JS_ASSERT(js_CodeSpec[*(pc)].format & (JOF_NAME | JOF_PROP));         \
+        (name) = atom_->asPropertyName();                                     \
+    JS_END_MACRO
+
 #define GET_DOUBLE_FROM_BYTECODE(script, pc, pcoff, dbl)                      \
     JS_BEGIN_MACRO                                                            \
         uintN index_ = js_GetIndexFromBytecode((script), (pc), (pcoff));      \
         JS_ASSERT(index_ < (script)->consts()->length);                       \
         (dbl) = (script)->getConst(index_).toDouble();                        \
     JS_END_MACRO
 
 #define GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj)                      \
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -153,35 +153,35 @@ PropertyCache::fill(JSContext *cx, JSObj
      * The modfills counter is not exact. It increases if a getter or setter
      * recurse into the interpreter.
      */
     PCMETER(entry == pctestentry || modfills++);
     PCMETER(pctestentry = NULL);
     return entry;
 }
 
-static inline JSAtom *
-GetAtomFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op, const JSCodeSpec &cs)
+static inline PropertyName *
+GetNameFromBytecode(JSContext *cx, jsbytecode *pc, JSOp op, const JSCodeSpec &cs)
 {
     if (op == JSOP_LENGTH)
         return cx->runtime->atomState.lengthAtom;
 
     // The method JIT's implementation of instanceof contains an internal lookup
     // of the prototype property.
     if (op == JSOP_INSTANCEOF)
         return cx->runtime->atomState.classPrototypeAtom;
 
     JSScript *script = cx->stack.currentScript();
     ptrdiff_t pcoff = (JOF_TYPE(cs.format) == JOF_SLOTATOM) ? SLOTNO_LEN : 0;
-    JSAtom *atom;
-    GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom);
-    return atom;
+    PropertyName *name;
+    GET_NAME_FROM_BYTECODE(script, pc, pcoff, name);
+    return name;
 }
 
-JSAtom *
+PropertyName *
 PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject **pobjp,
                         PropertyCacheEntry *entry)
 {
     JSObject *obj, *pobj, *tmp;
 #ifdef DEBUG
     JSScript *script = cx->stack.currentScript();
 #endif
 
@@ -191,40 +191,40 @@ PropertyCache::fullTest(JSContext *cx, j
     JSOp op = JSOp(*pc);
     const JSCodeSpec &cs = js_CodeSpec[op];
 
     obj = *objp;
 
     if (entry->kpc != pc) {
         PCMETER(kpcmisses++);
 
-        JSAtom *atom = GetAtomFromBytecode(cx, pc, op, cs);
+        PropertyName *name = GetNameFromBytecode(cx, pc, op, cs);
 #ifdef DEBUG_notme
         JSAutoByteString printable;
         fprintf(stderr,
                 "id miss for %s from %s:%u"
                 " (pc %u, kpc %u, kshape %p, shape %p)\n",
-                js_AtomToPrintableString(cx, atom, &printable),
+                js_AtomToPrintableString(cx, name, &printable),
                 script->filename,
                 js_PCToLineNumber(cx, script, pc),
                 pc - script->code,
                 entry->kpc - script->code,
                 entry->kshape,
                 obj->lastProperty());
                 js_Disassemble1(cx, script, pc,
                                 pc - script->code,
                                 JS_FALSE, stderr);
 #endif
 
-        return atom;
+        return name;
     }
 
     if (entry->kshape != obj->lastProperty()) {
         PCMETER(kshapemisses++);
-        return GetAtomFromBytecode(cx, pc, op, cs);
+        return GetNameFromBytecode(cx, pc, op, cs);
     }
 
     /*
      * PropertyCache::test handles only the direct and immediate-prototype hit
      * cases. All others go here.
      */
     pobj = obj;
 
@@ -247,28 +247,25 @@ PropertyCache::fullTest(JSContext *cx, j
         if (!tmp || !tmp->isNative())
             break;
         pobj = tmp;
         protoIndex--;
     }
 
     if (pobj->lastProperty() == entry->pshape) {
 #ifdef DEBUG
-        JSAtom *atom = GetAtomFromBytecode(cx, pc, op, cs);
-        jsid id = ATOM_TO_JSID(atom);
-
-        id = js_CheckForStringIndex(id);
-        JS_ASSERT(pobj->nativeContains(cx, id));
+        PropertyName *name = GetNameFromBytecode(cx, pc, op, cs);
+        JS_ASSERT(pobj->nativeContains(cx, js_CheckForStringIndex(ATOM_TO_JSID(name))));
 #endif
         *pobjp = pobj;
         return NULL;
     }
 
     PCMETER(vcapmisses++);
-    return GetAtomFromBytecode(cx, pc, op, cs);
+    return GetNameFromBytecode(cx, pc, op, cs);
 }
 
 #ifdef DEBUG
 void
 PropertyCache::assertEmpty()
 {
     JS_ASSERT(empty);
     for (uintN i = 0; i < SIZE; i++) {
--- a/js/src/jspropertycache.h
+++ b/js/src/jspropertycache.h
@@ -40,16 +40,18 @@
 
 #ifndef jspropertycache_h___
 #define jspropertycache_h___
 
 #include "jsapi.h"
 #include "jsprvtd.h"
 #include "jstypes.h"
 
+#include "vm/String.h"
+
 namespace js {
 
 /*
  * Property cache with structurally typed capabilities for invalidation, for
  * polymorphic callsite method/get/set speedups.  For details, see
  * <https://developer.mozilla.org/en/SpiderMonkey/Internals/Property_cache>.
  */
 class PropertyCache;
@@ -175,40 +177,41 @@ class PropertyCache
     static inline jsuword
     hash(jsbytecode *pc, const Shape *kshape)
     {
         return (((jsuword(pc) >> SIZE_LOG2) ^ jsuword(pc) ^ ((jsuword)kshape >> 3)) & MASK);
     }
 
     static inline bool matchShape(JSContext *cx, JSObject *obj, uint32_t shape);
 
-    JSAtom *fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp,
-                     JSObject **pobjp, PropertyCacheEntry *entry);
+    PropertyName *
+    fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp,
+             JSObject **pobjp, PropertyCacheEntry *entry);
 
 #ifdef DEBUG
     void assertEmpty();
 #else
     inline void assertEmpty() {}
 #endif
 
   public:
     JS_ALWAYS_INLINE void test(JSContext *cx, jsbytecode *pc,
                                JSObject *&obj, JSObject *&pobj,
-                               PropertyCacheEntry *&entry, JSAtom *&atom);
+                               PropertyCacheEntry *&entry, PropertyName *&name);
 
     /*
      * Test for cached information about a property set on *objp at pc.
      *
      * On a hit, set *entryp to the entry and return true.
      *
-     * On a miss, set *atomp to the name of the property being set and return false.
+     * On a miss, set *namep to the name of the property being set and return false.
      */
     JS_ALWAYS_INLINE bool testForSet(JSContext *cx, jsbytecode *pc, JSObject *obj,
                                      PropertyCacheEntry **entryp, JSObject **obj2p,
-                                     JSAtom **atomp);
+                                     PropertyName **namep);
 
     /*
      * Fill property cache entry for key cx->fp->pc, optimized value word
      * computed from obj and shape, and entry capability forged from 24-bit
      * obj->shape(), 4-bit scopeIndex, and 4-bit protoIndex.
      *
      * Return the filled cache entry or JS_NO_PROP_CACHE_FILL if caching was
      * not possible.
--- a/js/src/jspropertycacheinlines.h
+++ b/js/src/jspropertycacheinlines.h
@@ -49,28 +49,28 @@
 using namespace js;
 
 /*
  * This method is designed to inline the fast path in js_Interpret, so it makes
  * "just-so" restrictions on parameters, e.g. pobj and obj should not be the
  * same variable, since for JOF_PROP-mode opcodes, obj must not be changed
  * because of a cache miss.
  *
- * On return, if atom is null then obj points to the scope chain element in
- * which the property was found, pobj is locked, and entry is valid. If atom is
+ * On return, if name is null then obj points to the scope chain element in
+ * which the property was found, pobj is locked, and entry is valid. If name is
  * non-null then no object is locked but entry is still set correctly for use,
- * e.g., by PropertyCache::fill and atom should be used as the id to find.
+ * e.g., by PropertyCache::fill and name should be used as the id to find.
  *
  * We must lock pobj on a hit in order to close races with threads that might
  * be deleting a property from its scope, or otherwise invalidating property
  * caches (on all threads) by re-generating JSObject::shape().
  */
 JS_ALWAYS_INLINE void
 PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
-                    JSObject *&pobj, PropertyCacheEntry *&entry, JSAtom *&atom)
+                    JSObject *&pobj, PropertyCacheEntry *&entry, PropertyName *&name)
 {
     JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
 
     const Shape *kshape = obj->lastProperty();
     entry = &table[hash(pc, kshape)];
     PCMETER(pctestentry = entry);
     PCMETER(tests++);
     JS_ASSERT(&obj != &pobj);
@@ -80,43 +80,43 @@ PropertyCache::test(JSContext *cx, jsbyt
         if (entry->isPrototypePropertyHit() &&
             (tmp = pobj->getProto()) != NULL) {
             pobj = tmp;
         }
 
         if (pobj->lastProperty() == entry->pshape) {
             PCMETER(pchits++);
             PCMETER(entry->isOwnPropertyHit() || protopchits++);
-            atom = NULL;
+            name = NULL;
             return;
         }
     }
-    atom = fullTest(cx, pc, &obj, &pobj, entry);
-    if (atom)
+    name = fullTest(cx, pc, &obj, &pobj, entry);
+    if (name)
         PCMETER(misses++);
 }
 
 JS_ALWAYS_INLINE bool
 PropertyCache::testForSet(JSContext *cx, jsbytecode *pc, JSObject *obj,
-                          PropertyCacheEntry **entryp, JSObject **obj2p, JSAtom **atomp)
+                          PropertyCacheEntry **entryp, JSObject **obj2p, PropertyName **namep)
 {
     JS_ASSERT(this == &JS_PROPERTY_CACHE(cx));
 
     const Shape *kshape = obj->lastProperty();
     PropertyCacheEntry *entry = &table[hash(pc, kshape)];
     *entryp = entry;
     PCMETER(pctestentry = entry);
     PCMETER(tests++);
     PCMETER(settests++);
     if (entry->kpc == pc && entry->kshape == kshape)
         return true;
 
-    JSAtom *atom = fullTest(cx, pc, &obj, obj2p, entry);
-    JS_ASSERT(atom);
+    PropertyName *name = fullTest(cx, pc, &obj, obj2p, entry);
+    JS_ASSERT(name);
 
     PCMETER(misses++);
     PCMETER(setmisses++);
 
-    *atomp = atom;
+    *namep = name;
     return false;
 }
 
 #endif /* jspropertycacheinlines_h___ */
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -723,16 +723,20 @@ struct JSScript : public js::gc::Cell {
         return reinterpret_cast<JSConstArray *>(data + constOffset);
     }
 
     JSAtom *getAtom(size_t index) {
         JS_ASSERT(index < natoms);
         return atoms[index];
     }
 
+    js::PropertyName *getName(size_t index) {
+        return getAtom(index)->asPropertyName();
+    }
+
     JSObject *getObject(size_t index) {
         JSObjectArray *arr = objects();
         JS_ASSERT(index < arr->length);
         return arr->vector[index];
     }
 
     JSVersion getVersion() const {
         return JSVersion(version);
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1961,32 +1961,32 @@ mjit::Compiler::generateMethod()
 
           BEGIN_CASE(JSOP_POS)
             jsop_pos();
           END_CASE(JSOP_POS)
 
           BEGIN_CASE(JSOP_DELNAME)
           {
             uint32_t index = fullAtomIndex(PC);
-            JSAtom *atom = script->getAtom(index);
+            PropertyName *name = script->getName(index);
 
             prepareStubCall(Uses(0));
-            masm.move(ImmPtr(atom), Registers::ArgReg1);
+            masm.move(ImmPtr(name), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::DelName, REJOIN_FALLTHROUGH);
             pushSyncedEntry(0);
           }
           END_CASE(JSOP_DELNAME)
 
           BEGIN_CASE(JSOP_DELPROP)
           {
             uint32_t index = fullAtomIndex(PC);
-            JSAtom *atom = script->getAtom(index);
+            PropertyName *name = script->getName(index);
 
             prepareStubCall(Uses(1));
-            masm.move(ImmPtr(atom), Registers::ArgReg1);
+            masm.move(ImmPtr(name), Registers::ArgReg1);
             INLINE_STUBCALL(STRICT_VARIANT(stubs::DelProp), REJOIN_FALLTHROUGH);
             frame.pop();
             pushSyncedEntry(0);
           }
           END_CASE(JSOP_DELPROP)
 
           BEGIN_CASE(JSOP_DELELEM)
           {
@@ -2004,17 +2004,17 @@ mjit::Compiler::generateMethod()
 
           BEGIN_CASE(JSOP_VOID)
             frame.pop();
             frame.push(UndefinedValue());
           END_CASE(JSOP_VOID)
 
           BEGIN_CASE(JSOP_GETPROP)
           BEGIN_CASE(JSOP_LENGTH)
-            if (!jsop_getprop(script->getAtom(fullAtomIndex(PC)), knownPushedType(0)))
+            if (!jsop_getprop(script->getName(fullAtomIndex(PC)), knownPushedType(0)))
                 return Compile_Error;
           END_CASE(JSOP_GETPROP)
 
           BEGIN_CASE(JSOP_GETELEM)
             if (script->pcCounters)
                 updateElemCounters(PC, frame.peek(-2), frame.peek(-1));
             if (!jsop_getelem(false))
                 return Compile_Error;
@@ -2079,27 +2079,27 @@ mjit::Compiler::generateMethod()
                     return Compile_Error;
                 JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n");
             }
           }
           END_CASE(JSOP_CALL)
 
           BEGIN_CASE(JSOP_NAME)
           {
-            JSAtom *atom = script->getAtom(fullAtomIndex(PC));
-            jsop_name(atom, knownPushedType(0), false);
-            frame.extra(frame.peek(-1)).name = atom;
+            PropertyName *name = script->getName(fullAtomIndex(PC));
+            jsop_name(name, knownPushedType(0), false);
+            frame.extra(frame.peek(-1)).name = name;
           }
           END_CASE(JSOP_NAME)
 
           BEGIN_CASE(JSOP_CALLNAME)
           {
-            JSAtom *atom = script->getAtom(fullAtomIndex(PC));
-            jsop_name(atom, knownPushedType(0), true);
-            frame.extra(frame.peek(-2)).name = atom;
+            PropertyName *name = script->getName(fullAtomIndex(PC));
+            jsop_name(name, knownPushedType(0), true);
+            frame.extra(frame.peek(-2)).name = name;
           }
           END_CASE(JSOP_CALLNAME)
 
           BEGIN_CASE(JSOP_DOUBLE)
           {
             uint32_t index = fullAtomIndex(PC);
             double d = script->getConst(index).toDouble();
             frame.push(Value(DoubleValue(d)));
@@ -2397,34 +2397,34 @@ mjit::Compiler::generateMethod()
             if (script->pcCounters) {
                 FrameEntry *fe = frame.getLocal(GET_SLOTNO(PC));
                 updateArithCounters(PC, fe, arithFirstUseType, JSVAL_TYPE_INT32);
                 arithUpdated = true;
             }
           END_CASE(JSOP_LOCALDEC)
 
           BEGIN_CASE(JSOP_BINDNAME)
-            jsop_bindname(script->getAtom(fullAtomIndex(PC)), true);
+            jsop_bindname(script->getName(fullAtomIndex(PC)), true);
           END_CASE(JSOP_BINDNAME)
 
           BEGIN_CASE(JSOP_SETPROP)
           {
             jsbytecode *next = &PC[JSOP_SETPROP_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            if (!jsop_setprop(script->getAtom(fullAtomIndex(PC)), true, pop))
+            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), true, pop))
                 return Compile_Error;
           }
           END_CASE(JSOP_SETPROP)
 
           BEGIN_CASE(JSOP_SETNAME)
           BEGIN_CASE(JSOP_SETMETHOD)
           {
             jsbytecode *next = &PC[JSOP_SETNAME_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            if (!jsop_setprop(script->getAtom(fullAtomIndex(PC)), true, pop))
+            if (!jsop_setprop(script->getName(fullAtomIndex(PC)), true, pop))
                 return Compile_Error;
           }
           END_CASE(JSOP_SETNAME)
 
           BEGIN_CASE(JSOP_THROW)
             prepareStubCall(Uses(1));
             INLINE_STUBCALL(stubs::Throw, REJOIN_NONE);
             frame.pop();
@@ -2501,31 +2501,31 @@ mjit::Compiler::generateMethod()
             INLINE_STUBCALL(STRICT_VARIANT(stubs::DefFun), REJOIN_FALLTHROUGH);
           }
           END_CASE(JSOP_DEFFUN)
 
           BEGIN_CASE(JSOP_DEFVAR)
           BEGIN_CASE(JSOP_DEFCONST)
           {
             uint32_t index = fullAtomIndex(PC);
-            JSAtom *atom = script->getAtom(index);
+            PropertyName *name = script->getName(index);
 
             prepareStubCall(Uses(0));
-            masm.move(ImmPtr(atom), Registers::ArgReg1);
+            masm.move(ImmPtr(name), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::DefVarOrConst, REJOIN_FALLTHROUGH);
           }
           END_CASE(JSOP_DEFVAR)
 
           BEGIN_CASE(JSOP_SETCONST)
           {
             uint32_t index = fullAtomIndex(PC);
-            JSAtom *atom = script->getAtom(index);
+            PropertyName *name = script->getName(index);
 
             prepareStubCall(Uses(1));
-            masm.move(ImmPtr(atom), Registers::ArgReg1);
+            masm.move(ImmPtr(name), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::SetConst, REJOIN_FALLTHROUGH);
           }
           END_CASE(JSOP_SETCONST)
 
           BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
           {
             uint32_t slot = GET_SLOTNO(PC);
             JSFunction *fun = script->getFunction(fullAtomIndex(&PC[SLOTNO_LEN]));
@@ -2628,27 +2628,27 @@ mjit::Compiler::generateMethod()
             fallthrough = false;
           END_CASE(JSOP_RETRVAL)
 
           BEGIN_CASE(JSOP_GETGNAME)
           BEGIN_CASE(JSOP_CALLGNAME)
           {
             uint32_t index = fullAtomIndex(PC);
             jsop_getgname(index);
-            frame.extra(frame.peek(-1)).name = script->getAtom(index);
+            frame.extra(frame.peek(-1)).name = script->getName(index);
             if (op == JSOP_CALLGNAME)
                 jsop_callgname_epilogue();
           }
           END_CASE(JSOP_GETGNAME)
 
           BEGIN_CASE(JSOP_SETGNAME)
           {
             jsbytecode *next = &PC[JSOP_SETGNAME_LENGTH];
             bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
-            jsop_setgname(script->getAtom(fullAtomIndex(PC)), true, pop);
+            jsop_setgname(script->getName(fullAtomIndex(PC)), true, pop);
           }
           END_CASE(JSOP_SETGNAME)
 
           BEGIN_CASE(JSOP_REGEXP)
             if (!jsop_regexp())
                 return Compile_Error;
           END_CASE(JSOP_REGEXP)
 
@@ -2657,17 +2657,17 @@ mjit::Compiler::generateMethod()
             JSObject *object = script->getObject(fullAtomIndex(PC));
             RegisterID reg = frame.allocReg();
             masm.move(ImmPtr(object), reg);
             frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
           }
           END_CASE(JSOP_OBJECT)
 
           BEGIN_CASE(JSOP_CALLPROP)
-            if (!jsop_callprop(script->getAtom(fullAtomIndex(PC))))
+            if (!jsop_callprop(script->getName(fullAtomIndex(PC))))
                 return Compile_Error;
           END_CASE(JSOP_CALLPROP)
 
           BEGIN_CASE(JSOP_UINT24)
             frame.push(Value(Int32Value((int32_t) GET_UINT24(PC))));
           END_CASE(JSOP_UINT24)
 
           BEGIN_CASE(JSOP_CALLELEM)
@@ -2679,17 +2679,17 @@ mjit::Compiler::generateMethod()
           BEGIN_CASE(JSOP_STOP)
             if (script->pcCounters)
                 updatePCCounters(PC, &codeStart, &countersUpdated);
             emitReturn(NULL);
             goto done;
           END_CASE(JSOP_STOP)
 
           BEGIN_CASE(JSOP_GETXPROP)
-            if (!jsop_xname(script->getAtom(fullAtomIndex(PC))))
+            if (!jsop_xname(script->getName(fullAtomIndex(PC))))
                 return Compile_Error;
           END_CASE(JSOP_GETXPROP)
 
           BEGIN_CASE(JSOP_ENTERBLOCK)
           BEGIN_CASE(JSOP_ENTERLET0)
           BEGIN_CASE(JSOP_ENTERLET1)
             enterBlock(script->getObject(fullAtomIndex(PC)));
           END_CASE(JSOP_ENTERBLOCK);
@@ -4381,57 +4381,57 @@ mjit::Compiler::emitStubCmpOp(BoolStub s
 
     JS_ASSERT(fused == JSOP_IFEQ || fused == JSOP_IFNE);
     Jump j = masm.branchTest32(GetStubCompareCondition(fused), Registers::ReturnReg,
                                Registers::ReturnReg);
     return jumpAndRun(j, target);
 }
 
 void
-mjit::Compiler::jsop_setprop_slow(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_setprop_slow(PropertyName *name, bool usePropCache)
 {
     prepareStubCall(Uses(2));
-    masm.move(ImmPtr(atom), Registers::ArgReg1);
+    masm.move(ImmPtr(name), Registers::ArgReg1);
     if (usePropCache)
         INLINE_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
     else
         INLINE_STUBCALL(STRICT_VARIANT(stubs::SetPropNoCache), REJOIN_FALLTHROUGH);
     JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
     frame.shimmy(1);
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 }
 
 void
-mjit::Compiler::jsop_getprop_slow(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_getprop_slow(PropertyName *name, bool usePropCache)
 {
     /* See ::jsop_getprop */
     RejoinState rejoin = usePropCache ? REJOIN_GETTER : REJOIN_THIS_PROTOTYPE;
 
     prepareStubCall(Uses(1));
     if (usePropCache) {
         INLINE_STUBCALL(stubs::GetProp, rejoin);
         testPushedType(rejoin, -1, /* ool = */ false);
     } else {
-        masm.move(ImmPtr(atom), Registers::ArgReg1);
+        masm.move(ImmPtr(name), Registers::ArgReg1);
         INLINE_STUBCALL(stubs::GetPropNoCache, rejoin);
     }
 
     frame.pop();
     frame.pushSynced(JSVAL_TYPE_UNKNOWN);
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 }
 
 bool
-mjit::Compiler::jsop_callprop_slow(JSAtom *atom)
+mjit::Compiler::jsop_callprop_slow(PropertyName *name)
 {
     prepareStubCall(Uses(1));
-    masm.move(ImmPtr(atom), Registers::ArgReg1);
+    masm.move(ImmPtr(name), Registers::ArgReg1);
     INLINE_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
     testPushedType(REJOIN_FALLTHROUGH, -1, /* ool = */ false);
     frame.pop();
     pushSyncedEntry(0);
     pushSyncedEntry(1);
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
     return true;
@@ -4448,35 +4448,35 @@ mjit::Compiler::passMICAddress(GlobalNam
 #if defined JS_POLYIC
 void
 mjit::Compiler::passICAddress(BaseICInfo *ic)
 {
     ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 
 bool
-mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType,
+mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType,
                              bool doTypeCheck, bool usePropCache)
 {
     FrameEntry *top = frame.peek(-1);
 
     /*
      * 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 (!usePropCache) {
         JS_ASSERT(top->isType(JSVAL_TYPE_OBJECT) &&
-                  atom == cx->runtime->atomState.classPrototypeAtom);
+                  name == cx->runtime->atomState.classPrototypeAtom);
         rejoin = REJOIN_THIS_PROTOTYPE;
     }
 
     /* Handle length accesses on known strings without using a PIC. */
-    if (atom == cx->runtime->atomState.lengthAtom &&
+    if (name == cx->runtime->atomState.lengthAtom &&
         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);
@@ -4487,17 +4487,17 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
             frame.pop();
             frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
         }
         return true;
     }
 
     /* If the incoming type will never PIC, take slow path. */
     if (top->isNotType(JSVAL_TYPE_OBJECT)) {
-        jsop_getprop_slow(atom, usePropCache);
+        jsop_getprop_slow(name, usePropCache);
         return true;
     }
 
     frame.forgetMismatchedObject(top);
 
     if (JSOp(*PC) == JSOP_LENGTH && cx->typeInferenceEnabled() &&
         !hasTypeBarriers(PC) && knownPushedType(0) == JSVAL_TYPE_INT32) {
         /* Check if this is an array we can make a loop invariant entry for. */
@@ -4581,34 +4581,33 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
                 bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE);
             return true;
         }
     }
 
     /* Check if this is a property access we can make a loop invariant entry for. */
     if (loop && loop->generatingInvariants() && !hasTypeBarriers(PC)) {
         CrossSSAValue topv(a->inlineIndex, analysis->poppedValue(PC, 0));
-        FrameEntry *fe = loop->invariantProperty(topv, ATOM_TO_JSID(atom));
-        if (fe) {
+        if (FrameEntry *fe = loop->invariantProperty(topv, ATOM_TO_JSID(name))) {
             if (knownType != JSVAL_TYPE_UNKNOWN && knownType != JSVAL_TYPE_DOUBLE)
                 frame.learnType(fe, knownType, false);
             frame.pop();
             frame.pushCopyOf(fe);
             if (script->pcCounters)
                 bumpPropCounter(PC, OpcodeCounts::PROP_STATIC);
             return true;
         }
     }
 
     /*
      * Check if we are accessing a known type which always has the property
      * in a particular inline slot. Get the property directly in this case,
      * without using an IC.
      */
-    jsid id = ATOM_TO_JSID(atom);
+    jsid id = ATOM_TO_JSID(name);
     types::TypeSet *types = frame.extra(top).types;
     if (types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties() &&
         id == types::MakeTypeId(cx, id)) {
         JS_ASSERT(usePropCache);
         types::TypeObject *object = types->getTypeObject(0);
@@ -4649,17 +4648,17 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
 
     /*
      * These two must be loaded first. The objReg because the string path
      * wants to read it, and the shapeReg because it could cause a spill that
      * the string path wouldn't sink back.
      */
     RegisterID objReg = Registers::ReturnReg;
     RegisterID shapeReg = Registers::ReturnReg;
-    if (atom == cx->runtime->atomState.lengthAtom) {
+    if (name == cx->runtime->atomState.lengthAtom) {
         objReg = frame.copyDataIntoReg(top);
         shapeReg = frame.allocReg();
     }
 
     RESERVE_IC_SPACE(masm);
 
     PICGenInfo pic(ic::PICInfo::GET, JSOp(*PC), usePropCache);
 
@@ -4678,39 +4677,39 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
         pic.typeCheck = stubcc.linkExit(j, Uses(1));
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
         pic.hasTypeCheck = false;
         pic.typeReg = Registers::ReturnReg;
     }
 
-    if (atom != cx->runtime->atomState.lengthAtom) {
+    if (name != cx->runtime->atomState.lengthAtom) {
         objReg = frame.copyDataIntoReg(top);
         shapeReg = frame.allocReg();
     }
 
     /*
      * If this access has been on a shape with a getter hook, make preparations
      * so that we can generate a stub to call the hook directly (rather than be
      * forced to make a stub call). Sync the stack up front and kill all
      * registers so that PIC stubs can contain calls, and always generate a
      * type barrier if inference is enabled (known property types do not
      * reflect properties with getter hooks).
      */
     pic.canCallHook = pic.forcedTypeBarrier =
         usePropCache &&
         JSOp(*PC) == JSOP_GETPROP &&
-        atom != cx->runtime->atomState.lengthAtom &&
+        name != cx->runtime->atomState.lengthAtom &&
         analysis->getCode(PC).accessGetter;
     if (pic.canCallHook)
         frame.syncAndKillEverything();
 
     pic.shapeReg = shapeReg;
-    pic.atom = atom;
+    pic.name = name;
 
     /* Guard on shape. */
     masm.loadShape(objReg, shapeReg);
     pic.shapeGuard = masm.label();
 
     DataLabelPtr inlineShapeLabel;
     Jump j = masm.branchPtrWithPatch(Assembler::NotEqual, shapeReg,
                                      inlineShapeLabel, ImmPtr(NULL));
@@ -4759,17 +4758,17 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
     stubcc.rejoin(Changes(1));
     pics.append(pic);
 
     finishBarrier(barrier, rejoin, 0);
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
+mjit::Compiler::jsop_callprop_generic(PropertyName *name)
 {
     FrameEntry *top = frame.peek(-1);
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 
     /*
      * These two must be loaded first. The objReg because the string path
@@ -4804,17 +4803,17 @@ mjit::Compiler::jsop_callprop_generic(JS
     Jump typeCheckJump = masm.testObject(Assembler::NotEqual, pic.typeReg);
     Label typeCheck = masm.label();
     RETURN_IF_OOM(false);
 
     pic.typeCheck = stubcc.linkExit(typeCheckJump, Uses(1));
     pic.hasTypeCheck = true;
     pic.objReg = objReg;
     pic.shapeReg = shapeReg;
-    pic.atom = atom;
+    pic.name = name;
 
     /*
      * Store the type and object back. Don't bother keeping them in registers,
      * since a sync will be needed for the upcoming call.
      */
     uint32_t thisvSlot = frame.totalDepth();
     Address thisv = Address(JSFrameReg, sizeof(StackFrame) + thisvSlot * sizeof(Value));
 
@@ -4882,36 +4881,36 @@ mjit::Compiler::jsop_callprop_generic(JS
     stubcc.rejoin(Changes(2));
     pics.append(pic);
 
     finishBarrier(barrier, REJOIN_FALLTHROUGH, 1);
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop_str(JSAtom *atom)
+mjit::Compiler::jsop_callprop_str(PropertyName *name)
 {
     if (!globalObj) {
-        jsop_callprop_slow(atom);
+        jsop_callprop_slow(name);
         return true;
     }
 
     /* Bake in String.prototype. This is safe because of compileAndGo. */
     JSObject *obj = globalObj->getOrCreateStringPrototype(cx);
     if (!obj)
         return false;
 
     /* Force into a register because getprop won't expect a constant. */
     RegisterID reg = frame.allocReg();
 
     masm.move(ImmPtr(obj), reg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     /* Get the property. */
-    if (!jsop_getprop(atom, knownPushedType(0)))
+    if (!jsop_getprop(name, knownPushedType(0)))
         return false;
 
     /* Perform a swap. */
     frame.dup2();
     frame.shift(-3);
     frame.shift(-1);
 
     /*
@@ -4930,17 +4929,17 @@ mjit::Compiler::jsop_callprop_str(JSAtom
     frame.pop();
     frame.pushTypedPayload(JSVAL_TYPE_STRING, strReg);
     frame.forgetType(frame.peek(-1));
 
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
+mjit::Compiler::jsop_callprop_obj(PropertyName *name)
 {
     FrameEntry *top = frame.peek(-1);
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 
     PICGenInfo pic(ic::PICInfo::CALL, JSOp(*PC), true);
 
@@ -4951,17 +4950,17 @@ mjit::Compiler::jsop_callprop_obj(JSAtom
 
     pic.pc = PC;
     pic.fastPathStart = masm.label();
     pic.hasTypeCheck = false;
     pic.typeReg = Registers::ReturnReg;
 
     RegisterID shapeReg = frame.allocReg();
     pic.shapeReg = shapeReg;
-    pic.atom = atom;
+    pic.name = name;
 
     RegisterID objReg;
     if (top->isConstant()) {
         objReg = frame.allocReg();
         masm.move(ImmPtr(&top->getValue().toObject()), objReg);
     } else {
         objReg = frame.copyDataIntoReg(top);
     }
@@ -5135,29 +5134,29 @@ mjit::Compiler::testSingletonPropertyTyp
     JSObject *proto;
     if (!js_GetClassPrototype(cx, globalObj, key, &proto, NULL))
         return NULL;
 
     return testSingletonProperty(proto, id);
 }
 
 bool
-mjit::Compiler::jsop_callprop_dispatch(JSAtom *atom)
+mjit::Compiler::jsop_callprop_dispatch(PropertyName *name)
 {
     /*
      * Check for a CALLPROP which is a dynamic dispatch: every value it can
      * push is a singleton, and the pushed value is determined by the type of
      * the object being accessed. Return true if the CALLPROP has been fully
      * processed, false if no code was generated.
      */
     FrameEntry *top = frame.peek(-1);
     if (top->isNotType(JSVAL_TYPE_OBJECT))
         return false;
 
-    jsid id = ATOM_TO_JSID(atom);
+    jsid id = ATOM_TO_JSID(name);
     if (id != types::MakeTypeId(cx, id))
         return false;
 
     types::TypeSet *pushedTypes = pushedTypeSet(0);
     if (pushedTypes->unknownObject() || pushedTypes->baseFlags() != 0)
         return false;
 
     /* Check every pushed value is a singleton. */
@@ -5269,17 +5268,17 @@ mjit::Compiler::jsop_callprop_dispatch(J
             rejoins.append(masm.jump());
         }
     }
 
     for (unsigned i = 0; i < rejoins.length(); i++)
         rejoins[i].linkTo(masm.label(), &masm);
 
     stubcc.leave();
-    stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
+    stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
     OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
     testPushedType(REJOIN_FALLTHROUGH, -1);
 
     frame.dup();
     // THIS THIS
 
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, pushreg);
     // THIS THIS FUN
@@ -5290,30 +5289,30 @@ mjit::Compiler::jsop_callprop_dispatch(J
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE);
 
     stubcc.rejoin(Changes(2));
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop(JSAtom *atom)
+mjit::Compiler::jsop_callprop(PropertyName *name)
 {
     FrameEntry *top = frame.peek(-1);
 
     /* If the CALLPROP will definitely be fetching a particular value, nop it. */
     bool testObject;
     JSObject *singleton = pushedSingleton(0);
     if (singleton && singleton->isFunction() && !hasTypeBarriers(PC) &&
-        testSingletonPropertyTypes(top, ATOM_TO_JSID(atom), &testObject)) {
+        testSingletonPropertyTypes(top, ATOM_TO_JSID(name), &testObject)) {
         if (testObject) {
             Jump notObject = frame.testObject(Assembler::NotEqual, top);
             stubcc.linkExit(notObject, Uses(1));
             stubcc.leave();
-            stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
+            stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
             OOL_STUBCALL(stubs::CallProp, REJOIN_FALLTHROUGH);
             testPushedType(REJOIN_FALLTHROUGH, -1);
         }
 
         // THIS
 
         frame.dup();
         // THIS THIS
@@ -5330,51 +5329,51 @@ mjit::Compiler::jsop_callprop(JSAtom *at
         if (testObject)
             stubcc.rejoin(Changes(2));
 
         return true;
     }
 
     /* Check for a dynamic dispatch. */
     if (cx->typeInferenceEnabled()) {
-        if (jsop_callprop_dispatch(atom))
+        if (jsop_callprop_dispatch(name))
             return true;
     }
 
     /* If the incoming type will never PIC, take slow path. */
     if (top->isTypeKnown() && top->getKnownType() != JSVAL_TYPE_OBJECT) {
         if (top->getKnownType() == JSVAL_TYPE_STRING)
-            return jsop_callprop_str(atom);
-        return jsop_callprop_slow(atom);
+            return jsop_callprop_str(name);
+        return jsop_callprop_slow(name);
     }
 
     if (top->isTypeKnown())
-        return jsop_callprop_obj(atom);
-    return jsop_callprop_generic(atom);
+        return jsop_callprop_obj(name);
+    return jsop_callprop_generic(name);
 }
 
 bool
-mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed)
+mjit::Compiler::jsop_setprop(PropertyName *name, bool usePropCache, bool popGuaranteed)
 {
     FrameEntry *lhs = frame.peek(-2);
     FrameEntry *rhs = frame.peek(-1);
 
     /* If the incoming type will never PIC, take slow path. */
     if (lhs->isTypeKnown() && lhs->getKnownType() != JSVAL_TYPE_OBJECT) {
-        jsop_setprop_slow(atom, usePropCache);
+        jsop_setprop_slow(name, usePropCache);
         return true;
     }
 
     /*
      * If this is a SETNAME to a variable of a non-reentrant outer function,
      * set the variable's slot directly for the active call object.
      */
     if (cx->typeInferenceEnabled() && js_CodeSpec[*PC].format & JOF_NAME) {
         ScriptAnalysis::NameAccess access =
-            analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
+            analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
         if (access.nesting) {
             /* Use a SavedReg so it isn't clobbered by the stub call. */
             RegisterID nameReg = frame.allocReg(Registers::SavedRegs).reg();
             Address address = frame.loadNameAddress(access, nameReg);
 
 #ifdef JSGC_INCREMENTAL_MJ
             /* Write barrier. */
             if (cx->compartment->needsBarrier()) {
@@ -5392,17 +5391,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
             return true;
         }
     }
 
     /*
      * Set the property directly if we are accessing a known object which
      * always has the property in a particular inline slot.
      */
-    jsid id = ATOM_TO_JSID(atom);
+    jsid id = ATOM_TO_JSID(name);
     types::TypeSet *types = frame.extra(lhs).types;
     if (JSOp(*PC) == JSOP_SETPROP && id == types::MakeTypeId(cx, id) &&
         types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties()) {
         JS_ASSERT(usePropCache);
         types::TypeObject *object = types->getTypeObject(0);
@@ -5430,17 +5429,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
                 OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE);
                 stubcc.rejoin(Changes(0));
             }
             frame.unpinReg(reg);
 #endif
             if (!isObject) {
                 stubcc.linkExit(notObject.get(), Uses(2));
                 stubcc.leave();
-                stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
+                stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
                 OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
             }
             frame.storeTo(rhs, Address(reg, JSObject::getFixedSlotOffset(slot)), popGuaranteed);
             frame.shimmy(1);
             if (!isObject)
                 stubcc.rejoin(Changes(1));
             if (script->pcCounters)
                 bumpPropCounter(PC, OpcodeCounts::PROP_DEFINITE);
@@ -5449,28 +5448,28 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
     }
 
     if (script->pcCounters)
         bumpPropCounter(PC, OpcodeCounts::PROP_OTHER);
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
     if (cx->compartment->needsBarrier() && (!types || types->propertyNeedsBarrier(cx, id))) {
-        jsop_setprop_slow(atom, usePropCache);
+        jsop_setprop_slow(name, usePropCache);
         return true;
     }
 #endif
 
     JSOp op = JSOp(*PC);
 
     ic::PICInfo::Kind kind = (op == JSOP_SETMETHOD)
                              ? ic::PICInfo::SETMETHOD
                              : ic::PICInfo::SET;
     PICGenInfo pic(kind, op, usePropCache);
-    pic.atom = atom;
+    pic.name = name;
 
     if (monitored(PC)) {
         pic.typeMonitored = true;
         types::TypeSet *types = frame.extra(rhs).types;
         if (!types) {
             /* Handle FORNAME and other compound opcodes. Yuck. */
             types = types::TypeSet::make(cx, "unknownRHS");
             if (!types)
@@ -5494,17 +5493,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
 
         /* Start the hot path where it's easy to patch it. */
         pic.fastPathStart = masm.label();
         Jump j = masm.testObject(Assembler::NotEqual, reg);
 
         pic.typeCheck = stubcc.linkExit(j, Uses(2));
         stubcc.leave();
 
-        stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
+        stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
         if (usePropCache)
             OOL_STUBCALL(STRICT_VARIANT(stubs::SetName), REJOIN_FALLTHROUGH);
         else
             OOL_STUBCALL(STRICT_VARIANT(stubs::SetPropNoCache), REJOIN_FALLTHROUGH);
         typeCheck = stubcc.masm.jump();
         pic.hasTypeCheck = true;
     } else {
         pic.fastPathStart = masm.label();
@@ -5576,26 +5575,26 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
     labels.setInlineValueStore(masm, pic.fastPathRejoin, inlineValueStore);
     labels.setInlineShapeJump(masm, pic.shapeGuard, afterInlineShapeJump);
 
     pics.append(pic);
     return true;
 }
 
 void
-mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
+mjit::Compiler::jsop_name(PropertyName *name, JSValueType type, bool isCall)
 {
     /*
      * If this is a NAME for a variable of a non-reentrant outer function, get
      * the variable's slot directly for the active call object. We always need
      * to check for undefined, however.
      */
     if (cx->typeInferenceEnabled()) {
         ScriptAnalysis::NameAccess access =
-            analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
+            analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
         if (access.nesting) {
             Address address = frame.loadNameAddress(access);
             JSValueType type = knownPushedType(0);
             BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
                                                            /* testUndefined = */ true);
             finishBarrier(barrier, REJOIN_GETTER, 0);
             if (isCall)
                 jsop_callgname_epilogue();
@@ -5605,17 +5604,17 @@ mjit::Compiler::jsop_name(JSAtom *atom, 
 
     PICGenInfo pic(isCall ? ic::PICInfo::CALLNAME : ic::PICInfo::NAME, JSOp(*PC), true);
 
     RESERVE_IC_SPACE(masm);
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.allocReg();
     pic.typeReg = Registers::ReturnReg;
-    pic.atom = atom;
+    pic.name = name;
     pic.hasTypeCheck = false;
     pic.fastPathStart = masm.label();
 
     RejoinState rejoin = isCall ? REJOIN_FALLTHROUGH : REJOIN_GETTER;
 
     /* There is no inline implementation, so we always jump to the slow path or to a stub. */
     pic.shapeGuard = masm.label();
     Jump inlineJump = masm.jump();
@@ -5656,56 +5655,56 @@ mjit::Compiler::jsop_name(JSAtom *atom, 
     stubcc.rejoin(Changes(isCall ? 2 : 1));
 
     pics.append(pic);
 
     finishBarrier(barrier, rejoin, isCall ? 1 : 0);
 }
 
 bool
-mjit::Compiler::jsop_xname(JSAtom *atom)
+mjit::Compiler::jsop_xname(PropertyName *name)
 {
     /*
      * If this is a GETXPROP for a variable of a non-reentrant outer function,
      * treat in the same way as a NAME.
      */
     if (cx->typeInferenceEnabled()) {
         ScriptAnalysis::NameAccess access =
-            analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
+            analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
         if (access.nesting) {
             frame.pop();
             Address address = frame.loadNameAddress(access);
             JSValueType type = knownPushedType(0);
             BarrierState barrier = pushAddressMaybeBarrier(address, type, true,
                                                            /* testUndefined = */ true);
             finishBarrier(barrier, REJOIN_GETTER, 0);
             return true;
         }
     }
 
     PICGenInfo pic(ic::PICInfo::XNAME, JSOp(*PC), true);
 
     FrameEntry *fe = frame.peek(-1);
     if (fe->isNotType(JSVAL_TYPE_OBJECT)) {
-        return jsop_getprop(atom, knownPushedType(0));
+        return jsop_getprop(name, knownPushedType(0));
     }
 
     if (!fe->isTypeKnown()) {
         Jump notObject = frame.testObject(Assembler::NotEqual, fe);
         stubcc.linkExit(notObject, Uses(1));
     }
 
     frame.forgetMismatchedObject(fe);
 
     RESERVE_IC_SPACE(masm);
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.copyDataIntoReg(fe);
     pic.typeReg = Registers::ReturnReg;
-    pic.atom = atom;
+    pic.name = name;
     pic.hasTypeCheck = false;
     pic.fastPathStart = masm.label();
 
     /* There is no inline implementation, so we always jump to the slow path or to a stub. */
     pic.shapeGuard = masm.label();
     Jump inlineJump = masm.jump();
     {
         RESERVE_OOL_SPACE(stubcc.masm);
@@ -5736,25 +5735,25 @@ mjit::Compiler::jsop_xname(JSAtom *atom)
 
     pics.append(pic);
 
     finishBarrier(barrier, REJOIN_FALLTHROUGH, 0);
     return true;
 }
 
 void
-mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_bindname(PropertyName *name, bool usePropCache)
 {
     /*
      * If this is a BINDNAME for a variable of a non-reentrant outer function,
      * the object is definitely the outer function's active call object.
      */
     if (cx->typeInferenceEnabled()) {
         ScriptAnalysis::NameAccess access =
-            analysis->resolveNameAccess(cx, ATOM_TO_JSID(atom), true);
+            analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
         if (access.nesting) {
             RegisterID reg = frame.allocReg();
             JSObject **pobj = &access.nesting->activeCall;
             masm.move(ImmPtr(pobj), reg);
             masm.loadPtr(Address(reg), reg);
             frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
             return;
         }
@@ -5766,17 +5765,17 @@ mjit::Compiler::jsop_bindname(JSAtom *at
     // set. Rather, it relies on the up-front analysis statically determining
     // whether BINDNAME can be used, which reifies the scope chain at the
     // prologue.
     JS_ASSERT(analysis->usesScopeChain());
 
     pic.shapeReg = frame.allocReg();
     pic.objReg = frame.allocReg();
     pic.typeReg = Registers::ReturnReg;
-    pic.atom = atom;
+    pic.name = name;
     pic.hasTypeCheck = false;
 
     RESERVE_IC_SPACE(masm);
     pic.fastPathStart = masm.label();
 
     masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfScopeChain()), pic.objReg);
     masm.loadPtr(Address(pic.objReg, JSObject::offsetOfShape()), pic.shapeReg);
     masm.loadPtr(Address(pic.shapeReg, Shape::offsetOfBase()), pic.shapeReg);
@@ -5805,70 +5804,70 @@ mjit::Compiler::jsop_bindname(JSAtom *at
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 }
 
 #else /* !JS_POLYIC */
 
 void
-mjit::Compiler::jsop_name(JSAtom *atom, JSValueType type, bool isCall)
+mjit::Compiler::jsop_name(PropertyName *name, JSValueType type, bool isCall)
 {
     prepareStubCall(Uses(0));
     INLINE_STUBCALL(isCall ? stubs::CallName : stubs::Name, REJOIN_FALLTHROUGH);
     testPushedType(REJOIN_FALLTHROUGH, 0, /* ool = */ false);
     frame.pushSynced(type);
     if (isCall)
         frame.pushSynced(JSVAL_TYPE_UNKNOWN);
 }
 
 bool
-mjit::Compiler::jsop_xname(JSAtom *atom)
+mjit::Compiler::jsop_xname(PropertyName *name)
 {
-    return jsop_getprop(atom, knownPushedType(0), pushedTypeSet(0));
+    return jsop_getprop(name, knownPushedType(0), pushedTypeSet(0));
 }
 
 bool
-mjit::Compiler::jsop_getprop(JSAtom *atom, JSValueType knownType, types::TypeSet *typeSet,
+mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType, types::TypeSet *typeSet,
                              bool typecheck, bool usePropCache)
 {
-    jsop_getprop_slow(atom, usePropCache);
+    jsop_getprop_slow(name, usePropCache);
     return true;
 }
 
 bool
-mjit::Compiler::jsop_callprop(JSAtom *atom)
+mjit::Compiler::jsop_callprop(PropertyName *name)
 {
-    return jsop_callprop_slow(atom);
+    return jsop_callprop_slow(name);
 }
 
 bool
-mjit::Compiler::jsop_setprop(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_setprop(PropertyName *name, bool usePropCache)
 {
-    jsop_setprop_slow(atom, usePropCache);
+    jsop_setprop_slow(name, usePropCache);
     return true;
 }
 
 void
-mjit::Compiler::jsop_bindname(JSAtom *atom, bool usePropCache)
+mjit::Compiler::jsop_bindname(PropertyName *name, bool usePropCache)
 {
     RegisterID reg = frame.allocReg();
     Address scopeChain(JSFrameReg, StackFrame::offsetOfScopeChain());
     masm.loadPtr(scopeChain, reg);
 
     Address address(reg, offsetof(JSObject, parent));
 
     Jump j = masm.branchPtr(Assembler::NotEqual, address, ImmPtr(0));
 
     stubcc.linkExit(j, Uses(0));
     stubcc.leave();
     if (usePropCache) {
         OOL_STUBCALL(stubs::BindName, REJOIN_FALLTHROUGH);
     } else {
-        stubcc.masm.move(ImmPtr(atom), Registers::ArgReg1);
+        stubcc.masm.move(ImmPtr(name), Registers::ArgReg1);
         OOL_STUBCALL(stubs::BindNameNoCache, REJOIN_FALLTHROUGH);
     }
 
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     stubcc.rejoin(Changes(1));
 }
 #endif
@@ -6217,51 +6216,51 @@ mjit::Compiler::jsop_bindgname()
     frame.takeReg(Registers::ReturnReg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
 }
 
 void
 mjit::Compiler::jsop_getgname(uint32_t index)
 {
     /* Optimize undefined, NaN and Infinity. */
-    JSAtom *atom = script->getAtom(index);
-    if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID]) {
+    PropertyName *name = script->getName(index);
+    if (name == cx->runtime->atomState.typeAtoms[JSTYPE_VOID]) {
         frame.push(UndefinedValue());
         return;
     }
-    if (atom == cx->runtime->atomState.NaNAtom) {
+    if (name == cx->runtime->atomState.NaNAtom) {
         frame.push(cx->runtime->NaNValue);
         return;
     }
-    if (atom == cx->runtime->atomState.InfinityAtom) {
+    if (name == cx->runtime->atomState.InfinityAtom) {
         frame.push(cx->runtime->positiveInfinityValue);
         return;
     }
 
     /* Optimize singletons like Math for JSOP_CALLPROP. */
     JSObject *obj = pushedSingleton(0);
-    if (obj && !hasTypeBarriers(PC) && testSingletonProperty(globalObj, ATOM_TO_JSID(atom))) {
+    if (obj && !hasTypeBarriers(PC) && testSingletonProperty(globalObj, ATOM_TO_JSID(name))) {
         frame.push(ObjectValue(*obj));
         return;
     }
 
-    jsid id = ATOM_TO_JSID(atom);
+    jsid id = ATOM_TO_JSID(name);
     JSValueType type = knownPushedType(0);
     if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
         !globalObj->getType(cx)->unknownProperties()) {
         types::TypeSet *propertyTypes = globalObj->getType(cx)->getProperty(cx, id, false);
         if (!propertyTypes)
             return;
 
         /*
          * If we are accessing a defined global which is a normal data property
          * then bake its address into the jitcode and guard against future
          * reallocation of the global object's slots.
          */
-        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(atom));
+        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(name));
         if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
             HeapValue *value = &globalObj->getSlotRef(shape->slot());
             if (!value->isUndefined() &&
                 !propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
                 watchGlobalReallocation();
                 RegisterID reg = frame.allocReg();
                 masm.move(ImmPtr(value), reg);
 
@@ -6446,50 +6445,50 @@ mjit::Compiler::jsop_callgname_epilogue(
     if (isNotObj.isSet())
         isNotObj.getJump().linkTo(masm.label(), &masm);
     frame.pushUntypedValue(UndefinedValue());
 
     stubcc.rejoin(Changes(1));
 }
 
 void
-mjit::Compiler::jsop_setgname_slow(JSAtom *atom, bool usePropertyCache)
+mjit::Compiler::jsop_setgname_slow(PropertyName *name, bool usePropertyCache)
 {
     prepareStubCall(Uses(2));
-    masm.move(ImmPtr(atom), Registers::ArgReg1);
+    masm.move(ImmPtr(name), Registers::ArgReg1);
     if (usePropertyCache)
         INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalName), REJOIN_FALLTHROUGH);
     else
         INLINE_STUBCALL(STRICT_VARIANT(stubs::SetGlobalNameNoCache), REJOIN_FALLTHROUGH);
     frame.popn(2);
     pushSyncedEntry(0);
 }
 
 void
-mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache, bool popGuaranteed)
+mjit::Compiler::jsop_setgname(PropertyName *name, bool usePropertyCache, bool popGuaranteed)
 {
     if (monitored(PC)) {
         /* Global accesses are monitored only for a few names like __proto__. */
-        jsop_setgname_slow(atom, usePropertyCache);
+        jsop_setgname_slow(name, usePropertyCache);
         return;
     }
 
-    jsid id = ATOM_TO_JSID(atom);
+    jsid id = ATOM_TO_JSID(name);
     if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
         !globalObj->getType(cx)->unknownProperties()) {
         /*
          * Note: object branding is disabled when inference is enabled. With
          * branding there is no way to ensure that a non-function property
          * can't get a function later and cause the global object to become
          * branded, requiring a shape change if it changes again.
          */
         types::TypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
         if (!types)
             return;
-        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(atom));
+        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(name));
         if (shape && !shape->isMethod() && shape->hasDefaultSetter() &&
             shape->writable() && shape->hasSlot() &&
             !types->isOwnProperty(cx, globalObj->getType(cx), true)) {
             watchGlobalReallocation();
             HeapValue *value = &globalObj->getSlotRef(shape->slot());
             RegisterID reg = frame.allocReg();
 #ifdef JSGC_INCREMENTAL_MJ
             /* Write barrier. */
@@ -6507,17 +6506,17 @@ mjit::Compiler::jsop_setgname(JSAtom *at
             frame.freeReg(reg);
             return;
         }
     }
 
 #ifdef JSGC_INCREMENTAL_MJ
     /* Write barrier. */
     if (cx->compartment->needsBarrier()) {
-        jsop_setgname_slow(atom, usePropertyCache);
+        jsop_setgname_slow(name, usePropertyCache);
         return;
     }
 #endif
 
 #if defined JS_MONOIC
     FrameEntry *objFe = frame.peek(-2);
     FrameEntry *fe = frame.peek(-1);
     JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT);
@@ -6583,17 +6582,17 @@ mjit::Compiler::jsop_setgname(JSAtom *at
     frame.unpinEntry(ic.vr);
     frame.shimmy(1);
 
     stubcc.rejoin(Changes(1));
 
     ic.fastPathRejoin = masm.label();
     setGlobalNames.append(ic);
 #else
-    jsop_setgname_slow(atom, usePropertyCache);
+    jsop_setgname_slow(name, usePropertyCache);
 #endif
 }
 
 void
 mjit::Compiler::jsop_setelem_slow()
 {
     prepareStubCall(Uses(3));
     INLINE_STUBCALL(STRICT_VARIANT(stubs::SetElem), REJOIN_FALLTHROUGH);
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -243,17 +243,17 @@ class Compiler : public BaseCompiler
         ic::PICInfo::Kind kind;
         Label typeCheck;
         RegisterID shapeReg;
         RegisterID objReg;
         RegisterID typeReg;
         bool usePropCache;
         Label shapeGuard;
         jsbytecode *pc;
-        JSAtom *atom;
+        PropertyName *name;
         bool hasTypeCheck;
         bool typeMonitored;
         types::TypeSet *rhsTypes;
         ValueRemat vr;
         union {
             ic::GetPropLabels getPropLabels_;
             ic::SetPropLabels setPropLabels_;
             ic::BindNameLabels bindNameLabels_;
@@ -277,17 +277,17 @@ class Compiler : public BaseCompiler
                       kind == ic::PICInfo::XNAME);
             return scopeNameLabels_;
         }
 
         void copySimpleMembersTo(ic::PICInfo &ic) {
             ic.kind = kind;
             ic.shapeReg = shapeReg;
             ic.objReg = objReg;
-            ic.atom = atom;
+            ic.name = name;
             ic.usePropCache = usePropCache;
             if (ic.isSet()) {
                 ic.u.vr = vr;
             } else if (ic.isGet()) {
                 ic.u.get.typeReg = typeReg;
                 ic.u.get.hasTypeCheck = hasTypeCheck;
             }
             ic.typeMonitored = typeMonitored;
@@ -593,19 +593,19 @@ private:
      * or jump to the slow path per uses.
      */
     void tryConvertInteger(FrameEntry *fe, Uses uses);
 
     /* Opcode handlers. */
     bool jumpAndRun(Jump j, jsbytecode *target, Jump *slow = NULL, bool *trampoline = NULL);
     bool startLoop(jsbytecode *head, Jump entry, jsbytecode *entryTarget);
     bool finishLoop(jsbytecode *head);
-    void jsop_bindname(JSAtom *atom, bool usePropCache);
+    void jsop_bindname(PropertyName *name, bool usePropCache);
     void jsop_setglobal(uint32_t index);
-    void jsop_getprop_slow(JSAtom *atom, bool usePropCache = true);
+    void jsop_getprop_slow(PropertyName *name, bool usePropCache = true);
     void jsop_getarg(uint32_t slot);
     void jsop_setarg(uint32_t slot, bool popped);
     void jsop_this();
     void emitReturn(FrameEntry *fe);
     void emitFinalReturn(Assembler &masm);
     void loadReturnValue(Assembler *masm, FrameEntry *fe);
     void emitReturnValue(Assembler *masm, FrameEntry *fe);
     void emitInlineReturnValue(FrameEntry *fe);
@@ -618,35 +618,35 @@ private:
                                    MaybeRegisterID origCalleeType, RegisterID origCalleeData,
                                    MaybeRegisterID origThisType, RegisterID origThisData,
                                    Jump *uncachedCallSlowRejoin, CallPatchInfo *uncachedCallPatch);
     bool inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &callFrameSize);
     void fixPrimitiveReturn(Assembler *masm, FrameEntry *fe);
     void jsop_getgname(uint32_t index);
     void jsop_getgname_slow(uint32_t index);
     void jsop_callgname_epilogue();
-    void jsop_setgname(JSAtom *atom, bool usePropertyCache, bool popGuaranteed);
-    void jsop_setgname_slow(JSAtom *atom, bool usePropertyCache);
+    void jsop_setgname(PropertyName *name, bool usePropertyCache, bool popGuaranteed);
+    void jsop_setgname_slow(PropertyName *name, bool usePropertyCache);
     void jsop_bindgname();
     void jsop_setelem_slow();
     void jsop_getelem_slow();
     void jsop_callelem_slow();
-    bool jsop_getprop(JSAtom *atom, JSValueType type,
+    bool jsop_getprop(PropertyName *name, JSValueType type,
                       bool typeCheck = true, bool usePropCache = true);
-    bool jsop_setprop(JSAtom *atom, bool usePropCache, bool popGuaranteed);
-    void jsop_setprop_slow(JSAtom *atom, bool usePropCache = true);
-    bool jsop_callprop_slow(JSAtom *atom);
-    bool jsop_callprop(JSAtom *atom);
-    bool jsop_callprop_obj(JSAtom *atom);
-    bool jsop_callprop_str(JSAtom *atom);
-    bool jsop_callprop_generic(JSAtom *atom);
-    bool jsop_callprop_dispatch(JSAtom *atom);
+    bool jsop_setprop(PropertyName *name, bool usePropCache, bool popGuaranteed);
+    void jsop_setprop_slow(PropertyName *name, bool usePropCache = true);
+    bool jsop_callprop_slow(PropertyName *name);
+    bool jsop_callprop(PropertyName *name);
+    bool jsop_callprop_obj(PropertyName *name);
+    bool jsop_callprop_str(PropertyName *name);
+    bool jsop_callprop_generic(PropertyName *name);
+    bool jsop_callprop_dispatch(PropertyName *name);
     bool jsop_instanceof();
-    void jsop_name(JSAtom *atom, JSValueType type, bool isCall);
-    bool jsop_xname(JSAtom *atom);
+    void jsop_name(PropertyName *name, JSValueType type, bool isCall);
+    bool jsop_xname(PropertyName *name);
     void enterBlock(JSObject *obj);
     void leaveBlock();
     void emitEval(uint32_t argc);
     void jsop_arguments(RejoinState rejoin);
     bool jsop_tableswitch(jsbytecode *pc);
 
     /* Fast arithmetic. */
     bool jsop_binary(JSOp op, VoidStub stub, JSValueType type, types::TypeSet *typeSet);
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -545,17 +545,17 @@ typedef JSBool (JS_FASTCALL *BoolStub)(V
 typedef void * (JS_FASTCALL *VoidPtrStub)(VMFrame &);
 typedef void * (JS_FASTCALL *VoidPtrStubPC)(VMFrame &, jsbytecode *);
 typedef void * (JS_FASTCALL *VoidPtrStubUInt32)(VMFrame &, uint32_t);
 typedef JSObject * (JS_FASTCALL *JSObjStub)(VMFrame &);
 typedef JSObject * (JS_FASTCALL *JSObjStubUInt32)(VMFrame &, uint32_t);
 typedef JSObject * (JS_FASTCALL *JSObjStubFun)(VMFrame &, JSFunction *);
 typedef void (JS_FASTCALL *VoidStubFun)(VMFrame &, JSFunction *);
 typedef JSObject * (JS_FASTCALL *JSObjStubJSObj)(VMFrame &, JSObject *);
-typedef void (JS_FASTCALL *VoidStubAtom)(VMFrame &, JSAtom *);
+typedef void (JS_FASTCALL *VoidStubName)(VMFrame &, PropertyName *);
 typedef JSString * (JS_FASTCALL *JSStrStub)(VMFrame &);
 typedef JSString * (JS_FASTCALL *JSStrStubUInt32)(VMFrame &, uint32_t);
 typedef void (JS_FASTCALL *VoidStubJSObj)(VMFrame &, JSObject *);
 typedef void (JS_FASTCALL *VoidStubPC)(VMFrame &, jsbytecode *);
 typedef JSBool (JS_FASTCALL *BoolStubUInt32)(VMFrame &f, uint32_t);
 #ifdef JS_MONOIC
 typedef void (JS_FASTCALL *VoidStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
 typedef void * (JS_FASTCALL *VoidPtrStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -82,22 +82,21 @@ PatchGetFallback(VMFrame &f, ic::GetGlob
     JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stubs::GetGlobalName));
     repatch.relink(ic->slowPathCall, fptr);
 }
 
 void JS_FASTCALL
 ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
 {
     JSObject &obj = f.fp()->scopeChain().global();
-    JSAtom *atom = f.script()->getAtom(GET_INDEX(f.pc()));
-    jsid id = ATOM_TO_JSID(atom);
+    PropertyName *name = f.script()->getName(GET_INDEX(f.pc()));
 
     RecompilationMonitor monitor(f.cx);
 
-    const Shape *shape = obj.nativeLookup(f.cx, id);
+    const Shape *shape = obj.nativeLookup(f.cx, js_CheckForStringIndex(ATOM_TO_JSID(name)));
 
     if (monitor.recompiled()) {
         stubs::GetGlobalName(f);
         return;
     }
 
     if (!shape ||
         !shape->hasDefaultGetterOrIsMethod() ||
@@ -122,31 +121,27 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlo
     /* Do load anyway... this time. */
     stubs::GetGlobalName(f);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetGlobal(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
-    JSScript *script = f.script();
-    JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
-    stubs::SetGlobalName<strict>(f, atom);
+    stubs::SetGlobalName<strict>(f, f.script()->getName(GET_INDEX(f.pc())));
 }
 
 template void JS_FASTCALL DisabledSetGlobal<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
 template void JS_FASTCALL DisabledSetGlobal<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetGlobalNoCache(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
-    JSScript *script = f.script();
-    JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
-    stubs::SetGlobalNameNoCache<strict>(f, atom);
+    stubs::SetGlobalNameNoCache<strict>(f, f.script()->getName(GET_INDEX(f.pc())));
 }
 
 template void JS_FASTCALL DisabledSetGlobalNoCache<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
 template void JS_FASTCALL DisabledSetGlobalNoCache<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
 
 static void
 PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
@@ -205,32 +200,32 @@ UpdateSetGlobalName(VMFrame &f, ic::SetG
     return Lookup_Cacheable;
 }
 
 void JS_FASTCALL
 ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
     JSObject &obj = f.fp()->scopeChain().global();
     JSScript *script = f.script();
-    JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
+    PropertyName *name = script->getName(GET_INDEX(f.pc()));
 
     RecompilationMonitor monitor(f.cx);
 
-    const Shape *shape = obj.nativeLookup(f.cx, ATOM_TO_JSID(atom));
+    const Shape *shape = obj.nativeLookup(f.cx, ATOM_TO_JSID(name));
 
     if (!monitor.recompiled()) {
         LookupStatus status = UpdateSetGlobalName(f, ic, &obj, shape);
         if (status == Lookup_Error)
             THROW();
     }
 
     if (ic->usePropertyCache)
-        STRICT_VARIANT(stubs::SetGlobalName)(f, atom);
+        STRICT_VARIANT(stubs::SetGlobalName)(f, name);
     else
-        STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, atom);
+        STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, name);
 }
 
 class EqualityICLinker : public LinkerHelper
 {
     VMFrame &f;
 
   public:
     EqualityICLinker(Assembler &masm, VMFrame &f)
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -195,24 +195,24 @@ GeneratePrototypeGuards(JSContext *cx, V
     }
 
     return true;
 }
 
 class SetPropCompiler : public PICStubCompiler
 {
     JSObject *obj;
-    JSAtom *atom;
+    PropertyName *name;
     int lastStubSecondShapeGuard;
 
   public:
-    SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
+    SetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, PropertyName *name,
                     VoidStubPIC stub)
       : PICStubCompiler("setprop", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)),
-        obj(obj), atom(atom), lastStubSecondShapeGuard(pic.secondShapeGuard)
+        obj(obj), name(name), lastStubSecondShapeGuard(pic.secondShapeGuard)
     { }
 
     static void reset(Repatcher &repatcher, ic::PICInfo &pic)
     {
         SetPropLabels &labels = pic.setPropLabels();
         repatcher.repatchLEAToLoadPtr(labels.getDslotsLoad(pic.fastPathRejoin, pic.u.vr));
         repatcher.repatch(labels.getInlineShapeData(pic.fastPathStart, pic.shapeGuard),
                           NULL);
@@ -485,17 +485,17 @@ class SetPropCompiler : public PICStubCo
         return Lookup_Cacheable;
     }
 
     bool updateMonitoredTypes()
     {
         JS_ASSERT(pic.typeMonitored);
 
         RecompilationMonitor monitor(cx);
-        jsid id = ATOM_TO_JSID(atom);
+        jsid id = ATOM_TO_JSID(name);
 
         if (!obj->getType(cx)->unknownProperties()) {
             types::AutoEnterTypeInference enter(cx);
             types::TypeSet *types = obj->getType(cx)->getProperty(cx, types::MakeTypeId(cx, id), true);
             if (!types)
                 return false;
             pic.rhsTypes->addSubset(cx, types);
         }
@@ -518,24 +518,22 @@ class SetPropCompiler : public PICStubCo
 
         if (clasp->setProperty != JS_StrictPropertyStub)
             return disable("set property hook");
         if (clasp->ops.lookupProperty)
             return disable("ops lookup property hook");
         if (clasp->ops.setProperty)
             return disable("ops set property hook");
 
-        jsid id = ATOM_TO_JSID(atom);
-
         JSObject *holder;
         JSProperty *prop = NULL;
 
         /* lookupProperty can trigger recompilations. */
         RecompilationMonitor monitor(cx);
-        if (!obj->lookupGeneric(cx, id, &holder, &prop))
+        if (!obj->lookupProperty(cx, name, &holder, &prop))
             return error();
         if (monitor.recompiled())
             return Lookup_Uncacheable;
 
         /* If the property exists but is on a prototype, treat as addprop. */
         if (prop && holder != obj) {
             const Shape *shape = (const Shape *) prop;
 
@@ -561,20 +559,16 @@ class SetPropCompiler : public PICStubCo
             if (!obj->isExtensible())
                 return disable("not extensible");
 
             if (clasp->addProperty != JS_PropertyStub)
                 return disable("add property hook");
             if (clasp->ops.defineProperty)
                 return disable("ops define property hook");
 
-            uint32_t index;
-            if (js_IdIsIndex(id, &index))
-                return disable("index");
-
             /*
              * When adding a property we need to check shapes along the entire
              * prototype chain to watch for an added setter.
              */
             JSObject *proto = obj;
             while (proto) {
                 if (!proto->isNative())
                     return disable("non-native proto");
@@ -598,19 +592,18 @@ class SetPropCompiler : public PICStubCo
                 flags |= Shape::METHOD;
             }
 
             /*
              * Define the property but do not set it yet. For setmethod,
              * populate the slot to satisfy the method invariant (in case we
              * hit an early return below).
              */
-            id = js_CheckForStringIndex(id);
             const Shape *shape =
-                obj->putProperty(cx, id, getter, clasp->setProperty,
+                obj->putProperty(cx, name, getter, clasp->setProperty,
                                  SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0);
             if (!shape)
                 return error();
             if (flags & Shape::METHOD)
                 obj->nativeSetSlot(shape->slot(), f.regs.sp[-1]);
 
             if (monitor.recompiled())
                 return Lookup_Uncacheable;
@@ -724,43 +717,43 @@ IsCacheableProtoChain(JSObject *obj, JSO
         if (!proto || !proto->isNative())
             return false;
         obj = proto;
     }
     return true;
 }
 
 template <typename IC>
-struct GetPropertyHelper {
+struct GetPropHelper {
     // These fields are set in the constructor and describe a property lookup.
     JSContext   *cx;
     JSObject    *obj;
-    JSAtom      *atom;
+    PropertyName *name;
     IC          &ic;
     VMFrame     &f;
 
     // These fields are set by |bind| and |lookup|. After a call to either
     // function, these are set exactly as they are in JSOP_GETPROP or JSOP_NAME.
     JSObject    *aobj;
     JSObject    *holder;
     JSProperty  *prop;
 
     // This field is set by |bind| and |lookup| only if they returned
     // Lookup_Cacheable, otherwise it is NULL.
     const Shape *shape;
 
-    GetPropertyHelper(JSContext *cx, JSObject *obj, JSAtom *atom, IC &ic, VMFrame &f)
-      : cx(cx), obj(obj), atom(atom), ic(ic), f(f), holder(NULL), prop(NULL), shape(NULL)
+    GetPropHelper(JSContext *cx, JSObject *obj, PropertyName *name, IC &ic, VMFrame &f)
+      : cx(cx), obj(obj), name(name), ic(ic), f(f), holder(NULL), prop(NULL), shape(NULL)
     { }
 
   public:
     LookupStatus bind() {
         RecompilationMonitor monitor(cx);
         bool global = (js_CodeSpec[*f.pc()].format & JOF_GNAME);
-        if (!js_FindProperty(cx, ATOM_TO_JSID(atom), global, &obj, &holder, &prop))
+        if (!FindProperty(cx, name, global, &obj, &holder, &prop))
             return ic.error(cx);
         if (monitor.recompiled())
             return Lookup_Uncacheable;
         if (!prop)
             return ic.disable(cx, "lookup failed");
         if (!obj->isNative())
             return ic.disable(cx, "non-native");
         if (!IsCacheableProtoChain(obj, holder))
@@ -770,17 +763,17 @@ struct GetPropertyHelper {
     }
 
     LookupStatus lookup() {
         JSObject *aobj = js_GetProtoIfDenseArray(obj);
         if (!aobj->isNative())
             return ic.disable(cx, "non-native");
 
         RecompilationMonitor monitor(cx);
-        if (!aobj->lookupGeneric(cx, ATOM_TO_JSID(atom), &holder, &prop))
+        if (!aobj->lookupProperty(cx, name, &holder, &prop))
             return ic.error(cx);
         if (monitor.recompiled())
             return Lookup_Uncacheable;
 
         if (!prop)
             return ic.disable(cx, "lookup failed");
         if (!IsCacheableProtoChain(obj, holder))
             return ic.disable(cx, "non-native holder");
@@ -825,26 +818,26 @@ struct GetPropertyHelper {
             return status;
         return testForGet();
     }
 };
 
 class GetPropCompiler : public PICStubCompiler
 {
     JSObject    *obj;
-    JSAtom      *atom;
+    PropertyName *name;
     int         lastStubSecondShapeGuard;
 
   public:
-    GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
-                    VoidStubPIC stub)
+    GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic,
+                    PropertyName *name, VoidStubPIC stub)
       : PICStubCompiler(pic.kind == ic::PICInfo::CALL ? "callprop" : "getprop", f, script, pic,
                         JS_FUNC_TO_DATA_PTR(void *, stub)),
         obj(obj),
-        atom(atom),
+        name(name),
         lastStubSecondShapeGuard(pic.secondShapeGuard)
     { }
 
     int getLastStubSecondShapeGuard() const {
         return lastStubSecondShapeGuard ? POST_INST_OFFSET(lastStubSecondShapeGuard) : 0;
     }
 
     static void reset(Repatcher &repatcher, ic::PICInfo &pic)
@@ -998,17 +991,17 @@ class GetPropCompiler : public PICStubCo
     LookupStatus generateStringCallStub()
     {
         JS_ASSERT(pic.hasTypeCheck());
         JS_ASSERT(pic.kind == ic::PICInfo::CALL);
 
         if (!f.fp()->script()->hasGlobal())
             return disable("String.prototype without compile-and-go global");
 
-        GetPropertyHelper<GetPropCompiler> getprop(cx, obj, atom, *this, f);
+        GetPropHelper<GetPropCompiler> getprop(cx, obj, name, *this, f);
         LookupStatus status = getprop.lookupAndTest();
         if (status != Lookup_Cacheable)
             return status;
         if (getprop.obj != getprop.holder)
             return disable("proto walk on String.prototype");
         if (!getprop.shape->hasDefaultGetterOrIsMethod())
             return disable("getter hook on String.prototype");
         if (hadGC())
@@ -1374,17 +1367,17 @@ class GetPropCompiler : public PICStubCo
         if (secondGuardOffset)
             repatcher.relink(label.jumpAtOffset(secondGuardOffset), cs);
     }
 
     LookupStatus update()
     {
         JS_ASSERT(pic.hit);
 
-        GetPropertyHelper<GetPropCompiler> getprop(cx, obj, atom, *this, f);
+        GetPropHelper<GetPropCompiler> getprop(cx, obj, name, *this, f);
         LookupStatus status = getprop.lookupAndTest();
         if (status != Lookup_Cacheable)
             return status;
         if (hadGC())
             return Lookup_Uncacheable;
 
         if (obj == getprop.holder &&
             getprop.shape->hasDefaultGetterOrIsMethod() &&
@@ -1397,18 +1390,18 @@ class GetPropCompiler : public PICStubCo
 };
 
 class ScopeNameCompiler : public PICStubCompiler
 {
   private:
     typedef Vector<Jump, 8> JumpList;
 
     JSObject *scopeChain;
-    JSAtom *atom;
-    GetPropertyHelper<ScopeNameCompiler> getprop;
+    PropertyName *name;
+    GetPropHelper<ScopeNameCompiler> getprop;
     ScopeNameCompiler *thisFromCtor() { return this; }
 
     void patchPreviousToHere(CodeLocationLabel cs)
     {
         ScopeNameLabels &       labels = pic.scopeNameLabels();
         Repatcher               repatcher(pic.lastCodeBlock(f.jit()));
         CodeLocationLabel       start = pic.lastPathStart();
         JSC::CodeLocationJump   jump;
@@ -1452,20 +1445,20 @@ class ScopeNameCompiler : public PICStub
         if (tobj != getprop.holder)
             return disable("scope chain walk terminated early");
 
         return Lookup_Cacheable;
     }
 
   public:
     ScopeNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic,
-                      JSAtom *atom, VoidStubPIC stub)
+                      PropertyName *name, VoidStubPIC stub)
       : PICStubCompiler("name", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)),
-        scopeChain(scopeChain), atom(atom),
-        getprop(f.cx, NULL, atom, *thisFromCtor(), f)
+        scopeChain(scopeChain), name(name),
+        getprop(f.cx, NULL, name, *thisFromCtor(), f)
     { }
 
     static void reset(Repatcher &repatcher, ic::PICInfo &pic)
     {
         ScopeNameLabels &labels = pic.scopeNameLabels();
 
         /* Link the inline path back to the slow path. */
         JSC::CodeLocationJump inlineJump = labels.getInlineJump(pic.fastPathStart);
@@ -1741,24 +1734,24 @@ class ScopeNameCompiler : public PICStub
             /* Kludge to allow (typeof foo == "undefined") tests. */
             if (kind == ic::PICInfo::NAME) {
                 JSOp op2 = JSOp(f.pc()[JSOP_NAME_LENGTH]);
                 if (op2 == JSOP_TYPEOF) {
                     vp->setUndefined();
                     return true;
                 }
             }
-            ReportAtomNotDefined(cx, atom);
+            ReportAtomNotDefined(cx, name);
             return false;
         }
 
         // If the property was found, but we decided not to cache it, then
         // take a slow path and do a full property fetch.
         if (!getprop.shape) {
-            if (!obj->getGeneric(cx, ATOM_TO_JSID(atom), vp))
+            if (!obj->getProperty(cx, name, vp))
                 return false;
             if (thisvp)
                 return ComputeImplicitThis(cx, obj, *vp, thisvp);
             return true;
         }
 
         const Shape *shape = getprop.shape;
         JSObject *normalized = obj;
@@ -1769,23 +1762,23 @@ class ScopeNameCompiler : public PICStub
             return ComputeImplicitThis(cx, normalized, *vp, thisvp);
         return true;
     }
 };
 
 class BindNameCompiler : public PICStubCompiler
 {
     JSObject *scopeChain;
-    JSAtom *atom;
+    PropertyName *name;
 
   public:
     BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic,
-                      JSAtom *atom, VoidStubPIC stub)
+                     PropertyName *name, VoidStubPIC stub)
       : PICStubCompiler("bind", f, script, pic, JS_FUNC_TO_DATA_PTR(void *, stub)),
-        scopeChain(scopeChain), atom(atom)
+        scopeChain(scopeChain), name(name)
     { }
 
     static void reset(Repatcher &repatcher, ic::PICInfo &pic)
     {
         BindNameLabels &labels = pic.bindNameLabels();
 
         /* Link the inline jump back to the slow path. */
         JSC::CodeLocationJump inlineJump = labels.getInlineJump(pic.getFastShapeGuard());
@@ -1876,17 +1869,17 @@ class BindNameCompiler : public PICStubC
 
         return Lookup_Cacheable;
     }
 
     JSObject *update()
     {
         RecompilationMonitor monitor(cx);
 
-        JSObject *obj = js_FindIdentifierBase(cx, scopeChain, ATOM_TO_JSID(atom));
+        JSObject *obj = FindIdentifierBase(cx, scopeChain, name);
         if (!obj || monitor.recompiled())
             return obj;
 
         if (!pic.hit) {
             spew("first hit", "nop");
             pic.hit = true;
             return obj;
         }
@@ -1903,26 +1896,26 @@ static void JS_FASTCALL
 DisabledGetPropIC(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::GetProp(f);
 }
 
 static void JS_FASTCALL
 DisabledGetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::GetPropNoCache(f, pic->atom);
+    stubs::GetPropNoCache(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::GetProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    JSAtom *atom = pic->atom;
-    if (atom == f.cx->runtime->atomState.lengthAtom) {
+    PropertyName *name = pic->name;
+    if (name == f.cx->runtime->atomState.lengthAtom) {
         if (f.regs.sp[-1].isString()) {
             GetPropCompiler cc(f, script, NULL, *pic, NULL, DisabledGetPropIC);
             LookupStatus status = cc.generateStringLengthStub();
             if (status == Lookup_Error)
                 THROW();
             JSString *str = f.regs.sp[-1].toString();
             f.regs.sp[-1].setInt32(str->length());
             return;
@@ -1950,17 +1943,17 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
                     if (status == Lookup_Error)
                         THROW();
                     JSString *str = obj->getPrimitiveThis().toString();
                     f.regs.sp[-1].setInt32(str->length());
                 }
                 return;
             }
         }
-        atom = f.cx->runtime->atomState.lengthAtom;
+        name = f.cx->runtime->atomState.lengthAtom;
     }
 
     /*
      * ValueToObject can trigger recompilations if it lazily initializes any
      * of the primitive classes (Boolean, Number, String). :XXX: if these
      * classes are made eager then this monitoring is not necessary.
      */
     RecompilationMonitor monitor(f.cx);
@@ -1968,23 +1961,23 @@ ic::GetProp(VMFrame &f, ic::PICInfo *pic
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-1]);
     if (!obj)
         THROW();
 
     if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
         VoidStubPIC stub = pic->usePropCache
                            ? DisabledGetPropIC
                            : DisabledGetPropICNoCache;
-        GetPropCompiler cc(f, script, obj, *pic, atom, stub);
+        GetPropCompiler cc(f, script, obj, *pic, name, stub);
         if (!cc.update())
             THROW();
     }
 
     Value v;
-    if (!obj->getGeneric(f.cx, ATOM_TO_JSID(atom), &v))
+    if (!obj->getProperty(f.cx, name, &v))
         THROW();
 
     f.regs.sp[-1] = v;
 }
 
 void JS_FASTCALL
 ic::GetPropNoCache(VMFrame &f, ic::PICInfo *pic)
 {
@@ -1995,80 +1988,80 @@ ic::GetPropNoCache(VMFrame &f, ic::PICIn
      */
     GetProp(f, pic);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetPropIC(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::SetName<strict>(f, pic->atom);
+    stubs::SetName<strict>(f, pic->name);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
 DisabledSetPropICNoCache(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::SetPropNoCache<strict>(f, pic->atom);
+    stubs::SetPropNoCache<strict>(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::SetProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
     JS_ASSERT(pic->isSet());
 
     VoidStubPIC stub = pic->usePropCache
                        ? STRICT_VARIANT(DisabledSetPropIC)
                        : STRICT_VARIANT(DisabledSetPropICNoCache);
 
     // Save this in case the compiler triggers a recompilation of this script.
-    JSAtom *atom = pic->atom;
-    VoidStubAtom nstub = pic->usePropCache
+    PropertyName *name = pic->name;
+    VoidStubName nstub = pic->usePropCache
                          ? STRICT_VARIANT(stubs::SetName)
                          : STRICT_VARIANT(stubs::SetPropNoCache);
 
     RecompilationMonitor monitor(f.cx);
 
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
     if (!obj)
         THROW();
 
     // Note, we can't use SetName for PROPINC PICs because the property
     // cache can't handle a GET and SET from the same scripted PC.
     if (!monitor.recompiled() && pic->shouldUpdate(f.cx)) {
-        SetPropCompiler cc(f, script, obj, *pic, atom, stub);
+        SetPropCompiler cc(f, script, obj, *pic, name, stub);
         LookupStatus status = cc.update();
         if (status == Lookup_Error)
             THROW();
     }
 
-    nstub(f, atom);
+    nstub(f, name);
 }
 
 static void JS_FASTCALL
 DisabledCallPropIC(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::CallProp(f, pic->atom);
+    stubs::CallProp(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::CallProp(VMFrame &f, ic::PICInfo *pic)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     JSScript *script = f.fp()->script();
     RecompilationMonitor monitor(cx);
 
     Value lval;
     lval = regs.sp[-1];
 
     // Do this first in case js_GetClassPrototype triggers a recompilation.
-    jsid id = ATOM_TO_JSID(pic->atom);
+    PropertyName *name = pic->name;
 
     Value objv;
     if (lval.isObject()) {
         objv = lval;
     } else {
         GlobalObject &global = f.fp()->scopeChain().global();
         JSObject *pobj;
         if (lval.isString()) {
@@ -2087,70 +2080,69 @@ ic::CallProp(VMFrame &f, ic::PICInfo *pi
         objv.setObject(*pobj);
     }
 
     JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
     Value rval;
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, atom);
-    if (!atom) {
+    PropertyName *name_;
+    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name_);
+    if (!name_) {
         NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval,
                    THROW());
         /*
          * Adjust the stack to reflect the height after the GETPROP, here and
          * below. Getter hook ICs depend on this to know which value of sp they
          * are updating for consistent rejoins, don't modify this!
          */
         regs.sp++;
         regs.sp[-2] = rval;
         regs.sp[-1] = lval;
     } else {
-        /*
-         * Cache miss: use the immediate atom that was loaded for us under
-         * PropertyCache::test.
-         */
+        /* Cache miss: use the name loaded for us under PropertyCache::test. */
         regs.sp++;
         regs.sp[-1].setNull();
         if (lval.isObject()) {
-            if (!js_GetMethod(cx, &objv.toObject(), id,
-                              JS_LIKELY(!objv.toObject().getOps()->getProperty)
-                              ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                              : JSGET_NO_METHOD_BARRIER,
-                              &rval)) {
+            if (!GetMethod(cx, &objv.toObject(), name,
+                           JS_LIKELY(!objv.toObject().getOps()->getProperty)
+                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
+                           : JSGET_NO_METHOD_BARRIER,
+                           &rval))
+            {
                 THROW();
             }
             regs.sp[-1] = objv;
             regs.sp[-2] = rval;
         } else {
             JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
-                                      JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
-                                      &rval)) {
+            if (!GetPropertyHelper(cx, &objv.toObject(), name,
+                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
+                                   &rval))
+            {
                 THROW();
             }
             regs.sp[-1] = lval;
             regs.sp[-2] = rval;
         }
     }
 
 #if JS_HAS_NO_SUCH_METHOD
     if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        regs.sp[-2].setString(JSID_TO_STRING(id));
+        regs.sp[-2].setString(name);
         if (!OnUnknownMethod(cx, regs.sp - 2))
             THROW();
     }
 #endif
 
     if (monitor.recompiled())
         return;
 
-    GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->atom, DisabledCallPropIC);
+    GetPropCompiler cc(f, script, &objv.toObject(), *pic, pic->name, DisabledCallPropIC);
     if (lval.isObject()) {
         if (pic->shouldUpdate(cx)) {
             LookupStatus status = cc.update();
             if (status == Lookup_Error)
                 THROW();
         }
     } else if (lval.isString()) {
         LookupStatus status = cc.generateStringCallStub();
@@ -2176,34 +2168,34 @@ DisabledXNameIC(VMFrame &f, ic::PICInfo 
 void JS_FASTCALL
 ic::XName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
     /* GETXPROP is guaranteed to have an object. */
     JSObject *obj = &f.regs.sp[-1].toObject();
 
-    ScopeNameCompiler cc(f, script, obj, *pic, pic->atom, DisabledXNameIC);
+    ScopeNameCompiler cc(f, script, obj, *pic, pic->name, DisabledXNameIC);
 
     LookupStatus status = cc.updateForXName();
     if (status == Lookup_Error)
         THROW();
 
     Value rval;
     if (!cc.retrieve(&rval, NULL, PICInfo::XNAME))
         THROW();
     f.regs.sp[-1] = rval;
 }
 
 void JS_FASTCALL
 ic::Name(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledNameIC);
+    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->name, DisabledNameIC);
 
     LookupStatus status = cc.updateForName();
     if (status == Lookup_Error)
         THROW();
 
     Value rval;
     if (!cc.retrieve(&rval, NULL, PICInfo::NAME))
         THROW();
@@ -2216,17 +2208,17 @@ DisabledCallNameIC(VMFrame &f, ic::PICIn
     stubs::CallName(f);
 }
 
 void JS_FASTCALL
 ic::CallName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
-    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, DisabledCallNameIC);
+    ScopeNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->name, DisabledCallNameIC);
 
     LookupStatus status = cc.updateForName();
     if (status == Lookup_Error)
         THROW();
 
     Value rval, thisval;
     if (!cc.retrieve(&rval, &thisval, PICInfo::CALLNAME))
         THROW();
@@ -2239,28 +2231,28 @@ static void JS_FASTCALL
 DisabledBindNameIC(VMFrame &f, ic::PICInfo *pic)
 {
     stubs::BindName(f);
 }
 
 static void JS_FASTCALL
 DisabledBindNameICNoCache(VMFrame &f, ic::PICInfo *pic)
 {
-    stubs::BindNameNoCache(f, pic->atom);
+    stubs::BindNameNoCache(f, pic->name);
 }
 
 void JS_FASTCALL
 ic::BindName(VMFrame &f, ic::PICInfo *pic)
 {
     JSScript *script = f.fp()->script();
 
     VoidStubPIC stub = pic->usePropCache
                        ? DisabledBindNameIC
                        : DisabledBindNameICNoCache;
-    BindNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->atom, stub);
+    BindNameCompiler cc(f, script, &f.fp()->scopeChain(), *pic, pic->name, stub);
 
     JSObject *obj = cc.update();
     if (!obj)
         THROW();
 
     f.regs.sp[0].setObject(*obj);
 }
 
@@ -2394,22 +2386,23 @@ GetElementIC::purge(Repatcher &repatcher
                              FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::CallElement)));
         }
     }
 
     reset();
 }
 
 LookupStatus
-GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp)
+GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyName *name,
+                            Value *vp)
 {
     JS_ASSERT(v.isString());
     JSContext *cx = f.cx;
 
-    GetPropertyHelper<GetElementIC> getprop(cx, obj, JSID_TO_ATOM(id), *this, f);
+    GetPropHelper<GetElementIC> getprop(cx, obj, name, *this, f);
     LookupStatus status = getprop.lookupAndTest();
     if (status != Lookup_Cacheable)
         return status;
 
     // With TI enabled, string property stubs can only be added to an opcode if
     // the value read will go through a type barrier afterwards. TI only
     // accounts for integer-valued properties accessed by GETELEM/CALLELEM.
     if (cx->typeInferenceEnabled() && !forcedTypeBarrier)
@@ -2498,17 +2491,17 @@ GetElementIC::attachGetProp(VMFrame &f, 
     for (Jump *pj = otherGuards.begin(); pj != otherGuards.end(); ++pj)
         buffer.link(*pj, slowPathStart);
     buffer.link(done, fastPathRejoin);
 
     CodeLocationLabel cs = buffer.finalize(f);
 #if DEBUG
     char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
     JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
-               js_CodeName[op], cs.executableAddress(), (void*)JSID_TO_ATOM(id), chars,
+               js_CodeName[op], cs.executableAddress(), (void*)name, chars,
                (void*)holder->lastProperty(), cx->fp()->script()->filename, CurrentLine(cx));
     cx->free_(chars);
 #endif
 
     // Update the inline guards, if needed.
     if (shouldPatchInlineTypeGuard() || shouldPatchUnconditionalShapeGuard()) {
         Repatcher repatcher(cx->fp()->jit());
 
@@ -2820,17 +2813,17 @@ GetElementIC::update(VMFrame &f, JSObjec
 {
     /*
      * Only treat this as a GETPROP for non-numeric string identifiers. The
      * GETPROP IC assumes the id has already gone through filtering for string
      * indexes in the emitter, i.e. js_GetProtoIfDenseArray is only valid to
      * use when looking up non-integer identifiers.
      */
     if (v.isString() && js_CheckForStringIndex(id) == id)
-        return attachGetProp(f, obj, v, id, vp);
+        return attachGetProp(f, obj, v, JSID_TO_ATOM(id)->asPropertyName(), vp);
 
     if (obj->isArguments())
         return attachArguments(f, obj, v, id, vp);
 
 #if defined JS_METHODJIT_TYPED_ARRAY
     /*
      * Typed array ICs can make stub calls, and need to know which registers
      * are in use and need to be restored after the call. If type inference is
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -294,17 +294,18 @@ struct GetElementIC : public BasePolyIC 
         BasePolyIC::reset();
         inlineTypeGuardPatched = false;
         inlineShapeGuardPatched = false;
         typeRegHasBaseShape = false;
         hasLastStringStub = false;
     }
     void purge(Repatcher &repatcher);
     LookupStatus update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
-    LookupStatus attachGetProp(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
+    LookupStatus attachGetProp(VMFrame &f, JSObject *obj, const Value &v, PropertyName *name,
+                               Value *vp);
     LookupStatus attachArguments(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
     LookupStatus attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
     LookupStatus disable(JSContext *cx, const char *reason);
     LookupStatus error(JSContext *cx);
     bool shouldUpdate(JSContext *cx);
 };
 
 struct SetElementIC : public BaseIC {
@@ -529,17 +530,17 @@ struct PICInfo : public BasePolyIC {
         JS_ASSERT(kind == NAME || kind == CALLNAME || kind == XNAME);
         return scopeNameLabels_;
     }
 
     // Where in the script did we generate this PIC?
     jsbytecode *pc;
     
     // Index into the script's atom table.
-    JSAtom *atom;
+    PropertyName *name;
 
     // Reset the data members to the state of a fresh PIC before any patching
     // or stub generation was done.
     void reset() {
         BasePolyIC::reset();
         inlinePathPatched = false;
         shapeRegHasBaseShape = true;
     }
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -86,49 +86,48 @@ using namespace JSC;
 void JS_FASTCALL
 stubs::BindName(VMFrame &f)
 {
     PropertyCacheEntry *entry;
 
     /* Fast-path should have caught this. See comment in interpreter. */
     JS_ASSERT(!f.fp()->scopeChain().isGlobal());
 
-    JSAtom *atom;
+    PropertyName *name;
     JSObject *obj2;
     JSContext *cx = f.cx;
     JSObject *obj = &f.fp()->scopeChain();
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, atom);
-    if (atom) {
-        jsid id = ATOM_TO_JSID(atom);
-        obj = js_FindIdentifierBase(cx, &f.fp()->scopeChain(), id);
+    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, name);
+    if (name) {
+        obj = FindIdentifierBase(cx, &f.fp()->scopeChain(), name);
         if (!obj)
             THROW();
     }
     f.regs.sp++;
     f.regs.sp[-1].setObject(*obj);
 }
 
 void JS_FASTCALL
-stubs::BindNameNoCache(VMFrame &f, JSAtom *atom)
+stubs::BindNameNoCache(VMFrame &f, PropertyName *name)
 {
-    JSObject *obj = js_FindIdentifierBase(f.cx, &f.fp()->scopeChain(), ATOM_TO_JSID(atom));
+    JSObject *obj = FindIdentifierBase(f.cx, &f.fp()->scopeChain(), name);
     if (!obj)
         THROW();
     f.regs.sp[0].setObject(*obj);
 }
 
 JSObject * JS_FASTCALL
 stubs::BindGlobalName(VMFrame &f)
 {
     return &f.fp()->scopeChain().global();
 }
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetName(VMFrame &f, JSAtom *origAtom)
+stubs::SetName(VMFrame &f, PropertyName *origName)
 {
     JSContext *cx = f.cx;
 
     Value rval = f.regs.sp[-1];
     Value &lref = f.regs.sp[-2];
     JSObject *obj = ValueToObject(cx, &lref);
     if (!obj)
         THROW();
@@ -152,18 +151,18 @@ stubs::SetName(VMFrame &f, JSAtom *origA
          *   o.p = x;
          *
          * in a frequently executed method or loop body, where p will
          * (possibly after the first iteration) always exist in native
          * object o.
          */
         PropertyCacheEntry *entry;
         JSObject *obj2;
-        JSAtom *atom;
-        if (cache->testForSet(cx, f.pc(), obj, &entry, &obj2, &atom)) {
+        PropertyName *name;
+        if (cache->testForSet(cx, f.pc(), obj, &entry, &obj2, &name)) {
             /*
              * Property cache hit, only partially confirmed by testForSet. We
              * know that the entry applies to regs.pc and that obj's shape
              * matches.
              *
              * The entry predicts a set either an existing "own" property, or
              * on a prototype property that has a setter.
              */
@@ -186,89 +185,88 @@ stubs::SetName(VMFrame &f, JSAtom *origA
 
                 PCMETER(cache->pchits++);
                 PCMETER(cache->setpchits++);
                 NATIVE_SET(cx, obj, shape, entry, strict, &rval);
                 break;
             }
             PCMETER(cache->setpcmisses++);
 
-            atom = origAtom;
+            name = origName;
         } else {
-            JS_ASSERT(atom);
+            JS_ASSERT(name);
         }
 
-        jsid id = ATOM_TO_JSID(atom);
         if (entry && JS_LIKELY(!obj->getOps()->setProperty)) {
             uintN defineHow;
             JSOp op = JSOp(*f.pc());
             if (op == JSOP_SETMETHOD)
                 defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
             else if (op == JSOP_SETNAME)
                 defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
             else
                 defineHow = DNP_CACHE_RESULT;
-            if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rval, strict))
+            if (!SetPropertyHelper(cx, obj, name, defineHow, &rval, strict))
                 THROW();
         } else {
-            if (!obj->setGeneric(cx, id, &rval, strict))
+            if (!obj->setProperty(cx, name, &rval, strict))
                 THROW();
         }
     } while (0);
 
     f.regs.sp[-2] = f.regs.sp[-1];
 }
 
-template void JS_FASTCALL stubs::SetName<true>(VMFrame &f, JSAtom *origAtom);
-template void JS_FASTCALL stubs::SetName<false>(VMFrame &f, JSAtom *origAtom);
+template void JS_FASTCALL stubs::SetName<true>(VMFrame &f, PropertyName *origName);
+template void JS_FASTCALL stubs::SetName<false>(VMFrame &f, PropertyName *origName);
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetPropNoCache(VMFrame &f, JSAtom *atom)
+stubs::SetPropNoCache(VMFrame &f, PropertyName *name)
 {
     JSObject *obj = ValueToObject(f.cx, &f.regs.sp[-2]);
     if (!obj)
          THROW();
     Value rval = f.regs.sp[-1];
 
-    if (!obj->setGeneric(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1], strict))
+    if (!obj->setProperty(f.cx, name, &f.regs.sp[-1], strict))
         THROW();
     f.regs.sp[-2] = rval;
 }
 
-template void JS_FASTCALL stubs::SetPropNoCache<true>(VMFrame &f, JSAtom *origAtom);
-template void JS_FASTCALL stubs::SetPropNoCache<false>(VMFrame &f, JSAtom *origAtom);
+template void JS_FASTCALL stubs::SetPropNoCache<true>(VMFrame &f, PropertyName *name);
+template void JS_FASTCALL stubs::SetPropNoCache<false>(VMFrame &f, PropertyName *name);
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetGlobalNameNoCache(VMFrame &f, JSAtom *atom)
+stubs::SetGlobalNameNoCache(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
 
     Value rval = f.regs.sp[-1];
     Value &lref = f.regs.sp[-2];
     JSObject *obj = ValueToObject(cx, &lref);
-    if (!obj || !obj->setProperty(cx, atom->asPropertyName(), &rval, strict))
+    if (!obj || !obj->setProperty(cx, name, &rval, strict))
         THROW();
 
     f.regs.sp[-2] = f.regs.sp[-1];
 }
 
-template void JS_FASTCALL stubs::SetGlobalNameNoCache<true>(VMFrame &f, JSAtom *atom);
-template void JS_FASTCALL stubs::SetGlobalNameNoCache<false>(VMFrame &f, JSAtom *atom);
+template void JS_FASTCALL stubs::SetGlobalNameNoCache<true>(VMFrame &f, PropertyName *name);
+template void JS_FASTCALL stubs::SetGlobalNameNoCache<false>(VMFrame &f, PropertyName *name);
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::SetGlobalName(VMFrame &f, JSAtom *atom)
+stubs::SetGlobalName(VMFrame &f, PropertyName *name)
 {
-    SetName<strict>(f, atom);
+    SetName<strict>(f, name);
 }
 
-template void JS_FASTCALL stubs::SetGlobalName<true>(VMFrame &f, JSAtom *atom);
-template void JS_FASTCALL stubs::SetGlobalName<false>(VMFrame &f, JSAtom *atom);
+template void JS_FASTCALL stubs::SetGlobalName<true>(VMFrame &f, PropertyName *name);
+template void JS_FASTCALL stubs::SetGlobalName<false>(VMFrame &f, PropertyName *name);
 
 static inline void
 PushImplicitThis(VMFrame &f, JSObject *obj, Value &rval)
 {
     Value thisv;
 
     if (!ComputeImplicitThis(f.cx, obj, rval, &thisv))
         return;
@@ -277,61 +275,58 @@ PushImplicitThis(VMFrame &f, JSObject *o
 
 static JSObject *
 NameOp(VMFrame &f, JSObject *obj, bool callname)
 {
     JSContext *cx = f.cx;
 
     Value rval;
 
-    jsid id;
-
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, atom);
-    if (!atom) {
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), obj, obj2, entry, name);
+    if (!name) {
         NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval, return NULL);
         JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
     } else {
-        id = ATOM_TO_JSID(atom);
         JSProperty *prop;
         bool global = (js_CodeSpec[*f.pc()].format & JOF_GNAME);
-        if (!js_FindPropertyHelper(cx, id, true, global, &obj, &obj2, &prop))
+        if (!FindPropertyHelper(cx, name, true, global, &obj, &obj2, &prop))
             return NULL;
         if (!prop) {
             /* Kludge to allow (typeof foo == "undefined") tests. */
             JSOp op2 = JSOp(f.pc()[JSOP_NAME_LENGTH]);
             if (op2 == JSOP_TYPEOF) {
                 f.regs.sp++;
                 f.regs.sp[-1].setUndefined();
                 return obj;
             }
-            ReportAtomNotDefined(cx, atom);
+            ReportAtomNotDefined(cx, name);
             return NULL;
         }
 
         /* Take the slow path if prop was not found in a native object. */
         if (!obj->isNative() || !obj2->isNative()) {
-            if (!obj->getGeneric(cx, id, &rval))
+            if (!obj->getProperty(cx, name, &rval))
                 return NULL;
         } else {
             Shape *shape = (Shape *)prop;
             JSObject *normalized = obj;
             if (normalized->isWith() && !shape->hasDefaultGetter())
                 normalized = &normalized->asWith().object();
             NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
         }
 
         /*
          * If this is an incop, update the property's types themselves,
          * to capture the type effect on the intermediate value.
          */
         if (rval.isUndefined() && (js_CodeSpec[*f.pc()].format & (JOF_INC|JOF_DEC)))
-            AddTypePropertyId(cx, obj, id, Type::UndefinedType());
+            AddTypePropertyId(cx, obj, ATOM_TO_JSID(name), Type::UndefinedType());
     }
 
     *f.regs.sp++ = rval;
 
     if (callname)
         PushImplicitThis(f, obj, rval);
 
     return obj;
@@ -706,17 +701,16 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
      * We define the function as a property of the variable object and not the
      * current scope chain even for the case of function expression statements
      * and functions defined by eval inside let or with blocks.
      */
     JSObject *parent = &fp->varObj();
 
     /* ES5 10.5 (NB: with subsequent errata). */
     PropertyName *name = fun->atom->asPropertyName();
-    jsid id = ATOM_TO_JSID(name);
     JSProperty *prop = NULL;
     JSObject *pobj;
     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         THROW();
 
     Value rval = ObjectValue(*obj);
 
     do {
@@ -740,19 +734,19 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
                 {
                     THROW();
                 }
                 break;
             }
 
             if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
                 JSAutoByteString bytes;
-                if (const char *name = js_ValueToPrintable(cx, IdToValue(id), &bytes)) {
+                if (js_AtomToPrintableString(cx, name, &bytes)) {
                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                         JSMSG_CANT_REDEFINE_PROP, name);
+                                         JSMSG_CANT_REDEFINE_PROP, bytes.ptr());
                 }
                 THROW();
             }
         }
 
         /*
          * Non-global properties, and global properties which we aren't simply
          * redefining, must be set.  First, this preserves their attributes.
@@ -1474,62 +1468,60 @@ InlineGetProp(VMFrame &f)
         return false;
 
     Value rval;
     do {
         JSObject *aobj = js_GetProtoIfDenseArray(obj);
 
         PropertyCacheEntry *entry;
         JSObject *obj2;
-        JSAtom *atom;
-        JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, atom);
-        if (!atom) {
+        PropertyName *name;
+        JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name);
+        if (!name) {
             NATIVE_GET(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, &rval, return false);
             break;
         }
 
-        jsid id = ATOM_TO_JSID(atom);
         if (JS_LIKELY(!aobj->getOps()->getProperty)
-                ? !js_GetPropertyHelper(cx, obj, id,
-                    JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER,
-                    &rval)
-                : !obj->getGeneric(cx, id, &rval)) {
+            ? !GetPropertyHelper(cx, obj, name, JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER, &rval)
+            : !obj->getProperty(cx, name, &rval))
+        {
             return false;
         }
-    } while(0);
+    } while (false);
 
     regs.sp[-1] = rval;
     return true;
 }
 
 void JS_FASTCALL
 stubs::GetProp(VMFrame &f)
 {
     if (!InlineGetProp(f))
         THROW();
 }
 
 void JS_FASTCALL
-stubs::GetPropNoCache(VMFrame &f, JSAtom *atom)
+stubs::GetPropNoCache(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
 
     Value *vp = &f.regs.sp[-1];
     JSObject *obj = ValueToObject(cx, vp);
     if (!obj)
         THROW();
 
-    if (!obj->getGeneric(cx, ATOM_TO_JSID(atom), vp))
+    if (!obj->getProperty(cx, name, vp))
         THROW();
 
     /* Don't check for undefined, this is only used for 'prototype'. See ic::GetProp. */
 }
 
 void JS_FASTCALL
-stubs::CallProp(VMFrame &f, JSAtom *origAtom)
+stubs::CallProp(VMFrame &f, PropertyName *origName)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     Value lval;
     lval = regs.sp[-1];
 
     Value objv;
@@ -1554,74 +1546,70 @@ stubs::CallProp(VMFrame &f, JSAtom *orig
         objv.setObject(*pobj);
     }
 
     JSObject *aobj = js_GetProtoIfDenseArray(&objv.toObject());
     Value rval;
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom;
-    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, atom);
-    if (!atom) {
+    PropertyName *name;
+    JS_PROPERTY_CACHE(cx).test(cx, f.pc(), aobj, obj2, entry, name);
+    if (!name) {
         NATIVE_GET(cx, &objv.toObject(), obj2, entry->prop, JSGET_NO_METHOD_BARRIER, &rval,
                    THROW());
         regs.sp++;
         regs.sp[-2] = rval;
         regs.sp[-1] = lval;
     } else {
-        /*
-         * Cache miss: use the immediate atom that was loaded for us under
-         * PropertyCache::test.
-         */
-        jsid id;
-        id = ATOM_TO_JSID(origAtom);
-
+        /* Cache miss: use the name loaded for us under PropertyCache::test. */
         regs.sp++;
         regs.sp[-1].setNull();
         if (lval.isObject()) {
-            if (!js_GetMethod(cx, &objv.toObject(), id,
-                              JS_LIKELY(!aobj->getOps()->getProperty)
-                              ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                              : JSGET_NO_METHOD_BARRIER,
-                              &rval)) {
+            if (!GetMethod(cx, &objv.toObject(), name,
+                           JS_LIKELY(!aobj->getOps()->getProperty)
+                           ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
+                           : JSGET_NO_METHOD_BARRIER,
+                           &rval))
+            {
                 THROW();
             }
             regs.sp[-1] = objv;
             regs.sp[-2] = rval;
         } else {
             JS_ASSERT(!objv.toObject().getOps()->getProperty);
-            if (!js_GetPropertyHelper(cx, &objv.toObject(), id,
-                                      JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
-                                      &rval)) {
+            if (!GetPropertyHelper(cx, &objv.toObject(), name,
+                                   JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER,
+                                   &rval))
+            {
                 THROW();
             }
             regs.sp[-1] = lval;
             regs.sp[-2] = rval;
         }
     }
 #if JS_HAS_NO_SUCH_METHOD
     if (JS_UNLIKELY(rval.isPrimitive()) && regs.sp[-1].isObject()) {
-        regs.sp[-2].setString(origAtom);
+        regs.sp[-2].setString(origName);
         if (!OnUnknownMethod(cx, regs.sp - 2))
             THROW();
     }
 #endif
 }
 
 void JS_FASTCALL
 stubs::Iter(VMFrame &f, uint32_t flags)
 {
     if (!js_ValueToIterator(f.cx, flags, &f.regs.sp[-1]))
         THROW();
     JS_ASSERT(!f.regs.sp[-1].isPrimitive());
 }
 
 static void
-InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op)
+InitPropOrMethod(VMFrame &f, PropertyName *name, JSOp op)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
     /* Load the property's initial value into rval. */
     JS_ASSERT(regs.sp - f.fp()->base() >= 2);
     Value rval;
     rval = regs.sp[-1];
@@ -1638,52 +1626,50 @@ InitPropOrMethod(VMFrame &f, JSAtom *ato
      * So check first.
      *
      * On a hit, if the cached shape has a non-default setter, it must be
      * __proto__. If shape->previous() != obj->lastProperty(), there must be a
      * repeated property name. The fast path does not handle these two cases.
      */
     PropertyCacheEntry *entry;
     JSObject *obj2;
-    JSAtom *atom2;
-    if (JS_PROPERTY_CACHE(cx).testForSet(cx, f.pc(), obj, &entry, &obj2, &atom2) &&
+    PropertyName *name2;
+    if (JS_PROPERTY_CACHE(cx).testForSet(cx, f.pc(), obj, &entry, &obj2, &name2) &&
         entry->prop->hasDefaultSetter() &&
         entry->isOwnPropertyHit())
     {
         JS_ASSERT(obj == obj2);
         /* Fast path. Property cache hit. */
         obj->nativeSetSlotWithType(cx, entry->prop, rval);
     } else {
         PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
 
-        /* Get the immediate property name into id. */
-        jsid id = ATOM_TO_JSID(atom);
-
         uintN defineHow = (op == JSOP_INITMETHOD)
                           ? DNP_CACHE_RESULT | DNP_SET_METHOD
                           : DNP_CACHE_RESULT;
-        if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
-            ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, false)
-            : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
-                                    JSPROP_ENUMERATE, 0, 0, defineHow)) {
+        if (JS_UNLIKELY(name == cx->runtime->atomState.protoAtom)
+            ? !SetPropertyHelper(cx, obj, name, defineHow, &rval, false)
+            : !DefineNativeProperty(cx, obj, name, rval, NULL, NULL,
+                                    JSPROP_ENUMERATE, 0, 0, defineHow))
+        {
             THROW();
         }
     }
 }
 
 void JS_FASTCALL
-stubs::InitProp(VMFrame &f, JSAtom *atom)
+stubs::InitProp(VMFrame &f, PropertyName *name)
 {
-    InitPropOrMethod(f, atom, JSOP_INITPROP);
+    InitPropOrMethod(f, name, JSOP_INITPROP);
 }
 
 void JS_FASTCALL
-stubs::InitMethod(VMFrame &f, JSAtom *atom)
+stubs::InitMethod(VMFrame &f, PropertyName *name)
 {
-    InitPropOrMethod(f, atom, JSOP_INITMETHOD);
+    InitPropOrMethod(f, name, JSOP_INITMETHOD);
 }
 
 void JS_FASTCALL
 stubs::IterNext(VMFrame &f, int32_t offset)
 {
     JS_ASSERT(f.regs.sp - offset >= f.fp()->base());
     JS_ASSERT(f.regs.sp[-offset].isObject());
 
@@ -1716,18 +1702,17 @@ stubs::EndIter(VMFrame &f)
         THROW();
 }
 
 JSString * JS_FASTCALL
 stubs::TypeOf(VMFrame &f)
 {
     const Value &ref = f.regs.sp[-1];
     JSType type = JS_TypeOfValue(f.cx, ref);
-    JSAtom *atom = f.cx->runtime->atomState.typeAtoms[type];
-    return atom;
+    return f.cx->runtime->atomState.typeAtoms[type];
 }
 
 void JS_FASTCALL
 stubs::StrictEq(VMFrame &f)
 {
     const Value &rhs = f.regs.sp[-1];
     const Value &lhs = f.regs.sp[-2];
     JSBool equal;
@@ -2013,55 +1998,54 @@ stubs::Pos(VMFrame &f)
 {
     if (!ToNumber(f.cx, &f.regs.sp[-1]))
         THROW();
     if (!f.regs.sp[-1].isInt32())
         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
 }
 
 void JS_FASTCALL
-stubs::DelName(VMFrame &f, JSAtom *atom)
+stubs::DelName(VMFrame &f, PropertyName *name)
 {
-    jsid id = ATOM_TO_JSID(atom);
     JSObject *obj, *obj2;
     JSProperty *prop;
-    if (!js_FindProperty(f.cx, id, false, &obj, &obj2, &prop))
+    if (!FindProperty(f.cx, name, false, &obj, &obj2, &prop))
         THROW();
 
     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
     JS_ASSERT(!f.script()->strictModeCode);
 
     /* ECMA says to return true if name is undefined or inherited. */
     f.regs.sp++;
     f.regs.sp[-1] = BooleanValue(true);
     if (prop) {
-        if (!obj->deleteProperty(f.cx, atom->asPropertyName(), &f.regs.sp[-1], false))
+        if (!obj->deleteProperty(f.cx, name, &f.regs.sp[-1], false))
             THROW();
     }
 }
 
 template<JSBool strict>
 void JS_FASTCALL
-stubs::DelProp(VMFrame &f, JSAtom *atom)
+stubs::DelProp(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
 
     JSObject *obj = ValueToObject(cx, &f.regs.sp[-1]);
     if (!obj)
         THROW();
 
     Value rval;
-    if (!obj->deleteGeneric(cx, ATOM_TO_JSID(atom), &rval, strict))
+    if (!obj->deleteProperty(cx, name, &rval, strict))
         THROW();
 
     f.regs.sp[-1] = rval;
 }
 
-template void JS_FASTCALL stubs::DelProp<true>(VMFrame &f, JSAtom *atom);
-template void JS_FASTCALL stubs::DelProp<false>(VMFrame &f, JSAtom *atom);
+template void JS_FASTCALL stubs::DelProp<true>(VMFrame &f, PropertyName *name);
+template void JS_FASTCALL stubs::DelProp<false>(VMFrame &f, PropertyName *name);
 
 template<JSBool strict>
 void JS_FASTCALL
 stubs::DelElem(VMFrame &f)
 {
     JSContext *cx = f.cx;
 
     JSObject *obj = ValueToObject(cx, &f.regs.sp[-2]);
@@ -2072,73 +2056,72 @@ stubs::DelElem(VMFrame &f)
     if (!FetchElementId(f, obj, f.regs.sp[-1], id, &f.regs.sp[-1]))
         THROW();
 
     if (!obj->deleteGeneric(cx, id, &f.regs.sp[-2], strict))
         THROW();
 }
 
 void JS_FASTCALL
-stubs::DefVarOrConst(VMFrame &f, JSAtom *atom_)
+stubs::DefVarOrConst(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
     StackFrame *fp = f.fp();
 
     JSObject *obj = &fp->varObj();
     JS_ASSERT(!obj->getOps()->defineProperty);
     uintN attrs = JSPROP_ENUMERATE;
     if (!fp->isEvalFrame())
         attrs |= JSPROP_PERMANENT;
 
     /* Lookup id in order to check for redeclaration problems. */
-    PropertyName *name = atom_->asPropertyName();
-    jsid id = ATOM_TO_JSID(name);
     bool shouldDefine;
     if (JSOp(*f.pc()) == JSOP_DEFVAR) {
         /*
          * Redundant declaration of a |var|, even one for a non-writable
          * property like |undefined| in ES5, does nothing.
          */
         JSProperty *prop;
         JSObject *obj2;
         if (!obj->lookupProperty(cx, name, &obj2, &prop))
             THROW();
         shouldDefine = (!prop || obj2 != obj);
     } else {
         JS_ASSERT(JSOp(*f.pc()) == JSOP_DEFCONST);
         attrs |= JSPROP_READONLY;
-        if (!CheckRedeclaration(cx, obj, id, attrs))
+        if (!CheckRedeclaration(cx, obj, name, attrs))
             THROW();
 
         /*
          * As attrs includes readonly, CheckRedeclaration can succeed only
          * if prop does not exist.
          */
         shouldDefine = true;
     }
 
     /* Bind a variable only if it's not yet defined. */
     if (shouldDefine && 
-        !DefineNativeProperty(cx, obj, id, UndefinedValue(), JS_PropertyStub, JS_StrictPropertyStub,
-                              attrs, 0, 0)) {
+        !DefineNativeProperty(cx, obj, name, UndefinedValue(),
+                              JS_PropertyStub, JS_StrictPropertyStub, attrs, 0, 0))
+    {
         THROW();
     }
 }
 
 void JS_FASTCALL
-stubs::SetConst(VMFrame &f, JSAtom *atom)
+stubs::SetConst(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
 
     JSObject *obj = &f.fp()->varObj();
     const Value &ref = f.regs.sp[-1];
 
-    if (!obj->defineProperty(cx, atom->asPropertyName(), ref,
-                             JS_PropertyStub, JS_StrictPropertyStub,
-                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
+    if (!obj->defineProperty(cx, name, ref, JS_PropertyStub, JS_StrictPropertyStub,
+                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY))
+    {
         THROW();
     }
 }
 
 JSBool JS_FASTCALL
 stubs::In(VMFrame &f)
 {
     JSContext *cx = f.cx;
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -56,18 +56,18 @@ typedef enum JSTrapType {
 void JS_FASTCALL This(VMFrame &f);
 void JS_FASTCALL NewInitArray(VMFrame &f, uint32_t count);
 void JS_FASTCALL NewInitObject(VMFrame &f, JSObject *base);
 void JS_FASTCALL Trap(VMFrame &f, uint32_t trapTypes);
 void JS_FASTCALL DebuggerStatement(VMFrame &f, jsbytecode *pc);
 void JS_FASTCALL Interrupt(VMFrame &f, jsbytecode *pc);
 void JS_FASTCALL RecompileForInline(VMFrame &f);
 void JS_FASTCALL InitElem(VMFrame &f, uint32_t last);
-void JS_FASTCALL InitProp(VMFrame &f, JSAtom *atom);
-void JS_FASTCALL InitMethod(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL InitProp(VMFrame &f, PropertyName *name);
+void JS_FASTCALL InitMethod(VMFrame &f, PropertyName *name);
 
 void JS_FASTCALL HitStackQuota(VMFrame &f);
 void * JS_FASTCALL FixupArity(VMFrame &f, uint32_t argc);
 void * JS_FASTCALL CompileFunction(VMFrame &f, uint32_t argc);
 void JS_FASTCALL SlowNew(VMFrame &f, uint32_t argc);
 void JS_FASTCALL SlowCall(VMFrame &f, uint32_t argc);
 void * JS_FASTCALL UncachedNew(VMFrame &f, uint32_t argc);
 void * JS_FASTCALL UncachedCall(VMFrame &f, uint32_t argc);
@@ -111,42 +111,42 @@ void UncachedNewHelper(VMFrame &f, uint3
 
 void JS_FASTCALL CreateThis(VMFrame &f, JSObject *proto);
 void JS_FASTCALL Throw(VMFrame &f);
 
 void * JS_FASTCALL LookupSwitch(VMFrame &f, jsbytecode *pc);
 void * JS_FASTCALL TableSwitch(VMFrame &f, jsbytecode *origPc);
 
 void JS_FASTCALL BindName(VMFrame &f);
-void JS_FASTCALL BindNameNoCache(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL BindNameNoCache(VMFrame &f, PropertyName *name);
 JSObject * JS_FASTCALL BindGlobalName(VMFrame &f);
-template<JSBool strict> void JS_FASTCALL SetName(VMFrame &f, JSAtom *atom);
-template<JSBool strict> void JS_FASTCALL SetPropNoCache(VMFrame &f, JSAtom *atom);
-template<JSBool strict> void JS_FASTCALL SetGlobalName(VMFrame &f, JSAtom *atom);
-template<JSBool strict> void JS_FASTCALL SetGlobalNameNoCache(VMFrame &f, JSAtom *atom);
+template<JSBool strict> void JS_FASTCALL SetName(VMFrame &f, PropertyName *name);
+template<JSBool strict> void JS_FASTCALL SetPropNoCache(VMFrame &f, PropertyName *name);
+template<JSBool strict> void JS_FASTCALL SetGlobalName(VMFrame &f, PropertyName *name);
+template<JSBool strict> void JS_FASTCALL SetGlobalNameNoCache(VMFrame &f, PropertyName *name);
 void JS_FASTCALL Name(VMFrame &f);
 void JS_FASTCALL GetProp(VMFrame &f);
-void JS_FASTCALL GetPropNoCache(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL GetPropNoCache(VMFrame &f, PropertyName *name);
 void JS_FASTCALL GetElem(VMFrame &f);
 void JS_FASTCALL CallElem(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetElem(VMFrame &f);
 void JS_FASTCALL ToId(VMFrame &f);
 void JS_FASTCALL CallName(VMFrame &f);
 void JS_FASTCALL PushImplicitThisForGlobal(VMFrame &f);
 void JS_FASTCALL GetUpvar(VMFrame &f, uint32_t index);
 void JS_FASTCALL GetGlobalName(VMFrame &f);
 
-void JS_FASTCALL CallProp(VMFrame &f, JSAtom *atom);
-template <JSBool strict> void JS_FASTCALL DelProp(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL CallProp(VMFrame &f, PropertyName *name);
+template <JSBool strict> void JS_FASTCALL DelProp(VMFrame &f, PropertyName *name);
 template <JSBool strict> void JS_FASTCALL DelElem(VMFrame &f);
-void JS_FASTCALL DelName(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL DelName(VMFrame &f, PropertyName *name);
 JSBool JS_FASTCALL In(VMFrame &f);
 
-void JS_FASTCALL DefVarOrConst(VMFrame &f, JSAtom *atom);
-void JS_FASTCALL SetConst(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL DefVarOrConst(VMFrame &f, PropertyName *name);
+void JS_FASTCALL SetConst(VMFrame &f, PropertyName *name);
 template<JSBool strict> void JS_FASTCALL DefFun(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL DefLocalFun(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun);
 void JS_FASTCALL RegExp(VMFrame &f, JSObject *regex);
 JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaJoinableForInit(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaJoinableForSet(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);