Index: src/scopes.cc |
diff --git a/src/scopes.cc b/src/scopes.cc |
index 497f7940adfb3e42963ba21eb0f58b70adae6b5a..a756b50c0e1bfc063017fef17bfb75ffb6d9e244 100644 |
--- a/src/scopes.cc |
+++ b/src/scopes.cc |
@@ -170,6 +170,7 @@ void Scope::SetDefaults(ScopeType scope_type, |
strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; |
outer_scope_calls_sloppy_eval_ = false; |
inner_scope_calls_eval_ = false; |
+ inner_scope_contains_with_ = false; |
force_eager_compilation_ = false; |
force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) |
? outer_scope->has_forced_context_allocation() : false; |
@@ -194,6 +195,7 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, |
Scope* current_scope = NULL; |
Scope* innermost_scope = NULL; |
bool contains_with = false; |
+ bool inner_contains_with = false; |
while (!context->IsNativeContext()) { |
if (context->IsWithContext()) { |
Scope* with_scope = new(zone) Scope(current_scope, |
@@ -236,7 +238,11 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, |
current_scope = new(zone) Scope( |
current_scope, Handle<String>(name), zone); |
} |
- if (contains_with) current_scope->RecordWithStatement(); |
+ if (inner_contains_with) current_scope->inner_scope_contains_with_ = true; |
+ if (contains_with) { |
+ current_scope->RecordWithStatement(); |
+ inner_contains_with = true; |
+ } |
if (innermost_scope == NULL) innermost_scope = current_scope; |
// Forget about a with when we move to a context for a different function. |
@@ -806,9 +812,15 @@ static void PrintVar(int indent, Variable* var) { |
PrintName(var->name()); |
PrintF("; // "); |
PrintLocation(var); |
+ bool comma = !var->IsUnallocated(); |
if (var->has_forced_context_allocation()) { |
- if (!var->IsUnallocated()) PrintF(", "); |
+ if (comma) PrintF(", "); |
PrintF("forced context allocation"); |
+ comma = true; |
+ } |
+ if (var->is_assigned_in_inner_function()) { |
+ if (comma) PrintF(", "); |
+ PrintF("inner assignment"); |
} |
PrintF("\n"); |
} |
@@ -862,6 +874,9 @@ void Scope::Print(int n) { |
} |
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); |
if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); |
+ if (inner_scope_contains_with_) { |
+ Indent(n1, "// inner scope contains 'with'\n"); |
+ } |
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); |
if (outer_scope_calls_sloppy_eval_) { |
Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
@@ -938,7 +953,7 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) { |
} |
-Variable* Scope::LookupRecursive(Handle<String> name, |
+Variable* Scope::LookupRecursive(VariableProxy* proxy, |
BindingKind* binding_kind, |
AstNodeFactory<AstNullVisitor>* factory) { |
ASSERT(binding_kind != NULL); |
@@ -950,7 +965,7 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
} |
// Try to find the variable in this scope. |
- Variable* var = LookupLocal(name); |
+ Variable* var = LookupLocal(proxy->name()); |
// We found a variable and we are done. (Even if there is an 'eval' in |
// this scope which introduces the same variable again, the resulting |
@@ -964,11 +979,11 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
// if any. We can do this for all scopes, since the function variable is |
// only present - if at all - for function scopes. |
*binding_kind = UNBOUND; |
- var = LookupFunctionVar(name, factory); |
+ var = LookupFunctionVar(proxy->name(), factory); |
if (var != NULL) { |
*binding_kind = BOUND; |
} else if (outer_scope_ != NULL) { |
- var = outer_scope_->LookupRecursive(name, binding_kind, factory); |
+ var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); |
if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
var->ForceContextAllocation(); |
} |
@@ -984,6 +999,7 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
// the associated variable has to be marked as potentially being accessed |
// from inside of an inner with scope (the property may not be in the 'with' |
// object). |
+ if (proxy->is_assigned()) var->set_maybe_assigned(); |
*binding_kind = DYNAMIC_LOOKUP; |
return NULL; |
} else if (calls_sloppy_eval()) { |
@@ -1012,7 +1028,7 @@ bool Scope::ResolveVariable(CompilationInfo* info, |
// Otherwise, try to resolve the variable. |
BindingKind binding_kind; |
- Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory); |
+ Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
switch (binding_kind) { |
case BOUND: |
// We found a variable binding. |
@@ -1051,9 +1067,10 @@ bool Scope::ResolveVariable(CompilationInfo* info, |
} |
ASSERT(var != NULL); |
+ if (proxy->is_assigned()) var->set_maybe_assigned(); |
if (FLAG_harmony_scoping && strict_mode() == STRICT && |
- var->is_const_mode() && proxy->IsLValue()) { |
+ var->is_const_mode() && proxy->is_assigned()) { |
// Assignment to const. Throw a syntax error. |
MessageLocation location( |
info->script(), proxy->position(), proxy->position()); |
@@ -1125,7 +1142,7 @@ bool Scope::ResolveVariablesRecursively( |
} |
-bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { |
+void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { |
if (outer_scope_calls_sloppy_eval) { |
outer_scope_calls_sloppy_eval_ = true; |
} |
@@ -1133,16 +1150,18 @@ bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { |
bool calls_sloppy_eval = |
this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; |
for (int i = 0; i < inner_scopes_.length(); i++) { |
- Scope* inner_scope = inner_scopes_[i]; |
- if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) { |
+ Scope* inner = inner_scopes_[i]; |
+ inner->PropagateScopeInfo(calls_sloppy_eval); |
+ if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) { |
inner_scope_calls_eval_ = true; |
} |
- if (inner_scope->force_eager_compilation_) { |
+ if (inner->scope_contains_with_ || inner->inner_scope_contains_with_) { |
+ inner_scope_contains_with_ = true; |
+ } |
+ if (inner->force_eager_compilation_) { |
force_eager_compilation_ = true; |
} |
} |
- |
- return scope_calls_eval_ || inner_scope_calls_eval_; |
} |
@@ -1159,7 +1178,8 @@ bool Scope::MustAllocate(Variable* var) { |
is_block_scope() || |
is_module_scope() || |
is_global_scope())) { |
- var->set_is_used(true); |
+ var->set_is_used(); |
+ if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
} |
// Global variables do not need to be allocated. |
return !var->IsGlobalObjectProperty() && var->is_used(); |