summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects')
-rw-r--r--deps/v8/src/objects/module-info.h129
-rw-r--r--deps/v8/src/objects/object-macros-undef.h9
-rw-r--r--deps/v8/src/objects/object-macros.h32
-rw-r--r--deps/v8/src/objects/scope-info.cc947
-rw-r--r--deps/v8/src/objects/scope-info.h345
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_