| Index: src/ast/scopes.cc
|
| diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
|
| index 9c5395a0c32f8d0cf60cbdef436704398e803d03..5743fa2ba987025af52f0f7b16980d33752e3951 100644
|
| --- a/src/ast/scopes.cc
|
| +++ b/src/ast/scopes.cc
|
| @@ -1076,12 +1076,14 @@ void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) {
|
| }
|
| }
|
|
|
| -bool Scope::AllowsLazyParsing() const {
|
| - // If we are inside a block scope, we must parse eagerly to find out how
|
| - // to allocate variables on the block scope. At this point, declarations may
|
| - // not have yet been parsed.
|
| +bool Scope::AllowsLazyParsingWithoutUnresolvedVariables() const {
|
| + // If we are inside a block scope, we must find unresolved variables in the
|
| + // inner scopes to find out how to allocate variables on the block scope. At
|
| + // this point, declarations may not have yet been parsed.
|
| for (const Scope* s = this; s != nullptr; s = s->outer_scope_) {
|
| if (s->is_block_scope()) return false;
|
| + // TODO(marja): Refactor parsing modes: also add s->is_function_scope()
|
| + // here.
|
| }
|
| return true;
|
| }
|
| @@ -1181,7 +1183,7 @@ Scope* Scope::GetOuterScopeWithContext() {
|
|
|
| Handle<StringSet> DeclarationScope::CollectNonLocals(
|
| ParseInfo* info, Handle<StringSet> non_locals) {
|
| - VariableProxy* free_variables = FetchFreeVariables(this, info);
|
| + VariableProxy* free_variables = FetchFreeVariables(this, true, info);
|
| for (VariableProxy* proxy = free_variables; proxy != nullptr;
|
| proxy = proxy->next_unresolved()) {
|
| non_locals = StringSet::Add(non_locals, proxy->name());
|
| @@ -1194,8 +1196,9 @@ void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to,
|
| // Try to resolve unresolved variables for this Scope and migrate those which
|
| // cannot be resolved inside. It doesn't make sense to try to resolve them in
|
| // the outer Scopes here, because they are incomplete.
|
| - for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr;
|
| - proxy = proxy->next_unresolved()) {
|
| + for (VariableProxy* proxy =
|
| + FetchFreeVariables(this, !FLAG_lazy_inner_functions);
|
| + proxy != nullptr; proxy = proxy->next_unresolved()) {
|
| DCHECK(!proxy->is_resolved());
|
| VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy);
|
| migrate_to->AddUnresolved(copy);
|
| @@ -1518,6 +1521,27 @@ void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy) {
|
| DCHECK(!proxy->is_resolved());
|
| Variable* var = LookupRecursive(proxy, nullptr);
|
| ResolveTo(info, proxy, var);
|
| +
|
| + if (FLAG_lazy_inner_functions) {
|
| + if (info != nullptr && info->is_native()) return;
|
| + // Pessimistically force context allocation for all variables to which inner
|
| + // scope variables could potentially resolve to.
|
| + Scope* scope = GetClosureScope()->outer_scope_;
|
| + while (scope != nullptr && scope->scope_info_.is_null()) {
|
| + var = scope->LookupLocal(proxy->raw_name());
|
| + if (var != nullptr) {
|
| + if (!var->is_dynamic() && !var->is_this() &&
|
| + !var->has_forced_context_allocation() && !var->is_arguments()) {
|
| + var->ForceContextAllocation();
|
| + var->set_is_used();
|
| + // We don't know what the (potentially lazy parsed) inner function
|
| + // does with the variable; pessimistically assume that it's assigned.
|
| + var->set_maybe_assigned();
|
| + }
|
| + }
|
| + scope = scope->outer_scope_;
|
| + }
|
| + }
|
| }
|
|
|
| void Scope::ResolveTo(ParseInfo* info, VariableProxy* proxy, Variable* var) {
|
| @@ -1563,13 +1587,16 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info) {
|
| }
|
|
|
| VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
|
| - ParseInfo* info,
|
| + bool try_to_resolve, ParseInfo* info,
|
| VariableProxy* stack) {
|
| for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
|
| proxy = next) {
|
| next = proxy->next_unresolved();
|
| DCHECK(!proxy->is_resolved());
|
| - Variable* var = LookupRecursive(proxy, max_outer_scope->outer_scope());
|
| + Variable* var = nullptr;
|
| + if (try_to_resolve) {
|
| + var = LookupRecursive(proxy, max_outer_scope->outer_scope());
|
| + }
|
| if (var == nullptr) {
|
| proxy->set_next_unresolved(stack);
|
| stack = proxy;
|
| @@ -1582,7 +1609,8 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
|
| unresolved_ = nullptr;
|
|
|
| for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
|
| - stack = scope->FetchFreeVariables(max_outer_scope, info, stack);
|
| + stack =
|
| + scope->FetchFreeVariables(max_outer_scope, try_to_resolve, info, stack);
|
| }
|
|
|
| return stack;
|
|
|