Index: src/ast/scopeinfo.cc |
diff --git a/src/ast/scopeinfo.cc b/src/ast/scopeinfo.cc |
index a6ba5af0aad031f4d9973ef67e27affccf3c3ccc..b0b098483600b20f461d54b82a40961557b73c0f 100644 |
--- a/src/ast/scopeinfo.cc |
+++ b/src/ast/scopeinfo.cc |
@@ -19,8 +19,43 @@ enum ModuleVariableEntryOffset { |
kModuleVariableEntryLength // Sentinel value. |
}; |
-Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
- Scope* scope) { |
+#ifdef DEBUG |
+bool ScopeInfo::Equals(ScopeInfo* other) const { |
+ if (length() != other->length()) return false; |
+ for (int index = 0; index < length(); ++index) { |
+ Object* entry = get(index); |
+ Object* other_entry = other->get(index); |
+ if (entry->IsSmi()) { |
+ if (entry != other_entry) return false; |
+ } else { |
+ if (HeapObject::cast(entry)->map()->instance_type() != |
+ HeapObject::cast(other_entry)->map()->instance_type()) { |
+ return false; |
+ } |
+ if (entry->IsString()) { |
+ if (!String::cast(entry)->Equals(String::cast(other_entry))) { |
+ return false; |
+ } |
+ } else if (entry->IsScopeInfo()) { |
+ if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) { |
+ return false; |
+ } |
+ } else if (entry->IsModuleInfo()) { |
+ if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) { |
+ return false; |
+ } |
+ } else { |
+ UNREACHABLE(); |
+ return false; |
+ } |
+ } |
+ } |
+ return true; |
+} |
+#endif |
+ |
+Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope, |
+ MaybeHandle<ScopeInfo> outer_scope) { |
// Collect variables. |
ZoneList<Variable*>* locals = scope->locals(); |
int stack_local_count = 0; |
@@ -94,9 +129,11 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
const bool has_function_name = function_name_info != NONE; |
const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT; |
const int parameter_count = scope->num_parameters(); |
+ const bool has_outer_scope_info = !outer_scope.is_null(); |
const int length = kVariablePartIndex + parameter_count + |
(1 + stack_local_count) + 2 * context_local_count + |
(has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) + |
+ (has_outer_scope_info ? 1 : 0) + |
(scope->is_module_scope() |
? 2 + kModuleVariableEntryLength * module_vars_count |
: 0); |
@@ -127,7 +164,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
AsmModuleField::encode(asm_module) | |
AsmFunctionField::encode(asm_function) | |
HasSimpleParametersField::encode(has_simple_parameters) | |
- FunctionKindField::encode(function_kind); |
+ FunctionKindField::encode(function_kind) | |
+ HasOuterScopeInfoField::encode(has_outer_scope_info); |
scope_info->SetFlags(flags); |
scope_info->SetParameterCount(parameter_count); |
@@ -222,6 +260,12 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
var_index == scope_info->ContextLength() - 1); |
} |
+ // If present, add the outer scope info. |
+ DCHECK(index == scope_info->OuterScopeInfoEntryIndex()); |
+ if (has_outer_scope_info) { |
+ scope_info->set(index++, *outer_scope.ToHandleChecked()); |
+ } |
+ |
// Module-specific information (only for module scopes). |
if (scope->is_module_scope()) { |
Handle<ModuleInfo> module_info = |
@@ -241,8 +285,10 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
return scope_info; |
} |
-Handle<ScopeInfo> ScopeInfo::CreateForWithScope(Isolate* isolate) { |
- const int length = kVariablePartIndex + 1; |
+Handle<ScopeInfo> ScopeInfo::CreateForWithScope( |
+ Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) { |
+ const bool has_outer_scope_info = !outer_scope.is_null(); |
+ const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0); |
Factory* factory = isolate->factory(); |
Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
@@ -254,7 +300,8 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(Isolate* isolate) { |
ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) | |
FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) | |
AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) | |
- FunctionKindField::encode(kNormalFunction); |
+ FunctionKindField::encode(kNormalFunction) | |
+ HasOuterScopeInfoField::encode(has_outer_scope_info); |
scope_info->SetFlags(flags); |
scope_info->SetParameterCount(0); |
@@ -268,6 +315,10 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(Isolate* isolate) { |
DCHECK_EQ(index, scope_info->StackLocalEntriesIndex()); |
DCHECK_EQ(index, scope_info->ReceiverEntryIndex()); |
DCHECK_EQ(index, scope_info->FunctionNameEntryIndex()); |
+ DCHECK(index == scope_info->OuterScopeInfoEntryIndex()); |
+ if (has_outer_scope_info) { |
+ scope_info->set(index++, *outer_scope.ToHandleChecked()); |
+ } |
DCHECK_EQ(index, scope_info->length()); |
DCHECK_EQ(0, scope_info->ParameterCount()); |
DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength()); |
@@ -284,24 +335,26 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { |
const VariableAllocationInfo function_name_info = NONE; |
const bool has_function_name = false; |
const bool has_receiver = true; |
+ const bool has_outer_scope_info = false; |
const int parameter_count = 0; |
const int length = kVariablePartIndex + parameter_count + |
(1 + stack_local_count) + 2 * context_local_count + |
- (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0); |
+ (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) + |
+ (has_outer_scope_info ? 1 : 0); |
Factory* factory = isolate->factory(); |
Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); |
// Encode the flags. |
- int flags = ScopeTypeField::encode(SCRIPT_SCOPE) | |
- CallsEvalField::encode(false) | |
- LanguageModeField::encode(SLOPPY) | |
- DeclarationScopeField::encode(true) | |
- ReceiverVariableField::encode(receiver_info) | |
- FunctionVariableField::encode(function_name_info) | |
- AsmModuleField::encode(false) | AsmFunctionField::encode(false) | |
- HasSimpleParametersField::encode(has_simple_parameters) | |
- FunctionKindField::encode(FunctionKind::kNormalFunction); |
+ int flags = |
+ ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) | |
+ LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) | |
+ ReceiverVariableField::encode(receiver_info) | |
+ FunctionVariableField::encode(function_name_info) | |
+ AsmModuleField::encode(false) | AsmFunctionField::encode(false) | |
+ HasSimpleParametersField::encode(has_simple_parameters) | |
+ FunctionKindField::encode(FunctionKind::kNormalFunction) | |
+ HasOuterScopeInfoField::encode(has_outer_scope_info); |
scope_info->SetFlags(flags); |
scope_info->SetParameterCount(parameter_count); |
scope_info->SetStackLocalCount(stack_local_count); |
@@ -328,6 +381,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { |
scope_info->set(index++, Smi::FromInt(receiver_index)); |
DCHECK_EQ(index, scope_info->FunctionNameEntryIndex()); |
+ DCHECK_EQ(index, scope_info->OuterScopeInfoEntryIndex()); |
DCHECK_EQ(index, scope_info->length()); |
DCHECK_EQ(scope_info->ParameterCount(), 0); |
@@ -429,6 +483,13 @@ bool ScopeInfo::HasFunctionName() { |
} |
} |
+bool ScopeInfo::HasOuterScopeInfo() { |
+ if (length() > 0) { |
+ return HasOuterScopeInfoField::decode(Flags()); |
+ } else { |
+ return false; |
+ } |
+} |
bool ScopeInfo::HasHeapAllocatedLocals() { |
if (length() > 0) { |
@@ -449,6 +510,11 @@ String* ScopeInfo::FunctionName() { |
return String::cast(get(FunctionNameEntryIndex())); |
} |
+ScopeInfo* ScopeInfo::OuterScopeInfo() { |
+ DCHECK(HasOuterScopeInfo()); |
+ return ScopeInfo::cast(get(OuterScopeInfoEntryIndex())); |
+} |
+ |
ModuleInfo* ScopeInfo::ModuleDescriptorInfo() { |
DCHECK(scope_type() == MODULE_SCOPE); |
return static_cast<ModuleInfo*>(get(ModuleInfoEntryIndex())); |
@@ -700,10 +766,14 @@ int ScopeInfo::FunctionNameEntryIndex() { |
return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); |
} |
-int ScopeInfo::ModuleInfoEntryIndex() { |
+int ScopeInfo::OuterScopeInfoEntryIndex() { |
return FunctionNameEntryIndex() + (HasFunctionName() ? 2 : 0); |
} |
+int ScopeInfo::ModuleInfoEntryIndex() { |
+ return OuterScopeInfoEntryIndex() + (HasOuterScopeInfo() ? 1 : 0); |
+} |
+ |
int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoEntryIndex() + 1; } |
int ScopeInfo::ModuleVariableEntriesIndex() { |