| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/messages.h" | 9 #include "src/messages.h" |
| 10 #include "src/parser.h" | 10 #include "src/parser.h" |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // Propagate usage flags to outer scope. | 380 // Propagate usage flags to outer scope. |
| 381 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); | 381 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); |
| 382 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); | 382 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); |
| 383 if (uses_this()) outer_scope_->RecordThisUsage(); | 383 if (uses_this()) outer_scope_->RecordThisUsage(); |
| 384 if (scope_calls_eval_) outer_scope_->RecordEvalCall(); | 384 if (scope_calls_eval_) outer_scope_->RecordEvalCall(); |
| 385 | 385 |
| 386 return NULL; | 386 return NULL; |
| 387 } | 387 } |
| 388 | 388 |
| 389 | 389 |
| 390 Variable* Scope::LookupLocal(const AstRawString* name) { | 390 Variable* Scope::LookupLocal(const AstRawString* name, bool parameters_only) { |
| 391 Variable* result = variables_.Lookup(name); | 391 Variable* result = variables_.Lookup(name); |
| 392 if (result != NULL || scope_info_.is_null()) { | 392 if (result != NULL || scope_info_.is_null()) { |
| 393 if (result != NULL && parameters_only && !params_.Contains(result)) { |
| 394 result = NULL; |
| 395 } |
| 393 return result; | 396 return result; |
| 394 } | 397 } |
| 395 Handle<String> name_handle = name->string(); | 398 Handle<String> name_handle = name->string(); |
| 396 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 399 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
| 397 // heap-independent mode, and all strings must be internalized immediately. So | 400 // heap-independent mode, and all strings must be internalized immediately. So |
| 398 // it's ok to get the Handle<String> here. | 401 // it's ok to get the Handle<String> here. |
| 399 // If we have a serialized scope info, we might find the variable there. | 402 // If we have a serialized scope info, we might find the variable there. |
| 400 // There should be no local slot with the given name. | 403 // There should be no local slot with the given name. |
| 401 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); | 404 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); |
| 402 | 405 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 DeclareFunctionVar(declaration); | 449 DeclareFunctionVar(declaration); |
| 447 var->AllocateTo(Variable::CONTEXT, index); | 450 var->AllocateTo(Variable::CONTEXT, index); |
| 448 return var; | 451 return var; |
| 449 } else { | 452 } else { |
| 450 return NULL; | 453 return NULL; |
| 451 } | 454 } |
| 452 } | 455 } |
| 453 | 456 |
| 454 | 457 |
| 455 Variable* Scope::Lookup(const AstRawString* name) { | 458 Variable* Scope::Lookup(const AstRawString* name) { |
| 459 bool parameters_only = false; |
| 456 for (Scope* scope = this; | 460 for (Scope* scope = this; |
| 457 scope != NULL; | 461 scope != NULL; |
| 458 scope = scope->outer_scope()) { | 462 scope = scope->outer_scope()) { |
| 459 Variable* var = scope->LookupLocal(name); | 463 Variable* var = scope->LookupLocal(name, parameters_only); |
| 460 if (var != NULL) return var; | 464 if (var != NULL) return var; |
| 465 |
| 466 // if current scope is a parameter scope, the outer scope must be a |
| 467 // function scope, and should only search the function parameters |
| 468 parameters_only = scope->is_parameter_scope(); |
| 461 } | 469 } |
| 462 return NULL; | 470 return NULL; |
| 463 } | 471 } |
| 464 | 472 |
| 465 | 473 |
| 466 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, | 474 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, |
| 467 bool is_rest, bool* is_duplicate) { | 475 bool is_rest, bool* is_duplicate) { |
| 468 DCHECK(!already_resolved()); | 476 DCHECK(!already_resolved()); |
| 469 DCHECK(is_function_scope()); | 477 DCHECK(is_function_scope()); |
| 470 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, | 478 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 static const char* Header(ScopeType scope_type) { | 820 static const char* Header(ScopeType scope_type) { |
| 813 switch (scope_type) { | 821 switch (scope_type) { |
| 814 case EVAL_SCOPE: return "eval"; | 822 case EVAL_SCOPE: return "eval"; |
| 815 case FUNCTION_SCOPE: return "function"; | 823 case FUNCTION_SCOPE: return "function"; |
| 816 case MODULE_SCOPE: return "module"; | 824 case MODULE_SCOPE: return "module"; |
| 817 case SCRIPT_SCOPE: return "global"; | 825 case SCRIPT_SCOPE: return "global"; |
| 818 case CATCH_SCOPE: return "catch"; | 826 case CATCH_SCOPE: return "catch"; |
| 819 case BLOCK_SCOPE: return "block"; | 827 case BLOCK_SCOPE: return "block"; |
| 820 case WITH_SCOPE: return "with"; | 828 case WITH_SCOPE: return "with"; |
| 821 case ARROW_SCOPE: return "arrow"; | 829 case ARROW_SCOPE: return "arrow"; |
| 830 case PARAMETER_SCOPE: return "parameter"; |
| 822 } | 831 } |
| 823 UNREACHABLE(); | 832 UNREACHABLE(); |
| 824 return NULL; | 833 return NULL; |
| 825 } | 834 } |
| 826 | 835 |
| 827 | 836 |
| 828 static void Indent(int n, const char* str) { | 837 static void Indent(int n, const char* str) { |
| 829 PrintF("%*s%s", n, "", str); | 838 PrintF("%*s%s", n, "", str); |
| 830 } | 839 } |
| 831 | 840 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1006 init_flag); | 1015 init_flag); |
| 1007 // Allocate it by giving it a dynamic lookup. | 1016 // Allocate it by giving it a dynamic lookup. |
| 1008 var->AllocateTo(Variable::LOOKUP, -1); | 1017 var->AllocateTo(Variable::LOOKUP, -1); |
| 1009 } | 1018 } |
| 1010 return var; | 1019 return var; |
| 1011 } | 1020 } |
| 1012 | 1021 |
| 1013 | 1022 |
| 1014 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1023 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
| 1015 BindingKind* binding_kind, | 1024 BindingKind* binding_kind, |
| 1016 AstNodeFactory* factory) { | 1025 AstNodeFactory* factory, |
| 1026 bool parameters_only) { |
| 1017 DCHECK(binding_kind != NULL); | 1027 DCHECK(binding_kind != NULL); |
| 1018 if (already_resolved() && is_with_scope()) { | 1028 if (already_resolved() && is_with_scope()) { |
| 1019 // Short-cut: if the scope is deserialized from a scope info, variable | 1029 // Short-cut: if the scope is deserialized from a scope info, variable |
| 1020 // allocation is already fixed. We can simply return with dynamic lookup. | 1030 // allocation is already fixed. We can simply return with dynamic lookup. |
| 1021 *binding_kind = DYNAMIC_LOOKUP; | 1031 *binding_kind = DYNAMIC_LOOKUP; |
| 1022 return NULL; | 1032 return NULL; |
| 1023 } | 1033 } |
| 1024 | 1034 |
| 1025 // Try to find the variable in this scope. | 1035 // Try to find the variable in this scope. |
| 1026 Variable* var = LookupLocal(proxy->raw_name()); | 1036 Variable* var = LookupLocal(proxy->raw_name(), parameters_only); |
| 1027 | 1037 |
| 1028 // We found a variable and we are done. (Even if there is an 'eval' in | 1038 // We found a variable and we are done. (Even if there is an 'eval' in |
| 1029 // this scope which introduces the same variable again, the resulting | 1039 // this scope which introduces the same variable again, the resulting |
| 1030 // variable remains the same.) | 1040 // variable remains the same.) |
| 1031 if (var != NULL) { | 1041 if (var != NULL) { |
| 1032 *binding_kind = BOUND; | 1042 *binding_kind = BOUND; |
| 1033 return var; | 1043 return var; |
| 1034 } | 1044 } |
| 1035 | 1045 |
| 1036 // We did not find a variable locally. Check against the function variable, | 1046 // We did not find a variable locally. Check against the function variable, |
| 1037 // if any. We can do this for all scopes, since the function variable is | 1047 // if any. We can do this for all scopes, since the function variable is |
| 1038 // only present - if at all - for function scopes. | 1048 // only present - if at all - for function scopes. |
| 1039 *binding_kind = UNBOUND; | 1049 *binding_kind = UNBOUND; |
| 1040 var = LookupFunctionVar(proxy->raw_name(), factory); | 1050 var = LookupFunctionVar(proxy->raw_name(), factory); |
| 1041 if (var != NULL) { | 1051 if (var != NULL) { |
| 1042 *binding_kind = BOUND; | 1052 *binding_kind = BOUND; |
| 1043 } else if (outer_scope_ != NULL) { | 1053 } else if (outer_scope_ != NULL) { |
| 1044 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); | 1054 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, |
| 1055 is_parameter_scope()); |
| 1045 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 1056 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
| 1046 var->ForceContextAllocation(); | 1057 var->ForceContextAllocation(); |
| 1047 } | 1058 } |
| 1048 } else { | 1059 } else { |
| 1049 DCHECK(is_script_scope()); | 1060 DCHECK(is_script_scope()); |
| 1050 } | 1061 } |
| 1051 | 1062 |
| 1052 if (is_with_scope()) { | 1063 if (is_with_scope()) { |
| 1053 DCHECK(!already_resolved()); | 1064 DCHECK(!already_resolved()); |
| 1054 // The current scope is a with scope, so the variable binding can not be | 1065 // The current scope is a with scope, so the variable binding can not be |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1078 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, | 1089 bool Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, |
| 1079 AstNodeFactory* factory) { | 1090 AstNodeFactory* factory) { |
| 1080 DCHECK(info->script_scope()->is_script_scope()); | 1091 DCHECK(info->script_scope()->is_script_scope()); |
| 1081 | 1092 |
| 1082 // If the proxy is already resolved there's nothing to do | 1093 // If the proxy is already resolved there's nothing to do |
| 1083 // (functions and consts may be resolved by the parser). | 1094 // (functions and consts may be resolved by the parser). |
| 1084 if (proxy->is_resolved()) return true; | 1095 if (proxy->is_resolved()) return true; |
| 1085 | 1096 |
| 1086 // Otherwise, try to resolve the variable. | 1097 // Otherwise, try to resolve the variable. |
| 1087 BindingKind binding_kind; | 1098 BindingKind binding_kind; |
| 1088 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1099 Variable* var = LookupRecursive(proxy, &binding_kind, factory, |
| 1100 is_parameter_scope()); |
| 1089 switch (binding_kind) { | 1101 switch (binding_kind) { |
| 1090 case BOUND: | 1102 case BOUND: |
| 1091 // We found a variable binding. | 1103 // We found a variable binding. |
| 1092 if (is_strong(language_mode())) { | 1104 if (is_strong(language_mode())) { |
| 1093 if (!CheckStrongModeDeclaration(proxy, var)) return false; | 1105 if (!CheckStrongModeDeclaration(proxy, var)) return false; |
| 1094 } | 1106 } |
| 1095 break; | 1107 break; |
| 1096 | 1108 |
| 1097 case BOUND_EVAL_SHADOWED: | 1109 case BOUND_EVAL_SHADOWED: |
| 1098 // We either found a variable binding that might be shadowed by eval or | 1110 // We either found a variable binding that might be shadowed by eval or |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1543 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1555 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
| 1544 } | 1556 } |
| 1545 | 1557 |
| 1546 | 1558 |
| 1547 int Scope::ContextLocalCount() const { | 1559 int Scope::ContextLocalCount() const { |
| 1548 if (num_heap_slots() == 0) return 0; | 1560 if (num_heap_slots() == 0) return 0; |
| 1549 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1561 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1550 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1562 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
| 1551 } | 1563 } |
| 1552 } } // namespace v8::internal | 1564 } } // namespace v8::internal |
| OLD | NEW |