diff options
Diffstat (limited to 'deps/v8/src/objects')
-rw-r--r-- | deps/v8/src/objects/module-info.h | 129 | ||||
-rw-r--r-- | deps/v8/src/objects/object-macros-undef.h | 9 | ||||
-rw-r--r-- | deps/v8/src/objects/object-macros.h | 32 | ||||
-rw-r--r-- | deps/v8/src/objects/scope-info.cc | 947 | ||||
-rw-r--r-- | deps/v8/src/objects/scope-info.h | 345 |
5 files changed, 1462 insertions, 0 deletions
diff --git a/deps/v8/src/objects/module-info.h b/deps/v8/src/objects/module-info.h new file mode 100644 index 0000000000..099ee5f657 --- /dev/null +++ b/deps/v8/src/objects/module-info.h @@ -0,0 +1,129 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_MODULE_INFO_H_ +#define V8_OBJECTS_MODULE_INFO_H_ + +#include "src/objects.h" + +// Has to be the last include (doesn't have include guards): +#include "src/objects/object-macros.h" + +namespace v8 { +namespace internal { + +template <typename T> +class Handle; +class Isolate; +class ModuleDescriptor; +class ModuleInfoEntry; +class String; +class Zone; + +// ModuleInfo is to ModuleDescriptor what ScopeInfo is to Scope. +class ModuleInfo : public FixedArray { + public: + DECLARE_CAST(ModuleInfo) + + static Handle<ModuleInfo> New(Isolate* isolate, Zone* zone, + ModuleDescriptor* descr); + + inline FixedArray* module_requests() const { + return FixedArray::cast(get(kModuleRequestsIndex)); + } + + inline FixedArray* special_exports() const { + return FixedArray::cast(get(kSpecialExportsIndex)); + } + + inline FixedArray* regular_exports() const { + return FixedArray::cast(get(kRegularExportsIndex)); + } + + inline FixedArray* regular_imports() const { + return FixedArray::cast(get(kRegularImportsIndex)); + } + + inline FixedArray* namespace_imports() const { + return FixedArray::cast(get(kNamespaceImportsIndex)); + } + + // Accessors for [regular_exports]. + int RegularExportCount() const; + String* RegularExportLocalName(int i) const; + int RegularExportCellIndex(int i) const; + FixedArray* RegularExportExportNames(int i) const; + + static Handle<ModuleInfoEntry> LookupRegularImport(Handle<ModuleInfo> info, + Handle<String> local_name); + +#ifdef DEBUG + inline bool Equals(ModuleInfo* other) const { + return regular_exports() == other->regular_exports() && + regular_imports() == other->regular_imports() && + special_exports() == other->special_exports() && + namespace_imports() == other->namespace_imports(); + } +#endif + + private: + friend class Factory; + friend class ModuleDescriptor; + enum { + kModuleRequestsIndex, + kSpecialExportsIndex, + kRegularExportsIndex, + kNamespaceImportsIndex, + kRegularImportsIndex, + kLength + }; + enum { + kRegularExportLocalNameOffset, + kRegularExportCellIndexOffset, + kRegularExportExportNamesOffset, + kRegularExportLength + }; + DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfo); +}; + +class ModuleInfoEntry : public Struct { + public: + DECLARE_CAST(ModuleInfoEntry) + DECLARE_PRINTER(ModuleInfoEntry) + DECLARE_VERIFIER(ModuleInfoEntry) + + DECL_ACCESSORS(export_name, Object) + DECL_ACCESSORS(local_name, Object) + DECL_ACCESSORS(import_name, Object) + DECL_INT_ACCESSORS(module_request) + DECL_INT_ACCESSORS(cell_index) + DECL_INT_ACCESSORS(beg_pos) + DECL_INT_ACCESSORS(end_pos) + + static Handle<ModuleInfoEntry> New(Isolate* isolate, + Handle<Object> export_name, + Handle<Object> local_name, + Handle<Object> import_name, + int module_request, int cell_index, + int beg_pos, int end_pos); + + static const int kExportNameOffset = HeapObject::kHeaderSize; + static const int kLocalNameOffset = kExportNameOffset + kPointerSize; + static const int kImportNameOffset = kLocalNameOffset + kPointerSize; + static const int kModuleRequestOffset = kImportNameOffset + kPointerSize; + static const int kCellIndexOffset = kModuleRequestOffset + kPointerSize; + static const int kBegPosOffset = kCellIndexOffset + kPointerSize; + static const int kEndPosOffset = kBegPosOffset + kPointerSize; + static const int kSize = kEndPosOffset + kPointerSize; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleInfoEntry); +}; + +} // namespace internal +} // namespace v8 + +#include "src/objects/object-macros-undef.h" + +#endif // V8_OBJECTS_MODULE_INFO_H_ diff --git a/deps/v8/src/objects/object-macros-undef.h b/deps/v8/src/objects/object-macros-undef.h new file mode 100644 index 0000000000..509d29779f --- /dev/null +++ b/deps/v8/src/objects/object-macros-undef.h @@ -0,0 +1,9 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#undef DECL_BOOLEAN_ACCESSORS +#undef DECL_INT_ACCESSORS +#undef DECL_ACCESSORS +#undef DECLARE_CAST +#undef DECLARE_VERIFIER diff --git a/deps/v8/src/objects/object-macros.h b/deps/v8/src/objects/object-macros.h new file mode 100644 index 0000000000..a3ececc6f7 --- /dev/null +++ b/deps/v8/src/objects/object-macros.h @@ -0,0 +1,32 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Note 1: Any file that includes this one should include object-macros-undef.h +// at the bottom. + +// Note 2: This file is deliberately missing the include guards (the undeffing +// approach wouldn't work otherwise). + +#define DECL_BOOLEAN_ACCESSORS(name) \ + inline bool name() const; \ + inline void set_##name(bool value); + +#define DECL_INT_ACCESSORS(name) \ + inline int name() const; \ + inline void set_##name(int value); + +#define DECL_ACCESSORS(name, type) \ + inline type* name() const; \ + inline void set_##name(type* value, \ + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + +#define DECLARE_CAST(type) \ + INLINE(static type* cast(Object* object)); \ + INLINE(static const type* cast(const Object* object)); + +#ifdef VERIFY_HEAP +#define DECLARE_VERIFIER(Name) void Name##Verify(); +#else +#define DECLARE_VERIFIER(Name) +#endif diff --git a/deps/v8/src/objects/scope-info.cc b/deps/v8/src/objects/scope-info.cc new file mode 100644 index 0000000000..ae828cc1f0 --- /dev/null +++ b/deps/v8/src/objects/scope-info.cc @@ -0,0 +1,947 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdlib.h> + +#include "src/objects/scope-info.h" + +#include "src/ast/context-slot-cache.h" +#include "src/ast/scopes.h" +#include "src/ast/variables.h" +#include "src/bootstrapper.h" +#include "src/objects-inl.h" + +namespace v8 { +namespace internal { + +// An entry in ModuleVariableEntries consists of several slots: +enum ModuleVariableEntryOffset { + kModuleVariableNameOffset, + kModuleVariableIndexOffset, + kModuleVariablePropertiesOffset, + kModuleVariableEntryLength // Sentinel value. +}; + +#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. + 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 (Variable* var : *scope->locals()) { + 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()); + + // Make sure we allocate the correct amount. + DCHECK_EQ(scope->ContextLocalCount(), context_local_count); + + // Determine use and location of the "this" binding if it is present. + VariableAllocationInfo receiver_info; + if (scope->is_declaration_scope() && + scope->AsDeclarationScope()->has_this_declaration()) { + Variable* var = scope->AsDeclarationScope()->receiver(); + if (!var->is_used()) { + receiver_info = UNUSED; + } else if (var->IsContextSlot()) { + receiver_info = CONTEXT; + } else { + DCHECK(var->IsParameter()); + receiver_info = STACK; + } + } else { + receiver_info = NONE; + } + + bool has_new_target = + scope->is_declaration_scope() && + scope->AsDeclarationScope()->new_target_var() != nullptr; + + // Determine use and location of the function variable if it is present. + VariableAllocationInfo function_name_info; + if (scope->is_function_scope() && + scope->AsDeclarationScope()->function_var() != nullptr) { + Variable* var = scope->AsDeclarationScope()->function_var(); + if (!var->is_used()) { + function_name_info = UNUSED; + } else if (var->IsContextSlot()) { + function_name_info = CONTEXT; + } else { + DCHECK(var->IsStackLocal()); + function_name_info = STACK; + } + } else { + function_name_info = NONE; + } + + 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); + + Factory* factory = isolate->factory(); + Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length); + + bool has_simple_parameters = false; + bool asm_module = false; + bool asm_function = false; + if (scope->is_function_scope()) { + DeclarationScope* function_scope = scope->AsDeclarationScope(); + has_simple_parameters = function_scope->has_simple_parameters(); + asm_module = function_scope->asm_module(); + asm_function = function_scope->asm_function(); + } + FunctionKind function_kind = kNormalFunction; + if (scope->is_declaration_scope()) { + function_kind = scope->AsDeclarationScope()->function_kind(); + } + + // 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) | + 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); + + int index = kVariablePartIndex; + // Add parameters. + DCHECK_EQ(index, scope_info->ParameterNamesIndex()); + if (scope->is_declaration_scope()) { + for (int i = 0; i < parameter_count; ++i) { + scope_info->set(index++, + *scope->AsDeclarationScope()->parameter(i)->name()); + } + } + + // 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_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 (Variable* var : *scope->locals()) { + 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_EQ(index, scope_info->ReceiverInfoIndex()); + if (has_receiver) { + int var_index = scope->AsDeclarationScope()->receiver()->index(); + scope_info->set(index++, Smi::FromInt(var_index)); + // ?? DCHECK(receiver_info != CONTEXT || var_index == + // scope_info->ContextLength() - 1); + } + + // If present, add the function variable name and its index. + DCHECK_EQ(index, scope_info->FunctionNameInfoIndex()); + if (has_function_name) { + int var_index = scope->AsDeclarationScope()->function_var()->index(); + scope_info->set(index++, + *scope->AsDeclarationScope()->function_var()->name()); + scope_info->set(index++, Smi::FromInt(var_index)); + DCHECK(function_name_info != CONTEXT || + var_index == scope_info->ContextLength() - 1); + } + + // 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::kZero); + 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 bool has_simple_parameters = true; + const VariableAllocationInfo receiver_info = CONTEXT; + 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_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) | + 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); + + int index = kVariablePartIndex; + const int first_slot_index = 0; + DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex()); + scope_info->set(index++, Smi::FromInt(first_slot_index)); + DCHECK_EQ(index, scope_info->StackLocalNamesIndex()); + + // Here we add info for context-allocated "this". + DCHECK_EQ(index, scope_info->ContextLocalNamesIndex()); + scope_info->set(index++, isolate->heap()->this_string()); + 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_EQ(index, scope_info->ReceiverInfoIndex()); + const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; + scope_info->set(index++, Smi::FromInt(receiver_index)); + + 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); + + return scope_info; +} + +ScopeInfo* ScopeInfo::Empty(Isolate* isolate) { + return isolate->heap()->empty_scope_info(); +} + +ScopeType ScopeInfo::scope_type() { + DCHECK_LT(0, length()); + return ScopeTypeField::decode(Flags()); +} + +bool ScopeInfo::CallsEval() { + return length() > 0 && CallsEvalField::decode(Flags()); +} + +LanguageMode ScopeInfo::language_mode() { + return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY; +} + +bool ScopeInfo::is_declaration_scope() { + return DeclarationScopeField::decode(Flags()); +} + +int ScopeInfo::LocalCount() { return StackLocalCount() + ContextLocalCount(); } + +int ScopeInfo::StackSlotCount() { + if (length() > 0) { + bool function_name_stack_slot = + FunctionVariableField::decode(Flags()) == STACK; + return StackLocalCount() + (function_name_stack_slot ? 1 : 0); + } + return 0; +} + +int ScopeInfo::ContextLength() { + if (length() > 0) { + int context_locals = ContextLocalCount(); + bool function_name_context_slot = + FunctionVariableField::decode(Flags()) == CONTEXT; + bool has_context = context_locals > 0 || function_name_context_slot || + scope_type() == WITH_SCOPE || + (scope_type() == BLOCK_SCOPE && CallsSloppyEval() && + is_declaration_scope()) || + (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) || + (scope_type() == FUNCTION_SCOPE && IsAsmModule()) || + scope_type() == MODULE_SCOPE; + + if (has_context) { + return Context::MIN_CONTEXT_SLOTS + context_locals + + (function_name_context_slot ? 1 : 0); + } + } + return 0; +} + +bool ScopeInfo::HasReceiver() { + if (length() > 0) { + return NONE != ReceiverVariableField::decode(Flags()); + } else { + return false; + } +} + +bool ScopeInfo::HasAllocatedReceiver() { + if (length() > 0) { + VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags()); + return allocation == STACK || allocation == CONTEXT; + } else { + return false; + } +} + +bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); } + +bool ScopeInfo::HasFunctionName() { + if (length() > 0) { + return NONE != FunctionVariableField::decode(Flags()); + } else { + return false; + } +} + +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) { + return ContextLocalCount() > 0; + } else { + return false; + } +} + +bool ScopeInfo::HasContext() { return ContextLength() > 0; } + +String* ScopeInfo::FunctionName() { + DCHECK(HasFunctionName()); + 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_LE(0, var); + DCHECK_LT(var, ParameterCount()); + int info_index = ParameterNamesIndex() + var; + return String::cast(get(info_index)); +} + +String* ScopeInfo::LocalName(int 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_LE(0, var); + DCHECK_LT(var, StackLocalCount()); + int info_index = StackLocalNamesIndex() + var; + return String::cast(get(info_index)); +} + +int ScopeInfo::StackLocalIndex(int var) { + 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_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalNamesIndex() + var; + return String::cast(get(info_index)); +} + +VariableMode ScopeInfo::ContextLocalMode(int var) { + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; + int value = Smi::cast(get(info_index))->value(); + return VariableModeField::decode(value); +} + +InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; + int value = Smi::cast(get(info_index))->value(); + return InitFlagField::decode(value); +} + +MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { + DCHECK_LE(0, var); + DCHECK_LT(var, ContextLocalCount()); + int info_index = ContextLocalInfosIndex() + var; + int value = Smi::cast(get(info_index))->value(); + return MaybeAssignedFlagField::decode(value); +} + +bool ScopeInfo::VariableIsSynthetic(String* name) { + // There's currently no flag stored on the ScopeInfo to indicate that a + // variable is a compiler-introduced temporary. However, to avoid conflict + // with user declarations, the current temporaries like .generator_object and + // .result start with a dot, so we can use that as a flag. It's a hack! + return name->length() == 0 || name->Get(0) == '.' || + name->Equals(name->GetHeap()->this_string()); +} + +int ScopeInfo::StackSlotIndex(String* name) { + DCHECK(name->IsInternalizedString()); + if (length() > 0) { + int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); + int start = StackLocalNamesIndex(); + int end = start + StackLocalCount(); + for (int i = start; i < end; ++i) { + if (name == get(i)) { + return i - start + first_slot_index; + } + } + } + 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; + ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag); + return index; + } + entry += kModuleVariableEntryLength; + } + + return 0; +} + +int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, + Handle<String> name, VariableMode* mode, + InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag) { + DCHECK(name->IsInternalizedString()); + 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_LT(result, scope_info->ContextLength()); + return result; + } + + 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; + *mode = scope_info->ContextLocalMode(var); + *init_flag = scope_info->ContextLocalInitFlag(var); + *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); + result = Context::MIN_CONTEXT_SLOTS + var; + + context_slot_cache->Update(scope_info, name, *mode, *init_flag, + *maybe_assigned_flag, result); + DCHECK_LT(result, scope_info->ContextLength()); + return result; + } + } + // Cache as not found. Mode, init flag and maybe assigned flag don't matter. + context_slot_cache->Update(scope_info, name, TEMPORARY, + kNeedsInitialization, kNotAssigned, -1); + } + + 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()); + return ContextLocalName(var); +} + +int ScopeInfo::ParameterIndex(String* name) { + DCHECK(name->IsInternalizedString()); + if (length() > 0) { + // We must read parameters from the end since for + // multiply declared parameters the value of the + // 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 = ParameterNamesIndex(); + int end = start + ParameterCount(); + for (int i = end - 1; i >= start; --i) { + if (name == get(i)) { + return i - start; + } + } + } + return -1; +} + +int ScopeInfo::ReceiverContextSlotIndex() { + if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) + return Smi::cast(get(ReceiverInfoIndex()))->value(); + return -1; +} + +int ScopeInfo::FunctionContextSlotIndex(String* name) { + DCHECK(name->IsInternalizedString()); + if (length() > 0) { + if (FunctionVariableField::decode(Flags()) == CONTEXT && + FunctionName() == name) { + return Smi::cast(get(FunctionNameInfoIndex() + 1))->value(); + } + } + return -1; +} + +FunctionKind ScopeInfo::function_kind() { + return FunctionKindField::decode(Flags()); +} + +int ScopeInfo::ParameterNamesIndex() { + DCHECK_LT(0, length()); + return kVariablePartIndex; +} + +int ScopeInfo::StackLocalFirstSlotIndex() { + return ParameterNamesIndex() + ParameterCount(); +} + +int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; } + +int ScopeInfo::ContextLocalNamesIndex() { + return StackLocalNamesIndex() + StackLocalCount(); +} + +int ScopeInfo::ContextLocalInfosIndex() { + return ContextLocalNamesIndex() + ContextLocalCount(); +} + +int ScopeInfo::ReceiverInfoIndex() { + return ContextLocalInfosIndex() + ContextLocalCount(); +} + +int ScopeInfo::FunctionNameInfoIndex() { + return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0); +} + +int ScopeInfo::OuterScopeInfoIndex() { + return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0); +} + +int ScopeInfo::ModuleInfoIndex() { + return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0); +} + +int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; } + +int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; } + +void ScopeInfo::ModuleVariable(int i, String** name, int* index, + VariableMode* mode, + InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag) { + DCHECK_LE(0, i); + DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value()); + + int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength; + int properties = + Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value(); + + if (name != nullptr) { + *name = String::cast(get(entry + kModuleVariableNameOffset)); + } + if (index != nullptr) { + *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value(); + DCHECK_NE(*index, 0); + } + if (mode != nullptr) { + *mode = VariableModeField::decode(properties); + } + if (init_flag != nullptr) { + *init_flag = InitFlagField::decode(properties); + } + if (maybe_assigned_flag != nullptr) { + *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties); + } +} + +#ifdef DEBUG + +static void PrintList(const char* list_name, int nof_internal_slots, int start, + int end, ScopeInfo* scope_info) { + if (start < end) { + PrintF("\n // %s\n", list_name); + if (nof_internal_slots > 0) { + PrintF(" %2d - %2d [internal slots]\n", 0, nof_internal_slots - 1); + } + for (int i = nof_internal_slots; start < end; ++i, ++start) { + PrintF(" %2d ", i); + String::cast(scope_info->get(start))->ShortPrint(); + PrintF("\n"); + } + } +} + +void ScopeInfo::Print() { + PrintF("ScopeInfo "); + if (HasFunctionName()) { + FunctionName()->ShortPrint(); + } else { + PrintF("/* no function name */"); + } + PrintF("{"); + + if (length() > 0) { + PrintList("parameters", 0, ParameterNamesIndex(), + ParameterNamesIndex() + ParameterCount(), this); + PrintList("stack slots", 0, StackLocalNamesIndex(), + StackLocalNamesIndex() + StackLocalCount(), this); + PrintList("context slots", Context::MIN_CONTEXT_SLOTS, + 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, + int module_request, int cell_index, + int beg_pos, int end_pos) { + Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast( + isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE)); + result->set_export_name(*export_name); + result->set_local_name(*local_name); + result->set_import_name(*import_name); + result->set_module_request(module_request); + result->set_cell_index(cell_index); + result->set_beg_pos(beg_pos); + result->set_end_pos(end_pos); + 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()) { + Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate); + special_exports->set(i++, *serialized_entry); + } + } + + // Serialize namespace imports. + Handle<FixedArray> namespace_imports = + isolate->factory()->NewFixedArray(descr->namespace_imports().length()); + { + int i = 0; + for (auto entry : descr->namespace_imports()) { + Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate); + namespace_imports->set(i++, *serialized_entry); + } + } + + // 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()) { + Handle<ModuleInfoEntry> serialized_entry = + elem.second->Serialize(isolate); + regular_imports->set(i++, *serialized_entry); + } + } + + 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; +} + +int ModuleInfo::RegularExportCount() const { + DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0); + return regular_exports()->length() / kRegularExportLength; +} + +String* ModuleInfo::RegularExportLocalName(int i) const { + return String::cast(regular_exports()->get(i * kRegularExportLength + + kRegularExportLocalNameOffset)); +} + +int ModuleInfo::RegularExportCellIndex(int i) const { + return Smi::cast(regular_exports()->get(i * kRegularExportLength + + kRegularExportCellIndexOffset)) + ->value(); +} + +FixedArray* ModuleInfo::RegularExportExportNames(int i) const { + return FixedArray::cast(regular_exports()->get( + i * kRegularExportLength + kRegularExportExportNamesOffset)); +} + +Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport( + Handle<ModuleInfo> info, Handle<String> local_name) { + Isolate* isolate = info->GetIsolate(); + Handle<FixedArray> regular_imports(info->regular_imports(), isolate); + for (int i = 0, n = regular_imports->length(); i < n; ++i) { + Handle<ModuleInfoEntry> entry( + ModuleInfoEntry::cast(regular_imports->get(i)), isolate); + if (String::cast(entry->local_name())->Equals(*local_name)) { + return entry; + } + } + UNREACHABLE(); + return Handle<ModuleInfoEntry>(); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/objects/scope-info.h b/deps/v8/src/objects/scope-info.h new file mode 100644 index 0000000000..671734e05a --- /dev/null +++ b/deps/v8/src/objects/scope-info.h @@ -0,0 +1,345 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_SCOPE_INFO_H_ +#define V8_OBJECTS_SCOPE_INFO_H_ + +#include "src/globals.h" +#include "src/handles.h" +#include "src/objects.h" +#include "src/utils.h" + +// Has to be the last include (doesn't have include guards): +#include "src/objects/object-macros.h" + +namespace v8 { +namespace internal { + +class Isolate; +class Scope; +class Zone; + +// ScopeInfo represents information about different scopes of a source +// program and the allocation of the scope's variables. Scope information +// is stored in a compressed form in ScopeInfo objects and is used +// at runtime (stack dumps, deoptimization, etc.). + +// This object provides quick access to scope info details for runtime +// routines. +class ScopeInfo : public FixedArray { + public: + DECLARE_CAST(ScopeInfo) + + // Return the type of this scope. + ScopeType scope_type(); + + // Does this scope call eval? + bool CallsEval(); + + // Return the language mode of this scope. + LanguageMode language_mode(); + + // True if this scope is a (var) declaration scope. + bool is_declaration_scope(); + + // Does this scope make a sloppy eval call? + bool CallsSloppyEval() { return CallsEval() && is_sloppy(language_mode()); } + + // Return the total number of locals allocated on the stack and in the + // context. This includes the parameters that are allocated in the context. + int LocalCount(); + + // Return the number of stack slots for code. This number consists of two + // parts: + // 1. One stack slot per stack allocated local. + // 2. One stack slot for the function name if it is stack allocated. + int StackSlotCount(); + + // Return the number of context slots for code if a context is allocated. This + // number consists of three parts: + // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS + // 2. One context slot per context allocated local. + // 3. One context slot for the function name if it is context allocated. + // Parameters allocated in the context count as context allocated locals. If + // no contexts are allocated for this scope ContextLength returns 0. + int ContextLength(); + + // Does this scope declare a "this" binding? + bool HasReceiver(); + + // Does this scope declare a "this" binding, and the "this" binding is stack- + // or context-allocated? + bool HasAllocatedReceiver(); + + // Does this scope declare a "new.target" binding? + bool HasNewTarget(); + + // Is this scope the scope of a named function expression? + bool HasFunctionName(); + + // Return if this has context allocated locals. + bool HasHeapAllocatedLocals(); + + // Return if contexts are allocated for this scope. + bool HasContext(); + + // Return if this is a function scope with "use asm". + inline bool IsAsmModule() { return AsmModuleField::decode(Flags()); } + + // Return if this is a nested function within an asm module scope. + inline bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); } + + inline bool HasSimpleParameters() { + return HasSimpleParametersField::decode(Flags()); + } + + // Return the function_name if present. + String* FunctionName(); + + ModuleInfo* ModuleDescriptorInfo(); + + // Return the name of the given parameter. + String* ParameterName(int var); + + // Return the name of the given local. + String* LocalName(int var); + + // Return the name of the given stack local. + String* StackLocalName(int var); + + // Return the name of the given stack local. + int StackLocalIndex(int var); + + // Return the name of the given context local. + String* ContextLocalName(int var); + + // Return the mode of the given context local. + VariableMode ContextLocalMode(int var); + + // Return the initialization flag of the given context local. + InitializationFlag ContextLocalInitFlag(int var); + + // Return the initialization flag of the given context local. + MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var); + + // Return true if this local was introduced by the compiler, and should not be + // exposed to the user in a debugger. + static bool VariableIsSynthetic(String* name); + + // Lookup support for serialized scope info. Returns the + // the stack slot index for a given slot name if the slot is + // present; otherwise returns a value < 0. The name must be an internalized + // string. + int StackSlotIndex(String* name); + + // Lookup support for serialized scope info. Returns the local context slot + // index for a given slot name if the slot is present; otherwise + // returns a value < 0. The name must be an internalized string. + // If the slot is present and mode != NULL, sets *mode to the corresponding + // mode for that variable. + static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name, + VariableMode* mode, InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag); + + // Lookup metadata of a MODULE-allocated variable. Return 0 if there is no + // module variable with the given name (the index value of a MODULE variable + // is never 0). + int ModuleIndex(Handle<String> name, VariableMode* mode, + InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag); + + // Lookup the name of a certain context slot by its index. + String* ContextSlotName(int slot_index); + + // Lookup support for serialized scope info. Returns the + // parameter index for a given parameter name if the parameter is present; + // otherwise returns a value < 0. The name must be an internalized string. + int ParameterIndex(String* name); + + // Lookup support for serialized scope info. Returns the function context + // slot index if the function name is present and context-allocated (named + // function expressions, only), otherwise returns a value < 0. The name + // must be an internalized string. + int FunctionContextSlotIndex(String* name); + + // Lookup support for serialized scope info. Returns the receiver context + // slot index if scope has a "this" binding, and the binding is + // context-allocated. Otherwise returns a value < 0. + int ReceiverContextSlotIndex(); + + FunctionKind function_kind(); + + // Returns true if this ScopeInfo is linked to a outer ScopeInfo. + bool HasOuterScopeInfo(); + + // Returns true if this ScopeInfo was created for a debug-evaluate scope. + bool IsDebugEvaluateScope(); + + // Can be used to mark a ScopeInfo that looks like a with-scope as actually + // being a debug-evaluate scope. + void SetIsDebugEvaluateScope(); + + // Return the outer ScopeInfo if present. + ScopeInfo* OuterScopeInfo(); + +#ifdef DEBUG + bool Equals(ScopeInfo* other) const; +#endif + + static Handle<ScopeInfo> Create(Isolate* isolate, Zone* zone, Scope* scope, + MaybeHandle<ScopeInfo> outer_scope); + static Handle<ScopeInfo> CreateForWithScope( + Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope); + static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate); + + // Serializes empty scope info. + V8_EXPORT_PRIVATE static ScopeInfo* Empty(Isolate* isolate); + +#ifdef DEBUG + void Print(); +#endif + +// The layout of the static part of a ScopeInfo is as follows. Each entry is +// numeric and occupies one array slot. +// 1. A set of properties of the scope. +// 2. The number of parameters. For non-function scopes this is 0. +// 3. The number of non-parameter variables allocated on the stack. +// 4. The number of non-parameter and parameter variables allocated in the +// context. +#define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \ + V(Flags) \ + V(ParameterCount) \ + V(StackLocalCount) \ + V(ContextLocalCount) + +#define FIELD_ACCESSORS(name) \ + inline void Set##name(int value) { set(k##name, Smi::FromInt(value)); } \ + inline int name() { \ + if (length() > 0) { \ + return Smi::cast(get(k##name))->value(); \ + } else { \ + return 0; \ + } \ + } + + FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS) +#undef FIELD_ACCESSORS + + enum { +#define DECL_INDEX(name) k##name, + FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX) +#undef DECL_INDEX + kVariablePartIndex + }; + + private: + // The layout of the variable part of a ScopeInfo is as follows: + // 1. ParameterNames: + // This part stores the names of the parameters for function scopes. One + // slot is used per parameter, so in total this part occupies + // ParameterCount() slots in the array. For other scopes than function + // scopes ParameterCount() is 0. + // 2. StackLocalFirstSlot: + // Index of a first stack slot for stack local. Stack locals belonging to + // this scope are located on a stack at slots starting from this index. + // 3. StackLocalNames: + // Contains the names of local variables that are allocated on the stack, + // in increasing order of the stack slot index. First local variable has a + // stack slot index defined in StackLocalFirstSlot (point 2 above). + // One slot is used per stack local, so in total this part occupies + // StackLocalCount() slots in the array. + // 4. ContextLocalNames: + // Contains the names of local variables and parameters that are allocated + // in the context. They are stored in increasing order of the context slot + // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per + // context local, so in total this part occupies ContextLocalCount() slots + // in the array. + // 5. ContextLocalInfos: + // Contains the variable modes and initialization flags corresponding to + // the context locals in ContextLocalNames. One slot is used per + // context local, so in total this part occupies ContextLocalCount() + // slots in the array. + // 6. ReceiverInfo: + // If the scope binds a "this" value, one slot is reserved to hold the + // context or stack slot index for the variable. + // 7. FunctionNameInfo: + // If the scope belongs to a named function expression this part contains + // information about the function variable. It always occupies two array + // slots: a. The name of the function variable. + // b. The context or stack slot index for the variable. + // 8. OuterScopeInfoIndex: + // The outer scope's ScopeInfo or the hole if there's none. + // 9. ModuleInfo, ModuleVariableCount, and ModuleVariables: + // For a module scope, this part contains the ModuleInfo, the number of + // MODULE-allocated variables, and the metadata of those variables. For + // non-module scopes it is empty. + int ParameterNamesIndex(); + int StackLocalFirstSlotIndex(); + int StackLocalNamesIndex(); + int ContextLocalNamesIndex(); + int ContextLocalInfosIndex(); + int ReceiverInfoIndex(); + int FunctionNameInfoIndex(); + int OuterScopeInfoIndex(); + int ModuleInfoIndex(); + int ModuleVariableCountIndex(); + int ModuleVariablesIndex(); + + int Lookup(Handle<String> name, int start, int end, VariableMode* mode, + VariableLocation* location, InitializationFlag* init_flag, + MaybeAssignedFlag* maybe_assigned_flag); + + // Get metadata of i-th MODULE-allocated variable, where 0 <= i < + // ModuleVariableCount. The metadata is returned via out-arguments, which may + // be nullptr if the corresponding information is not requested + void ModuleVariable(int i, String** name, int* index, + VariableMode* mode = nullptr, + InitializationFlag* init_flag = nullptr, + MaybeAssignedFlag* maybe_assigned_flag = nullptr); + + // Used for the function name variable for named function expressions, and for + // the receiver. + enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED }; + + // Properties of scopes. + class ScopeTypeField : public BitField<ScopeType, 0, 4> {}; + class CallsEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {}; + STATIC_ASSERT(LANGUAGE_END == 2); + class LanguageModeField + : public BitField<LanguageMode, CallsEvalField::kNext, 1> {}; + class DeclarationScopeField + : public BitField<bool, LanguageModeField::kNext, 1> {}; + class ReceiverVariableField + : public BitField<VariableAllocationInfo, DeclarationScopeField::kNext, + 2> {}; + class HasNewTargetField + : public BitField<bool, ReceiverVariableField::kNext, 1> {}; + class FunctionVariableField + : public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {}; + class AsmModuleField + : public BitField<bool, FunctionVariableField::kNext, 1> {}; + class AsmFunctionField : public BitField<bool, AsmModuleField::kNext, 1> {}; + class HasSimpleParametersField + : public BitField<bool, AsmFunctionField::kNext, 1> {}; + class FunctionKindField + : public BitField<FunctionKind, HasSimpleParametersField::kNext, 10> {}; + class HasOuterScopeInfoField + : public BitField<bool, FunctionKindField::kNext, 1> {}; + class IsDebugEvaluateScopeField + : public BitField<bool, HasOuterScopeInfoField::kNext, 1> {}; + + // Properties of variables. + class VariableModeField : public BitField<VariableMode, 0, 3> {}; + class InitFlagField : public BitField<InitializationFlag, 3, 1> {}; + class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {}; + + friend class ScopeIterator; +}; + +} // namespace internal +} // namespace v8 + +#include "src/objects/object-macros-undef.h" + +#endif // V8_OBJECTS_SCOPE_INFO_H_ |