Bug 1113378 - Always fully parse IIFEs. r=Waldo

This commit is contained in:
Sean Stangl 2014-12-19 14:48:17 -08:00
Родитель 0abab85846
Коммит 35fd7d20a4
5 изменённых файлов: 56 добавлений и 32 удалений

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

@ -601,6 +601,9 @@ class FullParseHandler
pn->setInParens(true);
return pn;
}
ParseNode *setLikelyIIFE(ParseNode *pn) {
return setInParens(pn);
}
void setPrologue(ParseNode *pn) {
pn->pn_prologue = true;
}

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

@ -511,6 +511,7 @@ class ParseNode
/* Boolean attributes. */
bool isInParens() const { return pn_parens; }
bool isLikelyIIFE() const { return isInParens(); }
void setInParens(bool enabled) { pn_parens = enabled; }
bool isUsed() const { return pn_used; }
void setUsed(bool enabled) { pn_used = enabled; }

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

@ -2153,7 +2153,7 @@ template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::functionDef(HandlePropertyName funName,
FunctionType type, FunctionSyntaxKind kind,
GeneratorKind generatorKind)
GeneratorKind generatorKind, InvokedPrediction invoked)
{
MOZ_ASSERT_IF(kind == Statement, funName);
@ -2162,6 +2162,9 @@ Parser<ParseHandler>::functionDef(HandlePropertyName funName,
if (!pn)
return null();
if (invoked)
pn = handler.setLikelyIIFE(pn);
bool bodyProcessed;
if (!checkFunctionDefinition(funName, &pn, kind, &bodyProcessed))
return null();
@ -2321,6 +2324,13 @@ Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
// Try a syntax parse for this inner function.
do {
// If we're assuming this function is an IIFE, always perform a full
// parse to avoid the overhead of a lazy syntax-only parse. Although
// the prediction may be incorrect, IIFEs are common enough that it
// pays off for lots of code.
if (pn->isLikelyIIFE())
break;
Parser<SyntaxParseHandler> *parser = handler.syntaxParser;
if (!parser)
break;
@ -2635,7 +2645,7 @@ Parser<ParseHandler>::functionStmt()
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::functionExpr()
Parser<ParseHandler>::functionExpr(InvokedPrediction invoked)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
@ -2661,7 +2671,7 @@ Parser<ParseHandler>::functionExpr()
tokenStream.ungetToken();
}
return functionDef(name, Normal, Expression, generatorKind);
return functionDef(name, Normal, Expression, generatorKind, invoked);
}
/*
@ -4403,10 +4413,10 @@ Parser<SyntaxParseHandler>::exportDeclaration()
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::expressionStatement()
Parser<ParseHandler>::expressionStatement(InvokedPrediction invoked)
{
tokenStream.ungetToken();
Node pnexpr = expr();
Node pnexpr = expr(invoked);
if (!pnexpr)
return null();
if (!MatchOrInsertSemicolon(tokenStream))
@ -5884,6 +5894,9 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
return expressionStatement();
}
case TOK_NEW:
return expressionStatement(PredictInvoked);
default:
return expressionStatement();
}
@ -5891,9 +5904,9 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::expr()
Parser<ParseHandler>::expr(InvokedPrediction invoked)
{
Node pn = assignExpr();
Node pn = assignExpr(invoked);
if (!pn)
return null();
@ -6015,7 +6028,7 @@ Precedence(ParseNodeKind pnk) {
template <typename ParseHandler>
MOZ_ALWAYS_INLINE typename ParseHandler::Node
Parser<ParseHandler>::orExpr1()
Parser<ParseHandler>::orExpr1(InvokedPrediction invoked)
{
// Shift-reduce parser for the left-associative binary operator part of
// the JS syntax.
@ -6031,7 +6044,7 @@ Parser<ParseHandler>::orExpr1()
Node pn;
for (;;) {
pn = unaryExpr();
pn = unaryExpr(invoked);
if (!pn)
return pn;
@ -6081,9 +6094,9 @@ Parser<ParseHandler>::orExpr1()
template <typename ParseHandler>
MOZ_ALWAYS_INLINE typename ParseHandler::Node
Parser<ParseHandler>::condExpr1()
Parser<ParseHandler>::condExpr1(InvokedPrediction invoked)
{
Node condition = orExpr1();
Node condition = orExpr1(invoked);
if (!condition || !tokenStream.isCurrentTokenType(TOK_HOOK))
return condition;
@ -6182,7 +6195,7 @@ Parser<SyntaxParseHandler>::checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavo
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::assignExpr()
Parser<ParseHandler>::assignExpr(InvokedPrediction invoked)
{
JS_CHECK_RECURSION(context, return null());
@ -6234,7 +6247,7 @@ Parser<ParseHandler>::assignExpr()
TokenStream::Position start(keepAtoms);
tokenStream.tell(&start);
Node lhs = condExpr1();
Node lhs = condExpr1(invoked);
if (!lhs)
return null();
@ -6340,7 +6353,7 @@ Parser<ParseHandler>::unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::unaryExpr()
Parser<ParseHandler>::unaryExpr(InvokedPrediction invoked)
{
Node pn, pn2;
@ -6398,7 +6411,7 @@ Parser<ParseHandler>::unaryExpr()
}
default:
pn = memberExpr(tt, true);
pn = memberExpr(tt, /* allowCallSyntax = */ true, invoked);
if (!pn)
return null();
@ -7501,7 +7514,7 @@ Parser<ParseHandler>::argumentList(Node listNode, bool *isSpread)
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax, InvokedPrediction invoked)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
@ -7517,7 +7530,7 @@ Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
if (!tokenStream.getToken(&tt, TokenStream::Operand))
return null();
Node ctorExpr = memberExpr(tt, false);
Node ctorExpr = memberExpr(tt, false, PredictInvoked);
if (!ctorExpr)
return null();
@ -7534,7 +7547,7 @@ Parser<ParseHandler>::memberExpr(TokenKind tt, bool allowCallSyntax)
handler.setOp(lhs, JSOP_SPREADNEW);
}
} else {
lhs = primaryExpr(tt);
lhs = primaryExpr(tt, invoked);
if (!lhs)
return null();
}
@ -8126,14 +8139,14 @@ Parser<ParseHandler>::methodDefinition(Node literal, Node propname, FunctionType
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::primaryExpr(TokenKind tt)
Parser<ParseHandler>::primaryExpr(TokenKind tt, InvokedPrediction invoked)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(tt));
JS_CHECK_RECURSION(context, return null());
switch (tt) {
case TOK_FUNCTION:
return functionExpr();
return functionExpr(invoked);
case TOK_LB:
return arrayInitializer();
@ -8267,7 +8280,7 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
*/
bool oldParsingForInit = pc->parsingForInit;
pc->parsingForInit = false;
Node pn = expr();
Node pn = expr(PredictInvoked);
pc->parsingForInit = oldParsingForInit;
if (!pn)
@ -8345,7 +8358,7 @@ Parser<ParseHandler>::exprInParens()
*/
bool oldParsingForInit = pc->parsingForInit;
pc->parsingForInit = false;
Node pn = expr();
Node pn = expr(PredictInvoked);
pc->parsingForInit = oldParsingForInit;
if (!pn)

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

@ -518,6 +518,9 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
return tokenStream.options();
}
private:
enum InvokedPrediction { PredictUninvoked = false, PredictInvoked = true };
private:
/*
* JS parsers, from lowest to highest precedence.
@ -536,7 +539,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
* suffix) and a never-inlined version (with an 'n' suffix).
*/
Node functionStmt();
Node functionExpr();
Node functionExpr(InvokedPrediction invoked = PredictUninvoked);
Node statements();
Node blockStatement();
@ -558,19 +561,20 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node letStatement();
Node importDeclaration();
Node exportDeclaration();
Node expressionStatement();
Node expressionStatement(InvokedPrediction invoked = PredictUninvoked);
Node variables(ParseNodeKind kind, bool *psimple = nullptr,
StaticBlockObject *blockObj = nullptr,
VarContext varContext = HoistVars);
Node expr();
Node assignExpr();
Node expr(InvokedPrediction invoked = PredictUninvoked);
Node assignExpr(InvokedPrediction invoked = PredictUninvoked);
Node assignExprWithoutYield(unsigned err);
Node yieldExpression();
Node condExpr1();
Node orExpr1();
Node unaryExpr();
Node memberExpr(TokenKind tt, bool allowCallSyntax);
Node primaryExpr(TokenKind tt);
Node condExpr1(InvokedPrediction invoked = PredictUninvoked);
Node orExpr1(InvokedPrediction invoked = PredictUninvoked);
Node unaryExpr(InvokedPrediction invoked = PredictUninvoked);
Node memberExpr(TokenKind tt, bool allowCallSyntax,
InvokedPrediction invoked = PredictUninvoked);
Node primaryExpr(TokenKind tt, InvokedPrediction invoked = PredictUninvoked);
Node parenExprOrGeneratorComprehension();
Node exprInParens();
@ -584,7 +588,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
bool *hasRest);
Node functionDef(HandlePropertyName name, FunctionType type, FunctionSyntaxKind kind,
GeneratorKind generatorKind);
GeneratorKind generatorKind, InvokedPrediction invoked = PredictUninvoked);
bool functionArgsAndBody(Node pn, HandleFunction fun,
FunctionType type, FunctionSyntaxKind kind,
GeneratorKind generatorKind,

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

@ -231,6 +231,9 @@ class SyntaxParseHandler
// strict mode parsing.
return (pn == NodeString) ? NodeGeneric : pn;
}
Node setLikelyIIFE(Node pn) {
return pn; // Remain in syntax-parse mode.
}
void setPrologue(Node pn) {}
bool isConstant(Node pn) { return false; }