Bug 471703 - Don't optimize group assignment given holey RHS (r=igor).
--- 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);