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); |