diff options
Diffstat (limited to 'deps/v8/src/ast/scopeinfo.cc')
-rw-r--r-- | deps/v8/src/ast/scopeinfo.cc | 666 |
1 files changed, 435 insertions, 231 deletions
diff --git a/deps/v8/src/ast/scopeinfo.cc b/deps/v8/src/ast/scopeinfo.cc index 7189de3372..5354b8d737 100644 --- a/deps/v8/src/ast/scopeinfo.cc +++ b/deps/v8/src/ast/scopeinfo.cc @@ -2,33 +2,92 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "src/ast/scopeinfo.h" - #include <stdlib.h> #include "src/ast/context-slot-cache.h" #include "src/ast/scopes.h" +#include "src/ast/variables.h" #include "src/bootstrapper.h" namespace v8 { namespace internal { +// An entry in ModuleVariableEntries consists of several slots: +enum ModuleVariableEntryOffset { + kModuleVariableNameOffset, + kModuleVariableIndexOffset, + kModuleVariablePropertiesOffset, + kModuleVariableEntryLength // Sentinel value. +}; -Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, - Scope* scope) { - // Collect stack and context locals. - ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); - ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); - ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone); +#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; + int context_local_count = 0; + int module_vars_count = 0; + // Stack allocated block scope variables are allocated in the parent + // declaration scope, but are recorded in the block scope's scope info. First + // slot index indicates at which offset a particular scope starts in the + // parent declaration scope. + int first_slot_index = 0; + for (int i = 0; i < locals->length(); i++) { + Variable* var = locals->at(i); + switch (var->location()) { + case VariableLocation::LOCAL: + if (stack_local_count == 0) first_slot_index = var->index(); + stack_local_count++; + break; + case VariableLocation::CONTEXT: + context_local_count++; + break; + case VariableLocation::MODULE: + module_vars_count++; + break; + default: + break; + } + } + DCHECK(module_vars_count == 0 || scope->is_module_scope()); - scope->CollectStackAndContextLocals(&stack_locals, &context_locals, - &context_globals); - const int stack_local_count = stack_locals.length(); - const int context_local_count = context_locals.length(); - const int context_global_count = context_globals.length(); // Make sure we allocate the correct amount. DCHECK_EQ(scope->ContextLocalCount(), context_local_count); - DCHECK_EQ(scope->ContextGlobalCount(), context_global_count); // Determine use and location of the "this" binding if it is present. VariableAllocationInfo receiver_info; @@ -53,7 +112,6 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, // Determine use and location of the function variable if it is present. VariableAllocationInfo function_name_info; - VariableMode function_variable_mode; if (scope->is_function_scope() && scope->AsDeclarationScope()->function_var() != nullptr) { Variable* var = scope->AsDeclarationScope()->function_var(); @@ -65,20 +123,21 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, DCHECK(var->IsStackLocal()); function_name_info = STACK; } - function_variable_mode = var->mode(); } else { function_name_info = NONE; - function_variable_mode = VAR; } - DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE); 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 + - 2 * context_global_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) + + (scope->is_module_scope() + ? 2 + kModuleVariableEntryLength * module_vars_count + : 0); Factory* factory = isolate->factory(); Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); @@ -96,27 +155,29 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, } // Encode the flags. - int flags = ScopeTypeField::encode(scope->scope_type()) | - CallsEvalField::encode(scope->calls_eval()) | - LanguageModeField::encode(scope->language_mode()) | - DeclarationScopeField::encode(scope->is_declaration_scope()) | - ReceiverVariableField::encode(receiver_info) | - HasNewTargetField::encode(has_new_target) | - FunctionVariableField::encode(function_name_info) | - FunctionVariableMode::encode(function_variable_mode) | - AsmModuleField::encode(asm_module) | - AsmFunctionField::encode(asm_function) | - HasSimpleParametersField::encode(has_simple_parameters) | - FunctionKindField::encode(function_kind); + int flags = + ScopeTypeField::encode(scope->scope_type()) | + CallsEvalField::encode(scope->calls_eval()) | + LanguageModeField::encode(scope->language_mode()) | + DeclarationScopeField::encode(scope->is_declaration_scope()) | + ReceiverVariableField::encode(receiver_info) | + HasNewTargetField::encode(has_new_target) | + FunctionVariableField::encode(function_name_info) | + AsmModuleField::encode(asm_module) | + AsmFunctionField::encode(asm_function) | + HasSimpleParametersField::encode(has_simple_parameters) | + FunctionKindField::encode(function_kind) | + HasOuterScopeInfoField::encode(has_outer_scope_info) | + IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope()); scope_info->SetFlags(flags); + scope_info->SetParameterCount(parameter_count); scope_info->SetStackLocalCount(stack_local_count); scope_info->SetContextLocalCount(context_local_count); - scope_info->SetContextGlobalCount(context_global_count); int index = kVariablePartIndex; // Add parameters. - DCHECK(index == scope_info->ParameterEntriesIndex()); + DCHECK_EQ(index, scope_info->ParameterNamesIndex()); if (scope->is_declaration_scope()) { for (int i = 0; i < parameter_count; ++i) { scope_info->set(index++, @@ -124,68 +185,66 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, } } - // Add stack locals' names. We are assuming that the stack locals' - // slots are allocated in increasing order, so we can simply add - // them to the ScopeInfo object. - int first_slot_index; - if (stack_local_count > 0) { - first_slot_index = stack_locals[0]->index(); - } else { - first_slot_index = 0; - } - DCHECK(index == scope_info->StackLocalFirstSlotIndex()); + // Add stack locals' names, context locals' names and info, module variables' + // names and info. We are assuming that the stack locals' slots are allocated + // in increasing order, so we can simply add them to the ScopeInfo object. + // Context locals are added using their index. + DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); scope_info->set(index++, Smi::FromInt(first_slot_index)); - DCHECK(index == scope_info->StackLocalEntriesIndex()); - for (int i = 0; i < stack_local_count; ++i) { - DCHECK(stack_locals[i]->index() == first_slot_index + i); - scope_info->set(index++, *stack_locals[i]->name()); - } - - // Due to usage analysis, context-allocated locals are not necessarily in - // increasing order: Some of them may be parameters which are allocated before - // the non-parameter locals. When the non-parameter locals are sorted - // according to usage, the allocated slot indices may not be in increasing - // order with the variable list anymore. Thus, we first need to sort them by - // context slot index before adding them to the ScopeInfo object. - context_locals.Sort(&Variable::CompareIndex); - - // Add context locals' names. - DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); - for (int i = 0; i < context_local_count; ++i) { - scope_info->set(index++, *context_locals[i]->name()); - } - - // Add context globals' names. - DCHECK(index == scope_info->ContextGlobalNameEntriesIndex()); - for (int i = 0; i < context_global_count; ++i) { - scope_info->set(index++, *context_globals[i]->name()); - } - - // Add context locals' info. - DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); - for (int i = 0; i < context_local_count; ++i) { - Variable* var = context_locals[i]; - uint32_t value = - ContextLocalMode::encode(var->mode()) | - ContextLocalInitFlag::encode(var->initialization_flag()) | - ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); - scope_info->set(index++, Smi::FromInt(value)); - } - - // Add context globals' info. - DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex()); - for (int i = 0; i < context_global_count; ++i) { - Variable* var = context_globals[i]; - // TODO(ishell): do we need this kind of info for globals here? - uint32_t value = - ContextLocalMode::encode(var->mode()) | - ContextLocalInitFlag::encode(var->initialization_flag()) | - ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); - scope_info->set(index++, Smi::FromInt(value)); + DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); + + int stack_local_base = index; + int context_local_base = stack_local_base + stack_local_count; + int context_local_info_base = context_local_base + context_local_count; + int module_var_entry = scope_info->ModuleVariablesIndex(); + + for (int i = 0; i < locals->length(); ++i) { + Variable* var = locals->at(i); + switch (var->location()) { + case VariableLocation::LOCAL: { + int local_index = var->index() - first_slot_index; + DCHECK_LE(0, local_index); + DCHECK_LT(local_index, stack_local_count); + scope_info->set(stack_local_base + local_index, *var->name()); + break; + } + case VariableLocation::CONTEXT: { + // Due to duplicate parameters, context locals aren't guaranteed to come + // in order. + int local_index = var->index() - Context::MIN_CONTEXT_SLOTS; + DCHECK_LE(0, local_index); + DCHECK_LT(local_index, context_local_count); + uint32_t info = VariableModeField::encode(var->mode()) | + InitFlagField::encode(var->initialization_flag()) | + MaybeAssignedFlagField::encode(var->maybe_assigned()); + scope_info->set(context_local_base + local_index, *var->name()); + scope_info->set(context_local_info_base + local_index, + Smi::FromInt(info)); + break; + } + case VariableLocation::MODULE: { + scope_info->set(module_var_entry + kModuleVariableNameOffset, + *var->name()); + scope_info->set(module_var_entry + kModuleVariableIndexOffset, + Smi::FromInt(var->index())); + uint32_t properties = + VariableModeField::encode(var->mode()) | + InitFlagField::encode(var->initialization_flag()) | + MaybeAssignedFlagField::encode(var->maybe_assigned()); + scope_info->set(module_var_entry + kModuleVariablePropertiesOffset, + Smi::FromInt(properties)); + module_var_entry += kModuleVariableEntryLength; + break; + } + default: + break; + } } + index += stack_local_count + 2 * context_local_count; + // If the receiver is allocated, add its index. - DCHECK(index == scope_info->ReceiverEntryIndex()); + DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); if (has_receiver) { int var_index = scope->AsDeclarationScope()->receiver()->index(); scope_info->set(index++, Smi::FromInt(var_index)); @@ -194,7 +253,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, } // If present, add the function variable name and its index. - DCHECK(index == scope_info->FunctionNameEntryIndex()); + DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); if (has_function_name) { int var_index = scope->AsDeclarationScope()->function_var()->index(); scope_info->set(index++, @@ -204,75 +263,130 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, var_index == scope_info->ContextLength() - 1); } - DCHECK(index == scope_info->length()); - DCHECK(scope->num_parameters() == scope_info->ParameterCount()); - DCHECK(scope->num_heap_slots() == scope_info->ContextLength() || - (scope->num_heap_slots() == kVariablePartIndex && - scope_info->ContextLength() == 0)); + // If present, add the outer scope info. + DCHECK(index == scope_info->OuterScopeInfoIndex()); + 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 = + ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module()); + DCHECK_EQ(index, scope_info->ModuleInfoIndex()); + scope_info->set(index++, *module_info); + DCHECK_EQ(index, scope_info->ModuleVariableCountIndex()); + scope_info->set(index++, Smi::FromInt(module_vars_count)); + DCHECK_EQ(index, scope_info->ModuleVariablesIndex()); + // The variable entries themselves have already been written above. + index += kModuleVariableEntryLength * module_vars_count; + } + + DCHECK_EQ(index, scope_info->length()); + DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount()); + DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength()); return scope_info; } +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); + + // Encode the flags. + int flags = + ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) | + LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) | + ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) | + FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) | + AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) | + FunctionKindField::encode(kNormalFunction) | + HasOuterScopeInfoField::encode(has_outer_scope_info) | + IsDebugEvaluateScopeField::encode(false); + scope_info->SetFlags(flags); + + scope_info->SetParameterCount(0); + scope_info->SetStackLocalCount(0); + scope_info->SetContextLocalCount(0); + + int index = kVariablePartIndex; + DCHECK_EQ(index, scope_info->ParameterNamesIndex()); + DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); + scope_info->set(index++, Smi::FromInt(0)); + DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); + DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); + DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); + DCHECK(index == scope_info->OuterScopeInfoIndex()); + 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()); + return scope_info; +} Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { DCHECK(isolate->bootstrapper()->IsActive()); const int stack_local_count = 0; const int context_local_count = 1; - const int context_global_count = 0; const bool has_simple_parameters = true; const VariableAllocationInfo receiver_info = CONTEXT; const VariableAllocationInfo function_name_info = NONE; - const VariableMode function_variable_mode = VAR; 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 + - 2 * context_global_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) | - FunctionVariableMode::encode(function_variable_mode) | - 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) | + IsDebugEvaluateScopeField::encode(false); scope_info->SetFlags(flags); scope_info->SetParameterCount(parameter_count); scope_info->SetStackLocalCount(stack_local_count); scope_info->SetContextLocalCount(context_local_count); - scope_info->SetContextGlobalCount(context_global_count); int index = kVariablePartIndex; const int first_slot_index = 0; - DCHECK(index == scope_info->StackLocalFirstSlotIndex()); + DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); scope_info->set(index++, Smi::FromInt(first_slot_index)); - DCHECK(index == scope_info->StackLocalEntriesIndex()); + DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); // Here we add info for context-allocated "this". - DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); + DCHECK_EQ(index, scope_info->ContextLocalNamesIndex()); scope_info->set(index++, *isolate->factory()->this_string()); - DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); - const uint32_t value = ContextLocalMode::encode(CONST) | - ContextLocalInitFlag::encode(kCreatedInitialized) | - ContextLocalMaybeAssignedFlag::encode(kNotAssigned); + DCHECK_EQ(index, scope_info->ContextLocalInfosIndex()); + const uint32_t value = VariableModeField::encode(CONST) | + InitFlagField::encode(kCreatedInitialized) | + MaybeAssignedFlagField::encode(kNotAssigned); scope_info->set(index++, Smi::FromInt(value)); // And here we record that this scopeinfo binds a receiver. - DCHECK(index == scope_info->ReceiverEntryIndex()); + DCHECK_EQ(index, scope_info->ReceiverInfoIndex()); const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; scope_info->set(index++, Smi::FromInt(receiver_index)); - DCHECK(index == scope_info->FunctionNameEntryIndex()); - + DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); + DCHECK_EQ(index, scope_info->OuterScopeInfoIndex()); DCHECK_EQ(index, scope_info->length()); DCHECK_EQ(scope_info->ParameterCount(), 0); DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1); @@ -282,12 +396,12 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { - return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array()); + return isolate->heap()->empty_scope_info(); } ScopeType ScopeInfo::scope_type() { - DCHECK(length() > 0); + DCHECK_LT(0, length()); return ScopeTypeField::decode(Flags()); } @@ -325,19 +439,17 @@ int ScopeInfo::StackSlotCount() { int ScopeInfo::ContextLength() { if (length() > 0) { int context_locals = ContextLocalCount(); - int context_globals = ContextGlobalCount(); bool function_name_context_slot = FunctionVariableField::decode(Flags()) == CONTEXT; - bool has_context = context_locals > 0 || context_globals > 0 || - function_name_context_slot || + bool has_context = context_locals > 0 || function_name_context_slot || scope_type() == WITH_SCOPE || (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && - is_declaration_scope()) || + is_declaration_scope()) || (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || scope_type() == MODULE_SCOPE; if (has_context) { - return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals + + return Context::MIN_CONTEXT_SLOTS + context_locals + (function_name_context_slot ? 1 : 0); } } @@ -375,6 +487,30 @@ bool ScopeInfo::HasFunctionName() { } } +bool ScopeInfo::HasOuterScopeInfo() { + if (length() > 0) { + return HasOuterScopeInfoField::decode(Flags()); + } else { + return false; + } +} + +bool ScopeInfo::IsDebugEvaluateScope() { + if (length() > 0) { + return IsDebugEvaluateScopeField::decode(Flags()); + } else { + return false; + } +} + +void ScopeInfo::SetIsDebugEvaluateScope() { + if (length() > 0) { + DCHECK_EQ(scope_type(), WITH_SCOPE); + SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true)); + } else { + UNREACHABLE(); + } +} bool ScopeInfo::HasHeapAllocatedLocals() { if (length() > 0) { @@ -392,68 +528,85 @@ bool ScopeInfo::HasContext() { String* ScopeInfo::FunctionName() { DCHECK(HasFunctionName()); - return String::cast(get(FunctionNameEntryIndex())); + return String::cast(get(FunctionNameInfoIndex())); } +ScopeInfo* ScopeInfo::OuterScopeInfo() { + DCHECK(HasOuterScopeInfo()); + return ScopeInfo::cast(get(OuterScopeInfoIndex())); +} + +ModuleInfo* ScopeInfo::ModuleDescriptorInfo() { + DCHECK(scope_type() == MODULE_SCOPE); + return ModuleInfo::cast(get(ModuleInfoIndex())); +} String* ScopeInfo::ParameterName(int var) { - DCHECK(0 <= var && var < ParameterCount()); - int info_index = ParameterEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, ParameterCount()); + int info_index = ParameterNamesIndex() + var; return String::cast(get(info_index)); } String* ScopeInfo::LocalName(int var) { - DCHECK(0 <= var && var < LocalCount()); - DCHECK(StackLocalEntriesIndex() + StackLocalCount() == - ContextLocalNameEntriesIndex()); - int info_index = StackLocalEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, LocalCount()); + DCHECK(StackLocalNamesIndex() + StackLocalCount() == + ContextLocalNamesIndex()); + int info_index = StackLocalNamesIndex() + var; return String::cast(get(info_index)); } String* ScopeInfo::StackLocalName(int var) { - DCHECK(0 <= var && var < StackLocalCount()); - int info_index = StackLocalEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, StackLocalCount()); + int info_index = StackLocalNamesIndex() + var; return String::cast(get(info_index)); } int ScopeInfo::StackLocalIndex(int var) { - DCHECK(0 <= var && var < StackLocalCount()); + DCHECK_LE(0, var); + DCHECK_LT(var, StackLocalCount()); int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); return first_slot_index + var; } String* ScopeInfo::ContextLocalName(int var) { - DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); - int info_index = ContextLocalNameEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalNamesIndex() + var; return String::cast(get(info_index)); } VariableMode ScopeInfo::ContextLocalMode(int var) { - DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); - int info_index = ContextLocalInfoEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; int value = Smi::cast(get(info_index))->value(); - return ContextLocalMode::decode(value); + return VariableModeField::decode(value); } InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { - DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); - int info_index = ContextLocalInfoEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; int value = Smi::cast(get(info_index))->value(); - return ContextLocalInitFlag::decode(value); + return InitFlagField::decode(value); } MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { - DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); - int info_index = ContextLocalInfoEntriesIndex() + var; + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; int value = Smi::cast(get(info_index))->value(); - return ContextLocalMaybeAssignedFlag::decode(value); + return MaybeAssignedFlagField::decode(value); } bool ScopeInfo::VariableIsSynthetic(String* name) { @@ -470,8 +623,8 @@ int ScopeInfo::StackSlotIndex(String* name) { DCHECK(name->IsInternalizedString()); if (length() > 0) { int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); - int start = StackLocalEntriesIndex(); - int end = StackLocalEntriesIndex() + StackLocalCount(); + int start = StackLocalNamesIndex(); + int end = start + StackLocalCount(); for (int i = start; i < end; ++i) { if (name == get(i)) { return i - start + first_slot_index; @@ -481,27 +634,54 @@ int ScopeInfo::StackSlotIndex(String* name) { return -1; } +int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode, + InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag) { + DCHECK_EQ(scope_type(), MODULE_SCOPE); + DCHECK(name->IsInternalizedString()); + DCHECK_NOT_NULL(mode); + DCHECK_NOT_NULL(init_flag); + DCHECK_NOT_NULL(maybe_assigned_flag); + + int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value(); + int entry = ModuleVariablesIndex(); + for (int i = 0; i < module_vars_count; ++i) { + if (*name == get(entry + kModuleVariableNameOffset)) { + int index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value(); + int properties = + Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value(); + *mode = VariableModeField::decode(properties); + *init_flag = InitFlagField::decode(properties); + *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties); + return index; + } + entry += kModuleVariableEntryLength; + } + + return -1; +} int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name, VariableMode* mode, InitializationFlag* init_flag, MaybeAssignedFlag* maybe_assigned_flag) { DCHECK(name->IsInternalizedString()); - DCHECK(mode != NULL); - DCHECK(init_flag != NULL); + DCHECK_NOT_NULL(mode); + DCHECK_NOT_NULL(init_flag); + DCHECK_NOT_NULL(maybe_assigned_flag); + if (scope_info->length() > 0) { ContextSlotCache* context_slot_cache = scope_info->GetIsolate()->context_slot_cache(); int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, maybe_assigned_flag); if (result != ContextSlotCache::kNotFound) { - DCHECK(result < scope_info->ContextLength()); + DCHECK_LT(result, scope_info->ContextLength()); return result; } - int start = scope_info->ContextLocalNameEntriesIndex(); - int end = scope_info->ContextLocalNameEntriesIndex() + - scope_info->ContextLocalCount(); + int start = scope_info->ContextLocalNamesIndex(); + int end = start + scope_info->ContextLocalCount(); for (int i = start; i < end; ++i) { if (*name == scope_info->get(i)) { int var = i - start; @@ -512,7 +692,7 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, context_slot_cache->Update(scope_info, name, *mode, *init_flag, *maybe_assigned_flag, result); - DCHECK(result < scope_info->ContextLength()); + DCHECK_LT(result, scope_info->ContextLength()); return result; } } @@ -520,46 +700,14 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, context_slot_cache->Update(scope_info, name, TEMPORARY, kNeedsInitialization, kNotAssigned, -1); } - return -1; -} - -int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, - Handle<String> name, VariableMode* mode, - InitializationFlag* init_flag, - MaybeAssignedFlag* maybe_assigned_flag) { - DCHECK(name->IsInternalizedString()); - DCHECK(mode != NULL); - DCHECK(init_flag != NULL); - if (scope_info->length() > 0) { - // This is to ensure that ContextLocalMode() and co. queries would work. - DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), - scope_info->ContextLocalNameEntriesIndex() + - scope_info->ContextLocalCount()); - int base = scope_info->ContextLocalNameEntriesIndex(); - int start = scope_info->ContextGlobalNameEntriesIndex(); - int end = scope_info->ContextGlobalNameEntriesIndex() + - scope_info->ContextGlobalCount(); - for (int i = start; i < end; ++i) { - if (*name == scope_info->get(i)) { - int var = i - base; - *mode = scope_info->ContextLocalMode(var); - *init_flag = scope_info->ContextLocalInitFlag(var); - *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); - int result = Context::MIN_CONTEXT_SLOTS + var; - DCHECK(result < scope_info->ContextLength()); - return result; - } - } - } return -1; } - String* ScopeInfo::ContextSlotName(int slot_index) { int const var = slot_index - Context::MIN_CONTEXT_SLOTS; DCHECK_LE(0, var); - DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount()); + DCHECK_LT(var, ContextLocalCount()); return ContextLocalName(var); } @@ -572,8 +720,8 @@ int ScopeInfo::ParameterIndex(String* name) { // last declaration of that parameter is used // inside a function (and thus we need to look // at the last index). Was bug# 1110337. - int start = ParameterEntriesIndex(); - int end = ParameterEntriesIndex() + ParameterCount(); + int start = ParameterNamesIndex(); + int end = start + ParameterCount(); for (int i = end - 1; i >= start; --i) { if (name == get(i)) { return i - start; @@ -586,19 +734,16 @@ int ScopeInfo::ParameterIndex(String* name) { int ScopeInfo::ReceiverContextSlotIndex() { if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) - return Smi::cast(get(ReceiverEntryIndex()))->value(); + return Smi::cast(get(ReceiverInfoIndex()))->value(); return -1; } - -int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { +int ScopeInfo::FunctionContextSlotIndex(String* name) { DCHECK(name->IsInternalizedString()); - DCHECK(mode != NULL); if (length() > 0) { if (FunctionVariableField::decode(Flags()) == CONTEXT && FunctionName() == name) { - *mode = FunctionVariableMode::decode(Flags()); - return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); + return Smi::cast(get(FunctionNameInfoIndex() + 1))->value(); } } return -1; @@ -609,51 +754,45 @@ FunctionKind ScopeInfo::function_kind() { return FunctionKindField::decode(Flags()); } - -int ScopeInfo::ParameterEntriesIndex() { - DCHECK(length() > 0); +int ScopeInfo::ParameterNamesIndex() { + DCHECK_LT(0, length()); return kVariablePartIndex; } int ScopeInfo::StackLocalFirstSlotIndex() { - return ParameterEntriesIndex() + ParameterCount(); + return ParameterNamesIndex() + ParameterCount(); } +int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; } -int ScopeInfo::StackLocalEntriesIndex() { - return StackLocalFirstSlotIndex() + 1; +int ScopeInfo::ContextLocalNamesIndex() { + return StackLocalNamesIndex() + StackLocalCount(); } - -int ScopeInfo::ContextLocalNameEntriesIndex() { - return StackLocalEntriesIndex() + StackLocalCount(); +int ScopeInfo::ContextLocalInfosIndex() { + return ContextLocalNamesIndex() + ContextLocalCount(); } - -int ScopeInfo::ContextGlobalNameEntriesIndex() { - return ContextLocalNameEntriesIndex() + ContextLocalCount(); +int ScopeInfo::ReceiverInfoIndex() { + return ContextLocalInfosIndex() + ContextLocalCount(); } - -int ScopeInfo::ContextLocalInfoEntriesIndex() { - return ContextGlobalNameEntriesIndex() + ContextGlobalCount(); +int ScopeInfo::FunctionNameInfoIndex() { + return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0); } - -int ScopeInfo::ContextGlobalInfoEntriesIndex() { - return ContextLocalInfoEntriesIndex() + ContextLocalCount(); +int ScopeInfo::OuterScopeInfoIndex() { + return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0); } - -int ScopeInfo::ReceiverEntryIndex() { - return ContextGlobalInfoEntriesIndex() + ContextGlobalCount(); +int ScopeInfo::ModuleInfoIndex() { + return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0); } +int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; } -int ScopeInfo::FunctionNameEntryIndex() { - return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0); -} +int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; } #ifdef DEBUG @@ -686,19 +825,84 @@ void ScopeInfo::Print() { PrintF("{"); if (length() > 0) { - PrintList("parameters", 0, ParameterEntriesIndex(), - ParameterEntriesIndex() + ParameterCount(), this); - PrintList("stack slots", 0, StackLocalEntriesIndex(), - StackLocalEntriesIndex() + StackLocalCount(), this); + PrintList("parameters", 0, ParameterNamesIndex(), + ParameterNamesIndex() + ParameterCount(), this); + PrintList("stack slots", 0, StackLocalNamesIndex(), + StackLocalNamesIndex() + StackLocalCount(), this); PrintList("context slots", Context::MIN_CONTEXT_SLOTS, - ContextLocalNameEntriesIndex(), - ContextLocalNameEntriesIndex() + ContextLocalCount(), this); + ContextLocalNamesIndex(), + ContextLocalNamesIndex() + ContextLocalCount(), this); + // TODO(neis): Print module stuff if present. } PrintF("}\n"); } #endif // DEBUG +Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate, + Handle<Object> export_name, + Handle<Object> local_name, + Handle<Object> import_name, + Handle<Object> module_request) { + Handle<ModuleInfoEntry> result = isolate->factory()->NewModuleInfoEntry(); + result->set(kExportNameIndex, *export_name); + result->set(kLocalNameIndex, *local_name); + result->set(kImportNameIndex, *import_name); + result->set(kModuleRequestIndex, *module_request); + return result; +} + +Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone, + ModuleDescriptor* descr) { + // Serialize module requests. + Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray( + static_cast<int>(descr->module_requests().size())); + for (const auto& elem : descr->module_requests()) { + module_requests->set(elem.second, *elem.first->string()); + } + + // Serialize special exports. + Handle<FixedArray> special_exports = + isolate->factory()->NewFixedArray(descr->special_exports().length()); + { + int i = 0; + for (auto entry : descr->special_exports()) { + special_exports->set(i++, *entry->Serialize(isolate)); + } + } + + // Serialize namespace imports. + Handle<FixedArray> namespace_imports = + isolate->factory()->NewFixedArray(descr->namespace_imports().length()); + { + int i = 0; + for (auto entry : descr->namespace_imports()) { + namespace_imports->set(i++, *entry->Serialize(isolate)); + } + } + + // Serialize regular exports. + Handle<FixedArray> regular_exports = + descr->SerializeRegularExports(isolate, zone); + + // Serialize regular imports. + Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray( + static_cast<int>(descr->regular_imports().size())); + { + int i = 0; + for (const auto& elem : descr->regular_imports()) { + regular_imports->set(i++, *elem.second->Serialize(isolate)); + } + } + + Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo(); + result->set(kModuleRequestsIndex, *module_requests); + result->set(kSpecialExportsIndex, *special_exports); + result->set(kRegularExportsIndex, *regular_exports); + result->set(kNamespaceImportsIndex, *namespace_imports); + result->set(kRegularImportsIndex, *regular_imports); + return result; +} } // namespace internal } // namespace v8 |