Bug 433529: Part 2 - Add a displayAtom to JSFunction to store resolved names. r=jimb
authorAlex Crichton <acrichton@mozilla.com>
Sat, 18 Aug 2012 21:37:09 -0700
changeset 105147 4ebcfba34c383b8829d8e4d2e57d9ac248085249
parent 105146 d7568555261ce6c7166c880f35bd64d5ba99a94b
child 105148 8a751b65df8b19861b94fc6ce3303a05ce1d03de
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersjimb
bugs433529
milestone17.0a1
Bug 433529: Part 2 - Add a displayAtom to JSFunction to store resolved names. r=jimb
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/NameFunctions.cpp
js/src/frontend/ParseNode-inl.h
js/src/frontend/Parser.cpp
js/src/jsapi.cpp
js/src/jscntxt.cpp
js/src/jsdbgapi.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsfuninlines.h
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsreflect.cpp
js/src/methodjit/StubCalls.cpp
js/src/vm/Debugger.cpp
js/src/vm/SPSProfiler.cpp
js/src/vm/ScopeObject.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1391,17 +1391,17 @@ BindNameToSlot(JSContext *cx, BytecodeEm
         /*
          * Currently, the ALIASEDVAR ops do not support accessing the
          * callee of a DeclEnvObject, so use NAME.
          */
         if (dn->pn_cookie.level() != bce->script->staticLevel)
             return true;
 
         JS_ASSERT(bce->sc->fun()->flags & JSFUN_LAMBDA);
-        JS_ASSERT(pn->pn_atom == bce->sc->fun()->atom);
+        JS_ASSERT(pn->pn_atom == bce->sc->fun()->atom());
 
         /*
          * Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
          * address two cases: a new binding introduced by eval, and
          * assignment to the name in strict mode.
          *
          *   var fun = (function f(s) { eval(s); return f; });
          *   assertEq(fun("var f = 42"), 42);
@@ -4936,17 +4936,17 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
         bce->switchToMain();
 
         /* Emit NOP for the decompiler. */
         if (!EmitFunctionDefNop(cx, bce, index))
             return false;
     } else {
 #ifdef DEBUG
         BindingIter bi(bce->script->bindings);
-        while (bi->name() != fun->atom)
+        while (bi->name() != fun->atom())
             bi++;
         JS_ASSERT(bi->kind() == VARIABLE || bi->kind() == CONSTANT || bi->kind() == ARGUMENT);
         JS_ASSERT(bi.frameIndex() < JS_BIT(20));
 #endif
         pn->pn_index = index;
         if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
             return false;
         if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce))
--- a/js/src/frontend/NameFunctions.cpp
+++ b/js/src/frontend/NameFunctions.cpp
@@ -212,17 +212,18 @@ class NameResolver
         /*
          * functions which are "genuinely anonymous" but are contained in some
          * other namespace are rather considered as "contributing" to the outer
          * function, so give them a contribution symbol here.
          */
         if (!buf.empty() && *(buf.end() - 1) == '/' && !buf.append("<"))
             return NULL;
 
