Commit b7302e4b authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[preparser] Check duplicate '__proto__' using the underlying literal

That way we don't need to internalize kValue property names on object literals
(both STRING and identifier tokens). This speeds up object literal preparsing
by quite a bit (15% on a microbenchmark; 7-8% on actual object literals looking
like json from FB).

Change-Id: I9d7baeb94f1a8e4f7e3b7cd6406a826ba37017f3
Reviewed-on: https://chromium-review.googlesource.com/c/1491605Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59915}
parent 2cb8a6e3
...@@ -1543,7 +1543,10 @@ ParserBase<Impl>::ParseNonRestrictedIdentifier() { ...@@ -1543,7 +1543,10 @@ ParserBase<Impl>::ParseNonRestrictedIdentifier() {
template <typename Impl> template <typename Impl>
typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParsePropertyName() { typename ParserBase<Impl>::IdentifierT ParserBase<Impl>::ParsePropertyName() {
Token::Value next = Next(); Token::Value next = Next();
if (V8_LIKELY(Token::IsPropertyName(next))) return impl()->GetIdentifier(); if (V8_LIKELY(Token::IsPropertyName(next))) {
if (peek() == Token::COLON) return impl()->GetSymbol();
return impl()->GetIdentifier();
}
ReportUnexpectedToken(next); ReportUnexpectedToken(next);
return impl()->EmptyIdentifierString(); return impl()->EmptyIdentifierString();
...@@ -2039,7 +2042,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty( ...@@ -2039,7 +2042,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseProperty(
case Token::STRING: case Token::STRING:
Consume(Token::STRING); Consume(Token::STRING);
prop_info->name = impl()->GetIdentifier(); prop_info->name = peek() == Token::COLON ? impl()->GetSymbol()
: impl()->GetIdentifier();
is_array_index = impl()->IsArrayIndex(prop_info->name, &index); is_array_index = impl()->IsArrayIndex(prop_info->name, &index);
break; break;
...@@ -2349,7 +2353,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info, ...@@ -2349,7 +2353,7 @@ ParserBase<Impl>::ParseObjectPropertyDefinition(ParsePropertyInfo* prop_info,
DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal); DCHECK_EQ(function_flags, ParseFunctionFlag::kIsNormal);
if (!prop_info->is_computed_name && if (!prop_info->is_computed_name &&
impl()->IdentifierEquals(name, ast_value_factory()->proto_string())) { scanner()->CurrentLiteralEquals("__proto__")) {
if (*has_seen_proto) { if (*has_seen_proto) {
expression_scope()->RecordExpressionError( expression_scope()->RecordExpressionError(
scanner()->location(), MessageTemplate::kDuplicateProto); scanner()->location(), MessageTemplate::kDuplicateProto);
...@@ -4553,9 +4557,9 @@ void ParserBase<Impl>::ParseStatementList(StatementListT* body, ...@@ -4553,9 +4557,9 @@ void ParserBase<Impl>::ParseStatementList(StatementListT* body,
Scanner::Location token_loc = scanner()->peek_location(); Scanner::Location token_loc = scanner()->peek_location();
if (scanner()->NextLiteralEquals("use strict")) { if (scanner()->NextLiteralExactlyEquals("use strict")) {
use_strict = true; use_strict = true;
} else if (scanner()->NextLiteralEquals("use asm")) { } else if (scanner()->NextLiteralExactlyEquals("use asm")) {
use_asm = true; use_asm = true;
} }
......
...@@ -336,8 +336,8 @@ class Scanner { ...@@ -336,8 +336,8 @@ class Scanner {
} }
template <size_t N> template <size_t N>
bool NextLiteralEquals(const char (&s)[N]) { bool NextLiteralExactlyEquals(const char (&s)[N]) {
DCHECK_EQ(Token::STRING, peek()); DCHECK(next().CanAccessLiteral());
// The length of the token is used to make sure the literal equals without // The length of the token is used to make sure the literal equals without
// taking escape sequences (e.g., "use \x73trict") or line continuations // taking escape sequences (e.g., "use \x73trict") or line continuations
// (e.g., "use \(newline) strict") into account. // (e.g., "use \(newline) strict") into account.
...@@ -349,6 +349,16 @@ class Scanner { ...@@ -349,6 +349,16 @@ class Scanner {
return next.length() == N - 1 && strncmp(s, chars, N - 1) == 0; return next.length() == N - 1 && strncmp(s, chars, N - 1) == 0;
} }
template <size_t N>
bool CurrentLiteralEquals(const char (&s)[N]) {
DCHECK(current().CanAccessLiteral());
if (!is_literal_one_byte()) return false;
Vector<const uint8_t> current = literal_one_byte_string();
const char* chars = reinterpret_cast<const char*>(current.start());
return current.length() == N - 1 && strncmp(s, chars, N - 1) == 0;
}
// Returns the location of the last seen octal literal. // Returns the location of the last seen octal literal.
Location octal_position() const { return octal_pos_; } Location octal_position() const { return octal_pos_; }
void clear_octal_position() { void clear_octal_position() {
...@@ -522,7 +532,7 @@ class Scanner { ...@@ -522,7 +532,7 @@ class Scanner {
return token == Token::PRIVATE_NAME || token == Token::ILLEGAL || return token == Token::PRIVATE_NAME || token == Token::ILLEGAL ||
token == Token::UNINITIALIZED || token == Token::REGEXP_LITERAL || token == Token::UNINITIALIZED || token == Token::REGEXP_LITERAL ||
IsInRange(token, Token::NUMBER, Token::STRING) || IsInRange(token, Token::NUMBER, Token::STRING) ||
(Token::IsAnyIdentifier(token) && !Token::IsKeyword(token)) || Token::IsAnyIdentifier(token) || Token::IsKeyword(token) ||
IsInRange(token, Token::TEMPLATE_SPAN, Token::TEMPLATE_TAIL); IsInRange(token, Token::TEMPLATE_SPAN, Token::TEMPLATE_TAIL);
} }
bool CanAccessRawLiteral() const { bool CanAccessRawLiteral() const {
......
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