Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, | 217 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, |
| 218 Scope* global_scope) { | 218 Scope* global_scope) { |
| 219 // Reconstruct the outer scope chain from a closure's context chain. | 219 // Reconstruct the outer scope chain from a closure's context chain. |
| 220 ASSERT(!info->closure().is_null()); | 220 ASSERT(!info->closure().is_null()); |
| 221 Context* context = info->closure()->context(); | 221 Context* context = info->closure()->context(); |
| 222 Scope* current_scope = NULL; | 222 Scope* current_scope = NULL; |
| 223 Scope* innermost_scope = NULL; | 223 Scope* innermost_scope = NULL; |
| 224 bool contains_with = false; | 224 bool contains_with = false; |
| 225 while (!context->IsGlobalContext()) { | 225 while (!context->IsGlobalContext()) { |
| 226 if (context->IsWithContext()) { | 226 if (context->IsWithContext()) { |
| 227 Scope* with_scope = new Scope(WITH_SCOPE); | |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Make the constructor take the current scope and ca
Steven
2011/09/15 19:54:06
There's already such a constructor that is used du
| |
| 228 with_scope->AddInnerScope(current_scope); | |
| 229 current_scope = with_scope; | |
| 227 // All the inner scopes are inside a with. | 230 // All the inner scopes are inside a with. |
| 228 contains_with = true; | 231 contains_with = true; |
| 229 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { | 232 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { |
| 230 s->scope_inside_with_ = true; | 233 s->scope_inside_with_ = true; |
| 231 } | 234 } |
| 235 } else if (context->IsFunctionContext()) { | |
| 236 SerializedScopeInfo* scope_info = | |
| 237 context->closure()->shared()->scope_info(); | |
| 238 current_scope = new Scope(current_scope, FUNCTION_SCOPE, | |
| 239 Handle<SerializedScopeInfo>(scope_info)); | |
| 240 } else if (context->IsBlockContext()) { | |
| 241 SerializedScopeInfo* scope_info = | |
| 242 SerializedScopeInfo::cast(context->extension()); | |
| 243 current_scope = new Scope(current_scope, BLOCK_SCOPE, | |
| 244 Handle<SerializedScopeInfo>(scope_info)); | |
| 232 } else { | 245 } else { |
| 233 if (context->IsFunctionContext()) { | 246 ASSERT(context->IsCatchContext()); |
| 234 SerializedScopeInfo* scope_info = | 247 String* name = String::cast(context->extension()); |
| 235 context->closure()->shared()->scope_info(); | 248 current_scope = new Scope(current_scope, Handle<String>(name)); |
| 236 current_scope = new Scope(current_scope, FUNCTION_SCOPE, | |
| 237 Handle<SerializedScopeInfo>(scope_info)); | |
| 238 } else if (context->IsBlockContext()) { | |
| 239 SerializedScopeInfo* scope_info = | |
| 240 SerializedScopeInfo::cast(context->extension()); | |
| 241 current_scope = new Scope(current_scope, BLOCK_SCOPE, | |
| 242 Handle<SerializedScopeInfo>(scope_info)); | |
| 243 } else { | |
| 244 ASSERT(context->IsCatchContext()); | |
| 245 String* name = String::cast(context->extension()); | |
| 246 current_scope = new Scope(current_scope, Handle<String>(name)); | |
| 247 } | |
| 248 if (contains_with) current_scope->RecordWithStatement(); | |
| 249 if (innermost_scope == NULL) innermost_scope = current_scope; | |
| 250 } | 249 } |
| 250 if (contains_with) current_scope->RecordWithStatement(); | |
| 251 if (innermost_scope == NULL) innermost_scope = current_scope; | |
| 251 | 252 |
| 252 // Forget about a with when we move to a context for a different function. | 253 // Forget about a with when we move to a context for a different function. |
| 253 if (context->previous()->closure() != context->closure()) { | 254 if (context->previous()->closure() != context->closure()) { |
| 254 contains_with = false; | 255 contains_with = false; |
| 255 } | 256 } |
| 256 context = context->previous(); | 257 context = context->previous(); |
| 257 } | 258 } |
| 258 | 259 |
| 259 global_scope->AddInnerScope(current_scope); | 260 global_scope->AddInnerScope(current_scope); |
| 260 return (innermost_scope == NULL) ? global_scope : innermost_scope; | 261 return (innermost_scope == NULL) ? global_scope : innermost_scope; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 } | 294 } |
| 294 | 295 |
| 295 // Declare convenience variables. | 296 // Declare convenience variables. |
| 296 // Declare and allocate receiver (even for the global scope, and even | 297 // Declare and allocate receiver (even for the global scope, and even |
| 297 // if naccesses_ == 0). | 298 // if naccesses_ == 0). |
| 298 // NOTE: When loading parameters in the global scope, we must take | 299 // NOTE: When loading parameters in the global scope, we must take |
| 299 // care not to access them as properties of the global object, but | 300 // care not to access them as properties of the global object, but |
| 300 // instead load them directly from the stack. Currently, the only | 301 // instead load them directly from the stack. Currently, the only |
| 301 // such parameter is 'this' which is passed on the stack when | 302 // such parameter is 'this' which is passed on the stack when |
| 302 // invoking scripts | 303 // invoking scripts |
| 303 if (is_catch_scope() || is_block_scope()) { | 304 if (is_catch_scope() || is_block_scope() || is_with_scope()) { |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Flip the condition and use:
if (is_declaration_sc
Steven
2011/09/15 19:54:06
Done.
| |
| 304 ASSERT(outer_scope() != NULL); | 305 ASSERT(outer_scope() != NULL); |
| 305 receiver_ = outer_scope()->receiver(); | 306 receiver_ = outer_scope()->receiver(); |
| 306 } else { | 307 } else { |
| 307 ASSERT(is_function_scope() || | 308 ASSERT(is_function_scope() || |
| 308 is_global_scope() || | 309 is_global_scope() || |
| 309 is_eval_scope()); | 310 is_eval_scope()); |
| 310 Variable* var = | 311 Variable* var = |
| 311 variables_.Declare(this, | 312 variables_.Declare(this, |
| 312 isolate_->factory()->this_symbol(), | 313 isolate_->factory()->this_symbol(), |
| 313 Variable::VAR, | 314 Variable::VAR, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 501 } | 502 } |
| 502 | 503 |
| 503 | 504 |
| 504 Declaration* Scope::CheckConflictingVarDeclarations() { | 505 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 505 int length = decls_.length(); | 506 int length = decls_.length(); |
| 506 for (int i = 0; i < length; i++) { | 507 for (int i = 0; i < length; i++) { |
| 507 Declaration* decl = decls_[i]; | 508 Declaration* decl = decls_[i]; |
| 508 if (decl->mode() != Variable::VAR) continue; | 509 if (decl->mode() != Variable::VAR) continue; |
| 509 Handle<String> name = decl->proxy()->name(); | 510 Handle<String> name = decl->proxy()->name(); |
| 510 bool cond = true; | 511 bool cond = true; |
| 511 for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) { | 512 for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) { |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
I found the logic of this loop too complicated. Y
Steven
2011/09/15 19:54:06
Done.
| |
| 512 // There is a conflict if there exists a non-VAR binding. | 513 // There is a conflict if there exists a non-VAR binding. |
| 513 Variable* other_var = scope->variables_.Lookup(name); | 514 Variable* other_var = scope->variables_.Lookup(name); |
| 514 if (other_var != NULL && other_var->mode() != Variable::VAR) { | 515 if (other_var != NULL && other_var->mode() != Variable::VAR) { |
| 515 return decl; | 516 return decl; |
| 516 } | 517 } |
| 517 | 518 |
| 518 // Include declaration scope in the iteration but stop after. | 519 // Include declaration scope in the iteration but stop after. |
| 519 if (!scope->is_block_scope() && !scope->is_catch_scope()) cond = false; | 520 if (scope->is_declaration_scope()) cond = false; |
| 520 } | 521 } |
| 521 } | 522 } |
| 522 return NULL; | 523 return NULL; |
| 523 } | 524 } |
| 524 | 525 |
| 525 | 526 |
| 526 template<class Allocator> | 527 template<class Allocator> |
| 527 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { | 528 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { |
| 528 // Collect variables in this scope. | 529 // Collect variables in this scope. |
| 529 // Note that the function_ variable - if present - is not | 530 // Note that the function_ variable - if present - is not |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 for (Scope* s = this; s != scope; s = s->outer_scope_) { | 621 for (Scope* s = this; s != scope; s = s->outer_scope_) { |
| 621 ASSERT(s != NULL); // scope must be in the scope chain | 622 ASSERT(s != NULL); // scope must be in the scope chain |
| 622 if (s->num_heap_slots() > 0) n++; | 623 if (s->num_heap_slots() > 0) n++; |
| 623 } | 624 } |
| 624 return n; | 625 return n; |
| 625 } | 626 } |
| 626 | 627 |
| 627 | 628 |
| 628 Scope* Scope::DeclarationScope() { | 629 Scope* Scope::DeclarationScope() { |
| 629 Scope* scope = this; | 630 Scope* scope = this; |
| 630 while (scope->is_catch_scope() || | 631 while (!scope->is_declaration_scope()) { |
| 631 scope->is_block_scope()) { | |
| 632 scope = scope->outer_scope(); | 632 scope = scope->outer_scope(); |
| 633 } | 633 } |
| 634 return scope; | 634 return scope; |
| 635 } | 635 } |
| 636 | 636 |
| 637 | 637 |
| 638 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { | 638 Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() { |
| 639 if (scope_info_.is_null()) { | 639 if (scope_info_.is_null()) { |
| 640 scope_info_ = SerializedScopeInfo::Create(this); | 640 scope_info_ = SerializedScopeInfo::Create(this); |
| 641 } | 641 } |
| 642 return scope_info_; | 642 return scope_info_; |
| 643 } | 643 } |
| 644 | 644 |
| 645 | 645 |
| 646 #ifdef DEBUG | 646 #ifdef DEBUG |
| 647 static const char* Header(Scope::Type type) { | 647 static const char* Header(Scope::Type type) { |
| 648 switch (type) { | 648 switch (type) { |
| 649 case Scope::EVAL_SCOPE: return "eval"; | 649 case Scope::EVAL_SCOPE: return "eval"; |
| 650 case Scope::FUNCTION_SCOPE: return "function"; | 650 case Scope::FUNCTION_SCOPE: return "function"; |
| 651 case Scope::GLOBAL_SCOPE: return "global"; | 651 case Scope::GLOBAL_SCOPE: return "global"; |
| 652 case Scope::CATCH_SCOPE: return "catch"; | 652 case Scope::CATCH_SCOPE: return "catch"; |
| 653 case Scope::BLOCK_SCOPE: return "block"; | 653 case Scope::BLOCK_SCOPE: return "block"; |
| 654 case Scope::WITH_SCOPE: return "with"; | |
| 654 } | 655 } |
| 655 UNREACHABLE(); | 656 UNREACHABLE(); |
| 656 return NULL; | 657 return NULL; |
| 657 } | 658 } |
| 658 | 659 |
| 659 | 660 |
| 660 static void Indent(int n, const char* str) { | 661 static void Indent(int n, const char* str) { |
| 661 PrintF("%*s%s", n, "", str); | 662 PrintF("%*s%s", n, "", str); |
| 662 } | 663 } |
| 663 | 664 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 if (var == NULL) { | 805 if (var == NULL) { |
| 805 // Declare a new non-local. | 806 // Declare a new non-local. |
| 806 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 807 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
| 807 // Allocate it by giving it a dynamic lookup. | 808 // Allocate it by giving it a dynamic lookup. |
| 808 var->AllocateTo(Variable::LOOKUP, -1); | 809 var->AllocateTo(Variable::LOOKUP, -1); |
| 809 } | 810 } |
| 810 return var; | 811 return var; |
| 811 } | 812 } |
| 812 | 813 |
| 813 | 814 |
| 814 // Lookup a variable starting with this scope. The result is either | 815 Scope::LookupResult Scope::LookupRecursive(Handle<String> name, |
| 815 // the statically resolved variable belonging to an outer scope, or | 816 bool from_inner_scope, |
| 816 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 817 Variable** var) { |
| 817 // because the variable is just a guess (and may be shadowed by | 818 // Try to find the variable in this scope. |
| 818 // another variable that is introduced dynamically via an 'eval' call | 819 *var = LocalLookup(name); |
| 819 // or a 'with' statement). | |
| 820 Variable* Scope::LookupRecursive(Handle<String> name, | |
| 821 bool from_inner_scope, | |
| 822 Variable** invalidated_local) { | |
| 823 // If we find a variable, but the current scope calls 'eval', the found | |
| 824 // variable may not be the correct one (the 'eval' may introduce a | |
| 825 // property with the same name). In that case, remember that the variable | |
| 826 // found is just a guess. | |
| 827 bool guess = scope_calls_eval_; | |
| 828 | 820 |
| 829 // Try to find the variable in this scope. | 821 if (*var != NULL) { |
| 830 Variable* var = LocalLookup(name); | 822 // We found a variable and we are done. (Even if there is an 'eval' in this |
| 823 // scope which introduces the same variable again, the resulting variable | |
| 824 // remains the same.) | |
| 831 | 825 |
| 832 if (var != NULL) { | 826 // If this is a lookup from an inner scope, mark the variable. |
| 833 // We found a variable. If this is not an inner lookup, we are done. | 827 if (from_inner_scope) { |
| 834 // (Even if there is an 'eval' in this scope which introduces the | 828 (*var)->MarkAsAccessedFromInnerScope(); |
|
Kevin Millikin (Chromium)
2011/09/16 05:23:21
This is annoying to check here. Isn't it possible
Steven
2011/09/16 10:48:14
Sure, done.
On 2011/09/16 05:23:21, Kevin Millikin
| |
| 835 // same variable again, the resulting variable remains the same. | |
| 836 // Note that enclosing 'with' statements are handled at the call site.) | |
| 837 if (!from_inner_scope) | |
| 838 return var; | |
| 839 | |
| 840 } else { | |
| 841 // We did not find a variable locally. Check against the function variable, | |
| 842 // if any. We can do this for all scopes, since the function variable is | |
| 843 // only present - if at all - for function scopes. | |
| 844 // | |
| 845 // This lookup corresponds to a lookup in the "intermediate" scope sitting | |
| 846 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | |
| 847 // the name of named function literal is kept in an intermediate scope | |
| 848 // in between this scope and the next outer scope.) | |
| 849 if (function_ != NULL && function_->name().is_identical_to(name)) { | |
| 850 var = function_->var(); | |
| 851 | |
| 852 } else if (outer_scope_ != NULL) { | |
| 853 var = outer_scope_->LookupRecursive(name, true, invalidated_local); | |
| 854 // We may have found a variable in an outer scope. However, if | |
| 855 // the current scope is inside a 'with', the actual variable may | |
| 856 // be a property introduced via the 'with' statement. Then, the | |
| 857 // variable we may have found is just a guess. | |
| 858 if (scope_inside_with_) | |
| 859 guess = true; | |
| 860 } | 829 } |
| 861 | 830 |
| 862 // If we did not find a variable, we are done. | 831 if (is_global_scope()) return GLOBAL; |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
return is_global_scope() ? GLOBAL : FOUND;
Though
Steven
2011/09/15 19:54:06
We need to distinguish locally bound variables fro
Kevin Millikin (Chromium)
2011/09/16 05:23:21
That's what I'm asking about.
The old code will r
Steven
2011/09/16 10:48:14
Yes, I'm sorry you're right. The old code only thr
| |
| 863 if (var == NULL) | 832 return FOUND; |
| 864 return NULL; | |
| 865 } | 833 } |
| 866 | 834 |
| 867 ASSERT(var != NULL); | 835 // We did not find a variable locally. Check against the function variable, |
| 868 | 836 // if any. We can do this for all scopes, since the function variable is |
| 869 // If this is a lookup from an inner scope, mark the variable. | 837 // only present - if at all - for function scopes. |
| 870 if (from_inner_scope) { | 838 // |
| 871 var->MarkAsAccessedFromInnerScope(); | 839 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| 840 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | |
| 841 // the name of named function literal is kept in an intermediate scope | |
| 842 // in between this scope and the next outer scope.) | |
| 843 LookupResult result = GLOBAL; | |
| 844 if (function_ != NULL && function_->name().is_identical_to(name)) { | |
| 845 *var = function_->var(); | |
| 846 if (from_inner_scope) { | |
| 847 (*var)->MarkAsAccessedFromInnerScope(); | |
| 848 } | |
| 849 result = FOUND; | |
| 850 } else if (outer_scope_ != NULL) { | |
| 851 result = outer_scope_->LookupRecursive(name, true, var); | |
| 872 } | 852 } |
| 873 | 853 |
| 874 // If the variable we have found is just a guess, invalidate the | 854 // We may have found a variable in an outer scope. However, if the current |
| 875 // result. If the found variable is local, record that fact so we | 855 // scope is a 'with' scope, the actual variable may be a property introduced |
| 876 // can generate fast code to get it if it is not shadowed by eval. | 856 // via the 'with' statement. Then, the variable we may have found is just a |
| 877 if (guess) { | 857 // guess. |
| 878 if (!var->is_global()) *invalidated_local = var; | 858 // Note that we must do a lookup in the outer scope anyway, because if we find |
| 879 var = NULL; | 859 // one, we must mark that variable as potentially accessed from inside of an |
| 880 } | 860 // inner with scope (the property may not be in the 'with' object). |
| 861 if (is_with_scope()) return FOUND_WITH; | |
| 881 | 862 |
| 882 return var; | 863 // If we have found a variable in an outer scope, but the current scope calls |
| 864 // 'eval', the found variable may not be the correct one (the 'eval' may | |
| 865 // introduce a property with the same name). In that case, remember that the | |
| 866 // variable found is just a guess. | |
| 867 if (result == FOUND && scope_calls_eval_) return FOUND_EVAL; | |
| 868 | |
| 869 return result; | |
| 883 } | 870 } |
| 884 | 871 |
| 885 | 872 |
| 886 void Scope::ResolveVariable(Scope* global_scope, | 873 void Scope::ResolveVariable(Scope* global_scope, |
| 887 Handle<Context> context, | 874 Handle<Context> context, |
| 888 VariableProxy* proxy) { | 875 VariableProxy* proxy) { |
| 889 ASSERT(global_scope == NULL || global_scope->is_global_scope()); | 876 ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| 890 | 877 |
| 891 // If the proxy is already resolved there's nothing to do | 878 // If the proxy is already resolved there's nothing to do |
| 892 // (functions and consts may be resolved by the parser). | 879 // (functions and consts may be resolved by the parser). |
| 893 if (proxy->var() != NULL) return; | 880 if (proxy->var() != NULL) return; |
| 894 | 881 |
| 895 // Otherwise, try to resolve the variable. | 882 // Otherwise, try to resolve the variable. |
| 896 Variable* invalidated_local = NULL; | 883 Variable* var = NULL; |
| 897 Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local); | 884 LookupResult result = LookupRecursive(proxy->name(), false, &var); |
| 898 | 885 |
| 899 if (proxy->inside_with()) { | 886 switch (result) { |
| 900 // If we are inside a local 'with' statement, all bets are off | 887 case FOUND: |
| 901 // and we cannot resolve the proxy to a local variable even if | 888 break; |
| 902 // we found an outer matching variable. | |
| 903 // Note that we must do a lookup anyway, because if we find one, | |
| 904 // we must mark that variable as potentially accessed from this | |
| 905 // inner scope (the property may not be in the 'with' object). | |
| 906 var = NonLocal(proxy->name(), Variable::DYNAMIC); | |
| 907 | 889 |
| 908 } else { | 890 case FOUND_WITH: |
| 909 // We are not inside a local 'with' statement. | 891 // If we are inside a local 'with' statement, all bets are off |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
I lot of these comments are confusing and should b
Steven
2011/09/15 19:54:06
I cleaned them up. PTAL.
On 2011/09/15 09:38:13, K
| |
| 892 // and we cannot resolve the proxy to a local variable even if | |
| 893 // we found an outer matching variable. | |
| 894 var = NonLocal(proxy->name(), Variable::DYNAMIC); | |
| 895 break; | |
| 910 | 896 |
| 911 if (var == NULL) { | 897 case FOUND_EVAL: { |
| 898 // No with statements are involved and we found a local variable | |
| 899 // that might be shadowed by eval introduced variables. | |
| 900 Variable* invalidated_local = var; | |
| 901 var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL); | |
| 902 var->set_local_if_not_shadowed(invalidated_local); | |
| 903 break; | |
| 904 } | |
| 905 | |
| 906 case GLOBAL: | |
| 912 // We did not find the variable. We have a global variable | 907 // We did not find the variable. We have a global variable |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Or we did find it, and it was in the global scope.
Steven
2011/09/15 19:54:06
Eval in the global scope can't introduce shadowed
Kevin Millikin (Chromium)
2011/09/16 05:23:21
Yes, I know. Perhaps the names are a just bit off
Steven
2011/09/16 10:48:14
For BOUND it does indeed not matter much if the va
| |
| 913 // if we are in the global scope (we know already that we | 908 // if we are in the global scope (we know already that we |
| 914 // are outside a 'with' statement) or if there is no way | 909 // are outside a 'with' statement) or if there is no way |
| 915 // that the variable might be introduced dynamically (through | 910 // that the variable might be introduced dynamically (through |
| 916 // a local or outer eval() call, or an outer 'with' statement), | 911 // a local or outer eval() call, or an outer 'with' statement), |
| 917 // or we don't know about the outer scope (because we are | 912 // or we don't know about the outer scope (because we are |
| 918 // in an eval scope). | 913 // in an eval scope). |
| 919 if (is_global_scope() || | 914 if (is_global_scope() || |
| 920 !(scope_inside_with_ || outer_scope_is_eval_scope_ || | 915 !(scope_inside_with_ || outer_scope_is_eval_scope_ || |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Is all this junk still necessary? If we got GLOBA
Steven
2011/09/15 19:54:06
Not necessary anymore.
On 2011/09/15 09:38:13, Kev
| |
| 921 scope_calls_eval_ || outer_scope_calls_eval_)) { | 916 scope_calls_eval_ || outer_scope_calls_eval_)) { |
| 922 // We must have a global variable. | 917 // We must have a global variable. |
| 923 ASSERT(global_scope != NULL); | 918 ASSERT(global_scope != NULL); |
| 924 var = global_scope->DeclareGlobal(proxy->name()); | 919 var = global_scope->DeclareGlobal(proxy->name()); |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Is it right to (re)declare this variable even in t
Steven
2011/09/15 19:54:06
I think it matched the old behaviour, but now I av
| |
| 925 | 920 |
| 926 } else if (scope_inside_with_) { | 921 } else if (scope_inside_with_) { |
| 927 // If we are inside a with statement we give up and look up | 922 // If we are inside a with statement we give up and look up |
| 928 // the variable at runtime. | 923 // the variable at runtime. |
| 924 ASSERT(false); | |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
Just get rid of this case completely and assert !s
Steven
2011/09/15 19:54:06
Sorry, this is dead code I forgot to delete.
On 20
| |
| 929 var = NonLocal(proxy->name(), Variable::DYNAMIC); | 925 var = NonLocal(proxy->name(), Variable::DYNAMIC); |
| 930 | 926 |
| 931 } else if (invalidated_local != NULL) { | |
| 932 // No with statements are involved and we found a local | |
| 933 // variable that might be shadowed by eval introduced | |
| 934 // variables. | |
| 935 var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL); | |
| 936 var->set_local_if_not_shadowed(invalidated_local); | |
| 937 | |
| 938 } else if (outer_scope_is_eval_scope_) { | 927 } else if (outer_scope_is_eval_scope_) { |
|
Kevin Millikin (Chromium)
2011/09/15 09:38:13
It would be great if we could get rid of this flag
Steven
2011/09/15 19:54:06
Got rid of the flag, but still need the propagate
| |
| 939 // No with statements and we did not find a local and the code | 928 // No with statements and we did not find a local and the code |
| 940 // is executed with a call to eval. The context contains | 929 // is executed with a call to eval. The context contains |
| 941 // scope information that we can use to determine if the | 930 // scope information that we can use to determine if the |
| 942 // variable is global if it is not shadowed by eval-introduced | 931 // variable is global if it is not shadowed by eval-introduced |
| 943 // variables. | 932 // variables. |
| 944 if (context->GlobalIfNotShadowedByEval(proxy->name())) { | 933 if (context->GlobalIfNotShadowedByEval(proxy->name())) { |
| 945 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); | 934 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); |
| 946 | |
| 947 } else { | 935 } else { |
| 948 var = NonLocal(proxy->name(), Variable::DYNAMIC); | 936 var = NonLocal(proxy->name(), Variable::DYNAMIC); |
| 949 } | 937 } |
| 950 | 938 |
| 951 } else { | 939 } else { |
| 952 // No with statements and we did not find a local and the code | 940 // No with statements and we did not find a local and the code |
| 953 // is not executed with a call to eval. We know that this | 941 // is not executed with a call to eval. We know that this |
| 954 // variable is global unless it is shadowed by eval-introduced | 942 // variable is global unless it is shadowed by eval-introduced |
| 955 // variables. | 943 // variables. |
| 956 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); | 944 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); |
| 957 } | 945 } |
| 958 } | 946 break; |
| 959 } | 947 } |
| 960 | 948 |
| 949 ASSERT(var != NULL); | |
| 961 proxy->BindTo(var); | 950 proxy->BindTo(var); |
| 962 } | 951 } |
| 963 | 952 |
| 964 | 953 |
| 965 void Scope::ResolveVariablesRecursively(Scope* global_scope, | 954 void Scope::ResolveVariablesRecursively(Scope* global_scope, |
| 966 Handle<Context> context) { | 955 Handle<Context> context) { |
| 967 ASSERT(global_scope == NULL || global_scope->is_global_scope()); | 956 ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| 968 | 957 |
| 969 // Resolve unresolved variables for this scope. | 958 // Resolve unresolved variables for this scope. |
| 970 for (int i = 0; i < unresolved_.length(); i++) { | 959 for (int i = 0; i < unresolved_.length(); i++) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1199 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1188 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 1200 !must_have_local_context) { | 1189 !must_have_local_context) { |
| 1201 num_heap_slots_ = 0; | 1190 num_heap_slots_ = 0; |
| 1202 } | 1191 } |
| 1203 | 1192 |
| 1204 // Allocation done. | 1193 // Allocation done. |
| 1205 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1194 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1206 } | 1195 } |
| 1207 | 1196 |
| 1208 } } // namespace v8::internal | 1197 } } // namespace v8::internal |
| OLD | NEW |