Bug 471703 - Don't optimize group assignment given holey RHS (r=igor).
authorBrendan Eich <brendan@mozilla.org>
Thu, 07 May 2009 21:49:53 -0700
changeset 28123 834e62999a36ebc2fd232d1fc064fafb51bab6f8
parent 28122 81080882c3b5ca9b43d649a7dd4b6cdfbf5e5f29
child 28125 c4fcaec2898a3e95aad0692845f61fffb80ab964
push idunknown
push userunknown
push dateunknown
reviewersigor
bugs471703
milestone1.9.2a1pre
Bug 471703 - Don't optimize group assignment given holey RHS (r=igor).
js/src/jsemit.cpp
js/src/jsparse.cpp
js/src/jsparse.h
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -3823,42 +3823,35 @@ EmitGroupAssignment(JSContext *cx, JSCod
     depth = limit = (uintN) cg->stackDepth;
     for (pn = rhs->pn_head; pn; pn = pn->pn_next) {
         if (limit == JS_BIT(16)) {
             js_ReportCompileErrorNumber(cx, CG_TS(cg), rhs, JSREPORT_ERROR,
                                         JSMSG_ARRAY_INIT_TOO_BIG);
             return JS_FALSE;
         }
 
-        if (pn->pn_type == TOK_COMMA) {
-            if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
-                return JS_FALSE;
-        } else {
-            if (!js_EmitTree(cx, cg, pn))
-                return JS_FALSE;
-        }
+        /* MaybeEmitGroupAssignment won't call us if rhs is holey. */
+        JS_ASSERT(pn->pn_type != TOK_COMMA);
+        if (!js_EmitTree(cx, cg, pn))
+            return JS_FALSE;
         ++limit;
     }
 
     if (js_NewSrcNote2(cx, cg, SRC_GROUPASSIGN, OpToDeclType(prologOp)) < 0)
         return JS_FALSE;
 
     i = depth;
     for (pn = lhs->pn_head; pn; pn = pn->pn_next, ++i) {
-        if (i < limit) {
-            jsint slot;
-
-            slot = AdjustBlockSlot(cx, cg, i);
-            if (slot < 0)
-                return JS_FALSE;
-            EMIT_UINT16_IMM_OP(JSOP_GETLOCAL, slot);
-        } else {
-            if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
-                return JS_FALSE;
-        }
+        /* MaybeEmitGroupAssignment requires lhs->pn_count <= rhs->pn_count. */
+        JS_ASSERT(i < limit);
+        jsint slot = AdjustBlockSlot(cx, cg, i);
+        if (slot < 0)
+            return JS_FALSE;
+        EMIT_UINT16_IMM_OP(JSOP_GETLOCAL, slot);
+
         if (pn->pn_type == TOK_COMMA && pn->pn_arity == PN_NULLARY) {
             if (js_Emit1(cx, cg, JSOP_POP) < 0)
                 return JS_FALSE;
         } else {
             if (!EmitDestructuringLHS(cx, cg, pn))
                 return JS_FALSE;
         }
     }
@@ -3880,16 +3873,17 @@ MaybeEmitGroupAssignment(JSContext *cx, 
 {
     JSParseNode *lhs, *rhs;
 
     JS_ASSERT(pn->pn_type == TOK_ASSIGN);
     JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
     lhs = pn->pn_left;
     rhs = pn->pn_right;
     if (lhs->pn_type == TOK_RB && rhs->pn_type == TOK_RB &&
+        !(rhs->pn_xflags & PNX_HOLEY) &&
         lhs->pn_count <= rhs->pn_count) {
         if (!EmitGroupAssignment(cx, cg, prologOp, lhs, rhs))
             return JS_FALSE;
         *pop = JSOP_NOP;
     }
     return JS_TRUE;
 }
 
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -7563,16 +7563,17 @@ PrimaryExpr(JSContext *cx, JSTokenStream
                     pn->pn_xflags |= PNX_ENDCOMMA;
                     break;
                 }
 
                 if (tt == TOK_COMMA) {
                     /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */
                     js_MatchToken(cx, ts, TOK_COMMA);
                     pn2 = NewParseNode(PN_NULLARY, tc);
+                    pn->pn_xflags |= PNX_HOLEY;
                 } else {
                     pn2 = AssignExpr(cx, ts, tc);
                 }
                 if (!pn2)
                     return NULL;
                 pn->append(pn2);
 
                 if (tt != TOK_COMMA) {
--- a/js/src/jsparse.h
+++ b/js/src/jsparse.h
@@ -430,16 +430,17 @@ struct JSParseNode {
 #define PNX_FUNCDEFS   0x100            /* contains top-level function
                                            statements */
 #define PNX_DESTRUCT   0x200            /* destructuring special cases:
                                            1. shorthand syntax used, at present
                                               object destructuring ({x,y}) only;
                                            2. the first child of function body
                                               is code evaluating destructuring
                                               arguments */
+#define PNX_HOLEY      0x400            /* array initialiser has holes */
 
     uintN frameLevel() const {
         JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);
         return UPVAR_FRAME_SKIP(pn_cookie);
     }
 
     uintN frameSlot() const {
         JS_ASSERT(pn_arity == PN_FUNC || pn_arity == PN_NAME);