Bug 753249 (part 2) - Remove TCF_IN_FOR_INIT from TreeContextFlags. r=luke.

--HG--
extra : rebase_source : f70060e47de0130c558c798a572d83c9184f82c5
This commit is contained in:
Nicholas Nethercote 2012-05-14 21:38:36 -07:00
Родитель 48cdc0227e
Коммит 1c5be94e4d
4 изменённых файлов: 58 добавлений и 59 удалений

Просмотреть файл

@ -1252,7 +1252,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->flags & TCF_IN_FOR_INIT)
if (bce->sc->inForInit)
return JS_TRUE;
JS_ASSERT(caller->isScriptFrame());
@ -1682,11 +1682,11 @@ EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
ParseNode *pn2 = pn->pn_kid;
unsigned oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
if (!EmitTree(cx, bce, pn2))
return false;
bce->sc->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
return false;
@ -3375,11 +3375,11 @@ EmitVariables(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, VarEmitOption
return JS_FALSE;
}
unsigned oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
if (!EmitTree(cx, bce, pn3))
return JS_FALSE;
bce->sc->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
} else if (letNotes) {
/* JSOP_ENTERLETx expects at least 1 slot to have been pushed. */
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
@ -4526,10 +4526,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->flags |= TCF_IN_FOR_INIT;
bce->sc->inForInit = true;
if (!EmitVariables(cx, bce, decl, DefineVars))
return false;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bce->sc->inForInit = false;
}
/* Compile the object expression to the right of 'in'. */
@ -4669,7 +4669,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->flags |= TCF_IN_FOR_INIT;
bce->sc->inForInit = true;
#if JS_HAS_DESTRUCTURING
if (pn3->isKind(PNK_ASSIGN)) {
JS_ASSERT(pn3->isOp(JSOP_NOP));
@ -4692,7 +4692,7 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
op = JSOP_NOP;
}
}
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bce->sc->inForInit = false;
}
/*
@ -5394,13 +5394,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.
*/
unsigned oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
if (!EmitTree(cx, bce, pn3))
return false;
}
bce->sc->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - off) < 0)
return false;
@ -5880,12 +5880,12 @@ EmitUnary(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (op == JSOP_TYPEOF && !pn2->isKind(PNK_NAME))
op = JSOP_TYPEOFEXPR;
unsigned oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
if (!EmitTree(cx, bce, pn2))
return false;
bce->sc->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
return Emit1(cx, bce, op) >= 0;
}
@ -6116,7 +6116,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
}
} else {
#if JS_HAS_XML_SUPPORT
unsigned oldflags;
case PNK_DBLCOLON:
JS_ASSERT(pn->getOp() != JSOP_XMLNAME);
@ -6131,10 +6130,10 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
/*
* Binary :: has a right operand that brackets arbitrary code,
* possibly including a let (a = b) ... expression. We must clear
* TCF_IN_FOR_INIT to avoid mis-compiling such beasts.
* inForInit to avoid mis-compiling such beasts.
*/
oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
#endif
/* Binary operators that evaluate both operands unconditionally. */
@ -6143,7 +6142,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->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
#endif
if (Emit1(cx, bce, pn->getOp()) < 0)
return JS_FALSE;
@ -6158,11 +6157,11 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
} else {
JSOp op = pn->getOp();
JS_ASSERT(op == JSOP_BINDXMLNAME || op == JSOP_SETXMLNAME);
unsigned oldflags = bce->sc->flags;
bce->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = bce->sc->inForInit;
bce->sc->inForInit = false;
if (!EmitTree(cx, bce, pn->pn_kid))
return false;
bce->sc->flags |= oldflags & TCF_IN_FOR_INIT;
bce->sc->inForInit = oldInForInit;
if (Emit1(cx, bce, op) < 0)
return false;
}

Просмотреть файл

