Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index 292916d6a6fb9bdfd69495731a78d8132a66654a..264cd46e576343124ffab6937a7401e828814d0e 100644 |
--- a/src/ast/scopes.cc |
+++ b/src/ast/scopes.cc |
@@ -337,8 +337,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
DCHECK(context->previous()->IsNativeContext()); |
break; |
} else if (context->IsFunctionContext()) { |
- Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), |
- isolate); |
+ Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
// TODO(neis): For an eval scope, we currently create an ordinary function |
// context. This is wrong and needs to be fixed. |
// https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
@@ -360,7 +359,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, scope_info); |
} |
} else if (context->IsModuleContext()) { |
- ScopeInfo* scope_info = context->closure()->shared()->scope_info(); |
+ ScopeInfo* scope_info = context->scope_info(); |
DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); |
outer_scope = new (zone) ModuleScope( |
isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); |
@@ -373,6 +372,13 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
} |
if (current_scope != nullptr) { |
outer_scope->AddInnerScope(current_scope); |
+ DCHECK_IMPLIES( |
+ deserialization_mode == DeserializationMode::kKeepScopeInfo, |
+ current_scope->scope_info_->HasOuterScopeInfo()); |
+ DCHECK_IMPLIES( |
+ deserialization_mode == DeserializationMode::kKeepScopeInfo, |
+ outer_scope->scope_info_->Equals( |
+ current_scope->scope_info_->OuterScopeInfo())); |
} |
current_scope = outer_scope; |
if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
@@ -384,6 +390,17 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
if (innermost_scope == nullptr) return script_scope; |
script_scope->AddInnerScope(current_scope); |
+#if DEBUG |
+ if (deserialization_mode == DeserializationMode::kKeepScopeInfo) { |
+ if (script_scope->scope_info_.is_null()) { |
+ DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); |
+ } else { |
+ DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); |
+ DCHECK(script_scope->scope_info_->Equals( |
+ current_scope->scope_info_->OuterScopeInfo())); |
+ } |
+ } |
+#endif |
return innermost_scope; |
} |
@@ -956,7 +973,14 @@ Declaration* Scope::CheckLexDeclarationsConflictingWith( |
void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) { |
ResolveVariablesRecursively(info); |
AllocateVariablesRecursively(); |
- AllocateScopeInfosRecursively(info->isolate(), mode); |
+ |
+ MaybeHandle<ScopeInfo> outer_scope; |
+ for (const Scope* s = outer_scope_; s != nullptr; s = s->outer_scope_) { |
+ if (s->scope_info_.is_null()) continue; |
+ outer_scope = s->scope_info_; |
+ break; |
+ } |
+ AllocateScopeInfosRecursively(info->isolate(), mode, outer_scope); |
} |
bool Scope::AllowsLazyParsing() const { |
@@ -1687,15 +1711,21 @@ void Scope::AllocateVariablesRecursively() { |
DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
} |
-void Scope::AllocateScopeInfosRecursively(Isolate* isolate, AnalyzeMode mode) { |
+void Scope::AllocateScopeInfosRecursively(Isolate* isolate, AnalyzeMode mode, |
+ MaybeHandle<ScopeInfo> outer_scope) { |
DCHECK(scope_info_.is_null()); |
if (mode == AnalyzeMode::kDebugger || NeedsScopeInfo()) { |
- scope_info_ = ScopeInfo::Create(isolate, zone(), this); |
+ scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope); |
} |
+ // The ScopeInfo chain should mirror the context chain, so we only link to |
+ // the next outer scope that needs a context. |
+ MaybeHandle<ScopeInfo> next_outer_scope = outer_scope; |
+ if (NeedsContext()) next_outer_scope = scope_info_; |
+ |
// Allocate ScopeInfos for inner scopes. |
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
- scope->AllocateScopeInfosRecursively(isolate, mode); |
+ scope->AllocateScopeInfosRecursively(isolate, mode, next_outer_scope); |
} |
} |