Bug 784550 - Fix overly-conservative deoptimization of assignment to named lambda (r=jorendorff)
authorLuke Wagner <luke@mozilla.com>
Tue, 21 Aug 2012 18:26:22 -0700
changeset 105069 2a040b73f268165f182560b5ff8d3023a857aecd
parent 105068 2e06b3299a5e7e1325062d4bdb65a94705900ffb
child 105070 9c39400dd21d13d416759339f0505688e119629c
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersjorendorff
bugs784550
milestone17.0a1
Bug 784550 - Fix overly-conservative deoptimization of assignment to named lambda (r=jorendorff)
js/src/frontend/Parser.cpp
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1131,17 +1131,29 @@ LeaveFunction(ParseNode *fn, Parser *par
 
             if (atom == funName && kind == Expression) {
                 dn->setOp(JSOP_CALLEE);
                 if (!dn->pn_cookie.set(cx, funpc->staticLevel,
                                        UpvarCookie::CALLEE_SLOT))
                     return false;
                 dn->pn_dflags |= PND_BOUND;
                 JS_ASSERT(dn->kind() == Definition::NAMED_LAMBDA);
-                if (dn->isClosed())
+
+                /*
+                 * Since 'dn' is a placeholder, it has not been defined in the
+                 * ParseContext and hence we must manually flag a closed-over
+                 * callee name as needing a dynamic scope (this is done for all
+                 * definitions in the ParseContext by generateFunctionBindings).
+                 *
+                 * If 'dn' has been assigned to, then we also flag the function
+                 * scope has needing a dynamic scope so that dynamic scope
+                 * setter can either ignore the set (in non-strict mode) or
+                 * produce an error (in strict mode).
+                 */
+                if (dn->isClosed() || dn->isAssigned())
                     funpc->sc->fun()->flags |= JSFUN_HEAVYWEIGHT;
                 continue;
             }
 
             Definition *outer_dn = pc->decls().lookupFirst(atom);
 
             /*
              * Make sure to deoptimize lexical dependencies that are polluted
@@ -2217,27 +2229,16 @@ MakeSetCall(JSContext *cx, ParseNode *pn
 
 static void
 NoteLValue(JSContext *cx, ParseNode *pn, SharedContext *sc)
 {
     if (pn->isUsed())
         pn->pn_lexdef->pn_dflags |= PND_ASSIGNED;
 
     pn->pn_dflags |= PND_ASSIGNED;
-
-    /*
-     * An enclosing function's name is an immutable binding in ES5, so
-     * assignments to them must do nothing or throw a TypeError depending on
-     * code strictness. Outside strict mode, we optimize away assignment to
-     * the function name. For assignment to function name to fail in strict
-     * mode, we must have a binding for it in the scope chain; we ensure this
-     * happens by making such functions heavyweight.
-     */
-    if (sc->inFunction() && pn->pn_atom == sc->fun()->atom)
-        sc->setBindingsAccessedDynamically();
 }
 
 static bool
 NoteNameUse(ParseNode *pn, Parser *parser)
 {
     RootedPropertyName name(parser->context, pn->pn_atom->asPropertyName());
     StmtInfoPC *stmt = LexicalLookup(parser->pc, name, NULL, (StmtInfoPC *)NULL);