Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index 5f7ed84beecca11f7e5f3715c93b5aa4f58a903e..9214a3622e25eeaaffa73548b0822d831c612d94 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -14,6 +14,9 @@ |
namespace v8 { |
namespace internal { |
+// TODO(ishell): remove this once compiler support is landed. |
+bool enable_context_globals = false; |
+ |
// ---------------------------------------------------------------------------- |
// Implementation of LocalsMap |
// |
@@ -179,6 +182,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, |
num_var_or_const_ = 0; |
num_stack_slots_ = 0; |
num_heap_slots_ = 0; |
+ num_global_slots_ = 0; |
num_modules_ = 0; |
module_var_ = NULL, |
rest_parameter_ = NULL; |
@@ -390,11 +394,13 @@ Variable* Scope::LookupLocal(const AstRawString* name) { |
// Check context slot lookup. |
VariableMode mode; |
+ ContextSlotKindFlag slot_kind; |
Variable::Location location = Variable::CONTEXT; |
InitializationFlag init_flag; |
MaybeAssignedFlag maybe_assigned_flag; |
- int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, |
- &init_flag, &maybe_assigned_flag); |
+ int index = |
+ ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &slot_kind, |
+ &init_flag, &maybe_assigned_flag); |
if (index < 0) { |
// Check parameters. |
index = scope_info_->ParameterIndex(*name_handle); |
@@ -407,6 +413,11 @@ Variable* Scope::LookupLocal(const AstRawString* name) { |
// would require ScopeInfo to serialize the maybe_assigned bit also for |
// parameters. |
maybe_assigned_flag = kMaybeAssigned; |
+ |
+ } else if (slot_kind == ContextSlotKindFlag::kGlobal) { |
+ DCHECK(is_script_scope()); |
+ DCHECK(IsDeclaredVariableMode(mode) && !IsLexicalVariableMode(mode)); |
+ location = Variable::UNALLOCATED; |
} |
Variable::Kind kind = Variable::NORMAL; |
@@ -605,9 +616,11 @@ class VarAndOrder { |
void Scope::CollectStackAndContextLocals( |
ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, |
+ ZoneList<Variable*>* context_globals, |
ZoneList<Variable*>* strong_mode_free_variables) { |
DCHECK(stack_locals != NULL); |
DCHECK(context_locals != NULL); |
+ DCHECK(context_globals != NULL); |
// Collect internals which are always allocated on the heap. |
for (int i = 0; i < internals_.length(); i++) { |
@@ -656,6 +669,8 @@ void Scope::CollectStackAndContextLocals( |
stack_locals->Add(var, zone()); |
} else if (var->IsContextSlot()) { |
context_locals->Add(var, zone()); |
+ } else if (enable_context_globals && var->IsStaticGlobalObjectProperty()) { |
+ context_globals->Add(var, zone()); |
} |
} |
} |
@@ -695,7 +710,7 @@ bool Scope::HasTrivialContext() const { |
for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { |
if (scope->is_eval_scope()) return false; |
if (scope->scope_inside_with_) return false; |
- if (scope->num_heap_slots_ > 0) return false; |
+ if (scope->ContextLocalCount() > 0) return false; |
} |
return true; |
} |
@@ -831,6 +846,9 @@ static void PrintName(const AstRawString* name) { |
static void PrintLocation(Variable* var) { |
switch (var->location()) { |
case Variable::UNALLOCATED: |
+ if (var->IsStaticGlobalObjectProperty()) { |
+ PrintF("global[%d]", var->index()); |
+ } |
break; |
case Variable::PARAMETER: |
PrintF("parameter[%d]", var->index()); |
@@ -849,13 +867,14 @@ static void PrintLocation(Variable* var) { |
static void PrintVar(int indent, Variable* var) { |
- if (var->is_used() || !var->IsUnallocated()) { |
+ if (var->is_used() || !var->IsUnallocated() || |
+ var->IsStaticGlobalObjectProperty()) { |
Indent(indent, Variable::Mode2String(var->mode())); |
PrintF(" "); |
PrintName(var->raw_name()); |
PrintF("; // "); |
PrintLocation(var); |
- bool comma = !var->IsUnallocated(); |
+ bool comma = !var->IsUnallocated() || var->IsStaticGlobalObjectProperty(); |
if (var->has_forced_context_allocation()) { |
if (comma) PrintF(", "); |
PrintF("forced context allocation"); |
@@ -873,7 +892,11 @@ static void PrintVar(int indent, Variable* var) { |
static void PrintMap(int indent, VariableMap* map) { |
for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
Variable* var = reinterpret_cast<Variable*>(p->value); |
- PrintVar(indent, var); |
+ if (var == NULL) { |
+ Indent(indent, "<?>\n"); |
+ } else { |
+ PrintVar(indent, var); |
+ } |
} |
} |
@@ -930,10 +953,15 @@ void Scope::Print(int n) { |
Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
} |
if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
- if (num_stack_slots_ > 0) { Indent(n1, "// "); |
- PrintF("%d stack slots\n", num_stack_slots_); } |
- if (num_heap_slots_ > 0) { Indent(n1, "// "); |
- PrintF("%d heap slots\n", num_heap_slots_); } |
+ if (num_stack_slots_ > 0) { |
+ Indent(n1, "// "); |
+ PrintF("%d stack slots\n", num_stack_slots_); |
+ } |
+ if (num_heap_slots_ > 0) { |
+ Indent(n1, "// "); |
+ PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, |
+ num_global_slots_); |
+ } |
// Print locals. |
if (function_ != NULL) { |
@@ -1420,6 +1448,8 @@ void Scope::AllocateParameter(Variable* var, int index) { |
var->AllocateTo(Variable::PARAMETER, index); |
} |
} |
+ } else { |
+ DCHECK(!var->IsStaticGlobalObjectProperty()); |
} |
} |
@@ -1450,7 +1480,23 @@ void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) { |
} |
-void Scope::AllocateNonParameterLocals(Isolate* isolate) { |
+void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) { |
+ DCHECK(var->scope() == this); |
+ DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
+ !var->IsStackLocal()); |
+ if (var->IsUnallocated() && var->IsStaticGlobalObjectProperty()) { |
+ DCHECK_EQ(-1, var->index()); |
+ DCHECK(var->name()->IsString()); |
+ var->AllocateTo(Variable::UNALLOCATED, num_heap_slots_); |
+ num_global_slots_++; |
+ // Each global variable occupies two slots in the context: for reads |
+ // and writes. |
+ num_heap_slots_ += 2; |
+ } |
+} |
+ |
+ |
+void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) { |
// All variables that have no rewrite yet are non-parameter locals. |
for (int i = 0; i < temps_.length(); i++) { |
AllocateNonParameterLocal(isolate, temps_[i]); |
@@ -1473,6 +1519,12 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) { |
AllocateNonParameterLocal(isolate, vars[i].var()); |
} |
+ if (enable_context_globals) { |
+ for (int i = 0; i < var_count; i++) { |
+ AllocateDeclaredGlobal(isolate, vars[i].var()); |
+ } |
+ } |
+ |
// For now, function_ must be allocated at the very end. If it gets |
// allocated in the context, it must be the last slot in the context, |
// because of the current ScopeInfo implementation (see |
@@ -1518,7 +1570,7 @@ void Scope::AllocateVariablesRecursively(Isolate* isolate) { |
// Parameters must be allocated first, if any. |
if (is_function_scope()) AllocateParameterLocals(isolate); |
if (has_this_declaration()) AllocateReceiver(); |
- AllocateNonParameterLocals(isolate); |
+ AllocateNonParameterLocalsAndDeclaredGlobals(isolate); |
// Force allocation of a context for this scope if necessary. For a 'with' |
// scope and for a function scope that makes an 'eval' call we need a context, |
@@ -1562,8 +1614,13 @@ int Scope::StackLocalCount() const { |
int Scope::ContextLocalCount() const { |
if (num_heap_slots() == 0) return 0; |
+ bool is_function_var_in_context = |
+ function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
- (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
+ 2 * num_global_slots() - (is_function_var_in_context ? 1 : 0); |
} |
+ |
+ |
+int Scope::ContextGlobalCount() const { return num_global_slots(); } |
} // namespace internal |
} // namespace v8 |