Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index 288196150cea807a7ffdf24e3f7a8d3acfbde174..c088ecc24fb54537a9fa2eb1217c1b7f214c8bf2 100644 |
--- a/src/ast/scopes.cc |
+++ b/src/ast/scopes.cc |
@@ -979,18 +979,12 @@ Handle<ScopeInfo> Scope::GetScopeInfo(Isolate* isolate) { |
return scope_info_; |
} |
-Handle<StringSet> Scope::CollectNonLocals(Handle<StringSet> non_locals) { |
- // Collect non-local variables referenced in the scope. |
- // TODO(yangguo): store non-local variables explicitly if we can no longer |
- // rely on unresolved_ to find them. |
- for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
+Handle<StringSet> DeclarationScope::CollectNonLocals( |
+ ParseInfo* info, Handle<StringSet> non_locals) { |
+ VariableProxy* free_variables = FetchFreeVariables(this, info); |
+ for (VariableProxy* proxy = free_variables; proxy != nullptr; |
proxy = proxy->next_unresolved()) { |
- if (proxy->is_resolved() && proxy->var()->IsStackAllocated()) continue; |
- Handle<String> name = proxy->name(); |
- non_locals = StringSet::Add(non_locals, name); |
- } |
- for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
- non_locals = scope->CollectNonLocals(non_locals); |
+ non_locals = StringSet::Add(non_locals, proxy->name()); |
} |
return non_locals; |
} |
@@ -1003,7 +997,12 @@ 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. |
- MigrateUnresolvableLocals(migrate_to, ast_node_factory, this); |
+ for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr; |
+ proxy = proxy->next_unresolved()) { |
+ DCHECK(!proxy->is_resolved()); |
+ VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); |
+ migrate_to->AddUnresolved(copy); |
+ } |
// Push scope data up to migrate_to. Note that migrate_to and this Scope |
// describe the same Scope, just in different Zones. |
@@ -1359,6 +1358,11 @@ void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, |
BindingKind binding_kind; |
Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
+ ResolveTo(info, binding_kind, proxy, var); |
+} |
+ |
+void Scope::ResolveTo(ParseInfo* info, BindingKind binding_kind, |
+ VariableProxy* proxy, Variable* var) { |
#ifdef DEBUG |
if (info->script_is_native()) { |
// To avoid polluting the global object in native scripts |
@@ -1438,30 +1442,38 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info, |
} |
} |
-void Scope::MigrateUnresolvableLocals(DeclarationScope* migrate_to, |
- AstNodeFactory* ast_node_factory, |
- DeclarationScope* max_outer_scope) { |
- BindingKind binding_kind; |
+VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
+ ParseInfo* info, |
+ VariableProxy* stack) { |
+ BindingKind binding_kind = BOUND; |
for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
proxy = next) { |
next = proxy->next_unresolved(); |
+ if (proxy->is_resolved()) continue; |
// Note that we pass nullptr as AstNodeFactory: this phase should not create |
// any new AstNodes, since none of the Scopes involved are backed up by |
// ScopeInfo. |
- if (LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope) == |
- nullptr) { |
- // Re-create the VariableProxies in the right Zone and insert them into |
- // migrate_to. |
- DCHECK(!proxy->is_resolved()); |
- VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); |
- migrate_to->AddUnresolved(copy); |
+ Variable* var = |
+ LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope); |
+ // Anything that was bound |
+ if (var == nullptr) { |
+ proxy->set_next_unresolved(stack); |
+ stack = proxy; |
+ } else if (info != nullptr) { |
+ DCHECK_NE(UNBOUND, binding_kind); |
+ DCHECK_NE(UNBOUND_EVAL_SHADOWED, binding_kind); |
+ ResolveTo(info, binding_kind, proxy, var); |
} |
} |
+ // Clear unresolved_ as it's in an inconsistent state. |
+ unresolved_ = nullptr; |
+ |
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
- scope->MigrateUnresolvableLocals(migrate_to, ast_node_factory, |
- max_outer_scope); |
+ stack = scope->FetchFreeVariables(max_outer_scope, info, stack); |
} |
+ |
+ return stack; |
} |
void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval) { |