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