@ -3104,7 +3104,7 @@ Parser::forStatement()
/*
* Set pn1 to a var list or an initializing expression.
*
* Set the TCF_IN_FOR_INIT flag during parsing of the first clause
* Set the inForInit flag during parsing of the first clause
* of the for statement. This flag will be used by the RelExpr
* production; if it is set, then the 'in' keyword will not be
* recognized as an operator, leaving it available to be parsed as
@ -3114,7 +3114,7 @@ Parser::forStatement()
* expressions involving an 'in' operator are illegal in the init
* clause of an ordinary for loop.
*/
tc->sc->flags |= TCF_IN_FOR_INIT;
tc->sc->inForInit = true;
if (tt == TOK_VAR || tt == TOK_CONST) {
forDecl = true;
tokenStream.consumeKnownToken(tt);
@ -3137,7 +3137,7 @@ Parser::forStatement()
else {
pn1 = expr();
}
tc->sc->flags &= ~TCF_IN_FOR_INIT;
tc->sc->inForInit = false;
if (!pn1)
return NULL;
}
@ -3155,7 +3155,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
* the TCF_IN_FOR_INIT flag in our TreeContext.
* tc->sc->inForInit.
*/
ParseNode *forHead; /* initialized by both branches. */
StmtInfo letStmt(context); /* used if blockObj != NULL. */
@ -4217,7 +4217,7 @@ Parser::variables(ParseNodeKind kind, StaticBlockObject *blockObj, VarContext va
if (!CheckDestructuring(context, &data, pn2, this))
return NULL;
bool ignored;
if ((tc->sc->flags & TCF_IN_FOR_INIT) && matchInOrOf(&ignored)) {
if (tc->sc->inForInit && matchInOrOf(&ignored)) {
tokenStream.ungetToken();
pn->append(pn2);
continue;
@ -4420,13 +4420,12 @@ RelationalTokenToParseNodeKind(const Token &token)
BEGIN_EXPR_PARSER(relExpr1)
{
unsigned inForInitFlag = tc->sc->flags & TCF_IN_FOR_INIT;
/*
* Uses of the in operator in shiftExprs are always unambiguous,
* so unset the flag that prohibits recognizing it.
*/
tc->sc->flags &= ~TCF_IN_FOR_INIT;
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
ParseNode *pn = shiftExpr1i();
while (pn &&
@ -4435,14 +4434,14 @@ BEGIN_EXPR_PARSER(relExpr1)
* Recognize the 'in' token as an operator only if we're not
* currently in the init expr of a for loop.
*/
(inForInitFlag == 0 && tokenStream.isCurrentTokenType(TOK_IN)) ||
(oldInForInit == 0 && tokenStream.isCurrentTokenType(TOK_IN)) ||
tokenStream.isCurrentTokenType(TOK_INSTANCEOF))) {
ParseNodeKind kind = RelationalTokenToParseNodeKind(tokenStream.currentToken());
JSOp op = tokenStream.currentToken().t_op;
pn = ParseNode::newBinaryOrAppend(kind, op, pn, shiftExpr1n(), this);
}
/* Restore previous state of inForInit flag. */
tc->sc->flags |= inForInitFlag;
tc->sc->inForInit |= oldInForInit;
return pn;
}
@ -4536,10 +4535,12 @@ Parser::condExpr1()
* where it's unambiguous, even if we might be parsing the init of a
* for statement.
*/
unsigned oldflags = tc->sc->flags;
tc->sc->flags &= ~TCF_IN_FOR_INIT;
uint32_t oldflags = tc->sc->flags;
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
ParseNode *thenExpr = assignExpr();
tc->sc->flags = oldflags | (tc->sc->flags & TCF_FUN_FLAGS);
tc->sc->inForInit = oldInForInit;
if (!thenExpr)
return NULL;
@ -5803,18 +5804,17 @@ Parser::memberExpr(JSBool allowCallSyntax)
ParseNode *
Parser::bracketedExpr()
{
unsigned oldflags;
ParseNode *pn;
/*
* Always accept the 'in' operator in a parenthesized expression,
* where it's unambiguous, even if we might be parsing the init of a
* for statement.
*/
oldflags = tc->sc->flags;
tc->sc->flags &= ~TCF_IN_FOR_INIT;
pn = expr();
uint32_t oldflags = tc->sc->flags;
bool oldInForInit = tc->sc->inForInit;
tc->sc->inForInit = false;
ParseNode *pn = expr();
tc->sc->flags = oldflags | (tc->sc->flags & TCF_FUN_FLAGS);
tc->sc->inForInit = oldInForInit;
return pn;
}

Просмотреть файл

@ -64,7 +64,8 @@ SharedContext::SharedContext(JSContext *cx, bool inFunction)
functionList(NULL),
bindings(cx),
bindingsRoot(cx, &bindings),
inFunction(inFunction)
inFunction(inFunction),
inForInit(false)
{
}

Просмотреть файл

@ -58,24 +58,21 @@ namespace js {
JS_ENUM_HEADER(TreeContextFlags, uint32_t)
{
// parsing init expr of for; exclude 'in'
TCF_IN_FOR_INIT = 0x1,
// function needs Call object per call
TCF_FUN_HEAVYWEIGHT = 0x2,
TCF_FUN_HEAVYWEIGHT = 0x1,
// parsed yield statement in function
TCF_FUN_IS_GENERATOR = 0x4,
TCF_FUN_IS_GENERATOR = 0x2,
// flag lambda from generator expression
TCF_GENEXP_LAMBDA = 0x8,
TCF_GENEXP_LAMBDA = 0x4,
// This function/global/eval code body contained a Use Strict Directive.
// Treat certain strict warnings as errors, and forbid the use of 'with'.
// See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
// JSREPORT_STRICT_ERROR.
//
TCF_STRICT_MODE_CODE = 0x10,
TCF_STRICT_MODE_CODE = 0x8,
// The (static) bindings of this script need to support dynamic name
// read/write access. Here, 'dynamic' means dynamic dictionary lookup on
@ -97,17 +94,17 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// taken not to turn off the whole 'arguments' optimization). To answer the
// more general "is this argument aliased" question, script->needsArgsObj
// should be tested (see JSScript::argIsAlised).
TCF_BINDINGS_ACCESSED_DYNAMICALLY = 0x20,
TCF_BINDINGS_ACCESSED_DYNAMICALLY = 0x10,
// The function or a function that encloses it may define new local names
// at runtime through means other than calling eval.
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x40,
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x20,
// The script contains singleton initialiser JSOP_OBJECT.
TCF_HAS_SINGLETONS = 0x80,
TCF_HAS_SINGLETONS = 0x40,
// Some enclosing scope is a with-statement or E4X filter-expression.
TCF_IN_WITH = 0x100,
TCF_IN_WITH = 0x80,
// This function does something that can extend the set of bindings in its
// call objects --- it does a direct eval in non-strict code, or includes a
@ -116,7 +113,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// This flag is *not* inherited by enclosed or enclosing functions; it
// applies only to the function in whose flags it appears.
//
TCF_FUN_EXTENSIBLE_SCOPE = 0x200,
TCF_FUN_EXTENSIBLE_SCOPE = 0x100,
// Technically, every function has a binding named 'arguments'. Internally,
// this binding is only added when 'arguments' is mentioned by the function
@ -139,7 +136,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// have no special semantics: the initial value is unconditionally the
// actual argument (or undefined if nactual < nformal).
//
TCF_ARGUMENTS_HAS_LOCAL_BINDING = 0x400,
TCF_ARGUMENTS_HAS_LOCAL_BINDING = 0x200,
// In many cases where 'arguments' has a local binding (as described above)
// we do not need to actually create an arguments object in the function
@ -150,7 +147,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
// be unsound in several cases. The frontend filters out such cases by
// setting this flag which eagerly sets script->needsArgsObj to true.
//
TCF_DEFINITELY_NEEDS_ARGS_OBJ = 0x800
TCF_DEFINITELY_NEEDS_ARGS_OBJ = 0x400
} JS_ENUM_FOOTER(TreeContextFlags);
@ -198,7 +195,9 @@ struct SharedContext {
arguments if we're compiling a function */
Bindings::StackRoot bindingsRoot; /* root for stack allocated bindings. */
const bool inFunction; /* parsing/emitting inside function body */
const bool inFunction:1; /* parsing/emitting inside function body */
bool inForInit:1; /* parsing/emitting init expr of for; exclude 'in' */
inline SharedContext(JSContext *cx, bool inFunction);