Bug 759246 (part 4) - Don't share inForInit between Parser and BCE. r=jorendorff.

--HG--
extra : rebase_source : e96817e8d326a2f8f034e6166f70a05b86aaa49c
This commit is contained in:
Nicholas Nethercote 2012-05-28 21:57:36 -07:00
parent 669c9daf03
commit 0d58fdbb5f
5 changed files with 43 additions and 40 deletions

View File

@ -83,7 +83,8 @@ BytecodeEmitter::BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lin
typesetCount(0),
noScriptRval(noScriptRval),
needScriptGlobal(needScriptGlobal),
hasSingletons(false)
hasSingletons(false),
inForInit(false)
{
memset(&prolog, 0, sizeof prolog);
memset(&main, 0, sizeof main);
@ -1220,7 +1221,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* Don't generate upvars on the left side of a for loop. See
* bug 470758.
*/
if (bce->sc->inForInit)
if (bce->inForInit)
return JS_TRUE;
JS_ASSERT(caller->isScriptFrame());
@ -1653,11 +1654,11 @@ EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
ParseNode *pn2 = pn->pn_kid;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
if (!EmitTree(cx, bce, pn2))
return false;
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
return false;
@ -3346,11 +3347,11 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption
return JS_FALSE;
}
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
if (!EmitTree(cx, bce, pn3))
return JS_FALSE;
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
} else if (letNotes) {
/* JSOP_ENTERLETx expects at least 1 slot to have been pushed. */
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
@ -4499,10 +4500,10 @@ EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
if (pn1) {
ParseNode *decl = letDecl ? pn1->pn_expr : pn1;
JS_ASSERT(decl->isKind(PNK_VAR) || decl->isKind(PNK_LET));
bce->sc->inForInit = true;
bce->inForInit = true;
if (!EmitVariables(cx, bce, decl, DefineVars))
return false;
bce->sc->inForInit = false;
bce->inForInit = false;
}
/* Compile the object expression to the right of 'in'. */
@ -4642,7 +4643,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
/* No initializer: emit an annotated nop for the decompiler. */
op = JSOP_NOP;
} else {
bce->sc->inForInit = true;
bce->inForInit = true;
#if JS_HAS_DESTRUCTURING
if (pn3->isKind(PNK_ASSIGN)) {
JS_ASSERT(pn3->isOp(JSOP_NOP));
@ -4665,7 +4666,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
op = JSOP_NOP;
}
}
bce->sc->inForInit = false;
bce->inForInit = false;
}
/*
@ -5327,13 +5328,13 @@ EmitCallOrNew(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
* JSOP_NEW bytecode with a two-byte immediate telling how many args
* were pushed on the operand stack.
*/
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
if (!EmitTree(cx, bce, pn3))
return false;
}
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
return false;
@ -5813,12 +5814,12 @@ EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
op = JSOP_TYPEOFEXPR;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
if (!EmitTree(cx, bce, pn2))
return false;
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
return Emit1(cx, bce, op) >= 0;
}
@ -6220,8 +6221,8 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* possibly including a let (a = b) ... expression. We must clear
* inForInit to avoid mis-compiling such beasts.
*/
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
#endif
/* Binary operators that evaluate both operands unconditionally. */
@ -6230,7 +6231,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (!EmitTree(cx, bce, pn->pn_right))
return JS_FALSE;
#if JS_HAS_XML_SUPPORT
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
#endif
if (Emit1(cx, bce, pn->getOp()) < 0)
return JS_FALSE;
@ -6245,11 +6246,11 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
} else {
JSOp op = pn->getOp();
JS_ASSERT(op == JSOP_BINDXMLNAME || op == JSOP_SETXMLNAME);
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
bool oldInForInit = bce->inForInit;
bce->inForInit = false;
if (!EmitTree(cx, bce, pn->pn_kid))
return false;
bce->sc->inForInit = oldInForInit;
bce->inForInit = oldInForInit;
if (Emit1(cx, bce, op) < 0)
return false;
}

View File

@ -127,6 +127,8 @@ struct BytecodeEmitter
bool hasSingletons:1; /* script contains singleton initializer JSOP_OBJECT */
bool inForInit:1; /* emitting init expr of for; exclude 'in' */
BytecodeEmitter(Parser *parser, SharedContext *sc, unsigned lineno,
bool noScriptRval, bool needScriptGlobal);
bool init();

