| Index: src/scopes.cc
|
| diff --git a/src/scopes.cc b/src/scopes.cc
|
| index c20c85214f014b9ac033db8eee8820deb10af056..29712de6a8e04d0ab8e00567584ada6ef4c55011 100644
|
| --- a/src/scopes.cc
|
| +++ b/src/scopes.cc
|
| @@ -119,9 +119,9 @@ Scope::Scope(Type type)
|
| temps_(0),
|
| params_(0),
|
| unresolved_(0),
|
| - decls_(0) {
|
| + decls_(0),
|
| + already_resolved_(false) {
|
| SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
|
| - ASSERT(!resolved());
|
| }
|
|
|
|
|
| @@ -131,14 +131,14 @@ Scope::Scope(Scope* outer_scope, Type type)
|
| temps_(4),
|
| params_(4),
|
| unresolved_(16),
|
| - decls_(4) {
|
| + decls_(4),
|
| + already_resolved_(false) {
|
| SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
|
| // 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(!HasIllegalRedeclaration());
|
| - ASSERT(!resolved());
|
| }
|
|
|
|
|
| @@ -148,15 +148,34 @@ Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
|
| temps_(4),
|
| params_(4),
|
| unresolved_(16),
|
| - decls_(4) {
|
| + decls_(4),
|
| + already_resolved_(true) {
|
| ASSERT(!scope_info.is_null());
|
| SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
|
| - ASSERT(resolved());
|
| if (scope_info->HasHeapAllocatedLocals()) {
|
| num_heap_slots_ = scope_info_->NumberOfContextSlots();
|
| }
|
| + AddInnerScope(inner_scope);
|
| +}
|
| +
|
|
|
| +Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
|
| + : inner_scopes_(1),
|
| + variables_(),
|
| + temps_(0),
|
| + params_(0),
|
| + unresolved_(0),
|
| + decls_(0),
|
| + already_resolved_(true) {
|
| + SetDefaults(CATCH_SCOPE, NULL, Handle<SerializedScopeInfo>::null());
|
| AddInnerScope(inner_scope);
|
| + ++num_var_or_const_;
|
| + Variable* variable = variables_.Declare(this,
|
| + catch_variable_name,
|
| + Variable::VAR,
|
| + true, // Valid left-hand side.
|
| + Variable::NORMAL);
|
| + AllocateHeapSlot(variable);
|
| }
|
|
|
|
|
| @@ -190,30 +209,43 @@ void Scope::SetDefaults(Type type,
|
|
|
| Scope* Scope::DeserializeScopeChain(CompilationInfo* info,
|
| Scope* global_scope) {
|
| + // Reconstruct the outer scope chain from a closure's context chain.
|
| ASSERT(!info->closure().is_null());
|
| - // If we have a serialized scope info, reuse it.
|
| + Context* context = info->closure()->context();
|
| + Scope* current_scope = NULL;
|
| Scope* innermost_scope = NULL;
|
| - Scope* scope = NULL;
|
| -
|
| - SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
|
| - if (scope_info != SerializedScopeInfo::Empty()) {
|
| - JSFunction* current = *info->closure();
|
| - do {
|
| - current = current->context()->closure();
|
| - Handle<SerializedScopeInfo> scope_info(current->shared()->scope_info());
|
| - if (*scope_info != SerializedScopeInfo::Empty()) {
|
| - scope = new Scope(scope, scope_info);
|
| - if (innermost_scope == NULL) innermost_scope = scope;
|
| + bool contains_with = false;
|
| + while (!context->IsGlobalContext()) {
|
| + if (context->IsWithContext()) {
|
| + // All the inner scopes are inside a with.
|
| + contains_with = true;
|
| + for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
|
| + s->scope_inside_with_ = true;
|
| + }
|
| + } else {
|
| + if (context->IsFunctionContext()) {
|
| + SerializedScopeInfo* scope_info =
|
| + context->closure()->shared()->scope_info();
|
| + current_scope =
|
| + new Scope(current_scope, Handle<SerializedScopeInfo>(scope_info));
|
| } else {
|
| - ASSERT(current->context()->IsGlobalContext());
|
| + ASSERT(context->IsCatchContext());
|
| + String* name = String::cast(context->extension());
|
| + current_scope = new Scope(current_scope, Handle<String>(name));
|
| }
|
| - } while (!current->context()->IsGlobalContext());
|
| - }
|
| + if (contains_with) current_scope->RecordWithStatement();
|
| + if (innermost_scope == NULL) innermost_scope = current_scope;
|
| + }
|
|
|
| - global_scope->AddInnerScope(scope);
|
| - if (innermost_scope == NULL) innermost_scope = global_scope;
|
| + // Forget about a with when we move to a context for a different function.
|
| + if (context->previous()->closure() != context->closure()) {
|
| + contains_with = false;
|
| + }
|
| + context = context->previous();
|
| + }
|
|
|
| - return innermost_scope;
|
| + global_scope->AddInnerScope(current_scope);
|
| + return (innermost_scope == NULL) ? global_scope : innermost_scope;
|
| }
|
|
|
|
|
| @@ -238,7 +270,7 @@ bool Scope::Analyze(CompilationInfo* info) {
|
|
|
|
|
| void Scope::Initialize(bool inside_with) {
|
| - ASSERT(!resolved());
|
| + ASSERT(!already_resolved());
|
|
|
| // Add this scope as a new inner scope of the outer scope.
|
| if (outer_scope_ != NULL) {
|
| @@ -279,11 +311,10 @@ void Scope::Initialize(bool inside_with) {
|
|
|
| Variable* Scope::LocalLookup(Handle<String> name) {
|
| Variable* result = variables_.Lookup(name);
|
| - if (result != NULL || !resolved()) {
|
| + if (result != NULL || scope_info_.is_null()) {
|
| return result;
|
| }
|
| - // If the scope is resolved, we can find a variable in serialized scope
|
| - // info.
|
| + // 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.
|
| @@ -331,7 +362,7 @@ Variable* Scope::DeclareFunctionVar(Handle<String> name) {
|
|
|
|
|
| void Scope::DeclareParameter(Handle<String> name) {
|
| - ASSERT(!resolved());
|
| + ASSERT(!already_resolved());
|
| ASSERT(is_function_scope());
|
| Variable* var =
|
| variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
|
| @@ -340,7 +371,7 @@ void Scope::DeclareParameter(Handle<String> name) {
|
|
|
|
|
| Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
|
| - ASSERT(!resolved());
|
| + ASSERT(!already_resolved());
|
| // This function handles VAR and CONST modes. DYNAMIC variables are
|
| // introduces during variable allocation, INTERNAL variables are allocated
|
| // explicitly, and TEMPORARY variables are allocated via NewTemporary().
|
| @@ -363,7 +394,7 @@ VariableProxy* Scope::NewUnresolved(Handle<String> name,
|
| // Note that we must not share the unresolved variables with
|
| // the same name because they may be removed selectively via
|
| // RemoveUnresolved().
|
| - ASSERT(!resolved());
|
| + ASSERT(!already_resolved());
|
| VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
|
| unresolved_.Add(proxy);
|
| return proxy;
|
| @@ -383,7 +414,7 @@ void Scope::RemoveUnresolved(VariableProxy* var) {
|
|
|
|
|
| Variable* Scope::NewTemporary(Handle<String> name) {
|
| - ASSERT(!resolved());
|
| + ASSERT(!already_resolved());
|
| Variable* var =
|
| new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
|
| temps_.Add(var);
|
| @@ -1022,7 +1053,7 @@ void Scope::AllocateVariablesRecursively() {
|
|
|
| // If scope is already resolved, we still need to allocate
|
| // variables in inner scopes which might not had been resolved yet.
|
| - if (resolved()) return;
|
| + if (already_resolved()) return;
|
| // The number of slots required for variables.
|
| num_stack_slots_ = 0;
|
| num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
|
|
|