Commit 9f75c148 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Simplify StatementList parsing by splitting out directive parsing

Change-Id: I233a3f6d8b19b945cfc3572d72237ec5619d8cbc
Reviewed-on: https://chromium-review.googlesource.com/c/1307414Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57129}
parent 503cf13b
......@@ -4602,82 +4602,71 @@ ParserBase<Impl>::ParseStatementList(StatementListT body,
// StatementList ::
// (StatementListItem)* <end_token>
// Allocate a target stack to use for this set of source
// elements. This way, all scripts and functions get their own
// target stack thus avoiding illegal breaks and continues across
// functions.
typename Types::TargetScope target_scope(this);
int count_statements = 0;
DCHECK(!impl()->IsNull(body));
bool directive_prologue = true; // Parsing directive prologue.
while (peek() != end_token) {
if (directive_prologue && peek() != Token::STRING) {
directive_prologue = false;
}
bool starts_with_identifier = peek() == Token::IDENTIFIER;
while (peek() == Token::STRING && (scanner()->HasLineTerminatorAfterNext() ||
Token::IsAutoSemicolon(PeekAhead()))) {
const AstRawString* symbol = scanner()->NextSymbol(ast_value_factory_);
Scanner::Location token_loc = scanner()->peek_location();
StatementT stat = ParseStatementListItem();
RETURN_IF_PARSE_ERROR_CUSTOM(Return, kLazyParsingComplete)
if (impl()->IsNull(stat) || stat->IsEmptyStatement()) {
directive_prologue = false; // End of directive prologue.
continue;
}
if (directive_prologue) {
// The length of the token is used to distinguish between strings literals
// that evaluate equal to directives but contain either escape sequences
// (e.g., "use \x73trict") or line continuations (e.g., "use \(newline)
// strict").
if (impl()->IsUseStrictDirective(stat) &&
token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
// Directive "use strict" (ES5 14.1).
RaiseLanguageMode(LanguageMode::kStrict);
if (!scope()->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
// 29/7/2015. https://goo.gl/ueA7Ln
impl()->ReportMessageAt(
token_loc, MessageTemplate::kIllegalLanguageModeDirective,
"use strict");
return kLazyParsingComplete;
}
} else if (impl()->IsUseAsmDirective(stat) &&
token_loc.end_pos - token_loc.beg_pos ==
sizeof("use asm") + 1) {
// Directive "use asm".
impl()->SetAsmModule();
} else if (impl()->IsStringLiteral(stat)) {
// Possibly an unknown directive.
// Should not change mode, but will increment usage counters
// as appropriate. Ditto usages below.
RaiseLanguageMode(LanguageMode::kSloppy);
} else {
// End of the directive prologue.
directive_prologue = false;
RaiseLanguageMode(LanguageMode::kSloppy);
// The length of the token is used to distinguish between strings literals
// that evaluate equal to directives but contain either escape sequences
// (e.g., "use \x73trict") or line continuations (e.g., "use \(newline)
// strict").
if (symbol == ast_value_factory()->use_strict_string() &&
token_loc.end_pos - token_loc.beg_pos == sizeof("use strict") + 1) {
// Directive "use strict" (ES5 14.1).
RaiseLanguageMode(LanguageMode::kStrict);
if (!scope()->HasSimpleParameters()) {
// TC39 deemed "use strict" directives to be an error when occurring
// in the body of a function with non-simple parameter list, on
// 29/7/2015. https://goo.gl/ueA7Ln
impl()->ReportMessageAt(token_loc,
MessageTemplate::kIllegalLanguageModeDirective,
"use strict");
return kLazyParsingComplete;
}
} else if (symbol == ast_value_factory()->use_asm_string() &&
token_loc.end_pos - token_loc.beg_pos == sizeof("use asm") + 1) {
// Directive "use asm".
impl()->SetAsmModule();
} else {
// Possibly an unknown directive.
// Should not change mode, but will increment usage counters
// as appropriate. Ditto usages below.
RaiseLanguageMode(LanguageMode::kSloppy);
}
StatementT stat = ParseStatementListItem();
DCHECK(!has_error());
body->Add(stat, zone());
may_abort = false;
}
// If we're allowed to abort, we will do so when we see a "long and
// trivial" function. Our current definition of "long and trivial" is:
// - over kLazyParseTrialLimit statements
// - all starting with an identifier (i.e., no if, for, while, etc.)
if (may_abort) {
if (!starts_with_identifier) {
may_abort = false;
} else if (++count_statements > kLazyParseTrialLimit) {
return kLazyParsingAborted;
}
// Allocate a target stack to use for this set of source elements. This way,
// all scripts and functions get their own target stack thus avoiding illegal
// breaks and continues across functions.
typename Types::TargetScope target_scope(this);
int count_statements = 0;
if (may_abort) {
while (peek() == Token::IDENTIFIER) {
StatementT stat = ParseStatementListItem();
RETURN_IF_PARSE_ERROR_CUSTOM(Return, kLazyParsingComplete);
// If we're allowed to abort, we will do so when we see a "long and
// trivial" function. Our current definition of "long and trivial" is:
// - over kLazyParseTrialLimit statements
// - all starting with an identifier (i.e., no if, for, while, etc.)
if (++count_statements > kLazyParseTrialLimit) return kLazyParsingAborted;
body->Add(stat, zone());
}
}
while (peek() != end_token) {
StatementT stat = ParseStatementListItem();
RETURN_IF_PARSE_ERROR_CUSTOM(Return, kLazyParsingComplete)
if (impl()->IsNull(stat) || stat->IsEmptyStatement()) continue;
body->Add(stat, zone());
}
return kLazyParsingComplete;
}
......
......@@ -649,14 +649,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return string->AsArrayIndex(index);
}
V8_INLINE bool IsUseStrictDirective(Statement* statement) const {
return IsStringLiteral(statement, ast_value_factory()->use_strict_string());
}
V8_INLINE bool IsUseAsmDirective(Statement* statement) const {
return IsStringLiteral(statement, ast_value_factory()->use_asm_string());
}
// Returns true if the statement is an expression statement containing
// a single string literal. If a second argument is given, the literal
// is also compared with it and the result is true only if they are equal.
......
......@@ -149,16 +149,6 @@ class PreParserExpression {
return PreParserExpression(TypeField::encode(kStringLiteralExpression));
}
static PreParserExpression UseStrictStringLiteral() {
return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
IsUseStrictField::encode(true));
}
static PreParserExpression UseAsmStringLiteral() {
return PreParserExpression(TypeField::encode(kStringLiteralExpression) |
IsUseAsmField::encode(true));
}
static PreParserExpression This() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kThisExpression));
......@@ -244,16 +234,6 @@ class PreParserExpression {
return TypeField::decode(code_) == kStringLiteralExpression;
}
bool IsUseStrictLiteral() const {
return TypeField::decode(code_) == kStringLiteralExpression &&
IsUseStrictField::decode(code_);
}
bool IsUseAsmLiteral() const {
return TypeField::decode(code_) == kStringLiteralExpression &&
IsUseAsmField::decode(code_);
}
bool IsThis() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kThisExpression;
......@@ -389,8 +369,6 @@ class PreParserExpression {
// The rest of the bits are interpreted depending on the value
// of the Type field, so they can share the storage.
typedef BitField<ExpressionType, TypeField::kNext, 4> ExpressionTypeField;
typedef BitField<bool, TypeField::kNext, 1> IsUseStrictField;
typedef BitField<bool, IsUseStrictField::kNext, 1> IsUseAsmField;
typedef BitField<PreParserIdentifier::Type, TypeField::kNext, 8>
IdentifierTypeField;
typedef BitField<bool, TypeField::kNext, 1> HasCoverInitializedNameField;
......@@ -480,28 +458,13 @@ class PreParserStatement {
// "use strict".
static PreParserStatement ExpressionStatement(
const PreParserExpression& expression) {
if (expression.IsUseStrictLiteral()) {
return PreParserStatement(kUseStrictExpressionStatement);
}
if (expression.IsUseAsmLiteral()) {
return PreParserStatement(kUseAsmExpressionStatement);
}
if (expression.IsStringLiteral()) {
return PreParserStatement(kStringLiteralExpressionStatement);
}
return Default();
}
bool IsStringLiteral() {
return code_ == kStringLiteralExpressionStatement || IsUseStrictLiteral() ||
IsUseAsmLiteral();
}
bool IsUseStrictLiteral() {
return code_ == kUseStrictExpressionStatement;
}
bool IsUseAsmLiteral() { return code_ == kUseAsmExpressionStatement; }
bool IsStringLiteral() { return code_ == kStringLiteralExpressionStatement; }
bool IsJumpStatement() {
return code_ == kJumpStatement;
......@@ -535,8 +498,6 @@ class PreParserStatement {
kUnknownStatement,
kJumpStatement,
kStringLiteralExpressionStatement,
kUseStrictExpressionStatement,
kUseAsmExpressionStatement,
};
explicit PreParserStatement(Type code) : code_(code) {}
......@@ -1345,14 +1306,6 @@ class PreParser : public ParserBase<PreParser> {
return false;
}
V8_INLINE bool IsUseStrictDirective(PreParserStatement statement) const {
return statement.IsUseStrictLiteral();
}
V8_INLINE bool IsUseAsmDirective(PreParserStatement statement) const {
return statement.IsUseAsmLiteral();
}
V8_INLINE bool IsStringLiteral(PreParserStatement statement) const {
return statement.IsStringLiteral();
}
......@@ -1613,9 +1566,6 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE PreParserExpression ExpressionFromLiteral(Token::Value token,
int pos) {
if (token != Token::STRING) return PreParserExpression::Default();
if (scanner()->IsUseStrict()) {
return PreParserExpression::UseStrictStringLiteral();
}
return PreParserExpression::StringLiteral();
}
......
......@@ -357,12 +357,6 @@ class Scanner {
Token::String(token), Token::StringLength(token))));
}
bool IsUseStrict() const {
return current().token == Token::STRING &&
current().literal_chars.Equals(
Vector<const char>("use strict", strlen("use strict")));
}
bool IsGet() { return CurrentMatchesContextual(Token::GET); }
bool IsSet() { return CurrentMatchesContextual(Token::SET); }
......
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