summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/scope-info.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/scope-info.cc')
-rw-r--r--deps/v8/src/objects/scope-info.cc235
1 files changed, 79 insertions, 156 deletions
diff --git a/deps/v8/src/objects/scope-info.cc b/deps/v8/src/objects/scope-info.cc
index 479d7b3ca4..9ec87dcb92 100644
--- a/deps/v8/src/objects/scope-info.cc
+++ b/deps/v8/src/objects/scope-info.cc
@@ -10,7 +10,9 @@
#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/bootstrapper.h"
+#include "src/heap/heap-inl.h"
#include "src/objects-inl.h"
+#include "src/objects/module-inl.h"
namespace v8 {
namespace internal {
@@ -61,20 +63,14 @@ bool ScopeInfo::Equals(ScopeInfo* other) const {
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;
@@ -143,8 +139,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
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 +
+ const int length = kVariablePartIndex + 2 * context_local_count +
(has_receiver ? 1 : 0) +
(has_function_name ? kFunctionNameEntries : 0) +
(has_inferred_function_name ? 1 : 0) +
@@ -189,50 +184,29 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* 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.
+ // Add context locals' names and info, module variables' names and info.
// 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_base = index;
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());
+ uint32_t info =
+ VariableModeField::encode(var->mode()) |
+ InitFlagField::encode(var->initialization_flag()) |
+ MaybeAssignedFlagField::encode(var->maybe_assigned()) |
+ ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(context_local_base + local_index, *var->name());
scope_info->set(context_local_info_base + local_index,
Smi::FromInt(info));
@@ -246,7 +220,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
uint32_t properties =
VariableModeField::encode(var->mode()) |
InitFlagField::encode(var->initialization_flag()) |
- MaybeAssignedFlagField::encode(var->maybe_assigned());
+ MaybeAssignedFlagField::encode(var->maybe_assigned()) |
+ ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
Smi::FromInt(properties));
module_var_entry += kModuleVariableEntryLength;
@@ -257,7 +232,26 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
}
}
- index += stack_local_count + 2 * context_local_count;
+ if (scope->is_declaration_scope()) {
+ // Mark contexts slots with the parameter number they represent. We walk the
+ // list of parameters. That can include duplicate entries if a parameter
+ // name is repeated. By walking upwards, we'll automatically mark the
+ // context slot with the highest parameter number that uses this variable.
+ // That will be the parameter number that is represented by the context
+ // slot. All lower parameters will only be available on the stack through
+ // the arguments object.
+ for (int i = 0; i < parameter_count; i++) {
+ Variable* parameter = scope->AsDeclarationScope()->parameter(i);
+ if (parameter->location() != VariableLocation::CONTEXT) continue;
+ int index = parameter->index() - Context::MIN_CONTEXT_SLOTS;
+ int info_index = context_local_info_base + index;
+ int info = Smi::ToInt(scope_info->get(info_index));
+ info = ParameterNumberField::update(info, i);
+ scope_info->set(info_index, Smi::FromInt(info));
+ }
+ }
+
+ index += 2 * context_local_count;
// If the receiver is allocated, add its index.
DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
@@ -326,7 +320,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
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);
+ const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
Factory* factory = isolate->factory();
Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
@@ -345,14 +339,9 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
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_EQ(index, scope_info->InferredFunctionNameIndex());
@@ -384,14 +373,12 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);
const int parameter_count = 0;
- const int stack_local_count = 0;
const bool is_empty_function = type == FUNCTION_SCOPE;
const int context_local_count = is_empty_function ? 0 : 1;
const bool has_receiver = !is_empty_function;
const bool has_inferred_function_name = is_empty_function;
const bool has_position_info = true;
- const int length = kVariablePartIndex + parameter_count +
- (1 + stack_local_count) + 2 * context_local_count +
+ const int length = kVariablePartIndex + 2 * context_local_count +
(has_receiver ? 1 : 0) +
(is_empty_function ? kFunctionNameEntries : 0) +
(has_inferred_function_name ? 1 : 0) +
@@ -415,25 +402,22 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
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());
if (context_local_count) {
- scope_info->set(index++, isolate->heap()->this_string());
+ scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
}
DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
if (context_local_count) {
- const uint32_t value = VariableModeField::encode(CONST) |
- InitFlagField::encode(kCreatedInitialized) |
- MaybeAssignedFlagField::encode(kNotAssigned);
+ const uint32_t value =
+ VariableModeField::encode(VariableMode::kConst) |
+ InitFlagField::encode(kCreatedInitialized) |
+ MaybeAssignedFlagField::encode(kNotAssigned) |
+ ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(index++, Smi::FromInt(value));
}
@@ -470,7 +454,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
}
ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
- return isolate->heap()->empty_scope_info();
+ return ReadOnlyRoots(isolate).empty_scope_info();
}
ScopeType ScopeInfo::scope_type() const {
@@ -495,19 +479,6 @@ bool ScopeInfo::is_declaration_scope() const {
return DeclarationScopeField::decode(Flags());
}
-int ScopeInfo::LocalCount() const {
- return StackLocalCount() + ContextLocalCount();
-}
-
-int ScopeInfo::StackSlotCount() const {
- 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() const {
if (length() > 0) {
int context_locals = ContextLocalCount();
@@ -620,17 +591,17 @@ String* ScopeInfo::FunctionDebugName() const {
name = InferredFunctionName();
if (name->IsString()) return String::cast(name);
}
- return GetHeap()->empty_string();
+ return GetReadOnlyRoots().empty_string();
}
int ScopeInfo::StartPosition() const {
DCHECK(HasPositionInfo());
- return Smi::cast(get(PositionInfoIndex()))->value();
+ return Smi::ToInt(get(PositionInfoIndex()));
}
int ScopeInfo::EndPosition() const {
DCHECK(HasPositionInfo());
- return Smi::cast(get(PositionInfoIndex() + 1))->value();
+ return Smi::ToInt(get(PositionInfoIndex() + 1));
}
void ScopeInfo::SetPositionInfo(int start, int end) {
@@ -650,36 +621,6 @@ ModuleInfo* ScopeInfo::ModuleDescriptorInfo() const {
return ModuleInfo::cast(get(ModuleInfoIndex()));
}
-String* ScopeInfo::ParameterName(int var) const {
- DCHECK_LE(0, var);
- DCHECK_LT(var, ParameterCount());
- int info_index = ParameterNamesIndex() + var;
- return String::cast(get(info_index));
-}
-
-String* ScopeInfo::LocalName(int var) const {
- 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) const {
- DCHECK_LE(0, var);
- DCHECK_LT(var, StackLocalCount());
- int info_index = StackLocalNamesIndex() + var;
- return String::cast(get(info_index));
-}
-
-int ScopeInfo::StackLocalIndex(int var) const {
- DCHECK_LE(0, var);
- DCHECK_LT(var, StackLocalCount());
- int first_slot_index = Smi::ToInt(get(StackLocalFirstSlotIndex()));
- return first_slot_index + var;
-}
-
String* ScopeInfo::ContextLocalName(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
@@ -703,6 +644,21 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
return InitFlagField::decode(value);
}
+bool ScopeInfo::ContextLocalIsParameter(int var) const {
+ DCHECK_LE(0, var);
+ DCHECK_LT(var, ContextLocalCount());
+ int info_index = ContextLocalInfosIndex() + var;
+ int value = Smi::ToInt(get(info_index));
+ return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
+}
+
+uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
+ DCHECK(ContextLocalIsParameter(var));
+ int info_index = ContextLocalInfosIndex() + var;
+ int value = Smi::ToInt(get(info_index));
+ return ParameterNumberField::decode(value);
+}
+
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
@@ -718,26 +674,13 @@ bool ScopeInfo::VariableIsSynthetic(String* name) {
// 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) const {
- DCHECK(name->IsInternalizedString());
- if (length() == 0) return -1;
- int first_slot_index = Smi::ToInt(get(StackLocalFirstSlotIndex()));
- 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;
+ name->Equals(name->GetReadOnlyRoots().this_string());
}
int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag) {
+ DCHECK(name->IsInternalizedString());
DCHECK_EQ(scope_type(), MODULE_SCOPE);
DCHECK_NOT_NULL(mode);
DCHECK_NOT_NULL(init_flag);
@@ -770,8 +713,19 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
if (scope_info->length() == 0) return -1;
- ContextSlotCache* context_slot_cache =
- scope_info->GetIsolate()->context_slot_cache();
+ // Get the Isolate via the heap.
+ //
+ // Ideally we'd pass Isolate* through to this function, however this is mostly
+ // called from the parser, which is otherwise isolate independent. We can't
+ // assume that all scope infos are never RO space (like we can with JSReceiver
+ // or Context), but we can assume that *non-empty* scope infos are.
+ //
+ // So, we take the least-ugly approach of manually getting the isolate to be
+ // able to remove GetIsolate from ScopeInfo in the general case, while
+ // allowing it in this one particular case.
+ Isolate* isolate = Heap::FromWritableHeapObject(*scope_info)->isolate();
+
+ ContextSlotCache* context_slot_cache = isolate->context_slot_cache();
int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
maybe_assigned_flag);
if (result != ContextSlotCache::kNotFound) {
@@ -796,30 +750,12 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
}
}
// 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);
+ context_slot_cache->Update(scope_info, name, VariableMode::kTemporary,
+ kNeedsInitialization, kNotAssigned, -1);
return -1;
}
-int ScopeInfo::ParameterIndex(String* name) const {
- DCHECK(name->IsInternalizedString());
- if (length() == 0) return -1;
- // 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() const {
if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
return Smi::ToInt(get(ReceiverInfoIndex()));
@@ -842,23 +778,11 @@ FunctionKind ScopeInfo::function_kind() const {
return FunctionKindField::decode(Flags());
}
-int ScopeInfo::ParameterNamesIndex() const {
+int ScopeInfo::ContextLocalNamesIndex() const {
DCHECK_LT(0, length());
return kVariablePartIndex;
}
-int ScopeInfo::StackLocalFirstSlotIndex() const {
- return ParameterNamesIndex() + ParameterCount();
-}
-
-int ScopeInfo::StackLocalNamesIndex() const {
- return StackLocalFirstSlotIndex() + 1;
-}
-
-int ScopeInfo::ContextLocalNamesIndex() const {
- return StackLocalNamesIndex() + StackLocalCount();
-}
-
int ScopeInfo::ContextLocalInfosIndex() const {
return ContextLocalNamesIndex() + ContextLocalCount();
}
@@ -1030,9 +954,8 @@ String* ModuleInfo::RegularExportLocalName(int i) const {
}
int ModuleInfo::RegularExportCellIndex(int i) const {
- return Smi::cast(regular_exports()->get(i * kRegularExportLength +
- kRegularExportCellIndexOffset))
- ->value();
+ return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
+ kRegularExportCellIndexOffset));
}
FixedArray* ModuleInfo::RegularExportExportNames(int i) const {