Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Unified Diff: src/parsing/parser.cc

Issue 2349473004: Revert of Preparse inner functions. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 1e0932fe5fe6980cf516076e74b20fe0ad187aae..77173a40d70d4da11112647817391631715776ee 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -122,17 +122,11 @@
if (use_temp_zone) {
parser_->fni_ = &fni_;
parser_->zone_ = temp_zone;
- if (parser_->reusable_preparser_ != nullptr) {
- parser_->reusable_preparser_->zone_ = temp_zone;
- }
}
}
~DiscardableZoneScope() {
parser_->fni_ = prev_fni_;
parser_->zone_ = prev_zone_;
- if (parser_->reusable_preparser_ != nullptr) {
- parser_->reusable_preparser_->zone_ = prev_zone_;
- }
}
private:
@@ -3000,9 +2994,7 @@
// These are all things we can know at this point, without looking at the
// function itself.
- // We separate between lazy parsing top level functions and lazy parsing inner
- // functions, because the latter needs to do more work. In particular, we need
- // to track unresolved variables to distinguish between these cases:
+ // In addition, we need to distinguish between these cases:
// (function foo() {
// bar = function() { return 1; }
// })();
@@ -3014,19 +3006,17 @@
// Now foo will be parsed eagerly and compiled eagerly (optimization: assume
// parenthesis before the function means that it will be called
- // immediately). bar can be parsed lazily, but we need to parse it in a mode
- // that tracks unresolved variables.
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, FLAG_lazy);
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, allow_lazy());
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, !allow_natives());
- DCHECK_IMPLIES(mode() == PARSE_LAZILY, extension_ == nullptr);
-
- bool is_lazy_top_level_function =
- mode() == PARSE_LAZILY &&
- eager_compile_hint == FunctionLiteral::kShouldLazyCompile &&
- scope()->AllowsLazyParsingWithoutUnresolvedVariables();
-
- // Determine whether we can still do the inner function lazy parsing.
+ // immediately). The inner function *must* be parsed eagerly to resolve the
+ // possible reference to the variable in foo's scope. However, it's possible
+ // that it will be compiled lazily.
+
+ // To make this additional case work, both Parser and PreParser implement a
+ // logic where only top-level functions will be parsed lazily.
+ bool is_lazily_parsed = mode() == PARSE_LAZILY &&
+ scope()->AllowsLazyParsing() &&
+ !function_state_->next_function_is_parenthesized();
+
+ // Determine whether the function body can be discarded after parsing.
// The preconditions are:
// - Lazy compilation has to be enabled.
// - Neither V8 natives nor native function declarations can be allowed,
@@ -3041,19 +3031,15 @@
// - The function literal shouldn't be hinted to eagerly compile.
// - For asm.js functions the body needs to be available when module
// validation is active, because we examine the entire module at once.
-
- // Inner functions will be parsed by using a temporary Zone. After parsing, we
- // will migrate unresolved variable into a Scope in the main Zone.
- // TODO(marja): Refactor parsing modes: simplify this.
- bool is_lazy_inner_function =
- !is_lazy_top_level_function && FLAG_lazy && !allow_natives() &&
+ bool use_temp_zone =
+ !is_lazily_parsed && FLAG_lazy && !allow_natives() &&
extension_ == NULL && allow_lazy() &&
function_type == FunctionLiteral::kDeclaration &&
eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
!(FLAG_validate_asm && scope()->IsAsmModule());
DeclarationScope* main_scope = nullptr;
- if (is_lazy_inner_function) {
+ if (use_temp_zone) {
// This Scope lives in the main Zone; we'll migrate data into it later.
main_scope = NewFunctionScope(kind);
}
@@ -3078,11 +3064,11 @@
// to do scope analysis correctly after full parsing, we migrate needed
// information from scope into main_scope when the function has been parsed.
Zone temp_zone(zone()->allocator());
- DiscardableZoneScope zone_scope(this, &temp_zone, is_lazy_inner_function);
+ DiscardableZoneScope zone_scope(this, &temp_zone, use_temp_zone);
DeclarationScope* scope = NewFunctionScope(kind);
SetLanguageMode(scope, language_mode);
- if (!is_lazy_inner_function) {
+ if (!use_temp_zone) {
main_scope = scope;
} else {
DCHECK(main_scope->zone() != scope->zone());
@@ -3126,17 +3112,18 @@
// which says whether we need to create an arguments adaptor frame).
if (formals.has_rest) arity--;
- // Eager or lazy parse? If is_lazy_top_level_function, we'll parse
- // lazily. We'll call SkipLazyFunctionBody, which may decide to abort lazy
- // parsing if it suspects that wasn't a good idea. If so (in which case the
- // parser is expected to have backtracked), or if we didn't try to lazy
- // parse in the first place, we'll have to parse eagerly.
- if (is_lazy_top_level_function) {
+ // Eager or lazy parse?
+ // If is_lazily_parsed, we'll parse lazily. We'll call SkipLazyFunctionBody,
+ // which may decide to abort lazy parsing if it suspects that wasn't a good
+ // idea. If so (in which case the parser is expected to have backtracked),
+ // or if we didn't try to lazy parse in the first place, we'll have to parse
+ // eagerly.
+ if (is_lazily_parsed) {
Scanner::BookmarkScope bookmark(scanner());
bool may_abort = bookmark.Set();
- LazyParsingResult result = SkipLazyFunctionBody(
- &materialized_literal_count, &expected_property_count, false,
- may_abort, CHECK_OK);
+ LazyParsingResult result =
+ SkipLazyFunctionBody(&materialized_literal_count,
+ &expected_property_count, may_abort, CHECK_OK);
materialized_literal_count += formals.materialized_literals_count +
function_state.materialized_literal_count();
@@ -3144,7 +3131,7 @@
if (result == kLazyParsingAborted) {
bookmark.Reset();
// Trigger eager (re-)parsing, just below this block.
- is_lazy_top_level_function = false;
+ 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
@@ -3153,29 +3140,17 @@
should_be_used_once_hint = true;
}
}
- if (is_lazy_inner_function) {
- if (FLAG_lazy_inner_functions) {
- LazyParsingResult result = SkipLazyFunctionBody(
- &materialized_literal_count, &expected_property_count, true, false,
- CHECK_OK);
- materialized_literal_count +=
- formals.materialized_literals_count +
- function_state.materialized_literal_count();
- DCHECK(result != kLazyParsingAborted);
- USE(result);
- } else {
- ParseEagerFunctionBody(function_name, pos, formals, kind, function_type,
- CHECK_OK);
- materialized_literal_count =
- function_state.materialized_literal_count();
- expected_property_count = function_state.expected_property_count();
- }
- } else if (!is_lazy_top_level_function) {
+ if (!is_lazily_parsed) {
body = ParseEagerFunctionBody(function_name, pos, formals, kind,
function_type, CHECK_OK);
materialized_literal_count = function_state.materialized_literal_count();
expected_property_count = function_state.expected_property_count();
+ if (use_temp_zone) {
+ // If the preconditions are correct the function body should never be
+ // accessed, but do this anyway for better behaviour if they're wrong.
+ body = nullptr;
+ }
}
// Parsing the body may change the language mode in our scope.
@@ -3209,7 +3184,7 @@
has_duplicate_parameters =
!classifier()->is_valid_formal_parameter_list_without_duplicates();
- if (is_lazy_inner_function) {
+ if (use_temp_zone) {
DCHECK(main_scope != scope);
scope->AnalyzePartially(main_scope, &previous_zone_ast_node_factory);
}
@@ -3263,15 +3238,13 @@
Parser::LazyParsingResult Parser::SkipLazyFunctionBody(
int* materialized_literal_count, int* expected_property_count,
- bool is_inner_function, bool may_abort, bool* ok) {
+ bool may_abort, bool* ok) {
if (produce_cached_parse_data()) CHECK(log_);
int function_block_pos = position();
DeclarationScope* scope = this->scope()->AsDeclarationScope();
DCHECK(scope->is_function_scope());
- // Inner functions are not part of the cached data.
- if (!is_inner_function && consume_cached_parse_data() &&
- !cached_parse_data_->rejected()) {
+ if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
// If we have cached data, we use it to skip parsing the function body. The
// data contains the information we need to construct the lazy function.
FunctionEntry entry =
@@ -3298,7 +3271,7 @@
// AST. This gathers the data needed to build a lazy function.
SingletonLogger logger;
PreParser::PreParseResult result =
- ParseLazyFunctionBodyWithPreParser(&logger, is_inner_function, may_abort);
+ ParseLazyFunctionBodyWithPreParser(&logger, may_abort);
// Return immediately if pre-parser decided to abort parsing.
if (result == PreParser::kPreParseAbort) {
return kLazyParsingAborted;
@@ -3324,7 +3297,7 @@
SetLanguageMode(scope, logger.language_mode());
if (logger.uses_super_property()) scope->RecordSuperPropertyUsage();
if (logger.calls_eval()) scope->RecordEvalCall();
- if (!is_inner_function && produce_cached_parse_data()) {
+ if (produce_cached_parse_data()) {
DCHECK(log_);
// Position right after terminal '}'.
int body_end = scanner()->location().end_pos;
@@ -3626,12 +3599,11 @@
const AstRawString* function_name, int pos,
const ParserFormalParameters& parameters, FunctionKind kind,
FunctionLiteral::FunctionType function_type, bool* ok) {
- // Everything inside an eagerly parsed function will be parsed eagerly (see
- // comment above). Lazy inner functions are handled separately and they won't
- // require the mode to be PARSE_LAZILY (see ParseFunctionLiteral).
- // TODO(marja): Refactor parsing modes: remove this.
+ // Everything inside an eagerly parsed function will be parsed eagerly
+ // (see comment above).
ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
+
static const int kFunctionNameAssignmentIndex = 0;
if (function_type == FunctionLiteral::kNamedExpression) {
DCHECK(function_name != NULL);
@@ -3787,7 +3759,7 @@
}
PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
- SingletonLogger* logger, bool is_inner_function, bool may_abort) {
+ SingletonLogger* logger, bool may_abort) {
// This function may be called on a background thread too; record only the
// main thread preparse times.
if (pre_parse_timer_ != NULL) {
@@ -3812,36 +3784,10 @@
SET_ALLOW(harmony_class_fields);
#undef SET_ALLOW
}
- // Aborting inner function preparsing would leave scopes in an inconsistent
- // state; we don't parse inner functions in the abortable mode anyway.
- DCHECK(!is_inner_function || !may_abort);
-
- FunctionKind kind = function_state_->kind();
- PreParser::PreParseResult result;
- if (!is_inner_function) {
- // If we don't need to look at the scope, construct a dummy scope chain
- // which is not connected to the real scope chain.
- LanguageMode mode = language_mode();
- bool has_simple_parameters =
- scope()->AsDeclarationScope()->has_simple_parameters();
- DeclarationScope* top_scope = NewScriptScope();
- top_scope->SetLanguageMode(mode);
- FunctionState top_state(&function_state_, &scope_state_, top_scope,
- kNormalFunction);
- DeclarationScope* function_scope = NewFunctionScope(kind);
- if (!has_simple_parameters) {
- function_scope->SetHasNonSimpleParameters();
- }
- result = reusable_preparser_->PreParseLazyFunction(
- kind, function_scope, parsing_module_, logger, is_inner_function,
- may_abort, use_counts_);
- } else {
- // Detaching the scopes created by PreParser from the Scope chain must be
- // done above (see ParseFunctionLiteral & AnalyzePartially).
- result = reusable_preparser_->PreParseLazyFunction(
- kind, scope()->AsDeclarationScope(), parsing_module_, logger,
- is_inner_function, may_abort, use_counts_);
- }
+ PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
+ language_mode(), function_state_->kind(),
+ scope()->AsDeclarationScope()->has_simple_parameters(), parsing_module_,
+ logger, may_abort, use_counts_);
if (pre_parse_timer_ != NULL) {
pre_parse_timer_->Stop();
}
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698