| Index: src/ast/scopes.cc
|
| diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
|
| index e80f89f7a9904fa3dcb50999ffe496489f27406c..35507c36fb4221b838b52227201e48514d875c73 100644
|
| --- a/src/ast/scopes.cc
|
| +++ b/src/ast/scopes.cc
|
| @@ -357,6 +357,7 @@ bool Scope::Analyze(ParseInfo* info) {
|
| scope->Print();
|
| }
|
| scope->CheckScopePositions();
|
| + scope->CheckZones();
|
| #endif
|
|
|
| info->set_scope(scope);
|
| @@ -580,9 +581,11 @@ Variable* Scope::LookupFunctionVar(const AstRawString* name,
|
| if (index < 0) return NULL;
|
| Variable* var = new (zone())
|
| Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized);
|
| + DCHECK_NOT_NULL(factory);
|
| VariableProxy* proxy = factory->NewVariableProxy(var);
|
| VariableDeclaration* declaration =
|
| factory->NewVariableDeclaration(proxy, mode, this, kNoSourcePosition);
|
| + DCHECK_EQ(factory->zone(), zone());
|
| DeclareFunctionVar(declaration);
|
| var->AllocateTo(VariableLocation::CONTEXT, index);
|
| return var;
|
| @@ -967,6 +970,35 @@ Handle<StringSet> Scope::CollectNonLocals(Handle<StringSet> non_locals) {
|
| return non_locals;
|
| }
|
|
|
| +void Scope::AnalyzePartially(Scope* migrate_to,
|
| + AstNodeFactory* ast_node_factory) {
|
| + // Gather info from inner scopes.
|
| + PropagateScopeInfo(false);
|
| +
|
| + // 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);
|
| +
|
| + // Push scope data up to migrate_to. Note that migrate_to and this Scope
|
| + // describe the same Scope, just in different Zones.
|
| + PropagateUsageFlagsToScope(migrate_to);
|
| + if (inner_scope_calls_eval_) {
|
| + migrate_to->inner_scope_calls_eval_ = true;
|
| + }
|
| + DCHECK(!force_eager_compilation_);
|
| + migrate_to->set_start_position(start_position_);
|
| + migrate_to->set_end_position(end_position_);
|
| + migrate_to->language_mode_ = language_mode_;
|
| + migrate_to->arity_ = arity_;
|
| + migrate_to->force_context_allocation_ = force_context_allocation_;
|
| + outer_scope_->RemoveInnerScope(this);
|
| + DCHECK_EQ(outer_scope_, migrate_to->outer_scope_);
|
| + DCHECK_EQ(outer_scope_->zone(), migrate_to->zone());
|
| + DCHECK_EQ(NeedsHomeObject(), migrate_to->NeedsHomeObject());
|
| + DCHECK_EQ(asm_function_, migrate_to->asm_function_);
|
| + DCHECK_EQ(arguments() != nullptr, migrate_to->arguments() != nullptr);
|
| +}
|
|
|
| #ifdef DEBUG
|
| static const char* Header(ScopeType scope_type, FunctionKind function_kind,
|
| @@ -1175,6 +1207,12 @@ void Scope::CheckScopePositions() {
|
| scope->CheckScopePositions();
|
| }
|
| }
|
| +
|
| +void Scope::CheckZones() {
|
| + for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
|
| + CHECK_EQ(scope->zone(), zone());
|
| + }
|
| +}
|
| #endif // DEBUG
|
|
|
|
|
| @@ -1197,10 +1235,10 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
|
| return var;
|
| }
|
|
|
| -
|
| Variable* Scope::LookupRecursive(VariableProxy* proxy,
|
| BindingKind* binding_kind,
|
| - AstNodeFactory* factory) {
|
| + AstNodeFactory* factory,
|
| + Scope* max_outer_scope) {
|
| DCHECK(binding_kind != NULL);
|
| if (already_resolved() && is_with_scope()) {
|
| // Short-cut: if the scope is deserialized from a scope info, variable
|
| @@ -1227,13 +1265,14 @@ Variable* Scope::LookupRecursive(VariableProxy* proxy,
|
| var = LookupFunctionVar(proxy->raw_name(), factory);
|
| if (var != NULL) {
|
| *binding_kind = BOUND;
|
| - } else if (outer_scope_ != NULL) {
|
| - var = outer_scope_->LookupRecursive(proxy, binding_kind, factory);
|
| + } else if (outer_scope_ != nullptr && this != max_outer_scope) {
|
| + var = outer_scope_->LookupRecursive(proxy, binding_kind, factory,
|
| + max_outer_scope);
|
| if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
|
| var->ForceContextAllocation();
|
| }
|
| } else {
|
| - DCHECK(is_script_scope());
|
| + DCHECK(is_script_scope() || this == max_outer_scope);
|
| }
|
|
|
| // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
|
| @@ -1366,6 +1405,31 @@ bool Scope::ResolveVariablesRecursively(ParseInfo* info,
|
| return true;
|
| }
|
|
|
| +void Scope::MigrateUnresolvableLocals(Scope* migrate_to,
|
| + AstNodeFactory* ast_node_factory,
|
| + Scope* max_outer_scope) {
|
| + BindingKind binding_kind;
|
| + for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
|
| + proxy = next) {
|
| + next = proxy->next_unresolved();
|
| + // 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);
|
| + }
|
| + }
|
| +
|
| + for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
|
| + scope->MigrateUnresolvableLocals(migrate_to, ast_node_factory,
|
| + max_outer_scope);
|
| + }
|
| +}
|
|
|
| void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
|
| if (outer_scope_calls_sloppy_eval) {
|
|
|