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