| 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();
|
|
|