[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 ParseUnaryExpression(bool* ok);
|
||||||
V8_INLINE ExpressionT ParsePostfixExpression(bool* ok);
|
V8_INLINE ExpressionT ParsePostfixExpression(bool* ok);
|
||||||
V8_INLINE ExpressionT ParseLeftHandSideExpression(bool* ok);
|
V8_INLINE ExpressionT ParseLeftHandSideExpression(bool* ok);
|
||||||
|
ExpressionT ParseLeftHandSideContinuation(ExpressionT expression, bool* ok);
|
||||||
ExpressionT ParseMemberWithPresentNewPrefixesExpression(bool* ok);
|
ExpressionT ParseMemberWithPresentNewPrefixesExpression(bool* ok);
|
||||||
V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
|
V8_INLINE ExpressionT ParseMemberWithNewPrefixesExpression(bool* ok);
|
||||||
ExpressionT ParseFunctionExpression(bool* ok);
|
ExpressionT ParseFunctionExpression(bool* ok);
|
||||||
@ -3243,17 +3244,23 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
// (NewExpression | MemberExpression) ...
|
// (NewExpression | MemberExpression) ...
|
||||||
|
|
||||||
ExpressionT result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
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()) {
|
switch (peek()) {
|
||||||
case Token::LBRACK: {
|
case Token::LBRACK: {
|
||||||
ValidateExpression(CHECK_OK);
|
|
||||||
BindingPatternUnexpectedToken();
|
|
||||||
ArrowFormalParametersUnexpectedToken();
|
ArrowFormalParametersUnexpectedToken();
|
||||||
Consume(Token::LBRACK);
|
Consume(Token::LBRACK);
|
||||||
int pos = position();
|
int pos = position();
|
||||||
ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK);
|
ExpressionT index = ParseExpressionCoverGrammar(true, CHECK_OK);
|
||||||
ValidateExpression(CHECK_OK);
|
|
||||||
result = factory()->NewProperty(result, index, pos);
|
result = factory()->NewProperty(result, index, pos);
|
||||||
Expect(Token::RBRACK, CHECK_OK);
|
Expect(Token::RBRACK, CHECK_OK);
|
||||||
break;
|
break;
|
||||||
@ -3261,8 +3268,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
|
|
||||||
case Token::LPAREN: {
|
case Token::LPAREN: {
|
||||||
int pos;
|
int pos;
|
||||||
ValidateExpression(CHECK_OK);
|
|
||||||
BindingPatternUnexpectedToken();
|
|
||||||
if (scanner()->current_token() == Token::IDENTIFIER ||
|
if (scanner()->current_token() == Token::IDENTIFIER ||
|
||||||
scanner()->current_token() == Token::SUPER ||
|
scanner()->current_token() == Token::SUPER ||
|
||||||
scanner()->current_token() == Token::ASYNC) {
|
scanner()->current_token() == Token::ASYNC) {
|
||||||
@ -3341,8 +3346,6 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Token::PERIOD: {
|
case Token::PERIOD: {
|
||||||
ValidateExpression(CHECK_OK);
|
|
||||||
BindingPatternUnexpectedToken();
|
|
||||||
ArrowFormalParametersUnexpectedToken();
|
ArrowFormalParametersUnexpectedToken();
|
||||||
Consume(Token::PERIOD);
|
Consume(Token::PERIOD);
|
||||||
int pos = position();
|
int pos = position();
|
||||||
@ -3353,17 +3356,16 @@ ParserBase<Impl>::ParseLeftHandSideExpression(bool* ok) {
|
|||||||
|
|
||||||
case Token::TEMPLATE_SPAN:
|
case Token::TEMPLATE_SPAN:
|
||||||
case Token::TEMPLATE_TAIL: {
|
case Token::TEMPLATE_TAIL: {
|
||||||
ValidateExpression(CHECK_OK);
|
|
||||||
BindingPatternUnexpectedToken();
|
|
||||||
ArrowFormalParametersUnexpectedToken();
|
ArrowFormalParametersUnexpectedToken();
|
||||||
result = ParseTemplateLiteral(result, position(), true, CHECK_OK);
|
result = ParseTemplateLiteral(result, position(), true, CHECK_OK);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return result;
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
} while (Token::IsPropertyOrCall(peek()));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
|
@ -58,16 +58,22 @@ namespace internal {
|
|||||||
/* End of source indicator. */ \
|
/* End of source indicator. */ \
|
||||||
T(EOS, "EOS", 0) \
|
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). */ \
|
/* Punctuators (ECMA-262, section 7.7, page 15). */ \
|
||||||
|
T(PERIOD, ".", 0) \
|
||||||
T(LPAREN, "(", 0) \
|
T(LPAREN, "(", 0) \
|
||||||
T(RPAREN, ")", 0) \
|
|
||||||
T(LBRACK, "[", 0) \
|
T(LBRACK, "[", 0) \
|
||||||
|
/* END PropertyOrCall */ \
|
||||||
|
T(RPAREN, ")", 0) \
|
||||||
T(RBRACK, "]", 0) \
|
T(RBRACK, "]", 0) \
|
||||||
T(LBRACE, "{", 0) \
|
T(LBRACE, "{", 0) \
|
||||||
T(RBRACE, "}", 0) \
|
T(RBRACE, "}", 0) \
|
||||||
T(COLON, ":", 0) \
|
T(COLON, ":", 0) \
|
||||||
T(SEMICOLON, ";", 0) \
|
T(SEMICOLON, ";", 0) \
|
||||||
T(PERIOD, ".", 0) \
|
|
||||||
T(ELLIPSIS, "...", 0) \
|
T(ELLIPSIS, "...", 0) \
|
||||||
T(CONDITIONAL, "?", 3) \
|
T(CONDITIONAL, "?", 3) \
|
||||||
T(INC, "++", 0) \
|
T(INC, "++", 0) \
|
||||||
@ -180,10 +186,6 @@ namespace internal {
|
|||||||
T(UNINITIALIZED, nullptr, 0) \
|
T(UNINITIALIZED, nullptr, 0) \
|
||||||
T(REGEXP_LITERAL, nullptr, 0) \
|
T(REGEXP_LITERAL, nullptr, 0) \
|
||||||
\
|
\
|
||||||
/* ES6 Template Literals */ \
|
|
||||||
T(TEMPLATE_SPAN, nullptr, 0) \
|
|
||||||
T(TEMPLATE_TAIL, nullptr, 0) \
|
|
||||||
\
|
|
||||||
/* Contextual keyword tokens */ \
|
/* Contextual keyword tokens */ \
|
||||||
C(GET, "get", 0) \
|
C(GET, "get", 0) \
|
||||||
C(SET, "set", 0) \
|
C(SET, "set", 0) \
|
||||||
@ -247,6 +249,10 @@ class Token {
|
|||||||
return IsInRange(token, NULL_LITERAL, STRING);
|
return IsInRange(token, NULL_LITERAL, STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsPropertyOrCall(Value token) {
|
||||||
|
return IsInRange(token, TEMPLATE_SPAN, LBRACK);
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsAssignmentOp(Value token) {
|
static bool IsAssignmentOp(Value token) {
|
||||||
return IsInRange(token, INIT, ASSIGN_EXP);
|
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) {
|
bool TokenIsCountOp(Token::Value token) {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case Token::INC:
|
case Token::INC:
|
||||||
|
Loading…
Reference in New Issue
Block a user