зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1113378 - Part 1/2 - Always fully parse IIFEs. r=Waldo
This commit is contained in:
Родитель
a4a116c79d
Коммит
61a4d0e8f4
|
@ -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; }
|
||||
|
|
|
@ -2155,7 +2155,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);
|
||||
|
||||
|
@ -2164,6 +2164,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();
|
||||
|
@ -2323,6 +2326,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;
|
||||
|
@ -2637,7 +2647,7 @@ Parser<ParseHandler>::functionStmt()
|
|||
|
||||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::functionExpr()
|
||||
Parser<ParseHandler>::functionExpr(InvokedPrediction invoked)
|
||||
{
|
||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
|
||||
|
||||
|
@ -2663,7 +2673,7 @@ Parser<ParseHandler>::functionExpr()
|
|||
tokenStream.ungetToken();
|
||||
}
|
||||
|
||||
return functionDef(name, Normal, Expression, generatorKind);
|
||||
return functionDef(name, Normal, Expression, generatorKind, invoked);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4405,10 +4415,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))
|
||||
|
@ -5886,6 +5896,9 @@ Parser<ParseHandler>::statement(bool canHaveDirectives)
|
|||
return expressionStatement();
|
||||
}
|
||||
|
||||
case TOK_NEW:
|
||||
return expressionStatement(PredictInvoked);
|
||||
|
||||
default:
|
||||
return expressionStatement();
|
||||
}
|
||||
|
@ -5893,9 +5906,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();
|
||||
|
||||
|
@ -6017,7 +6030,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.
|
||||
|
@ -6033,7 +6046,7 @@ Parser<ParseHandler>::orExpr1()
|
|||
|
||||
Node pn;
|
||||
for (;;) {
|
||||
pn = unaryExpr();
|
||||
pn = unaryExpr(invoked);
|
||||
if (!pn)
|
||||
return pn;
|
||||
|
||||
|
@ -6083,9 +6096,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;
|
||||
|
||||
|
@ -6184,7 +6197,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());
|
||||
|
||||
|
@ -6236,7 +6249,7 @@ Parser<ParseHandler>::assignExpr()
|
|||
TokenStream::Position start(keepAtoms);
|
||||
tokenStream.tell(&start);
|
||||
|
||||
Node lhs = condExpr1();
|
||||
Node lhs = condExpr1(invoked);
|
||||
if (!lhs)
|
||||
return null();
|
||||
|
||||
|
@ -6342,7 +6355,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;
|
||||
|
||||
|
@ -6400,7 +6413,7 @@ Parser<ParseHandler>::unaryExpr()
|
|||
}
|
||||
|
||||
default:
|
||||
pn = memberExpr(tt, true);
|
||||
pn = memberExpr(tt, /* allowCallSyntax = */ true, invoked);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
|
@ -7503,7 +7516,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));
|
||||
|
||||
|
@ -7519,7 +7532,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();
|
||||
|
||||
|
@ -7536,7 +7549,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();
|
||||
}
|
||||
|
@ -8129,14 +8142,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();
|
||||
|
@ -8270,7 +8283,7 @@ Parser<ParseHandler>::parenExprOrGeneratorComprehension()
|
|||
*/
|
||||
bool oldParsingForInit = pc->parsingForInit;
|
||||
pc->parsingForInit = false;
|
||||
Node pn = expr();
|
||||
Node pn = expr(PredictInvoked);
|
||||
pc->parsingForInit = oldParsingForInit;
|
||||
|
||||
if (!pn)
|
||||
|
@ -8348,7 +8361,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; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче