Speed up parsing w/ grammar shortcut.
Certain token combinations (e.g. number literal followed by semicolon) will result in a single AST node, but require many levels of recursive descent parsing to determine this (11 in this example). For some 'obvious' combinations, we'll simply generate the appropriate AST node fairly far up in the call tree. This yields a mild but consistent parser speedup. The main con is code duplication. [Speedup between 0..20ms in parse time among a set of 25 commonly used sites. Speedup of ~180ms for a site w/ a very large codebase (adwords.google.com). Minor slow-downs between 0..8ms for <20% of sites.] R=marja@chromium.org BUG=v8:4947 Review-Url: https://codereview.chromium.org/2188153002 Cr-Commit-Position: refs/heads/master@{#38591}
This commit is contained in:
parent
93ad996e28
commit
7a100dffc6
@ -1130,6 +1130,7 @@ class ParserBase : public Traits {
|
||||
int formals_end_pos, bool* ok);
|
||||
|
||||
bool IsNextLetKeyword();
|
||||
bool IsTrivialExpression();
|
||||
|
||||
// Checks if the expression is a valid reference expression (e.g., on the
|
||||
// left-hand side of assignments). Although ruled out by ECMA as early errors,
|
||||
@ -1556,8 +1557,6 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
|
||||
case Token::NULL_LITERAL:
|
||||
case Token::TRUE_LITERAL:
|
||||
case Token::FALSE_LITERAL:
|
||||
BindingPatternUnexpectedToken(classifier);
|
||||
return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
|
||||
case Token::SMI:
|
||||
case Token::NUMBER:
|
||||
BindingPatternUnexpectedToken(classifier);
|
||||
@ -2310,8 +2309,17 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
|
||||
if (!is_async && !parenthesized_formals) {
|
||||
ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
|
||||
}
|
||||
ExpressionT expression = this->ParseConditionalExpression(
|
||||
|
||||
// Parse a simple, faster sub-grammar (primary expression) if it's evident
|
||||
// that we have only a trivial expression to parse.
|
||||
ExpressionT expression;
|
||||
if (IsTrivialExpression()) {
|
||||
expression = this->ParsePrimaryExpression(&arrow_formals_classifier,
|
||||
&is_async, CHECK_OK);
|
||||
} else {
|
||||
expression = this->ParseConditionalExpression(
|
||||
accept_IN, &arrow_formals_classifier, CHECK_OK);
|
||||
}
|
||||
|
||||
if (is_async && peek_any_identifier() && PeekAhead() == Token::ARROW) {
|
||||
// async Identifier => AsyncConciseBody
|
||||
@ -3367,6 +3375,24 @@ bool ParserBase<Traits>::IsNextLetKeyword() {
|
||||
}
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
bool ParserBase<Traits>::IsTrivialExpression() {
|
||||
Token::Value peek_token = peek();
|
||||
if (peek_token == Token::SMI || peek_token == Token::NUMBER ||
|
||||
peek_token == Token::NULL_LITERAL || peek_token == Token::TRUE_LITERAL ||
|
||||
peek_token == Token::FALSE_LITERAL || peek_token == Token::STRING ||
|
||||
peek_token == Token::IDENTIFIER || peek_token == Token::THIS) {
|
||||
// PeekAhead() is expensive & may not always be called, so we only call it
|
||||
// after checking peek().
|
||||
Token::Value peek_ahead = PeekAhead();
|
||||
if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN ||
|
||||
peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Traits>
|
||||
typename ParserBase<Traits>::ExpressionT
|
||||
ParserBase<Traits>::ParseArrowFunctionLiteral(
|
||||
|
Loading…
Reference in New Issue
Block a user