Commit 5d6eabb0 authored by nikolaos's avatar nikolaos Committed by Commit bot

[parser] Refactor bookmark in SkipLazyFunctionBody

This patch refactors the scanner bookmark in SkipLazyFunctionBody,
so that it is only used locally, instead of being passed to several
other methods.  It is replaced by a "may_abort" parameter and an
appropriate result denoting whether lazy parsing has been aborted.

It also applies the hack of aborting lazy parsing for arrow
functions that are considered to be "initialization functions".

R=adamk@chromium.org, vogelheim@chromium.org
BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2297733002
Cr-Commit-Position: refs/heads/master@{#39072}
parent 5e7428b5
...@@ -126,8 +126,8 @@ struct FormalParametersBase { ...@@ -126,8 +126,8 @@ struct FormalParametersBase {
// thus it must never be used where only a single statement // thus it must never be used where only a single statement
// is correct (e.g. an if statement branch w/o braces)! // is correct (e.g. an if statement branch w/o braces)!
#define CHECK_OK_CUSTOM(x) ok); \ #define CHECK_OK_CUSTOM(x, ...) ok); \
if (!*ok) return impl()->x(); \ if (!*ok) return impl()->x(__VA_ARGS__); \
((void)0 ((void)0
#define DUMMY ) // to make indentation work #define DUMMY ) // to make indentation work
#undef DUMMY #undef DUMMY
...@@ -273,6 +273,7 @@ class ParserBase { ...@@ -273,6 +273,7 @@ class ParserBase {
protected: protected:
friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>; friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>;
// clang-format off
enum AllowRestrictedIdentifiers { enum AllowRestrictedIdentifiers {
kAllowRestrictedIdentifiers, kAllowRestrictedIdentifiers,
kDontAllowRestrictedIdentifiers kDontAllowRestrictedIdentifiers
...@@ -283,11 +284,17 @@ class ParserBase { ...@@ -283,11 +284,17 @@ class ParserBase {
PARSE_EAGERLY PARSE_EAGERLY
}; };
enum LazyParsingResult {
kLazyParsingComplete,
kLazyParsingAborted
};
enum VariableDeclarationContext { enum VariableDeclarationContext {
kStatementListItem, kStatementListItem,
kStatement, kStatement,
kForStatement kForStatement
}; };
// clang-format on
class Checkpoint; class Checkpoint;
class ObjectLiteralCheckerBase; class ObjectLiteralCheckerBase;
...@@ -785,8 +792,12 @@ class ParserBase { ...@@ -785,8 +792,12 @@ class ParserBase {
Expect(Token::SEMICOLON, ok); Expect(Token::SEMICOLON, ok);
} }
// A dummy function, just useful as an argument to CHECK_OK_CUSTOM. // Dummy functions, just useful as arguments to CHECK_OK_CUSTOM.
static void Void() {} static void Void() {}
template <typename T>
static T Return(T result) {
return result;
}
bool is_any_identifier(Token::Value token) { bool is_any_identifier(Token::Value token) {
return token == Token::IDENTIFIER || token == Token::ENUM || return token == Token::IDENTIFIER || token == Token::ENUM ||
...@@ -820,7 +831,7 @@ class ParserBase { ...@@ -820,7 +831,7 @@ class ParserBase {
} }
} }
bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
if (Check(Token::IN)) { if (Check(Token::IN)) {
*visit_mode = ForEachStatement::ENUMERATE; *visit_mode = ForEachStatement::ENUMERATE;
return true; return true;
...@@ -3484,12 +3495,15 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( ...@@ -3484,12 +3495,15 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
return impl()->EmptyExpression(); return impl()->EmptyExpression();
} }
typename Types::StatementList body; typename Types::StatementList body = impl()->NullStatementList();
int num_parameters = formal_parameters.scope->num_parameters(); int num_parameters = formal_parameters.scope->num_parameters();
int materialized_literal_count = -1; int materialized_literal_count = -1;
int expected_property_count = -1; int expected_property_count = -1;
FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction; FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction;
FunctionLiteral::EagerCompileHint eager_compile_hint =
FunctionLiteral::kShouldLazyCompile;
bool should_be_used_once_hint = false;
{ {
FunctionState function_state(&function_state_, &scope_state_, FunctionState function_state(&function_state_, &scope_state_,
formal_parameters.scope, arrow_kind); formal_parameters.scope, arrow_kind);
...@@ -3508,14 +3522,30 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( ...@@ -3508,14 +3522,30 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
bool is_lazily_parsed = (mode() == PARSE_LAZILY && bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
formal_parameters.scope->AllowsLazyParsing()); formal_parameters.scope->AllowsLazyParsing());
if (is_lazily_parsed) { if (is_lazily_parsed) {
body = impl()->NewStatementList(0); Scanner::BookmarkScope bookmark(scanner());
impl()->SkipLazyFunctionBody(&materialized_literal_count, bool may_abort = bookmark.Set();
&expected_property_count, CHECK_OK); LazyParsingResult result = impl()->SkipLazyFunctionBody(
&materialized_literal_count, &expected_property_count, may_abort,
CHECK_OK);
if (formal_parameters.materialized_literals_count > 0) { if (formal_parameters.materialized_literals_count > 0) {
materialized_literal_count += materialized_literal_count +=
formal_parameters.materialized_literals_count; formal_parameters.materialized_literals_count;
} }
} else {
if (result == kLazyParsingAborted) {
bookmark.Reset();
// Trigger eager (re-)parsing, just below this block.
is_lazily_parsed = false;
// This is probably an initialization function. Inform the compiler it
// should also eager-compile this function, and that we expect it to
// be used once.
eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
should_be_used_once_hint = true;
}
}
if (!is_lazily_parsed) {
body = impl()->ParseEagerFunctionBody( body = impl()->ParseEagerFunctionBody(
impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters,
arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK);
...@@ -3576,12 +3606,14 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( ...@@ -3576,12 +3606,14 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
impl()->EmptyIdentifierString(), formal_parameters.scope, body, impl()->EmptyIdentifierString(), formal_parameters.scope, body,
materialized_literal_count, expected_property_count, num_parameters, materialized_literal_count, expected_property_count, num_parameters,
FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression, FunctionLiteral::kAnonymousExpression, eager_compile_hint, arrow_kind,
FunctionLiteral::kShouldLazyCompile, arrow_kind,
formal_parameters.scope->start_position()); formal_parameters.scope->start_position());
function_literal->set_function_token_position( function_literal->set_function_token_position(
formal_parameters.scope->start_position()); formal_parameters.scope->start_position());
if (should_be_used_once_hint) {
function_literal->set_should_be_used_once_hint();
}
if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal); if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal);
...@@ -3733,7 +3765,6 @@ void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, ...@@ -3733,7 +3765,6 @@ void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
} }
} }
#undef CHECK_OK #undef CHECK_OK
#undef CHECK_OK_CUSTOM #undef CHECK_OK_CUSTOM
......
...@@ -277,17 +277,14 @@ class TargetScope BASE_EMBEDDED { ...@@ -277,17 +277,14 @@ class TargetScope BASE_EMBEDDED {
// thus it must never be used where only a single statement // thus it must never be used where only a single statement
// is correct (e.g. an if statement branch w/o braces)! // is correct (e.g. an if statement branch w/o braces)!
#define CHECK_OK ok); \ #define CHECK_OK_VALUE(x) ok); \
if (!*ok) return nullptr; \ if (!*ok) return x; \
((void)0 ((void)0
#define DUMMY ) // to make indentation work #define DUMMY ) // to make indentation work
#undef DUMMY #undef DUMMY
#define CHECK_OK_VOID ok); \ #define CHECK_OK CHECK_OK_VALUE(nullptr)
if (!*ok) return; \ #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
#define CHECK_FAILED /**/); \ #define CHECK_FAILED /**/); \
if (failed_) return nullptr; \ if (failed_) return nullptr; \
...@@ -3255,8 +3252,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3255,8 +3252,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
int each_beg_pos = scanner()->location().beg_pos; int each_beg_pos = scanner()->location().beg_pos;
int each_end_pos = scanner()->location().end_pos; int each_end_pos = scanner()->location().end_pos;
if (CheckInOrOf(&mode, ok)) { if (CheckInOrOf(&mode)) {
if (!*ok) return nullptr;
if (parsing_result.declarations.length() != 1) { if (parsing_result.declarations.length() != 1) {
ReportMessageAt(parsing_result.bindings_loc, ReportMessageAt(parsing_result.bindings_loc,
MessageTemplate::kForInOfLoopMultiBindings, MessageTemplate::kForInOfLoopMultiBindings,
...@@ -3450,7 +3446,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, ...@@ -3450,7 +3446,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
int lhs_end_pos = scanner()->location().end_pos; int lhs_end_pos = scanner()->location().end_pos;
ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE; ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
bool is_for_each = CheckInOrOf(&mode, CHECK_OK); bool is_for_each = CheckInOrOf(&mode);
bool is_destructuring = is_for_each && (expression->IsArrayLiteral() || bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
expression->IsObjectLiteral()); expression->IsObjectLiteral());
...@@ -3964,22 +3960,23 @@ FunctionLiteral* Parser::ParseFunctionLiteral( ...@@ -3964,22 +3960,23 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
if (formals.has_rest) arity--; if (formals.has_rest) arity--;
// Eager or lazy parse? // Eager or lazy parse?
// If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody,
// pass it to SkipLazyFunctionBody, which may use it to abort lazy // which may decide to abort lazy parsing if it suspects that wasn't a good
// parsing if it suspect that wasn't a good idea. If so, or if we didn't // idea. If so (in which case the parser is expected to have backtracked),
// try to lazy parse in the first place, we'll have to parse eagerly. // or if we didn't try to lazy parse in the first place, we'll have to parse
Scanner::BookmarkScope bookmark(scanner()); // eagerly.
if (is_lazily_parsed) { if (is_lazily_parsed) {
Scanner::BookmarkScope* maybe_bookmark = Scanner::BookmarkScope bookmark(scanner());
bookmark.Set() ? &bookmark : nullptr; bool may_abort = bookmark.Set();
LazyParsingResult result =
SkipLazyFunctionBody(&materialized_literal_count, SkipLazyFunctionBody(&materialized_literal_count,
&expected_property_count, /*CHECK_OK*/ ok, &expected_property_count, may_abort, CHECK_OK);
maybe_bookmark);
materialized_literal_count += formals.materialized_literals_count + materialized_literal_count += formals.materialized_literals_count +
function_state.materialized_literal_count(); function_state.materialized_literal_count();
if (bookmark.HasBeenReset()) { if (result == kLazyParsingAborted) {
bookmark.Reset();
// Trigger eager (re-)parsing, just below this block. // Trigger eager (re-)parsing, just below this block.
is_lazily_parsed = false; is_lazily_parsed = false;
...@@ -4079,10 +4076,9 @@ Expression* Parser::ParseAsyncFunctionExpression(bool* ok) { ...@@ -4079,10 +4076,9 @@ Expression* Parser::ParseAsyncFunctionExpression(bool* ok) {
language_mode(), CHECK_OK); language_mode(), CHECK_OK);
} }
void Parser::SkipLazyFunctionBody(int* materialized_literal_count, Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
int* expected_property_count, bool* ok, int* materialized_literal_count, int* expected_property_count,
Scanner::BookmarkScope* bookmark) { bool may_abort, bool* ok) {
DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
if (produce_cached_parse_data()) CHECK(log_); if (produce_cached_parse_data()) CHECK(log_);
int function_block_pos = position(); int function_block_pos = position();
...@@ -4100,14 +4096,14 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count, ...@@ -4100,14 +4096,14 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
scanner()->SeekForward(entry.end_pos() - 1); scanner()->SeekForward(entry.end_pos() - 1);
scope->set_end_position(entry.end_pos()); scope->set_end_position(entry.end_pos());
Expect(Token::RBRACE, CHECK_OK_VOID); Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
total_preparse_skipped_ += scope->end_position() - function_block_pos; total_preparse_skipped_ += scope->end_position() - function_block_pos;
*materialized_literal_count = entry.literal_count(); *materialized_literal_count = entry.literal_count();
*expected_property_count = entry.property_count(); *expected_property_count = entry.property_count();
SetLanguageMode(scope, entry.language_mode()); SetLanguageMode(scope, entry.language_mode());
if (entry.uses_super_property()) scope->RecordSuperPropertyUsage(); if (entry.uses_super_property()) scope->RecordSuperPropertyUsage();
if (entry.calls_eval()) scope->RecordEvalCall(); if (entry.calls_eval()) scope->RecordEvalCall();
return; return kLazyParsingComplete;
} }
cached_parse_data_->Reject(); cached_parse_data_->Reject();
} }
...@@ -4115,25 +4111,26 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count, ...@@ -4115,25 +4111,26 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
// AST. This gathers the data needed to build a lazy function. // AST. This gathers the data needed to build a lazy function.
SingletonLogger logger; SingletonLogger logger;
PreParser::PreParseResult result = PreParser::PreParseResult result =
ParseLazyFunctionBodyWithPreParser(&logger, bookmark); ParseLazyFunctionBodyWithPreParser(&logger, may_abort);
if (bookmark && bookmark->HasBeenReset()) { // Return immediately if pre-parser decided to abort parsing.
return; // Return immediately if pre-parser devided to abort parsing. if (result == PreParser::kPreParseAbort) {
return kLazyParsingAborted;
} }
if (result == PreParser::kPreParseStackOverflow) { if (result == PreParser::kPreParseStackOverflow) {
// Propagate stack overflow. // Propagate stack overflow.
set_stack_overflow(); set_stack_overflow();
*ok = false; *ok = false;
return; return kLazyParsingComplete;
} }
if (logger.has_error()) { if (logger.has_error()) {
ReportMessageAt(Scanner::Location(logger.start(), logger.end()), ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
logger.message(), logger.argument_opt(), logger.message(), logger.argument_opt(),
logger.error_type()); logger.error_type());
*ok = false; *ok = false;
return; return kLazyParsingComplete;
} }
scope->set_end_position(logger.end()); scope->set_end_position(logger.end());
Expect(Token::RBRACE, CHECK_OK_VOID); Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
total_preparse_skipped_ += scope->end_position() - function_block_pos; total_preparse_skipped_ += scope->end_position() - function_block_pos;
*materialized_literal_count = logger.literals(); *materialized_literal_count = logger.literals();
*expected_property_count = logger.properties(); *expected_property_count = logger.properties();
...@@ -4148,6 +4145,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count, ...@@ -4148,6 +4145,7 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
*expected_property_count, language_mode(), *expected_property_count, language_mode(),
scope->uses_super_property(), scope->calls_eval()); scope->uses_super_property(), scope->calls_eval());
} }
return kLazyParsingComplete;
} }
...@@ -4599,9 +4597,8 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody( ...@@ -4599,9 +4597,8 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
return result; return result;
} }
PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
SingletonLogger* logger, Scanner::BookmarkScope* bookmark) { SingletonLogger* logger, bool may_abort) {
// This function may be called on a background thread too; record only the // This function may be called on a background thread too; record only the
// main thread preparse times. // main thread preparse times.
if (pre_parse_timer_ != NULL) { if (pre_parse_timer_ != NULL) {
...@@ -4628,7 +4625,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser( ...@@ -4628,7 +4625,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
language_mode(), function_state_->kind(), language_mode(), function_state_->kind(),
scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_, scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_,
logger, bookmark, use_counts_); logger, may_abort, use_counts_);
if (pre_parse_timer_ != NULL) { if (pre_parse_timer_ != NULL) {
pre_parse_timer_->Stop(); pre_parse_timer_->Stop();
} }
......
...@@ -510,16 +510,14 @@ class Parser : public ParserBase<Parser> { ...@@ -510,16 +510,14 @@ class Parser : public ParserBase<Parser> {
// Skip over a lazy function, either using cached data if we have it, or // Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }. // by parsing the function with PreParser. Consumes the ending }.
// // If may_abort == true, the (pre-)parser may decide to abort skipping
// If bookmark is set, the (pre-)parser may decide to abort skipping
// in order to force the function to be eagerly parsed, after all. // in order to force the function to be eagerly parsed, after all.
// In this case, it'll reset the scanner using the bookmark. LazyParsingResult SkipLazyFunctionBody(int* materialized_literal_count,
void SkipLazyFunctionBody(int* materialized_literal_count, int* expected_property_count,
int* expected_property_count, bool* ok, bool may_abort, bool* ok);
Scanner::BookmarkScope* bookmark = nullptr);
PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser( PreParser::PreParseResult ParseLazyFunctionBodyWithPreParser(
SingletonLogger* logger, Scanner::BookmarkScope* bookmark = nullptr); SingletonLogger* logger, bool may_abort);
Block* BuildParameterInitializationBlock( Block* BuildParameterInitializationBlock(
const ParserFormalParameters& parameters, bool* ok); const ParserFormalParameters& parameters, bool* ok);
...@@ -849,6 +847,7 @@ class Parser : public ParserBase<Parser> { ...@@ -849,6 +847,7 @@ class Parser : public ParserBase<Parser> {
V8_INLINE static ZoneList<Expression*>* NullExpressionList() { V8_INLINE static ZoneList<Expression*>* NullExpressionList() {
return nullptr; return nullptr;
} }
V8_INLINE static ZoneList<Statement*>* NullStatementList() { return nullptr; }
// Non-NULL empty string. // Non-NULL empty string.
V8_INLINE const AstRawString* EmptyIdentifierString() const { V8_INLINE const AstRawString* EmptyIdentifierString() const {
......
...@@ -29,18 +29,14 @@ namespace internal { ...@@ -29,18 +29,14 @@ namespace internal {
// thus it must never be used where only a single statement // thus it must never be used where only a single statement
// is correct (e.g. an if statement branch w/o braces)! // is correct (e.g. an if statement branch w/o braces)!
#define CHECK_OK ok); \ #define CHECK_OK_VALUE(x) ok); \
if (!*ok) return Statement::Default(); \ if (!*ok) return x; \
((void)0 ((void)0
#define DUMMY ) // to make indentation work #define DUMMY ) // to make indentation work
#undef DUMMY #undef DUMMY
// Used in functions where the return type is not ExpressionT. #define CHECK_OK CHECK_OK_VALUE(Statement::Default())
#define CHECK_OK_CUSTOM(x) ok); \ #define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
if (!*ok) return this->x(); \
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
PreParserIdentifier PreParser::GetSymbol() const { PreParserIdentifier PreParser::GetSymbol() const {
switch (scanner()->current_token()) { switch (scanner()->current_token()) {
...@@ -75,8 +71,7 @@ PreParserIdentifier PreParser::GetSymbol() const { ...@@ -75,8 +71,7 @@ PreParserIdentifier PreParser::GetSymbol() const {
PreParser::PreParseResult PreParser::PreParseLazyFunction( PreParser::PreParseResult PreParser::PreParseLazyFunction(
LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters, LanguageMode language_mode, FunctionKind kind, bool has_simple_parameters,
bool parsing_module, ParserRecorder* log, Scanner::BookmarkScope* bookmark, bool parsing_module, ParserRecorder* log, bool may_abort, int* use_counts) {
int* use_counts) {
parsing_module_ = parsing_module; parsing_module_ = parsing_module;
log_ = log; log_ = log;
use_counts_ = use_counts; use_counts_ = use_counts;
...@@ -93,10 +88,10 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( ...@@ -93,10 +88,10 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
DCHECK_EQ(Token::LBRACE, scanner()->current_token()); DCHECK_EQ(Token::LBRACE, scanner()->current_token());
bool ok = true; bool ok = true;
int start_position = peek_position(); int start_position = peek_position();
ParseLazyFunctionLiteralBody(&ok, bookmark); LazyParsingResult result = ParseLazyFunctionLiteralBody(may_abort, &ok);
use_counts_ = nullptr; use_counts_ = nullptr;
if (bookmark && bookmark->HasBeenReset()) { if (result == kLazyParsingAborted) {
// Do nothing, as we've just aborted scanning this function. return kPreParseAbort;
} else if (stack_overflow()) { } else if (stack_overflow()) {
return kPreParseStackOverflow; return kPreParseStackOverflow;
} else if (!ok) { } else if (!ok) {
...@@ -107,7 +102,6 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( ...@@ -107,7 +102,6 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
int end_pos = scanner()->location().end_pos; int end_pos = scanner()->location().end_pos;
CheckStrictOctalLiteral(start_position, end_pos, &ok); CheckStrictOctalLiteral(start_position, end_pos, &ok);
CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos); CheckDecimalLiteralWithLeadingZero(use_counts, start_position, end_pos);
if (!ok) return kPreParseSuccess;
} }
} }
return kPreParseSuccess; return kPreParseSuccess;
...@@ -171,15 +165,12 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { ...@@ -171,15 +165,12 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
return ParseStatement(kAllowLabelledFunctionStatement, ok); return ParseStatement(kAllowLabelledFunctionStatement, ok);
} }
PreParser::LazyParsingResult PreParser::ParseStatementList(int end_token,
void PreParser::ParseStatementList(int end_token, bool* ok, bool may_abort,
Scanner::BookmarkScope* bookmark) { bool* ok) {
// SourceElements :: // SourceElements ::
// (Statement)* <end_token> // (Statement)* <end_token>
// Bookkeeping for trial parse if bookmark is set:
DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
bool maybe_reset = bookmark != nullptr;
int count_statements = 0; int count_statements = 0;
bool directive_prologue = true; bool directive_prologue = true;
...@@ -189,7 +180,8 @@ void PreParser::ParseStatementList(int end_token, bool* ok, ...@@ -189,7 +180,8 @@ void PreParser::ParseStatementList(int end_token, bool* ok,
} }
bool starts_with_identifier = peek() == Token::IDENTIFIER; bool starts_with_identifier = peek() == Token::IDENTIFIER;
Scanner::Location token_loc = scanner()->peek_location(); Scanner::Location token_loc = scanner()->peek_location();
Statement statement = ParseStatementListItem(CHECK_OK_CUSTOM(Void)); Statement statement =
ParseStatementListItem(CHECK_OK_VALUE(kLazyParsingComplete));
if (directive_prologue) { if (directive_prologue) {
bool use_strict_found = statement.IsUseStrictLiteral(); bool use_strict_found = statement.IsUseStrictLiteral();
...@@ -209,7 +201,7 @@ void PreParser::ParseStatementList(int end_token, bool* ok, ...@@ -209,7 +201,7 @@ void PreParser::ParseStatementList(int end_token, bool* ok,
MessageTemplate::kIllegalLanguageModeDirective, MessageTemplate::kIllegalLanguageModeDirective,
"use strict"); "use strict");
*ok = false; *ok = false;
return; return kLazyParsingComplete;
} }
} }
...@@ -218,15 +210,15 @@ void PreParser::ParseStatementList(int end_token, bool* ok, ...@@ -218,15 +210,15 @@ void PreParser::ParseStatementList(int end_token, bool* ok,
// Our current definition of 'long and trivial' is: // Our current definition of 'long and trivial' is:
// - over 200 statements // - over 200 statements
// - all starting with an identifier (i.e., no if, for, while, etc.) // - all starting with an identifier (i.e., no if, for, while, etc.)
if (maybe_reset && (!starts_with_identifier || if (may_abort) {
++count_statements > kLazyParseTrialLimit)) { if (!starts_with_identifier) {
if (count_statements > kLazyParseTrialLimit) { may_abort = false;
bookmark->Reset(); } else if (++count_statements > kLazyParseTrialLimit) {
return; return kLazyParsingAborted;
} }
maybe_reset = false;
} }
} }
return kLazyParsingComplete;
} }
...@@ -815,8 +807,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { ...@@ -815,8 +807,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
&is_binding_pattern, &first_initializer_loc, &is_binding_pattern, &first_initializer_loc,
&bindings_loc, CHECK_OK); &bindings_loc, CHECK_OK);
if (is_lexical) has_lexical = true; if (is_lexical) has_lexical = true;
if (CheckInOrOf(&mode, ok)) { if (CheckInOrOf(&mode)) {
if (!*ok) return Statement::Default();
if (decl_count != 1) { if (decl_count != 1) {
ReportMessageAt(bindings_loc, ReportMessageAt(bindings_loc,
MessageTemplate::kForInOfLoopMultiBindings, MessageTemplate::kForInOfLoopMultiBindings,
...@@ -860,7 +851,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) { ...@@ -860,7 +851,7 @@ PreParser::Statement PreParser::ParseForStatement(bool* ok) {
ExpressionClassifier classifier(this); ExpressionClassifier classifier(this);
Expression lhs = ParseExpressionCoverGrammar(false, CHECK_OK); Expression lhs = ParseExpressionCoverGrammar(false, CHECK_OK);
int lhs_end_pos = scanner()->location().end_pos; int lhs_end_pos = scanner()->location().end_pos;
bool is_for_each = CheckInOrOf(&mode, CHECK_OK); bool is_for_each = CheckInOrOf(&mode);
bool is_destructuring = is_for_each && bool is_destructuring = is_for_each &&
(lhs->IsArrayLiteral() || lhs->IsObjectLiteral()); (lhs->IsArrayLiteral() || lhs->IsObjectLiteral());
...@@ -1020,12 +1011,7 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) { ...@@ -1020,12 +1011,7 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
// Redefinition of CHECK_OK for parsing expressions. // Redefinition of CHECK_OK for parsing expressions.
#undef CHECK_OK #undef CHECK_OK
#define CHECK_OK ok); \ #define CHECK_OK CHECK_OK_VALUE(Expression::Default())
if (!*ok) return Expression::Default(); \
((void)0
#define DUMMY ) // to make indentation work
#undef DUMMY
PreParser::Expression PreParser::ParseFunctionLiteral( PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name, Scanner::Location function_name_location, Identifier function_name, Scanner::Location function_name_location,
...@@ -1062,7 +1048,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( ...@@ -1062,7 +1048,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
if (is_lazily_parsed) { if (is_lazily_parsed) {
ParseLazyFunctionLiteralBody(CHECK_OK); ParseLazyFunctionLiteralBody(false, CHECK_OK);
} else { } else {
ParseStatementList(Token::RBRACE, CHECK_OK); ParseStatementList(Token::RBRACE, CHECK_OK);
} }
...@@ -1116,12 +1102,12 @@ PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) { ...@@ -1116,12 +1102,12 @@ PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) {
return Expression::Default(); return Expression::Default();
} }
void PreParser::ParseLazyFunctionLiteralBody(bool* ok, PreParser::LazyParsingResult PreParser::ParseLazyFunctionLiteralBody(
Scanner::BookmarkScope* bookmark) { bool may_abort, bool* ok) {
int body_start = position(); int body_start = position();
ParseStatementList(Token::RBRACE, ok, bookmark); LazyParsingResult result = ParseStatementList(
if (!*ok) return; Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
if (bookmark && bookmark->HasBeenReset()) return; if (result == kLazyParsingAborted) return result;
// Position right after terminal '}'. // Position right after terminal '}'.
DCHECK_EQ(Token::RBRACE, scanner()->peek()); DCHECK_EQ(Token::RBRACE, scanner()->peek());
...@@ -1132,6 +1118,7 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok, ...@@ -1132,6 +1118,7 @@ void PreParser::ParseLazyFunctionLiteralBody(bool* ok,
function_state_->materialized_literal_count(), function_state_->materialized_literal_count(),
function_state_->expected_property_count(), language_mode(), function_state_->expected_property_count(), language_mode(),
scope->uses_super_property(), scope->calls_eval()); scope->uses_super_property(), scope->calls_eval());
return kLazyParsingComplete;
} }
PreParserExpression PreParser::ParseClassLiteral( PreParserExpression PreParser::ParseClassLiteral(
...@@ -1228,7 +1215,7 @@ void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body, ...@@ -1228,7 +1215,7 @@ void PreParser::ParseAsyncArrowSingleExpressionBody(PreParserStatementList body,
scope()->ForceContextAllocation(); scope()->ForceContextAllocation();
PreParserExpression return_value = PreParserExpression return_value =
ParseAssignmentExpression(accept_IN, CHECK_OK_CUSTOM(Void)); ParseAssignmentExpression(accept_IN, CHECK_OK_VOID);
body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); body->Add(PreParserStatement::ExpressionStatement(return_value), zone());
} }
......
...@@ -296,6 +296,7 @@ class PreParserExpression { ...@@ -296,6 +296,7 @@ class PreParserExpression {
// More dummy implementations of things PreParser doesn't need to track: // More dummy implementations of things PreParser doesn't need to track:
void set_index(int index) {} // For YieldExpressions void set_index(int index) {} // For YieldExpressions
void set_should_eager_compile() {} void set_should_eager_compile() {}
void set_should_be_used_once_hint() {}
int position() const { return kNoSourcePosition; } int position() const { return kNoSourcePosition; }
void set_function_token_position(int position) {} void set_function_token_position(int position) {}
...@@ -642,6 +643,7 @@ class PreParser : public ParserBase<PreParser> { ...@@ -642,6 +643,7 @@ class PreParser : public ParserBase<PreParser> {
enum PreParseResult { enum PreParseResult {
kPreParseStackOverflow, kPreParseStackOverflow,
kPreParseAbort,
kPreParseSuccess kPreParseSuccess
}; };
...@@ -698,11 +700,7 @@ class PreParser : public ParserBase<PreParser> { ...@@ -698,11 +700,7 @@ class PreParser : public ParserBase<PreParser> {
FunctionKind kind, FunctionKind kind,
bool has_simple_parameters, bool has_simple_parameters,
bool parsing_module, ParserRecorder* log, bool parsing_module, ParserRecorder* log,
Scanner::BookmarkScope* bookmark, bool may_abort, int* use_counts);
int* use_counts);
// A dummy function, just useful as an argument to CHECK_OK_CUSTOM.
static void Void() {}
private: private:
static const int kLazyParseTrialLimit = 200; static const int kLazyParseTrialLimit = 200;
...@@ -717,8 +715,12 @@ class PreParser : public ParserBase<PreParser> { ...@@ -717,8 +715,12 @@ class PreParser : public ParserBase<PreParser> {
// By making the 'exception handling' explicit, we are forced to check // By making the 'exception handling' explicit, we are forced to check
// for failure at the call sites. // for failure at the call sites.
Statement ParseStatementListItem(bool* ok); Statement ParseStatementListItem(bool* ok);
void ParseStatementList(int end_token, bool* ok, V8_INLINE void ParseStatementList(int end_token, bool* ok) {
Scanner::BookmarkScope* bookmark = nullptr); LazyParsingResult result = ParseStatementList(end_token, false, ok);
USE(result); // The result is just used in debug modes.
DCHECK_EQ(result, kLazyParsingComplete);
}
LazyParsingResult ParseStatementList(int end_token, bool may_abort, bool* ok);
Statement ParseStatement(AllowLabelledFunctionStatement allow_function, Statement ParseStatement(AllowLabelledFunctionStatement allow_function,
bool* ok); bool* ok);
Statement ParseSubStatement(AllowLabelledFunctionStatement allow_function, Statement ParseSubStatement(AllowLabelledFunctionStatement allow_function,
...@@ -764,18 +766,18 @@ class PreParser : public ParserBase<PreParser> { ...@@ -764,18 +766,18 @@ class PreParser : public ParserBase<PreParser> {
const PreParserFormalParameters& parameters, FunctionKind kind, const PreParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok); FunctionLiteral::FunctionType function_type, bool* ok);
V8_INLINE void SkipLazyFunctionBody( V8_INLINE LazyParsingResult
int* materialized_literal_count, int* expected_property_count, bool* ok, SkipLazyFunctionBody(int* materialized_literal_count,
Scanner::BookmarkScope* bookmark = nullptr) { int* expected_property_count, bool may_abort, bool* ok) {
UNREACHABLE(); UNREACHABLE();
return kLazyParsingComplete;
} }
Expression ParseFunctionLiteral( Expression ParseFunctionLiteral(
Identifier name, Scanner::Location function_name_location, Identifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind, FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionLiteral::FunctionType function_type, int function_token_pos, FunctionLiteral::FunctionType function_type,
LanguageMode language_mode, bool* ok); LanguageMode language_mode, bool* ok);
void ParseLazyFunctionLiteralBody(bool* ok, LazyParsingResult ParseLazyFunctionLiteralBody(bool may_abort, bool* ok);
Scanner::BookmarkScope* bookmark = nullptr);
PreParserExpression ParseClassLiteral(PreParserIdentifier name, PreParserExpression ParseClassLiteral(PreParserIdentifier name,
Scanner::Location class_name_location, Scanner::Location class_name_location,
...@@ -1009,6 +1011,9 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1009,6 +1011,9 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE static PreParserExpressionList NullExpressionList() { V8_INLINE static PreParserExpressionList NullExpressionList() {
return PreParserExpressionList(); return PreParserExpressionList();
} }
V8_INLINE static PreParserStatementList NullStatementList() {
return PreParserStatementList();
}
V8_INLINE PreParserIdentifier EmptyIdentifierString() const { V8_INLINE PreParserIdentifier EmptyIdentifierString() const {
return PreParserIdentifier::Default(); return PreParserIdentifier::Default();
} }
......
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