[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:
parent
518d91e93d
commit
ee9ac86ad9
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user