Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index 390a0b6e11ba8f1ccd4081fda789f582c8bc1554..84a02f0bdbe25425c1230ff4d4db5a584dcce4ba 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -146,7 +146,7 @@ Scope::Scope(Scope* outer_scope, Type type) |
} |
-Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info) |
+Scope::Scope(Scope* inner_scope, Type type, Handle<SerializedScopeInfo> scope_info) |
: isolate_(Isolate::Current()), |
inner_scopes_(4), |
variables_(), |
@@ -156,7 +156,7 @@ Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info) |
decls_(4), |
already_resolved_(true) { |
ASSERT(!scope_info.is_null()); |
- SetDefaults(FUNCTION_SCOPE, NULL, scope_info); |
+ SetDefaults(type, NULL, scope_info); |
if (scope_info->HasHeapAllocatedLocals()) { |
num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
} |
@@ -232,8 +232,13 @@ Scope* Scope::DeserializeScopeChain(CompilationInfo* info, |
if (context->IsFunctionContext()) { |
SerializedScopeInfo* scope_info = |
context->closure()->shared()->scope_info(); |
- current_scope = |
- new Scope(current_scope, Handle<SerializedScopeInfo>(scope_info)); |
+ current_scope = new Scope(current_scope, FUNCTION_SCOPE, |
+ Handle<SerializedScopeInfo>(scope_info)); |
+ } else if (context->IsBlockContext()) { |
+ SerializedScopeInfo* scope_info = |
+ SerializedScopeInfo::cast(context->extension()); |
+ current_scope = new Scope(current_scope, BLOCK_SCOPE, |
+ Handle<SerializedScopeInfo>(scope_info)); |
} else { |
ASSERT(context->IsCatchContext()); |
String* name = String::cast(context->extension()); |
@@ -294,10 +299,13 @@ void Scope::Initialize(bool inside_with) { |
// instead load them directly from the stack. Currently, the only |
// such parameter is 'this' which is passed on the stack when |
// invoking scripts |
- if (is_catch_scope()) { |
+ if (is_catch_scope() || is_block_scope()) { |
ASSERT(outer_scope() != NULL); |
receiver_ = outer_scope()->receiver(); |
} else { |
+ ASSERT(is_function_scope() || |
+ is_global_scope() || |
+ is_eval_scope()); |
Variable* var = |
variables_.Declare(this, |
isolate_->factory()->this_symbol(), |
@@ -559,13 +567,22 @@ int Scope::ContextChainLength(Scope* scope) { |
Scope* Scope::DeclarationScope() { |
Scope* scope = this; |
- while (scope->is_catch_scope()) { |
+ while (scope->is_catch_scope() || |
+ scope->is_block_scope()) { |
scope = scope->outer_scope(); |
} |
return scope; |
} |
+Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { |
+ if (scope_info_.is_null()) { |
+ scope_info_ = SerializedScopeInfo::Create(this); |
+ } |
+ return scope_info_; |
+} |
+ |
+ |
#ifdef DEBUG |
static const char* Header(Scope::Type type) { |
switch (type) { |
@@ -573,6 +590,7 @@ static const char* Header(Scope::Type type) { |
case Scope::FUNCTION_SCOPE: return "function"; |
case Scope::GLOBAL_SCOPE: return "global"; |
case Scope::CATCH_SCOPE: return "catch"; |
+ case Scope::BLOCK_SCOPE: return "block"; |
} |
UNREACHABLE(); |
return NULL; |
@@ -753,7 +771,10 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
var = function_; |
} else if (outer_scope_ != NULL) { |
- var = outer_scope_->LookupRecursive(name, true, invalidated_local); |
+ var = outer_scope_->LookupRecursive( |
+ name, |
+ is_block_scope() || is_catch_scope() ? inner_lookup : true, |
Kevin Millikin (Chromium)
2011/08/10 11:19:27
This is subtle. I'd probably change all the ident
Steven
2011/08/10 12:21:00
Done.
|
+ invalidated_local); |
// We may have found a variable in an outer scope. However, if |
// the current scope is inside a 'with', the actual variable may |
// be a property introduced via the 'with' statement. Then, the |
@@ -926,7 +947,8 @@ bool Scope::MustAllocate(Variable* var) { |
scope_calls_eval_ || |
inner_scope_calls_eval_ || |
scope_contains_with_ || |
- is_catch_scope())) { |
+ is_catch_scope() || |
+ is_block_scope())) { |
var->set_is_used(true); |
} |
// Global variables do not need to be allocated. |
@@ -943,7 +965,7 @@ bool Scope::MustAllocateInContext(Variable* var) { |
// Exceptions: temporary variables are never allocated in a context; |
// catch-bound variables are always allocated in a context. |
if (var->mode() == Variable::TEMPORARY) return false; |
- if (is_catch_scope()) return true; |
+ if (is_catch_scope() || is_block_scope()) return true; |
return var->is_accessed_from_inner_scope() || |
scope_calls_eval_ || |
inner_scope_calls_eval_ || |