Commit 93fea343 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[parser] Use more range checks to reduce branches

- Introduce Token::IsLiteral helper
- Introduce Token::IsStrictReservedWord helper


Drive-by-fix:
- Use "token" instead of "tok" as variable name
- Keep enum order consistent accross files

Change-Id: Ie3b30a62dfbea761a31c32465c0afa681d326710
Reviewed-on: https://chromium-review.googlesource.com/1203952Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55804}
parent a15ad0d3
......@@ -1727,9 +1727,7 @@ ParserBase<Impl>::ParseAndClassifyIdentifier(bool* ok) {
}
return name;
} else if (is_sloppy(language_mode()) &&
(next == Token::FUTURE_STRICT_RESERVED_WORD ||
next == Token::ESCAPED_STRICT_RESERVED_WORD ||
next == Token::LET || next == Token::STATIC ||
(Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !is_generator()))) {
classifier()->RecordStrictModeFormalParameterError(
scanner()->location(), MessageTemplate::kUnexpectedStrictReserved);
......@@ -1762,9 +1760,7 @@ ParserBase<Impl>::ParseIdentifierOrStrictReservedWord(
next == Token::ASYNC) {
*is_strict_reserved = false;
*is_await = next == Token::AWAIT;
} else if (next == Token::ESCAPED_STRICT_RESERVED_WORD ||
next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
next == Token::STATIC ||
} else if (Token::IsStrictReservedWord(next) ||
(next == Token::YIELD && !IsGeneratorFunction(function_kind))) {
*is_strict_reserved = true;
} else {
......@@ -1780,12 +1776,8 @@ template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParseIdentifierName(
bool* ok) {
Token::Value next = Next();
if (next != Token::IDENTIFIER && next != Token::ASYNC &&
next != Token::ENUM && next != Token::AWAIT && next != Token::LET &&
next != Token::STATIC && next != Token::YIELD &&
next != Token::FUTURE_STRICT_RESERVED_WORD &&
next != Token::ESCAPED_KEYWORD &&
next != Token::ESCAPED_STRICT_RESERVED_WORD && !Token::IsKeyword(next)) {
if (!Token::IsAnyIdentifier(next) && next != Token::ESCAPED_KEYWORD &&
!Token::IsKeyword(next)) {
ReportUnexpectedToken(next);
*ok = false;
return impl()->NullIdentifier();
......@@ -1860,7 +1852,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
// AsyncFunctionLiteral
int beg_pos = peek_position();
switch (peek()) {
Token::Value token = peek();
switch (token) {
case Token::THIS: {
BindingPatternUnexpectedToken();
Consume(Token::THIS);
......@@ -1872,9 +1865,18 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::FALSE_LITERAL:
case Token::SMI:
case Token::NUMBER:
case Token::BIGINT:
case Token::BIGINT: {
// Ensure continuous enum range.
DCHECK(Token::IsLiteral(token));
BindingPatternUnexpectedToken();
return impl()->ExpressionFromLiteral(Next(), beg_pos);
}
case Token::STRING: {
DCHECK(Token::IsLiteral(token));
BindingPatternUnexpectedToken();
Consume(Token::STRING);
return impl()->ExpressionFromString(beg_pos);
}
case Token::ASYNC:
if (!scanner()->HasLineTerminatorAfterNext() &&
......@@ -1891,19 +1893,16 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::STATIC:
case Token::YIELD:
case Token::AWAIT:
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD: {
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD: {
// Ensure continuous enum range.
DCHECK(IsInRange(token, Token::IDENTIFIER,
Token::ESCAPED_STRICT_RESERVED_WORD));
// Using eval or arguments in this context is OK even in strict mode.
IdentifierT name = ParseAndClassifyIdentifier(CHECK_OK);
return impl()->ExpressionFromIdentifier(name, beg_pos);
}
case Token::STRING: {
BindingPatternUnexpectedToken();
Consume(Token::STRING);
return impl()->ExpressionFromString(beg_pos);
}
case Token::ASSIGN_DIV:
case Token::DIV:
classifier()->RecordBindingPatternError(
......@@ -1919,8 +1918,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParsePrimaryExpression(
case Token::LPAREN: {
// Arrow function formal parameters are either a single identifier or a
// list of BindingPattern productions enclosed in parentheses.
// Parentheses are not valid on the LHS of a BindingPattern, so we use the
// is_valid_binding_pattern() check to detect multiple levels of
// Parentheses are not valid on the LHS of a BindingPattern, so we use
// the is_valid_binding_pattern() check to detect multiple levels of
// parenthesization.
bool pattern_error = !classifier()->is_valid_binding_pattern();
classifier()->RecordPatternError(scanner()->peek_location(),
......
......@@ -146,23 +146,23 @@ namespace internal {
K(FALSE_LITERAL, "false", 0) \
T(NUMBER, nullptr, 0) \
T(SMI, nullptr, 0) \
T(STRING, nullptr, 0) \
T(BIGINT, nullptr, 0) \
T(STRING, nullptr, 0) \
\
/* BEGIN AnyIdentifier. */ \
/* BEGIN AnyIdentifier */ \
/* Identifiers (not keywords or future reserved words). */ \
T(IDENTIFIER, nullptr, 0) \
K(ASYNC, "async", 0) \
/* `await` is a reserved word in module code only */ \
K(AWAIT, "await", 0) \
K(YIELD, "yield", 0) \
K(LET, "let", 0) \
K(STATIC, "static", 0) \
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_STRICT_RESERVED_WORD, nullptr, 0) \
T(ESCAPED_STRICT_RESERVED_WORD, nullptr, 0) \
K(LET, "let", 0) \
K(STATIC, "static", 0) \
K(ENUM, "enum", 0) \
/* `await` is a reserved word in module code only */ \
K(AWAIT, "await", 0) \
K(YIELD, "yield", 0) \
/* END AnyIdentifier. */ \
/* END AnyIdentifier */ \
K(CLASS, "class", 0) \
K(CONST, "const", 0) \
K(EXPORT, "export", 0) \
......@@ -211,38 +211,44 @@ class Token {
// Returns a string corresponding to the C++ token name
// (e.g. "LT" for the token LT).
static const char* Name(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return name_[tok];
static const char* Name(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return name_[token];
}
static char TypeForTesting(Value tok) { return token_type[tok]; }
static char TypeForTesting(Value token) { return token_type[token]; }
// Predicates
static bool IsKeyword(Value tok) {
return token_type[tok] == 'K';
}
static bool IsContextualKeyword(Value tok) {
return IsInRange(tok, GET, ANONYMOUS);
static bool IsKeyword(Value token) { return token_type[token] == 'K'; }
static bool IsContextualKeyword(Value token) {
return IsInRange(token, GET, ANONYMOUS);
}
static bool IsIdentifier(Value tok, LanguageMode language_mode,
static bool IsIdentifier(Value token, LanguageMode language_mode,
bool is_generator, bool disallow_await) {
if (IsInRange(tok, IDENTIFIER, ASYNC)) return true;
if (IsInRange(tok, FUTURE_STRICT_RESERVED_WORD, STATIC)) {
if (IsInRange(token, IDENTIFIER, ASYNC)) return true;
if (IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD)) {
return is_sloppy(language_mode);
}
if (tok == AWAIT) return !disallow_await;
if (tok == YIELD) return !is_generator && is_sloppy(language_mode);
if (token == AWAIT) return !disallow_await;
if (token == YIELD) return !is_generator && is_sloppy(language_mode);
return false;
}
static bool IsAnyIdentifier(Value tok) {
return IsInRange(tok, IDENTIFIER, YIELD);
static bool IsAnyIdentifier(Value token) {
return IsInRange(token, IDENTIFIER, ENUM);
}
static bool IsStrictReservedWord(Value token) {
return IsInRange(token, LET, ESCAPED_STRICT_RESERVED_WORD);
}
static bool IsLiteral(Value token) {
return IsInRange(token, NULL_LITERAL, STRING);
}
static bool IsAssignmentOp(Value tok) {
return IsInRange(tok, INIT, ASSIGN_EXP);
static bool IsAssignmentOp(Value token) {
return IsInRange(token, INIT, ASSIGN_EXP);
}
static bool IsGetOrSet(Value op) { return IsInRange(op, GET, SET); }
......@@ -282,21 +288,21 @@ class Token {
// Returns a string corresponding to the JS token string
// (.e., "<" for the token LT) or nullptr if the token doesn't
// have a (unique) string (e.g. an IDENTIFIER).
static const char* String(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return string_[tok];
static const char* String(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return string_[token];
}
static uint8_t StringLength(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return string_length_[tok];
static uint8_t StringLength(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return string_length_[token];
}
// Returns the precedence > 0 for binary and compare
// operators; returns 0 otherwise.
static int Precedence(Value tok) {
DCHECK_GT(NUM_TOKENS, tok); // tok is unsigned
return precedence_[tok];
static int Precedence(Value token) {
DCHECK_GT(NUM_TOKENS, token); // token is unsigned
return precedence_[token];
}
private:
......
......@@ -73,23 +73,23 @@ void MockUseCounterCallback(v8::Isolate* isolate,
TEST(IsContextualKeyword) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(Token::TypeForTesting(tok) == 'C',
Token::IsContextualKeyword(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(Token::TypeForTesting(token) == 'C',
Token::IsContextualKeyword(token));
}
}
bool TokenIsAnyIdentifier(Token::Value tok) {
switch (tok) {
bool TokenIsAnyIdentifier(Token::Value token) {
switch (token) {
case Token::IDENTIFIER:
case Token::ASYNC:
case Token::AWAIT:
case Token::ENUM:
case Token::YIELD:
case Token::LET:
case Token::STATIC:
case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::ENUM:
return true;
default:
return false;
......@@ -98,51 +98,94 @@ bool TokenIsAnyIdentifier(Token::Value tok) {
TEST(AnyIdentifierToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsAnyIdentifier(tok), Token::IsAnyIdentifier(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsAnyIdentifier(token), Token::IsAnyIdentifier(token));
}
}
bool TokenIsIdentifier(Token::Value tok, LanguageMode language_mode,
bool TokenIsIdentifier(Token::Value token, LanguageMode language_mode,
bool is_generator, bool disallow_await) {
switch (tok) {
switch (token) {
case Token::IDENTIFIER:
case Token::ASYNC:
return true;
case Token::ESCAPED_STRICT_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::LET:
case Token::STATIC:
return is_sloppy(language_mode);
case Token::YIELD:
return !is_generator && is_sloppy(language_mode);
case Token::AWAIT:
return !disallow_await;
case Token::LET:
case Token::STATIC:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD:
return is_sloppy(language_mode);
default:
return false;
}
UNREACHABLE();
}
TEST(IsIdentifier) {
TEST(IsIdentifierToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
Token::Value token = static_cast<Token::Value>(i);
for (size_t raw_language_mode = 0; raw_language_mode < LanguageModeSize;
raw_language_mode++) {
LanguageMode mode = static_cast<LanguageMode>(raw_language_mode);
for (int is_generator = 0; is_generator < 2; is_generator++) {
for (int disallow_await = 0; disallow_await < 2; disallow_await++) {
CHECK_EQ(
TokenIsIdentifier(tok, mode, is_generator, disallow_await),
Token::IsIdentifier(tok, mode, is_generator, disallow_await));
TokenIsIdentifier(token, mode, is_generator, disallow_await),
Token::IsIdentifier(token, mode, is_generator, disallow_await));
}
}
}
}
}
bool TokenIsAssignmentOp(Token::Value tok) {
switch (tok) {
bool TokenIsStrictReservedWord(Token::Value token) {
switch (token) {
case Token::LET:
case Token::STATIC:
case Token::FUTURE_STRICT_RESERVED_WORD:
case Token::ESCAPED_STRICT_RESERVED_WORD:
return true;
default:
return false;
}
UNREACHABLE();
}
TEST(IsStrictReservedWord) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsStrictReservedWord(token),
Token::IsStrictReservedWord(token));
}
}
bool TokenIsLiteral(Token::Value token) {
switch (token) {
case Token::NULL_LITERAL:
case Token::TRUE_LITERAL:
case Token::FALSE_LITERAL:
case Token::NUMBER:
case Token::SMI:
case Token::BIGINT:
case Token::STRING:
return true;
default:
return false;
}
UNREACHABLE();
}
TEST(IsLiteralToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsLiteral(token), Token::IsLiteral(token));
}
}
bool TokenIsAssignmentOp(Token::Value token) {
switch (token) {
case Token::INIT:
case Token::ASSIGN:
#define T(name, string, precedence) case Token::name:
......@@ -156,13 +199,13 @@ bool TokenIsAssignmentOp(Token::Value tok) {
TEST(AssignmentOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsAssignmentOp(tok), Token::IsAssignmentOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsAssignmentOp(token), Token::IsAssignmentOp(token));
}
}
bool TokenIsBinaryOp(Token::Value tok) {
switch (tok) {
bool TokenIsBinaryOp(Token::Value token) {
switch (token) {
case Token::COMMA:
case Token::OR:
case Token::AND:
......@@ -177,13 +220,13 @@ bool TokenIsBinaryOp(Token::Value tok) {
TEST(BinaryOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsBinaryOp(tok), Token::IsBinaryOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsBinaryOp(token), Token::IsBinaryOp(token));
}
}
bool TokenIsCompareOp(Token::Value tok) {
switch (tok) {
bool TokenIsCompareOp(Token::Value token) {
switch (token) {
case Token::EQ:
case Token::EQ_STRICT:
case Token::NE:
......@@ -202,13 +245,13 @@ bool TokenIsCompareOp(Token::Value tok) {
TEST(CompareOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsCompareOp(tok), Token::IsCompareOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsCompareOp(token), Token::IsCompareOp(token));
}
}
bool TokenIsOrderedRelationalCompareOp(Token::Value tok) {
switch (tok) {
bool TokenIsOrderedRelationalCompareOp(Token::Value token) {
switch (token) {
case Token::LT:
case Token::GT:
case Token::LTE:
......@@ -221,14 +264,14 @@ bool TokenIsOrderedRelationalCompareOp(Token::Value tok) {
TEST(IsOrderedRelationalCompareOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsOrderedRelationalCompareOp(tok),
Token::IsOrderedRelationalCompareOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsOrderedRelationalCompareOp(token),
Token::IsOrderedRelationalCompareOp(token));
}
}
bool TokenIsEqualityOp(Token::Value tok) {
switch (tok) {
bool TokenIsEqualityOp(Token::Value token) {
switch (token) {
case Token::EQ:
case Token::EQ_STRICT:
return true;
......@@ -239,13 +282,13 @@ bool TokenIsEqualityOp(Token::Value tok) {
TEST(IsEqualityOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsEqualityOp(tok), Token::IsEqualityOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsEqualityOp(token), Token::IsEqualityOp(token));
}
}
bool TokenIsBitOp(Token::Value tok) {
switch (tok) {
bool TokenIsBitOp(Token::Value token) {
switch (token) {
case Token::BIT_OR:
case Token::BIT_XOR:
case Token::BIT_AND:
......@@ -261,13 +304,13 @@ bool TokenIsBitOp(Token::Value tok) {
TEST(IsBitOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsBitOp(tok), Token::IsBitOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsBitOp(token), Token::IsBitOp(token));
}
}
bool TokenIsUnaryOp(Token::Value tok) {
switch (tok) {
bool TokenIsUnaryOp(Token::Value token) {
switch (token) {
case Token::NOT:
case Token::BIT_NOT:
case Token::DELETE:
......@@ -283,13 +326,13 @@ bool TokenIsUnaryOp(Token::Value tok) {
TEST(IsUnaryOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsUnaryOp(tok), Token::IsUnaryOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsUnaryOp(token), Token::IsUnaryOp(token));
}
}
bool TokenIsCountOp(Token::Value tok) {
switch (tok) {
bool TokenIsCountOp(Token::Value token) {
switch (token) {
case Token::INC:
case Token::DEC:
return true;
......@@ -300,13 +343,13 @@ bool TokenIsCountOp(Token::Value tok) {
TEST(IsCountOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsCountOp(tok), Token::IsCountOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsCountOp(token), Token::IsCountOp(token));
}
}
bool TokenIsShiftOp(Token::Value tok) {
switch (tok) {
bool TokenIsShiftOp(Token::Value token) {
switch (token) {
case Token::SHL:
case Token::SAR:
case Token::SHR:
......@@ -318,13 +361,13 @@ bool TokenIsShiftOp(Token::Value tok) {
TEST(IsShiftOp) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsShiftOp(tok), Token::IsShiftOp(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsShiftOp(token), Token::IsShiftOp(token));
}
}
bool TokenIsTrivialExpressionToken(Token::Value tok) {
switch (tok) {
bool TokenIsTrivialExpressionToken(Token::Value token) {
switch (token) {
case Token::SMI:
case Token::NUMBER:
case Token::BIGINT:
......@@ -342,9 +385,9 @@ bool TokenIsTrivialExpressionToken(Token::Value tok) {
TEST(IsTrivialExpressionToken) {
for (int i = 0; i < Token::NUM_TOKENS; i++) {
Token::Value tok = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsTrivialExpressionToken(tok),
Token::IsTrivialExpressionToken(tok));
Token::Value token = static_cast<Token::Value>(i);
CHECK_EQ(TokenIsTrivialExpressionToken(token),
Token::IsTrivialExpressionToken(token));
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment