Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index b6ae337877ca8368a03a90364f6b205d0775b771..8d23875ab6bca368251b9dd13d2172e8291a571d 100644 |
--- a/src/ast/scopes.cc |
+++ b/src/ast/scopes.cc |
@@ -1073,12 +1073,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; |
} |
@@ -1178,7 +1180,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()); |
@@ -1191,8 +1193,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); |
@@ -1515,6 +1518,29 @@ 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) { |
+ // Since we don't lazy parse inner arrow functions, inner functions |
+ // cannot refer to the outer "this". |
+ if (!var->is_dynamic() && !var->is_this() && |
+ !var->has_forced_context_allocation()) { |
+ 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) { |
@@ -1560,13 +1586,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; |
@@ -1579,7 +1608,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; |