Chromium Code Reviews| Index: src/scopes.cc |
| diff --git a/src/scopes.cc b/src/scopes.cc |
| index f9cebcddaafff5532c4aac23ab7af06dd9a7c220..356b578d2256ed172a3271107b34b4ed61fee08c 100644 |
| --- a/src/scopes.cc |
| +++ b/src/scopes.cc |
| @@ -148,6 +148,8 @@ Scope::Scope(Scope* inner_scope, |
| SetDefaults(type, NULL, scope_info); |
| if (!scope_info.is_null()) { |
| num_heap_slots_ = scope_info_->ContextLength(); |
| + } else if (is_with_scope()) { |
| + num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| } |
| AddInnerScope(inner_scope); |
| } |
| @@ -165,6 +167,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) |
| SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
| AddInnerScope(inner_scope); |
| ++num_var_or_const_; |
| + num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| Variable* variable = variables_.Declare(this, |
| catch_variable_name, |
| VAR, |
| @@ -201,14 +204,16 @@ void Scope::SetDefaults(ScopeType type, |
| scope_info_ = scope_info; |
| start_position_ = RelocInfo::kNoPosition; |
| end_position_ = RelocInfo::kNoPosition; |
| + if (!scope_info.is_null()) { |
| + scope_calls_eval_ = scope_info->CallsEval(); |
| + strict_mode_flag_ = |
| + scope_info->IsStrictMode() ? kStrictMode : kNonStrictMode; |
| + } |
| } |
| -Scope* Scope::DeserializeScopeChain(CompilationInfo* info, |
| - Scope* global_scope) { |
| +Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope) { |
| // Reconstruct the outer scope chain from a closure's context chain. |
| - ASSERT(!info->closure().is_null()); |
| - Context* context = info->closure()->context(); |
| Scope* current_scope = NULL; |
| Scope* innermost_scope = NULL; |
| bool contains_with = false; |
| @@ -356,10 +361,6 @@ Variable* Scope::LocalLookup(Handle<String> name) { |
| return result; |
| } |
| // If we have a serialized scope info, we might find the variable there. |
| - // |
| - // We should never lookup 'arguments' in this scope as it is implicitly |
| - // present in every scope. |
| - ASSERT(*name != *isolate_->factory()->arguments_symbol()); |
| // There should be no local slot with the given name. |
| ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
| @@ -372,11 +373,7 @@ Variable* Scope::LocalLookup(Handle<String> name) { |
| mode = VAR; |
| init_flag = kCreatedInitialized; |
| index = scope_info_->ParameterIndex(*name); |
| - if (index < 0) { |
| - // Check the function name. |
| - index = scope_info_->FunctionContextSlotIndex(*name, &mode); |
| - if (index < 0) return NULL; |
| - } |
| + if (index < 0) return NULL; |
| } |
| Variable* var = |
| @@ -391,6 +388,23 @@ Variable* Scope::LocalLookup(Handle<String> name) { |
| } |
| +Variable* Scope::LookupFunctionVar(Handle<String> name) { |
| + if (function_ != NULL && function_->name().is_identical_to(name)) { |
| + return function_->var(); |
| + } else if (!scope_info_.is_null()) { |
| + // If we are backed by a scope info, try to lookup the variable there. |
| + VariableMode mode; |
| + int index = scope_info_->FunctionContextSlotIndex(*name, &mode); |
| + if (index < 0) return NULL; |
| + Variable* var = DeclareFunctionVar(name, mode); |
| + var->AllocateTo(Variable::CONTEXT, index); |
| + return var; |
| + } else { |
| + return NULL; |
| + } |
| +} |
| + |
| + |
| Variable* Scope::Lookup(Handle<String> name) { |
| for (Scope* scope = this; |
| scope != NULL; |
| @@ -559,7 +573,7 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
| } |
| -void Scope::AllocateVariables(Handle<Context> context) { |
| +void Scope::AllocateVariables(Handle<Context> calling_context) { |
| ASSERT(outer_scope_ == NULL); // eval or global scopes only |
| // 1) Propagate scope information. |
| @@ -569,16 +583,19 @@ void Scope::AllocateVariables(Handle<Context> context) { |
| // this information in the ScopeInfo and then use it here (by traversing |
| // the call chain stack, at compile time). |
| - bool outer_scope_calls_non_strict_eval = false; |
| - if (!is_global_scope()) { |
| - context->ComputeEvalScopeInfo(&outer_scope_calls_non_strict_eval); |
| + Scope* global_scope; |
| + if (is_global_scope()) { |
| + global_scope = this; |
| + } else { |
| + global_scope = new Scope(NULL, GLOBAL_SCOPE); |
| + Scope* calling_scope = |
| + DeserializeScopeChain(*calling_context, global_scope); |
|
Kevin Millikin (Chromium)
2011/11/10 12:55:21
I don't like this. It doesn't seem consistent. F
Steven
2011/11/11 08:35:04
Done.
|
| + calling_scope->AddInnerScope(this); |
| } |
| - PropagateScopeInfo(outer_scope_calls_non_strict_eval); |
| + global_scope->PropagateScopeInfo(false); |
| // 2) Resolve variables. |
| - Scope* global_scope = NULL; |
| - if (is_global_scope()) global_scope = this; |
| - ResolveVariablesRecursively(global_scope, context); |
| + ResolveVariablesRecursively(global_scope); |
| // 3) Allocate variables. |
| AllocateVariablesRecursively(); |
| @@ -832,7 +849,6 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) { |
| Variable* Scope::LookupRecursive(Handle<String> name, |
| - Handle<Context> context, |
| BindingKind* binding_kind) { |
| ASSERT(binding_kind != NULL); |
| // Try to find the variable in this scope. |
| @@ -849,20 +865,17 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
| // We did not find a variable locally. Check against the function variable, |
| // if any. We can do this for all scopes, since the function variable is |
| // only present - if at all - for function scopes. |
| - // |
| - // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| - // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
| - // the name of named function literal is kept in an intermediate scope |
| - // in between this scope and the next outer scope.) |
| *binding_kind = UNBOUND; |
| - if (function_ != NULL && function_->name().is_identical_to(name)) { |
| - var = function_->var(); |
| + var = LookupFunctionVar(name); |
| + if (var != NULL) { |
| *binding_kind = BOUND; |
| } else if (outer_scope_ != NULL) { |
| - var = outer_scope_->LookupRecursive(name, context, binding_kind); |
| + var = outer_scope_->LookupRecursive(name, binding_kind); |
| if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
| var->ForceContextAllocation(); |
| } |
| + } else { |
| + ASSERT(is_global_scope()); |
| } |
| if (is_with_scope()) { |
| @@ -874,16 +887,6 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
| // object). |
| *binding_kind = DYNAMIC_LOOKUP; |
| return NULL; |
| - } else if (is_eval_scope()) { |
| - // No local binding was found, no 'with' statements have been encountered |
| - // and the code is executed as part of a call to 'eval'. The calling context |
| - // contains scope information that we can use to determine if the variable |
| - // is global, i.e. the calling context chain does not contain a binding and |
| - // no 'with' contexts. |
| - ASSERT(*binding_kind == UNBOUND); |
| - *binding_kind = context->GlobalIfNotShadowedByEval(name) |
| - ? UNBOUND_EVAL_SHADOWED : DYNAMIC_LOOKUP; |
| - return NULL; |
| } else if (calls_non_strict_eval()) { |
| // A variable binding may have been found in an outer scope, but the current |
| // scope makes a non-strict 'eval' call, so the found variable may not be |
| @@ -900,7 +903,6 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
| void Scope::ResolveVariable(Scope* global_scope, |
| - Handle<Context> context, |
| VariableProxy* proxy) { |
| ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| @@ -910,7 +912,7 @@ void Scope::ResolveVariable(Scope* global_scope, |
| // Otherwise, try to resolve the variable. |
| BindingKind binding_kind; |
| - Variable* var = LookupRecursive(proxy->name(), context, &binding_kind); |
| + Variable* var = LookupRecursive(proxy->name(), &binding_kind); |
| switch (binding_kind) { |
| case BOUND: |
| // We found a variable binding. |
| @@ -951,18 +953,17 @@ void Scope::ResolveVariable(Scope* global_scope, |
| } |
| -void Scope::ResolveVariablesRecursively(Scope* global_scope, |
| - Handle<Context> context) { |
| +void Scope::ResolveVariablesRecursively(Scope* global_scope) { |
| ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| // Resolve unresolved variables for this scope. |
| for (int i = 0; i < unresolved_.length(); i++) { |
| - ResolveVariable(global_scope, context, unresolved_[i]); |
| + ResolveVariable(global_scope, unresolved_[i]); |
| } |
| // Resolve unresolved variables for inner scopes. |
| for (int i = 0; i < inner_scopes_.length(); i++) { |
| - inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context); |
| + inner_scopes_[i]->ResolveVariablesRecursively(global_scope); |
| } |
| } |