Bug 842884 - Don't do array assignment optimizations when spread is involved. r=jorendorff
authorBenjamin Peterson <benjamin@python.org>
Wed, 20 Feb 2013 14:48:59 -0500
changeset 122506 534b246aa51be8af0d263ef73b0715d6848e0103
parent 122505 cff90661f8cae50ebac52d218b6bacf8f2382fb4
child 122507 4bb3b21ec4e5f52862f738711a9b45e9e275a9ab
push id24342
push userryanvm@gmail.com
push dateThu, 21 Feb 2013 13:05:06 +0000
treeherdermozilla-central@702d2814efbf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs842884
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 842884 - Don't do array assignment optimizations when spread is involved. r=jorendorff
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/ParseNode.h
js/src/frontend/Parser.cpp
js/src/jit-test/tests/basic/spread-array-bug842884.js
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2991,17 +2991,17 @@ MaybeEmitGroupAssignment(JSContext *cx, 
 {
     JS_ASSERT(pn->isKind(PNK_ASSIGN));
     JS_ASSERT(pn->isOp(JSOP_NOP));
     JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
 
     ParseNode *lhs = pn->pn_left;
     ParseNode *rhs = pn->pn_right;
     if (lhs->isKind(PNK_ARRAY) && rhs->isKind(PNK_ARRAY) &&
-        !(rhs->pn_xflags & PNX_HOLEY) &&
+        !(rhs->pn_xflags & PNX_SPECIALARRAYINIT) &&
         lhs->pn_count <= rhs->pn_count)
     {
         if (groupOption == GroupIsDecl && !EmitDestructuringDecls(cx, bce, prologOp, lhs))
             return false;
         if (!EmitGroupAssignment(cx, bce, prologOp, lhs, rhs))
             return false;
         *pop = JSOP_NOP;
     }
@@ -3023,18 +3023,18 @@ MaybeEmitLetGroupDecl(JSContext *cx, Byt
 {
     JS_ASSERT(pn->isKind(PNK_ASSIGN));
     JS_ASSERT(pn->isOp(JSOP_NOP));
     JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
 
     ParseNode *lhs = pn->pn_left;
     ParseNode *rhs = pn->pn_right;
     if (lhs->isKind(PNK_ARRAY) && rhs->isKind(PNK_ARRAY) &&
-        !(rhs->pn_xflags & PNX_HOLEY) &&
-        !(lhs->pn_xflags & PNX_HOLEY) &&
+        !(rhs->pn_xflags & PNX_SPECIALARRAYINIT) &&
+        !(lhs->pn_xflags & PNX_SPECIALARRAYINIT) &&
         lhs->pn_count == rhs->pn_count)
     {
         for (ParseNode *l = lhs->pn_head; l; l = l->pn_next) {
             if (l->getOp() != JSOP_SETLOCAL)
                 return true;
         }
 
         for (ParseNode *r = rhs->pn_head; r; r = r->pn_next) {
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -647,17 +647,19 @@ struct ParseNode {
 #define PNX_FUNCDEFS    0x40            /* contains top-level function statements */
 #define PNX_SETCALL     0x80            /* call expression in lvalue context */
 #define PNX_DESTRUCT   0x100            /* destructuring special cases:
                                            1. shorthand syntax used, at present
                                               object destructuring ({x,y}) only;
                                            2. code evaluating destructuring
                                               arguments occurs before function
                                               body */
-#define PNX_HOLEY      0x200            /* array initialiser has holes */
+#define PNX_SPECIALARRAYINIT 0x200      /* one or more of
+                                           1. array initialiser has holes
+                                           2. array initializer has spread node */
 #define PNX_NONCONST   0x400            /* initialiser has non-constants */
 
     unsigned frameLevel() const {
         JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
         return pn_cookie.level();
     }
 
     unsigned frameSlot() const {
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -5732,33 +5732,34 @@ Parser::primaryExpr(TokenKind tt)
                     pn->pn_xflags |= PNX_ENDCOMMA;
                     break;
                 }
 
                 if (tt == TOK_COMMA) {
                     /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */
                     tokenStream.matchToken(TOK_COMMA);
                     pn2 = NullaryNode::create(PNK_COMMA, this);
-                    pn->pn_xflags |= PNX_HOLEY | PNX_NONCONST;
+                    pn->pn_xflags |= PNX_SPECIALARRAYINIT | PNX_NONCONST;
                 } else {
                     ParseNode *spreadNode = NULL;
                     if (tt == TOK_TRIPLEDOT) {
                         spread = true;
                         spreadNode = UnaryNode::create(PNK_SPREAD, this);
                         if (!spreadNode)
                             return NULL;
                         tokenStream.getToken();
                     }
                     pn2 = assignExpr();
                     if (pn2) {
                         if (foldConstants && !FoldConstants(context, &pn2, this))
                             return NULL;
                         if (!pn2->isConstant() || spreadNode)
                             pn->pn_xflags |= PNX_NONCONST;
                         if (spreadNode) {
+                            pn->pn_xflags |= PNX_SPECIALARRAYINIT;
                             spreadNode->pn_kid = pn2;
                             pn2 = spreadNode;
                         }
                     }
                 }
                 if (!pn2)
                     return NULL;
                 pn->append(pn2);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/spread-array-bug842884.js
@@ -0,0 +1,5 @@
+load(libdir + "asserts.js");
+
+assertThrowsInstanceOf(function () {
+    var [] = [x, ...d];
+}, ReferenceError);