View File

@ -3151,7 +3151,7 @@ Parser::forStatement()
* expressions involving an 'in' operator are illegal in the init
* clause of an ordinary for loop.
*/
tc->sc->inForInit = true;
tc->inForInit = true;
if (tt == TOK_VAR || tt == TOK_CONST) {
forDecl = true;
tokenStream.consumeKnownToken(tt);
@ -3174,7 +3174,7 @@ Parser::forStatement()
else {
pn1 = expr();
}
tc->sc->inForInit = false;
tc->inForInit = false;
if (!pn1)
return NULL;
}
@ -3192,7 +3192,7 @@ Parser::forStatement()
* We can be sure that it's a for/in loop if there's still an 'in'
* keyword here, even if JavaScript recognizes 'in' as an operator,
* as we've excluded 'in' from being parsed in RelExpr by setting
* tc->sc->inForInit.
* tc->inForInit.
*/
ParseNode *forHead; /* initialized by both branches. */
StmtInfo letStmt(context); /* used if blockObj != NULL. */
@ -4255,7 +4255,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
if (!CheckDestructuring(context, &data, pn2, this))
return NULL;
bool ignored;
if (tc->sc->inForInit && matchInOrOf(&ignored)) {
if (tc->inForInit && matchInOrOf(&ignored)) {
tokenStream.ungetToken();
pn->append(pn2);
continue;
@ -4462,8 +4462,8 @@ BEGIN_EXPR_PARSER(relExpr1)
* Uses of the in operator in shiftExprs are always unambiguous,
* so unset the flag that prohibits recognizing it.
*/
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
bool oldInForInit = tc->inForInit;
tc->inForInit = false;
ParseNode *pn = shiftExpr1i();
while (pn &&
@ -4479,7 +4479,7 @@ BEGIN_EXPR_PARSER(relExpr1)
pn = ParseNode::newBinaryOrAppend(kind, op, pn, shiftExpr1n(), this);
}
/* Restore previous state of inForInit flag. */
tc->sc->inForInit |= oldInForInit;
tc->inForInit |= oldInForInit;
return pn;
}
@ -4573,10 +4573,10 @@ Parser::condExpr1()
* where it's unambiguous, even if we might be parsing the init of a
* for statement.
*/
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
bool oldInForInit = tc->inForInit;
tc->inForInit = false;
ParseNode *thenExpr = assignExpr();
tc->sc->inForInit = oldInForInit;
tc->inForInit = oldInForInit;
if (!thenExpr)
return NULL;
@ -5874,10 +5874,10 @@ Parser::bracketedExpr()
* where it's unambiguous, even if we might be parsing the init of a
* for statement.
*/
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
bool oldInForInit = tc->inForInit;
tc->inForInit = false;
ParseNode *pn = expr();
tc->sc->inForInit = oldInForInit;
tc->inForInit = oldInForInit;
return pn;
}

View File

@ -30,7 +30,6 @@ SharedContext::SharedContext(JSContext *cx, JSObject *scopeChain, JSFunction *fu
staticLevel(0),
bindings(cx),
bindingsRoot(cx, &bindings),
inForInit(false),
cxFlags(cx)
{
JS_ASSERT((fun && !scopeChain_) || (!fun && !funbox));
@ -78,6 +77,7 @@ TreeContext::TreeContext(Parser *prs, SharedContext *sc)
funcStmts(NULL),
hasReturnExpr(false),
hasReturnVoid(false),
inForInit(false),
inDeclDestructuring(false)
{
prs->tc = this;

View File

@ -156,8 +156,6 @@ struct SharedContext {
arguments if we're compiling a function */
Bindings::AutoRooter bindingsRoot; /* root for stack allocated bindings. */
bool inForInit:1; /* parsing/emitting init expr of for; exclude 'in' */
ContextFlags cxFlags;
// If it's function code, fun must be non-NULL and scopeChain must be NULL.
@ -256,6 +254,8 @@ struct TreeContext { /* tree context for semantic checks */
bool hasReturnExpr:1; /* function has 'return <expr>;' */
bool hasReturnVoid:1; /* function has 'return;' */
bool inForInit:1; /* parsing init expr of for; exclude 'in' */
// Set when parsing a declaration-like destructuring pattern. This flag
// causes PrimaryExpr to create PN_NAME parse nodes for variable references
// which are not hooked into any definition's use chain, added to any tree