-        return buf.finishAtom();
+        fun->setGuessedAtom(buf.finishAtom());
+        return fun->displayAtom();
     }
 
     /*
      * Tests whether parents[pos] is a function call whose callee is cur.
      * This is the case for functions which do things like simply create a scope
      * for new variables and then return an anonymous function using this scope.
      */
     bool isDirectCall(int pos, ParseNode *cur) {
--- a/js/src/frontend/ParseNode-inl.h
+++ b/js/src/frontend/ParseNode-inl.h
@@ -27,17 +27,17 @@ UpvarCookie::set(JSContext *cx, unsigned
     slot_ = newSlot;
     return true;
 }
 
 inline PropertyName *
 ParseNode::name() const
 {
     JS_ASSERT(isKind(PNK_FUNCTION) || isKind(PNK_NAME) || isKind(PNK_INTRINSICNAME));
-    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom : pn_atom;
+    JSAtom *atom = isKind(PNK_FUNCTION) ? pn_funbox->function()->atom() : pn_atom;
     return atom->asPropertyName();
 }
 
 inline bool
 ParseNode::isConstant()
 {
     switch (pn_type) {
       case PNK_NUMBER:
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -630,18 +630,18 @@ HasFinalReturn(ParseNode *pn)
     }
 }
 
 static bool
 ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter reporter,
                 unsigned errnum, unsigned anonerrnum)
 {
     JSAutoByteString name;
-    if (parser->pc->sc->fun()->atom) {
-        if (!js_AtomToPrintableString(cx, parser->pc->sc->fun()->atom, &name))
+    if (parser->pc->sc->fun()->atom()) {
+        if (!js_AtomToPrintableString(cx, parser->pc->sc->fun()->atom(), &name))
             return false;
     } else {
         errnum = anonerrnum;
     }
     return (parser->*reporter)(pn, errnum, name.ptr());
 }
 
 static bool
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2675,20 +2675,20 @@ JS_GetTraceThingInfo(char *buf, size_t b
             Class *clasp = obj->getClass();
             if (clasp == &FunctionClass) {
                 JSFunction *fun = obj->toFunction();
                 if (!fun) {
                     JS_snprintf(buf, bufsize, " <newborn>");
                 } else if (fun != obj) {
                     JS_snprintf(buf, bufsize, " %p", fun);
                 } else {
-                    if (fun->atom) {
+                    if (fun->displayAtom()) {
                         *buf++ = ' ';
                         bufsize--;
-                        PutEscapedString(buf, bufsize, fun->atom, 0);
+                        PutEscapedString(buf, bufsize, fun->displayAtom(), 0);
                     }
                 }
             } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
                 JS_snprintf(buf, bufsize, " %p", obj->getPrivate());
             } else {
                 JS_snprintf(buf, bufsize, " <no private>");
             }
             break;
@@ -4916,17 +4916,17 @@ JS_PUBLIC_API(JSObject *)
 JS_GetFunctionObject(JSFunction *fun)
 {
     return fun;
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetFunctionId(JSFunction *fun)
 {
-    return fun->atom;
+    return fun->atom();
 }
 
 JS_PUBLIC_API(unsigned)
 JS_GetFunctionFlags(JSFunction *fun)
 {
     return fun->flags;
 }
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -930,17 +930,17 @@ js_ReportMissingArg(JSContext *cx, Handl
 {
     char argbuf[11];
     char *bytes;
     RootedAtom atom(cx);
 
     JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
     bytes = NULL;
     if (IsFunctionObject(v)) {
-        atom = v.toObject().toFunction()->atom;
+        atom = v.toObject().toFunction()->atom();
         bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
                                         v, atom);
         if (!bytes)
             return;
     }
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_MISSING_FUN_ARG, argbuf,
                          bytes ? bytes : "");
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -999,18 +999,18 @@ JS_PUBLIC_API(size_t)
 JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
 {
     size_t nbytes;
 
     nbytes = sizeof *fun;
     nbytes += JS_GetObjectTotalSize(cx, fun);
     if (fun->isInterpreted())
         nbytes += JS_GetScriptTotalSize(cx, fun->script());
-    if (fun->atom)
-        nbytes += GetAtomTotalSize(cx, fun->atom);
+    if (fun->displayAtom())
+        nbytes += GetAtomTotalSize(cx, fun->displayAtom());
     return nbytes;
 }
 
 JS_PUBLIC_API(size_t)
 JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
 {
     size_t nbytes, pbytes;
     jssrcnote *sn, *notes;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -277,17 +277,19 @@ InitExnPrivate(JSContext *cx, HandleObje
                 if (!checkAccess(cx, obj, callerid, JSACC_READ, &v))
                     break;
             }
 
             if (!frames.growBy(1))
                 return false;
             JSStackTraceStackElem &frame = frames.back();
             if (i.isNonEvalFunctionFrame()) {
-                JSAtom *atom = fp->fun()->atom ? fp->fun()->atom : cx->runtime->emptyString;
+                JSAtom *atom = fp->fun()->atom();
+                if (atom == NULL)
+                    atom = cx->runtime->emptyString;
                 frame.funName = atom;
             } else {
                 frame.funName = NULL;
             }
             const char *cfilename = i.script()->filename;
             if (!cfilename)
                 cfilename = "";
             frame.filename = SaveScriptFilename(cx, cfilename);
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -291,17 +291,17 @@ fun_resolve(JSContext *cx, HandleObject 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
         JSID_IS_ATOM(id, cx->runtime->atomState.nameAtom)) {
         JS_ASSERT(!IsInternalFunctionObject(obj));
 
         RootedValue v(cx);
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
             v.setInt32(fun->nargs - fun->hasRest());
         else
-            v.setString(fun->atom ? fun->atom : cx->runtime->emptyString);
+            v.setString(fun->atom() == NULL ?  cx->runtime->emptyString : fun->atom());
 
         if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
             return false;
         }
         objp.set(fun);
         return true;
     }
@@ -359,19 +359,19 @@ js::XDRInterpretedFunction(XDRState<mode
         if (!fun->isInterpreted()) {
             JSAutoByteString funNameBytes;
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
                                      name);
             }
             return false;
         }
-        firstword = !!fun->atom;
+        firstword = !!fun->atom();
         flagsword = (fun->nargs << 16) | fun->flags;
-        atom = fun->atom;
+        atom = fun->atom();
         script = fun->script();
     } else {
         RootedObject parent(cx, NULL);
         fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, parent, NULL);
         if (!fun)
             return false;
         if (!JSObject::clearParent(cx, fun))
             return false;
@@ -389,17 +389,17 @@ js::XDRInterpretedFunction(XDRState<mode
         return false;
 
     if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
         return false;
 
     if (mode == XDR_DECODE) {
         fun->nargs = flagsword >> 16;
         fun->flags = uint16_t(flagsword);
-        fun->atom.init(atom);
+        fun->initAtom(atom);
         fun->initScript(script);
         script->setFunction(fun);
         if (!JSFunction::setTypeForScriptedFunction(cx, fun))
             return false;
         JS_ASSERT(fun->nargs == fun->script()->bindings.numArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
         objp.set(fun);
     }
@@ -429,17 +429,17 @@ js::CloneInterpretedFunction(JSContext *
 
     Rooted<JSScript*> srcScript(cx, srcFun->script());
     JSScript *clonedScript = CloneScript(cx, enclosingScope, clone, srcScript);
     if (!clonedScript)
         return NULL;
 
     clone->nargs = srcFun->nargs;
     clone->flags = srcFun->flags;
-    clone->atom.init(srcFun->atom);
+    clone->initAtom(srcFun->displayAtom());
     clone->initScript(clonedScript);
     clonedScript->setFunction(clone);
     if (!JSFunction::setTypeForScriptedFunction(cx, clone))
         return NULL;
 
     js_CallNewScriptHook(cx, clone->script(), clone);
     return clone;
 }
@@ -481,18 +481,18 @@ fun_hasInstance(JSContext *cx, HandleObj
 inline void
 JSFunction::trace(JSTracer *trc)
 {
     if (isExtended()) {
         MarkValueRange(trc, ArrayLength(toExtended()->extendedSlots),
                        toExtended()->extendedSlots, "nativeReserved");
     }
 
-    if (atom)
-        MarkString(trc, &atom, "atom");
+    if (atom_)
+        MarkString(trc, &atom_, "atom");
 
     if (isInterpreted()) {
         if (u.i.script_)
             MarkScriptUnbarriered(trc, &u.i.script_, "script");
         if (u.i.env_)
             MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
     }
 }
@@ -596,18 +596,18 @@ js::FunctionToString(JSContext *cx, Hand
     if (!bodyOnly) {
         // If we're not in pretty mode, put parentheses around lambda functions.
         if (fun->isInterpreted() && !lambdaParen && (fun->flags & JSFUN_LAMBDA)) {
             if (!out.append("("))
                 return NULL;
         }
         if (!out.append("function "))
             return NULL;
-        if (fun->atom) {
-            if (!out.append(fun->atom))
+        if (fun->atom()) {
+            if (!out.append(fun->atom()))
                 return NULL;
         }
     }
     bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin();
     if (haveSource && !fun->script()->scriptSource()->hasSourceData() &&
         !fun->script()->loadSource(cx, &haveSource))
     {
         return NULL;
@@ -1100,17 +1100,17 @@ js_fun_bind(JSContext *cx, HandleObject 
     unsigned length = 0;
     if (target->isFunction()) {
         unsigned nargs = target->toFunction()->nargs;
         if (nargs > argslen)
             length = nargs - argslen;
     }
 
     /* Step 4-6, 10-11. */
-    JSAtom *name = target->isFunction() ? target->toFunction()->atom.get() : NULL;
+    JSAtom *name = target->isFunction() ? target->toFunction()->atom() : NULL;
 
     RootedObject funobj(cx, js_NewFunction(cx, NULL, CallOrConstructBoundFunction, length,
                                            JSFUN_CONSTRUCTOR, target, name));
     if (!funobj)
         return NULL;
 
     /* NB: Bound functions abuse |parent| to store their target. */
     if (!JSObject::setParent(cx, funobj, target))
@@ -1387,17 +1387,17 @@ js_NewFunction(JSContext *cx, JSObject *
     } else {
         JS_ASSERT(native);
         fun->initNative(native, NULL);
     }
     if (kind == JSFunction::ExtendedFinalizeKind) {
         fun->flags |= JSFUN_EXTENDED;
         fun->initializeExtended();
     }
-    fun->atom.init(atom);
+    fun->initAtom(atom);
 
     if (native && !JSObject::setSingletonType(cx, fun))
         return NULL;
 
     return fun;
 }
 
 JSFunction * JS_FASTCALL
@@ -1416,17 +1416,17 @@ js_CloneFunctionObject(JSContext *cx, Ha
     clone->nargs = fun->nargs;
     clone->flags = fun->flags & ~JSFUN_EXTENDED;
     if (fun->isInterpreted()) {
         clone->initScript(fun->script());
         clone->initEnvironment(parent);
     } else {
         clone->initNative(fun->native(), fun->jitInfo());
     }
-    clone->atom.init(fun->atom);
+    clone->initAtom(fun->displayAtom());
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFUN_EXTENDED;
         clone->initializeExtended();
     }
 
     if (cx->compartment == fun->compartment() && !types::UseNewTypeForClone(fun)) {
         /*
@@ -1510,17 +1510,17 @@ js_DefineFunction(JSContext *cx, HandleO
         fun = js_NewFunction(cx, NULL, native, nargs,
                              attrs & (JSFUN_FLAGS_MASK),
                              obj,
                              JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL,
                              kind);
     } else {
         JS_ASSERT(attrs & JSFUN_INTERPRETED);
         fun = cx->runtime->getSelfHostedFunction(cx, selfHostedName);
-        fun->atom = JSID_TO_ATOM(id);
+        fun->initAtom(JSID_TO_ATOM(id));
     }
     if (!fun)
         return NULL;
 
     RootedValue funVal(cx, ObjectValue(*fun));
     if (!JSObject::defineGeneric(cx, obj, id, funVal, gop, sop, attrs & ~JSFUN_FLAGS_MASK))
         return NULL;
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -40,16 +40,19 @@
 #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
 #define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
 /*
  * NB: JSFUN_INTERPRETED is hardcode duplicated in SET_JITINFO() in
  * jsfriendapi.h. If it changes, it must also be updated there.
  */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.native */
 
+#define JSFUN_HAS_GUESSED_ATOM  0x8000  /* function had no explicit name, but a
+                                           name was guessed for it anyway */
+
 namespace js { class FunctionExtended; }
 
 struct JSFunction : public JSObject
 {
     uint16_t        nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
     uint16_t        flags;        /* flags, see JSFUN_* below and in jsapi.h */
     union U {
@@ -63,30 +66,35 @@ struct JSFunction : public JSObject
         struct Scripted {
             JSScript    *script_; /* interpreted bytecode descriptor or null;
                                      use the accessor! */
             JSObject    *env_;    /* environment for new activations;
                                      use the accessor! */
         } i;
         void            *nativeOrScript;
     } u;
-    js::HeapPtrAtom  atom;        /* name for diagnostics and decompiling */
+  private:
+    js::HeapPtrAtom  atom_;       /* name for diagnostics and decompiling */
+  public:
 
     bool hasDefaults()       const { return flags & JSFUN_HAS_DEFAULTS; }
     bool hasRest()           const { return flags & JSFUN_HAS_REST; }
+    bool hasGuessedAtom()    const { return flags & JSFUN_HAS_GUESSED_ATOM; }
     bool isInterpreted()     const { return flags & JSFUN_INTERPRETED; }
     bool isNative()          const { return !isInterpreted(); }
     bool isSelfHostedBuiltin()  const { return flags & JSFUN_SELF_HOSTED; }
     bool isNativeConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
     bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
     bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
     bool isInterpretedConstructor() const {
         return isInterpreted() && !isFunctionPrototype() && !isSelfHostedBuiltin();
     }
-    bool isNamedLambda()     const { return (flags & JSFUN_LAMBDA) && atom; }
+    bool isNamedLambda()     const {
+        return (flags & JSFUN_LAMBDA) && atom_ && !hasGuessedAtom();
+    }
 
     /* Returns the strictness of this function, which must be interpreted. */
     inline bool inStrictMode() const;
 
     void setArgCount(uint16_t nargs) {
         JS_ASSERT(this->nargs == 0);
         this->nargs = nargs;
     }
@@ -96,16 +104,28 @@ struct JSFunction : public JSObject
         this->flags |= JSFUN_HAS_REST;
     }
 
     void setHasDefaults() {
         JS_ASSERT(!hasDefaults());
         this->flags |= JSFUN_HAS_DEFAULTS;
     }
 
+    JSAtom *atom() { return hasGuessedAtom() ? NULL : atom_.get(); }
+    void initAtom(JSAtom *atom) { atom_.init(atom); }
+    JSAtom *displayAtom() { return atom_; }
+
+    void setGuessedAtom(JSAtom *atom) {
+        JS_ASSERT(this->atom_ == NULL);
+        JS_ASSERT(atom != NULL);
+        JS_ASSERT(!hasGuessedAtom());
+        this->atom_ = atom;
+        this->flags |= JSFUN_HAS_GUESSED_ATOM;
+    }
+
     /* uint16_t representation bounds number of call object dynamic slots. */
     enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
 
     /*
      * For an interpreted function, accessors for the initial scope object of
      * activations (stack frames) of the function.
      */
     inline JSObject *environment() const;
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -177,18 +177,19 @@ inline bool
 IsConstructing(CallReceiver call)
 {
     return IsConstructing(call.base());
 }
 
 inline const char *
 GetFunctionNameBytes(JSContext *cx, JSFunction *fun, JSAutoByteString *bytes)
 {
-    if (fun->atom)
-        return bytes->encode(cx, fun->atom);
+    JSAtom *atom = fun->atom();
+    if (atom)
+        return bytes->encode(cx, atom);
     return js_anonymous_str;
 }
 
 extern JSFunctionSpec function_methods[];
 
 extern JSBool
 Function(JSContext *cx, unsigned argc, Value *vp);
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2866,17 +2866,17 @@ BEGIN_CASE(JSOP_DEFFUN)
      * current scope chain even for the case of function expression statements
      * and functions defined by eval inside let or with blocks.
      */
     RootedObject &parent = rootObject0;
     parent = &regs.fp()->varObj();
 
     /* ES5 10.5 (NB: with subsequent errata). */
     RootedPropertyName &name = rootName0;
-    name = fun->atom->asPropertyName();
+    name = fun->atom()->asPropertyName();
     RootedShape &shape = rootShape0;
     RootedObject &pobj = rootObject1;
     if (!JSObject::lookupProperty(cx, parent, name, &pobj, &shape))
         goto error;
 
     RootedValue &rval = rootValue0;
     rval = ObjectValue(*fun);
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5558,19 +5558,19 @@ dumpValue(const Value &v)
     else if (v.isInt32())
         fprintf(stderr, "%d", v.toInt32());
     else if (v.isDouble())
         fprintf(stderr, "%g", v.toDouble());
     else if (v.isString())
         v.toString()->dump();
     else if (v.isObject() && v.toObject().isFunction()) {
         JSFunction *fun = v.toObject().toFunction();
-        if (fun->atom) {
+        if (fun->displayAtom()) {
             fputs("<function ", stderr);
-            FileEscapedString(stderr, fun->atom, 0);
+            FileEscapedString(stderr, fun->displayAtom(), 0);
         } else {
             fputs("<unnamed function", stderr);
         }
         if (fun->isInterpreted()) {
             JSScript *script = fun->script();
             fprintf(stderr, " (%s:%u)",
                     script->filename ? script->filename : "", script->lineno);
         }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -520,17 +520,17 @@ namespace js {
 
 /*
  * Any name atom for a function which will be added as a DeclEnv object to the
  * scope chain above call objects for fun.
  */
 static inline JSAtom *
 CallObjectLambdaName(JSFunction &fun)
 {
-    return (fun.flags & JSFUN_LAMBDA) ? fun.atom.get() : NULL;
+    return fun.isNamedLambda() ? fun.atom() : NULL;
 }
 
 } /* namespace js */
 
 inline const js::Value &
 JSObject::getDateUTCTime() const
 {
     JS_ASSERT(isDate());
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -3614,17 +3614,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     /* Turn on parens around comma-expression here. */
                     op = JSOP_SETNAME;
                     rval = PopStr(ss, op, &rvalpc);
                     bool parens = (*rval == '{');
                     if (parens)
                         js_printf(jp, "(");
                     SprintOpcodePermanent(jp, rval, rvalpc);
                     js_printf(jp, parens ? ")%s" : "%s",
-                              ((fun->flags & JSFUN_LAMBDA) || !fun->atom)
+                              ((fun->flags & JSFUN_LAMBDA) || !fun->atom())
                               ? ""
                               : ";");
                     todo = -2;
                     break;
                 }
                 /* FALL THROUGH */
 
               case JSOP_SETRVAL:
@@ -4845,18 +4845,18 @@ Decompile(SprintStack *ss, jsbytecode *p
                     if (!str)
                         return NULL;
                 }
               sprint_string:
                 todo = ss->sprinter.putString(str);
                 break;
 
               case JSOP_CALLEE:
-                JS_ASSERT(jp->fun && jp->fun->atom);
-                todo = ss->sprinter.putString(jp->fun->atom);
+                JS_ASSERT(jp->fun && jp->fun->atom());
+                todo = ss->sprinter.putString(jp->fun->atom());
                 break;
 
               case JSOP_OBJECT:
                 obj = jp->script->getObject(GET_UINT32_INDEX(pc));
                 str = js_ValueToSource(cx, ObjectValue(*obj));
                 if (!str)
                     return NULL;
                 goto sprint_string;
@@ -5595,17 +5595,17 @@ js_DecompileFunction(JSPrinter *jp)
     if (jp->pretty) {
         js_printf(jp, "\t");
     } else {
         if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
             js_puts(jp, "(");
     }
 
     js_printf(jp, "%s ", js_function_str);
-    if (fun->atom && !QuoteString(&jp->sprinter, fun->atom, 0))
+    if (fun->atom() && !QuoteString(&jp->sprinter, fun->atom(), 0))
         return JS_FALSE;
     js_puts(jp, "(");
 
     if (fun->isNative() || fun->isSelfHostedBuiltin()) {
         js_printf(jp, ") {\n");
         jp->indent += 4;
         js_printf(jp, native_code_str);
         jp->indent -= 4;
@@ -6565,17 +6565,17 @@ GetPCCountScriptSummary(JSContext *cx, s
     if (!str || !(str = JS_ValueToSource(cx, StringValue(str))))
         return NULL;
     buf.append(str);
 
     AppendJSONProperty(buf, "line");
     NumberValueToStringBuffer(cx, Int32Value(script->lineno), buf);
 
     if (script->function()) {
-        JSAtom *atom = script->function()->atom;
+        JSAtom *atom = script->function()->displayAtom();
         if (atom) {
             AppendJSONProperty(buf, "name");
             if (!(str = JS_ValueToSource(cx, StringValue(atom))))
                 return NULL;
             buf.append(str);
         }
     }
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3100,17 +3100,17 @@ ASTSerializer::function(ParseNode *pn, A
     bool isExpression =
 #if JS_HAS_EXPR_CLOSURES
         func->flags & JSFUN_EXPR_CLOSURE;
 #else
         false;
 #endif
 
     Value id;
-    if (!optIdentifier(func->atom, NULL, &id))
+    if (!optIdentifier(func->atom(), NULL, &id))
         return false;
 
     NodeVector args(cx);
     NodeVector defaults(cx);
 
     Value body;
     Value rest;
     if (func->hasRest())
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -321,17 +321,17 @@ 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.
      */
     Rooted<JSObject*> parent(cx, &fp->varObj());
 
     /* ES5 10.5 (NB: with subsequent errata). */
-    RootedPropertyName name(cx, fun->atom->asPropertyName());
+    RootedPropertyName name(cx, fun->atom()->asPropertyName());
     RootedShape shape(cx);
     RootedObject pobj(cx);
     if (!JSObject::lookupProperty(cx, parent, name, &pobj, &shape))
         THROW();
 
     RootedValue rval(cx, ObjectValue(*fun));
 
     do {
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3703,17 +3703,17 @@ static JSBool
 DebuggerObject_getName(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "get name", args, dbg, obj);
     if (!obj->isFunction()) {
         args.rval().setUndefined();
         return true;
     }
 
-    JSString *name = obj->toFunction()->atom;
+    JSString *name = obj->toFunction()->atom();
     if (!name) {
         args.rval().setUndefined();
         return true;
     }
 
     Value namev = StringValue(name);
     if (!dbg->wrapDebuggeeValue(cx, &namev))
         return false;
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -165,19 +165,19 @@ SPSProfiler::pop()
  * some scripts, resize the hash table of profile strings, and invalidate the
  * AddPtr held while invoking allocProfileString.
  */
 const char*
 SPSProfiler::allocProfileString(JSContext *cx, JSScript *script, JSFunction *maybeFun)
 {
     DebugOnly<uint64_t> gcBefore = cx->runtime->gcNumber;
     StringBuffer buf(cx);
-    bool hasAtom = maybeFun != NULL && maybeFun->atom != NULL;
+    bool hasAtom = maybeFun != NULL && maybeFun->displayAtom() != NULL;
     if (hasAtom) {
-        if (!buf.append(maybeFun->atom))
+        if (!buf.append(maybeFun->displayAtom()))
             return NULL;
         if (!buf.append(" ("))
             return NULL;
     }
     if (script->filename) {
         if (!buf.appendInflated(script->filename, strlen(script->filename)))
             return NULL;
     } else if (!buf.append("<unknown>")) {
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -251,17 +251,17 @@ DeclEnvObject::create(JSContext *cx, Sta
 
     RootedObject obj(cx, JSObject::create(cx, FINALIZE_KIND, emptyDeclEnvShape, type, NULL));
     if (!obj)
         return NULL;
 
     if (!obj->asScope().setEnclosingScope(cx, fp->scopeChain()))
         return NULL;
 
-    Rooted<jsid> id(cx, AtomToId(fp->fun()->atom));
+    Rooted<jsid> id(cx, AtomToId(fp->fun()->atom()));
     RootedValue value(cx, ObjectValue(fp->callee()));
     if (!DefineNativeProperty(cx, obj, id, value, NULL, NULL,
                               JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
                               0, 0)) {
         return NULL;
     }
 
     return &obj->asDeclEnv();