| Index: src/scopeinfo.cc
|
| diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
|
| index f77ef96ebac4cd8da6bd33f1bd58936a021f354f..4ed22b19dcd9a37b60f07aacd92b09c923079ca2 100644
|
| --- a/src/scopeinfo.cc
|
| +++ b/src/scopeinfo.cc
|
| @@ -19,16 +19,20 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
|
| // Collect stack and context locals.
|
| ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
|
| ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
|
| + ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
|
| ZoneList<Variable*> strong_mode_free_variables(0, zone);
|
|
|
| scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
|
| + &context_globals,
|
| &strong_mode_free_variables);
|
| const int stack_local_count = stack_locals.length();
|
| const int context_local_count = context_locals.length();
|
| + const int context_global_count = context_globals.length();
|
| const int strong_mode_free_variable_count =
|
| strong_mode_free_variables.length();
|
| // Make sure we allocate the correct amount.
|
| - DCHECK(scope->ContextLocalCount() == context_local_count);
|
| + DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
|
| + DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
|
|
|
| bool simple_parameter_list =
|
| scope->is_function_scope() ? scope->is_simple_parameter_list() : true;
|
| @@ -67,12 +71,14 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
|
| function_name_info = NONE;
|
| function_variable_mode = VAR;
|
| }
|
| + DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
|
|
|
| const bool has_function_name = function_name_info != NONE;
|
| const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
|
| const int parameter_count = scope->num_parameters();
|
| const int length = kVariablePartIndex + parameter_count +
|
| (1 + stack_local_count) + 2 * context_local_count +
|
| + 2 * context_global_count +
|
| 3 * strong_mode_free_variable_count +
|
| (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
|
|
|
| @@ -94,6 +100,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
|
| scope_info->SetParameterCount(parameter_count);
|
| scope_info->SetStackLocalCount(stack_local_count);
|
| scope_info->SetContextLocalCount(context_local_count);
|
| + scope_info->SetContextGlobalCount(context_global_count);
|
| scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
|
|
|
| int index = kVariablePartIndex;
|
| @@ -134,6 +141,12 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
|
| scope_info->set(index++, *context_locals[i]->name());
|
| }
|
|
|
| + // Add context globals' names.
|
| + DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
|
| + for (int i = 0; i < context_global_count; ++i) {
|
| + scope_info->set(index++, *context_globals[i]->name());
|
| + }
|
| +
|
| // Add context locals' info.
|
| DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
|
| for (int i = 0; i < context_local_count; ++i) {
|
| @@ -145,6 +158,18 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
|
| scope_info->set(index++, Smi::FromInt(value));
|
| }
|
|
|
| + // Add context globals' info.
|
| + DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
|
| + for (int i = 0; i < context_global_count; ++i) {
|
| + Variable* var = context_globals[i];
|
| + // TODO(ishell): do we need this kind of info for globals here?
|
| + uint32_t value =
|
| + ContextLocalMode::encode(var->mode()) |
|
| + ContextLocalInitFlag::encode(var->initialization_flag()) |
|
| + ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
|
| + scope_info->set(index++, Smi::FromInt(value));
|
| + }
|
| +
|
| DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
|
| for (int i = 0; i < strong_mode_free_variable_count; ++i) {
|
| scope_info->set(index++, *strong_mode_free_variables[i]->name());
|
| @@ -197,6 +222,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
|
|
|
| const int stack_local_count = 0;
|
| const int context_local_count = 1;
|
| + const int context_global_count = 0;
|
| const int strong_mode_free_variable_count = 0;
|
| const bool simple_parameter_list = true;
|
| const VariableAllocationInfo receiver_info = CONTEXT;
|
| @@ -207,6 +233,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
|
| const int parameter_count = 0;
|
| const int length = kVariablePartIndex + parameter_count +
|
| (1 + stack_local_count) + 2 * context_local_count +
|
| + 2 * context_global_count +
|
| 3 * strong_mode_free_variable_count +
|
| (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
|
|
|
| @@ -227,6 +254,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
|
| scope_info->SetParameterCount(parameter_count);
|
| scope_info->SetStackLocalCount(stack_local_count);
|
| scope_info->SetContextLocalCount(context_local_count);
|
| + scope_info->SetContextGlobalCount(context_global_count);
|
| scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
|
|
|
| int index = kVariablePartIndex;
|
| @@ -301,16 +329,19 @@ int ScopeInfo::StackSlotCount() {
|
| int ScopeInfo::ContextLength() {
|
| if (length() > 0) {
|
| int context_locals = ContextLocalCount();
|
| + int context_globals = ContextGlobalCount();
|
| bool function_name_context_slot =
|
| FunctionVariableField::decode(Flags()) == CONTEXT;
|
| - bool has_context = context_locals > 0 || function_name_context_slot ||
|
| + bool has_context = context_locals > 0 || context_globals > 0 ||
|
| + function_name_context_slot ||
|
| scope_type() == WITH_SCOPE ||
|
| (scope_type() == ARROW_SCOPE && CallsSloppyEval()) ||
|
| (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
|
| scope_type() == MODULE_SCOPE;
|
| +
|
| if (has_context) {
|
| - return Context::MIN_CONTEXT_SLOTS + context_locals +
|
| - (function_name_context_slot ? 1 : 0);
|
| + return Context::MIN_CONTEXT_SLOTS + context_locals + 2 * context_globals +
|
| + (function_name_context_slot ? 1 : 0);
|
| }
|
| }
|
| return 0;
|
| @@ -396,14 +427,14 @@ int ScopeInfo::StackLocalIndex(int var) {
|
|
|
|
|
| String* ScopeInfo::ContextLocalName(int var) {
|
| - DCHECK(0 <= var && var < ContextLocalCount());
|
| + DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
|
| int info_index = ContextLocalNameEntriesIndex() + var;
|
| return String::cast(get(info_index));
|
| }
|
|
|
|
|
| VariableMode ScopeInfo::ContextLocalMode(int var) {
|
| - DCHECK(0 <= var && var < ContextLocalCount());
|
| + DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
|
| int info_index = ContextLocalInfoEntriesIndex() + var;
|
| int value = Smi::cast(get(info_index))->value();
|
| return ContextLocalMode::decode(value);
|
| @@ -411,7 +442,7 @@ VariableMode ScopeInfo::ContextLocalMode(int var) {
|
|
|
|
|
| InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
|
| - DCHECK(0 <= var && var < ContextLocalCount());
|
| + DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
|
| int info_index = ContextLocalInfoEntriesIndex() + var;
|
| int value = Smi::cast(get(info_index))->value();
|
| return ContextLocalInitFlag::decode(value);
|
| @@ -419,7 +450,7 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
|
|
|
|
|
| MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
|
| - DCHECK(0 <= var && var < ContextLocalCount());
|
| + DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
|
| int info_index = ContextLocalInfoEntriesIndex() + var;
|
| int value = Smi::cast(get(info_index))->value();
|
| return ContextLocalMaybeAssignedFlag::decode(value);
|
| @@ -485,39 +516,56 @@ int ScopeInfo::StackSlotIndex(String* name) {
|
|
|
| int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
|
| Handle<String> name, VariableMode* mode,
|
| + VariableLocation* location,
|
| InitializationFlag* init_flag,
|
| MaybeAssignedFlag* maybe_assigned_flag) {
|
| DCHECK(name->IsInternalizedString());
|
| DCHECK(mode != NULL);
|
| + DCHECK(location != NULL);
|
| DCHECK(init_flag != NULL);
|
| 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);
|
| + int result = context_slot_cache->Lookup(*scope_info, *name, mode, location,
|
| + init_flag, maybe_assigned_flag);
|
| if (result != ContextSlotCache::kNotFound) {
|
| DCHECK(result < scope_info->ContextLength());
|
| return result;
|
| }
|
|
|
| + DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
|
| + scope_info->ContextLocalNameEntriesIndex() +
|
| + scope_info->ContextLocalCount());
|
| int start = scope_info->ContextLocalNameEntriesIndex();
|
| - int end = scope_info->ContextLocalNameEntriesIndex() +
|
| - scope_info->ContextLocalCount();
|
| + int end = scope_info->ContextGlobalNameEntriesIndex() +
|
| + scope_info->ContextGlobalCount();
|
| 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);
|
| +
|
| + if (var < scope_info->ContextLocalCount()) {
|
| + *location = VariableLocation::CONTEXT;
|
| + result = Context::MIN_CONTEXT_SLOTS + var;
|
| + } else {
|
| + var -= scope_info->ContextLocalCount();
|
| + *location = VariableLocation::GLOBAL;
|
| + result = Context::MIN_CONTEXT_SLOTS +
|
| + scope_info->ContextLocalCount() + 2 * var;
|
| + }
|
| +
|
| + context_slot_cache->Update(scope_info, name, *mode, *location,
|
| + *init_flag, *maybe_assigned_flag, result);
|
| DCHECK(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, INTERNAL, kNeedsInitialization,
|
| + // Cache as not found. Mode, location, init flag and maybe assigned flag
|
| + // don't matter.
|
| + context_slot_cache->Update(scope_info, name, INTERNAL,
|
| + VariableLocation::CONTEXT, kNeedsInitialization,
|
| kNotAssigned, -1);
|
| }
|
| return -1;
|
| @@ -615,16 +663,26 @@ int ScopeInfo::ContextLocalNameEntriesIndex() {
|
| }
|
|
|
|
|
| -int ScopeInfo::ContextLocalInfoEntriesIndex() {
|
| +int ScopeInfo::ContextGlobalNameEntriesIndex() {
|
| return ContextLocalNameEntriesIndex() + ContextLocalCount();
|
| }
|
|
|
|
|
| -int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
|
| +int ScopeInfo::ContextLocalInfoEntriesIndex() {
|
| + return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
|
| +}
|
| +
|
| +
|
| +int ScopeInfo::ContextGlobalInfoEntriesIndex() {
|
| return ContextLocalInfoEntriesIndex() + ContextLocalCount();
|
| }
|
|
|
|
|
| +int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
|
| + return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
|
| +}
|
| +
|
| +
|
| int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
|
| return StrongModeFreeVariableNameEntriesIndex() +
|
| StrongModeFreeVariableCount();
|
| @@ -651,6 +709,7 @@ int ContextSlotCache::Hash(Object* data, String* name) {
|
|
|
|
|
| int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
|
| + VariableLocation* location,
|
| InitializationFlag* init_flag,
|
| MaybeAssignedFlag* maybe_assigned_flag) {
|
| int index = Hash(data, name);
|
| @@ -658,6 +717,7 @@ int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
|
| if ((key.data == data) && key.name->Equals(name)) {
|
| Value result(values_[index]);
|
| if (mode != NULL) *mode = result.mode();
|
| + if (location != NULL) *location = result.location();
|
| if (init_flag != NULL) *init_flag = result.initialization_flag();
|
| if (maybe_assigned_flag != NULL)
|
| *maybe_assigned_flag = result.maybe_assigned_flag();
|
| @@ -668,7 +728,8 @@ int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
|
|
|
|
|
| void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
|
| - VariableMode mode, InitializationFlag init_flag,
|
| + VariableMode mode, VariableLocation location,
|
| + InitializationFlag init_flag,
|
| MaybeAssignedFlag maybe_assigned_flag,
|
| int slot_index) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -681,10 +742,11 @@ void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
|
| key.data = *data;
|
| key.name = *internalized_name;
|
| // Please note value only takes a uint as index.
|
| - values_[index] = Value(mode, init_flag, maybe_assigned_flag,
|
| + values_[index] = Value(mode, location, init_flag, maybe_assigned_flag,
|
| slot_index - kNotFound).raw();
|
| #ifdef DEBUG
|
| - ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
|
| + ValidateEntry(data, name, mode, location, init_flag, maybe_assigned_flag,
|
| + slot_index);
|
| #endif
|
| }
|
| }
|
| @@ -699,6 +761,7 @@ void ContextSlotCache::Clear() {
|
|
|
| void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
|
| VariableMode mode,
|
| + VariableLocation location,
|
| InitializationFlag init_flag,
|
| MaybeAssignedFlag maybe_assigned_flag,
|
| int slot_index) {
|
| @@ -712,6 +775,7 @@ void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
|
| DCHECK(key.name->Equals(*name));
|
| Value result(values_[index]);
|
| DCHECK(result.mode() == mode);
|
| + DCHECK(result.location() == location);
|
| DCHECK(result.initialization_flag() == init_flag);
|
| DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
|
| DCHECK(result.index() + kNotFound == slot_index);
|
|
|