| Index: src/scopes.cc
|
| diff --git a/src/scopes.cc b/src/scopes.cc
|
| index f9cebcddaafff5532c4aac23ab7af06dd9a7c220..2140ee7cb6113350335bc87b6bd9e0d8e8d6e9e7 100644
|
| --- a/src/scopes.cc
|
| +++ b/src/scopes.cc
|
| @@ -129,7 +129,7 @@ Scope::Scope(Scope* outer_scope, ScopeType type)
|
| // At some point we might want to provide outer scopes to
|
| // eval scopes (by walking the stack and reading the scope info).
|
| // In that case, the ASSERT below needs to be adjusted.
|
| - ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
|
| + ASSERT_EQ(type == GLOBAL_SCOPE, outer_scope == NULL);
|
| ASSERT(!HasIllegalRedeclaration());
|
| }
|
|
|
| @@ -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;
|
| @@ -249,26 +254,36 @@ Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
|
| }
|
|
|
| global_scope->AddInnerScope(current_scope);
|
| + global_scope->PropagateScopeInfo(false);
|
| return (innermost_scope == NULL) ? global_scope : innermost_scope;
|
| }
|
|
|
|
|
| bool Scope::Analyze(CompilationInfo* info) {
|
| ASSERT(info->function() != NULL);
|
| - Scope* top = info->function()->scope();
|
| + Scope* scope = info->function()->scope();
|
| + Scope* top = scope;
|
| +
|
| + // When there are unresolved outer scopes, traverse the scope tree up and
|
| + // start scope resolution and variable allocation from the first unresolved
|
| + // ancestor.
|
| + while (!top->is_global_scope() &&
|
| + !top->outer_scope()->already_resolved()) {
|
| + top = top->outer_scope();
|
| + }
|
|
|
| - while (top->outer_scope() != NULL) top = top->outer_scope();
|
| - top->AllocateVariables(info->calling_context());
|
| + // Allocated the variables.
|
| + top->AllocateVariables(info->global_scope());
|
|
|
| #ifdef DEBUG
|
| if (info->isolate()->bootstrapper()->IsActive()
|
| ? FLAG_print_builtin_scopes
|
| : FLAG_print_scopes) {
|
| - info->function()->scope()->Print();
|
| + scope->Print();
|
| }
|
| #endif
|
|
|
| - info->SetScope(info->function()->scope());
|
| + info->SetScope(scope);
|
| return true; // Can not fail.
|
| }
|
|
|
| @@ -356,10 +371,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 +383,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 +398,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,26 +583,18 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
|
| }
|
|
|
|
|
| -void Scope::AllocateVariables(Handle<Context> context) {
|
| - ASSERT(outer_scope_ == NULL); // eval or global scopes only
|
| -
|
| +void Scope::AllocateVariables(Scope* global_scope) {
|
| // 1) Propagate scope information.
|
| - // If we are in an eval scope, we may have other outer scopes about
|
| - // which we don't know anything at this point. Thus we must be conservative
|
| - // and assume they may invoke eval themselves. Eventually we could capture
|
| - // 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);
|
| + if (outer_scope_ != NULL) {
|
| + outer_scope_calls_non_strict_eval =
|
| + outer_scope_->outer_scope_calls_non_strict_eval() |
|
| + outer_scope_->calls_non_strict_eval();
|
| }
|
| PropagateScopeInfo(outer_scope_calls_non_strict_eval);
|
|
|
| // 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 +848,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 +864,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 +886,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 +902,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 +911,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 +952,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);
|
| }
|
| }
|
|
|
| @@ -973,8 +973,7 @@ bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
|
| }
|
|
|
| bool calls_non_strict_eval =
|
| - (scope_calls_eval_ && !is_strict_mode()) ||
|
| - outer_scope_calls_non_strict_eval_;
|
| + this->calls_non_strict_eval() || outer_scope_calls_non_strict_eval_;
|
| for (int i = 0; i < inner_scopes_.length(); i++) {
|
| Scope* inner_scope = inner_scopes_[i];
|
| if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
|
|
|