Index: src/scopeinfo.cc |
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc |
index 8bc0a9a503440441b9ac99ffe2ae60d452c3a5cb..7657affd1df1e592092581cc267ac021a3d16e09 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); |
@@ -95,6 +101,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; |
@@ -135,6 +142,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) { |
@@ -146,6 +159,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()); |
@@ -198,6 +223,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; |
@@ -208,6 +234,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); |
@@ -229,6 +256,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; |
@@ -303,16 +331,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; |
@@ -398,14 +429,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); |
@@ -413,7 +444,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); |
@@ -421,7 +452,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); |
@@ -487,40 +518,57 @@ int ScopeInfo::StackSlotIndex(String* name) { |
int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
Handle<String> name, VariableMode* mode, |
+ ContextSlotKindFlag* context_slot_kind, |
InitializationFlag* init_flag, |
MaybeAssignedFlag* maybe_assigned_flag) { |
DCHECK(name->IsInternalizedString()); |
DCHECK(mode != NULL); |
+ DCHECK(context_slot_kind != 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, context_slot_kind, |
+ 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()) { |
+ *context_slot_kind = ContextSlotKindFlag::kLocal; |
+ result = Context::MIN_CONTEXT_SLOTS + var; |
+ } else { |
+ var -= scope_info->ContextLocalCount(); |
+ *context_slot_kind = ContextSlotKindFlag::kGlobal; |
+ result = Context::MIN_CONTEXT_SLOTS + |
+ scope_info->ContextLocalCount() + 2 * var; |
+ } |
+ |
+ context_slot_cache->Update(scope_info, name, *mode, *context_slot_kind, |
+ *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, |
- kNotAssigned, -1); |
+ context_slot_cache->Update(scope_info, name, INTERNAL, |
+ ContextSlotKindFlag::kLocal, |
+ kNeedsInitialization, kNotAssigned, -1); |
} |
return -1; |
} |
@@ -622,16 +670,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(); |
@@ -658,6 +716,7 @@ int ContextSlotCache::Hash(Object* data, String* name) { |
int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode, |
+ ContextSlotKindFlag* context_slot_kind, |
InitializationFlag* init_flag, |
MaybeAssignedFlag* maybe_assigned_flag) { |
int index = Hash(data, name); |
@@ -665,6 +724,8 @@ 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 (context_slot_kind != NULL) |
+ *context_slot_kind = result.context_slot_kind(); |
if (init_flag != NULL) *init_flag = result.initialization_flag(); |
if (maybe_assigned_flag != NULL) |
*maybe_assigned_flag = result.maybe_assigned_flag(); |
@@ -675,7 +736,9 @@ 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, |
+ ContextSlotKindFlag context_slot_kind, |
+ InitializationFlag init_flag, |
MaybeAssignedFlag maybe_assigned_flag, |
int slot_index) { |
DisallowHeapAllocation no_gc; |
@@ -688,10 +751,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, |
- slot_index - kNotFound).raw(); |
+ values_[index] = Value(mode, context_slot_kind, 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, context_slot_kind, init_flag, |
+ maybe_assigned_flag, slot_index); |
#endif |
} |
} |
@@ -706,6 +770,7 @@ void ContextSlotCache::Clear() { |
void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name, |
VariableMode mode, |
+ ContextSlotKindFlag context_slot_kind, |
InitializationFlag init_flag, |
MaybeAssignedFlag maybe_assigned_flag, |
int slot_index) { |
@@ -719,6 +784,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.context_slot_kind() == context_slot_kind); |
DCHECK(result.initialization_flag() == init_flag); |
DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag); |
DCHECK(result.index() + kNotFound == slot_index); |