From ee9ac86ad9999b9ebf4bc89915b6104494aa7ba9 Mon Sep 17 00:00:00 2001 From: Toon Verwaest Date: Mon, 15 Oct 2018 13:56:05 +0200 Subject: [PATCH] [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 Reviewed-by: Sathya Gunasekaran Cr-Commit-Position: refs/heads/master@{#56633} --- src/parsing/parser-base.h | 26 ++++++++++++++------------ src/parsing/token.h | 18 ++++++++++++------ test/cctest/test-parsing.cc | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h index 2a55cf3bf8..a50c25dded 100644 --- a/src/parsing/parser-base.h +++ b/src/parsing/parser-base.h @@ -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::ParseLeftHandSideExpression(bool* ok) { // (NewExpression | MemberExpression) ... ExpressionT result = ParseMemberWithNewPrefixesExpression(CHECK_OK); + if (!Token::IsPropertyOrCall(peek())) return result; + return ParseLeftHandSideContinuation(result, ok); +} - while (true) { +template +typename ParserBase::ExpressionT +ParserBase::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::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::ParseLeftHandSideExpression(bool* ok) { } case Token::PERIOD: { - ValidateExpression(CHECK_OK); - BindingPatternUnexpectedToken(); ArrowFormalParametersUnexpectedToken(); Consume(Token::PERIOD); int pos = position(); @@ -3353,17 +3356,16 @@ ParserBase::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 diff --git a/src/parsing/token.h b/src/parsing/token.h index e1c6239e36..262dd91011 100644 --- a/src/parsing/token.h +++ b/src/parsing/token.h @@ -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); } diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 4289e49fe2..393def9feb 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -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(i); + CHECK_EQ(TokenIsPropertyOrCall(token), Token::IsPropertyOrCall(token)); + } +} + bool TokenIsCountOp(Token::Value token) { switch (token) { case Token::INC: