[parser] Restructure ParseLeftHandSide

- use a token-range to quickly identify LHS continuation
- queue binding pattern errors only once
- outline LHS continuation to reduce memory overhead from aggressive inlining (30kb)

Change-Id: Ic0f3cfc3ea0bd6cedb6cea991a69f55f2bada14a
Reviewed-on: https://chromium-review.googlesource.com/c/1280207
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56633}
This commit is contained in:
Toon Verwaest 2018-10-15 13:56:05 +02:00 committed by Commit Bot
parent 518d91e93d
commit ee9ac86ad9
3 changed files with 46 additions and 18 deletions

View File

@ -1096,6 +1096,7 @@ class ParserBase {
V8_INLINE ExpressionT ParseUnaryExpression(bool* ok);
V8_INLINE ExpressionT ParsePostfixExpression(bool* ok);
V8_INLINE ExpressionT ParseLeftHandSideExpression(bool* ok);
ExpressionT ParseLeftHandSideContinuation(ExpressionT expression, bool* ok);
ExpressionT ParseMemberWithPresentNewPrefixesExpression(bool* ok);
V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
ExpressionT ParseFunctionExpression(bool* ok);
@ -3243,17 +3244,23 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
// (NewExpression | MemberExpression) ...
ExpressionT result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
if (!Token::IsPropertyOrCall(peek())) return result;
return ParseLeftHandSideContinuation(result, ok);
}
while (true) {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result, bool* ok) {
BindingPatternUnexpectedToken();
do {
ValidateExpression(CHECK_OK);
switch (peek()) {
case Token::LBRACK: {
ValidateExpression(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
Consume(Token::LBRACK);
int pos = position();
ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK);
ValidateExpression(CHECK_OK);
result = factory()->NewProperty(result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
@ -3261,8 +3268,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
case Token::LPAREN: {
int pos;
ValidateExpression(CHECK_OK);
BindingPatternUnexpectedToken();
if (scanner()->current_token() == Token::IDENTIFIER ||
scanner()->current_token() == Token::SUPER ||
scanner()->current_token() == Token::ASYNC) {
@ -3341,8 +3346,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
}
case Token::PERIOD: {
ValidateExpression(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
Consume(Token::PERIOD);
int pos = position();
@ -3353,17 +3356,16 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL: {
ValidateExpression(CHECK_OK);
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
result = ParseTemplateLiteral(result, position(), true, CHECK_OK);
break;
}
default:
return result;
UNREACHABLE();
}
}
} while (Token::IsPropertyOrCall(peek()));
return result;
}
template <typename Impl>

View File

@ -58,16 +58,22 @@ namespace internal {
/* End of source indicator. */ \
T(EOS, "EOS", 0) \
\
/* BEGIN PropertyOrCall */ \
/* ES6 Template Literals */ \
T(TEMPLATE_SPAN, nullptr, 0) \
T(TEMPLATE_TAIL, nullptr, 0) \
\
/* Punctuators (ECMA-262, section 7.7, page 15). */ \
T(PERIOD, ".", 0) \
T(LPAREN, "(", 0) \
T(RPAREN, ")", 0) \
T(LBRACK, "[", 0) \
/* END PropertyOrCall */ \
T(RPAREN, ")", 0) \
T(RBRACK, "]", 0) \
T(LBRACE, "{", 0) \
T(RBRACE, "}", 0) \
T(COLON, ":", 0) \
T(SEMICOLON, ";", 0) \
T(PERIOD, ".", 0) \
T(ELLIPSIS, "...", 0) \
T(CONDITIONAL, "?", 3) \
T(INC, "++", 0) \
@ -180,10 +186,6 @@ namespace internal {
T(UNINITIALIZED, nullptr, 0) \
T(REGEXP_LITERAL, nullptr, 0) \
\
/* ES6 Template Literals */ \
T(TEMPLATE_SPAN, nullptr, 0) \
T(TEMPLATE_TAIL, nullptr, 0) \
\
/* Contextual keyword tokens */ \
C(GET, "get", 0) \
C(SET, "set", 0) \
@ -247,6 +249,10 @@ class Token {
return IsInRange(token, NULL_LITERAL, STRING);
}
static bool IsPropertyOrCall(Value token) {
return IsInRange(token, TEMPLATE_SPAN, LBRACK);
}
static bool IsAssignmentOp(Value token) {
return IsInRange(token, INIT, ASSIGN_EXP);
}

View File

@ -331,6 +331,26 @@ TEST(IsUnaryOp) {
}
}
bool TokenIsPropertyOrCall(Token::Value token) {
switch (token) {
case Token::TEMPLATE_SPAN:
case Token::TEMPLATE_TAIL:
case Token::PERIOD:
case Token::LPAREN:
case Token::LBRACK:
return true;
default:
return false;
}
}
TEST(IsPropertyOrCall) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsPropertyOrCall(token), Token::IsPropertyOrCall(token));
}
}
bool TokenIsCountOp(Token::Value token) {
switch (token) {
case Token::INC: