| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index f97174136887ae5be63b81dc44b3a8eea62b9da2..860da1340ba01332d59f012b8d200a2f25542f1c 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -4076,14 +4076,33 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| !parenthesized_function_);
|
| parenthesized_function_ = false; // The bit was set for this function only.
|
|
|
| + // Eager or lazy parse?
|
| + // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
|
| + // pass it to SkipLazyFunctionBody, which may use it to abort lazy
|
| + // parsing if it suspect that wasn't a good idea. If so, or if we didn't
|
| + // try to lazy parse in the first place, we'll have to parse eagerly.
|
| + Scanner::BookmarkScope bookmark(scanner());
|
| if (is_lazily_parsed) {
|
| for (Scope* s = scope_->outer_scope();
|
| s != nullptr && (s != s->DeclarationScope()); s = s->outer_scope()) {
|
| s->ForceContextAllocation();
|
| }
|
| +
|
| + Scanner::BookmarkScope* maybe_bookmark =
|
| + bookmark.Set() ? &bookmark : nullptr;
|
| SkipLazyFunctionBody(&materialized_literal_count,
|
| - &expected_property_count, CHECK_OK);
|
| - } else {
|
| + &expected_property_count, /*CHECK_OK*/ ok,
|
| + maybe_bookmark);
|
| +
|
| + if (bookmark.HasBeenReset()) {
|
| + // Trigger eager (re-)parsing, just below this block.
|
| + is_lazily_parsed = false;
|
| +
|
| + // Inform the compiler it should also eager-compile this function.
|
| + eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
|
| + }
|
| + }
|
| + if (!is_lazily_parsed) {
|
| body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
|
| kind, CHECK_OK);
|
| materialized_literal_count = function_state.materialized_literal_count();
|
| @@ -4138,8 +4157,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|
|
|
|
| void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
|
| - int* expected_property_count,
|
| - bool* ok) {
|
| + int* expected_property_count, bool* ok,
|
| + Scanner::BookmarkScope* bookmark) {
|
| + DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
|
| if (produce_cached_parse_data()) CHECK(log_);
|
|
|
| int function_block_pos = position();
|
| @@ -4172,7 +4192,10 @@ void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
|
| // AST. This gathers the data needed to build a lazy function.
|
| SingletonLogger logger;
|
| PreParser::PreParseResult result =
|
| - ParseLazyFunctionBodyWithPreParser(&logger);
|
| + ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
|
| + if (bookmark && bookmark->HasBeenReset()) {
|
| + return; // Return immediately if pre-parser devided to abort parsing.
|
| + }
|
| if (result == PreParser::kPreParseStackOverflow) {
|
| // Propagate stack overflow.
|
| set_stack_overflow();
|
| @@ -4301,7 +4324,7 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
|
|
|
|
| PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| - SingletonLogger* logger) {
|
| + SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
|
| // This function may be called on a background thread too; record only the
|
| // main thread preparse times.
|
| if (pre_parse_timer_ != NULL) {
|
| @@ -4331,7 +4354,7 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
|
| }
|
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
|
| - language_mode(), function_state_->kind(), logger);
|
| + language_mode(), function_state_->kind(), logger, bookmark);
|
| if (pre_parse_timer_ != NULL) {
|
| pre_parse_timer_->Stop();
|
| }
|
|
|