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 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 688 } | 688 } |
| 689 | 689 |
| 690 | 690 |
| 691 static void PrintVar(int indent, Variable* var) { | 691 static void PrintVar(int indent, Variable* var) { |
| 692 if (var->is_used() || !var->IsUnallocated()) { | 692 if (var->is_used() || !var->IsUnallocated()) { |
| 693 Indent(indent, Variable::Mode2String(var->mode())); | 693 Indent(indent, Variable::Mode2String(var->mode())); |
| 694 PrintF(" "); | 694 PrintF(" "); |
| 695 PrintName(var->name()); | 695 PrintName(var->name()); |
| 696 PrintF("; // "); | 696 PrintF("; // "); |
| 697 PrintLocation(var); | 697 PrintLocation(var); |
| 698 if (var->is_accessed_from_inner_function_scope()) { | 698 if (var->is_accessed_from_inner_scope()) { |
| 699 if (!var->IsUnallocated()) PrintF(", "); | 699 if (!var->IsUnallocated()) PrintF(", "); |
| 700 PrintF("inner scope access"); | 700 PrintF("inner scope access"); |
| 701 } | 701 } |
| 702 PrintF("\n"); | 702 PrintF("\n"); |
| 703 } | 703 } |
| 704 } | 704 } |
| 705 | 705 |
| 706 | 706 |
| 707 static void PrintMap(int indent, VariableMap* map) { | 707 static void PrintMap(int indent, VariableMap* map) { |
| 708 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 708 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 811 } | 811 } |
| 812 | 812 |
| 813 | 813 |
| 814 // Lookup a variable starting with this scope. The result is either | 814 // Lookup a variable starting with this scope. The result is either |
| 815 // the statically resolved variable belonging to an outer scope, or | 815 // the statically resolved variable belonging to an outer scope, or |
| 816 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 816 // NULL. It may be NULL because a) we couldn't find a variable, or b) |
| 817 // because the variable is just a guess (and may be shadowed by | 817 // because the variable is just a guess (and may be shadowed by |
| 818 // another variable that is introduced dynamically via an 'eval' call | 818 // another variable that is introduced dynamically via an 'eval' call |
| 819 // or a 'with' statement). | 819 // or a 'with' statement). |
| 820 Variable* Scope::LookupRecursive(Handle<String> name, | 820 Variable* Scope::LookupRecursive(Handle<String> name, |
| 821 bool from_inner_function, | 821 bool from_inner_scope, |
| 822 Variable** invalidated_local) { | 822 Variable** invalidated_local) { |
| 823 // If we find a variable, but the current scope calls 'eval', the found | 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 | 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 | 825 // property with the same name). In that case, remember that the variable |
| 826 // found is just a guess. | 826 // found is just a guess. |
| 827 bool guess = scope_calls_eval_; | 827 bool guess = scope_calls_eval_; |
| 828 | 828 |
| 829 // Try to find the variable in this scope. | 829 // Try to find the variable in this scope. |
| 830 Variable* var = LocalLookup(name); | 830 Variable* var = LocalLookup(name); |
| 831 | 831 |
| 832 if (var != NULL) { | 832 if (var != NULL) { |
| 833 // We found a variable. If this is not an inner lookup, we are done. | 833 // We found a variable. If this is not an inner lookup, we are done. |
| 834 // (Even if there is an 'eval' in this scope which introduces the | 834 // (Even if there is an 'eval' in this scope which introduces the |
| 835 // same variable again, the resulting variable remains the same. | 835 // same variable again, the resulting variable remains the same. |
| 836 // Note that enclosing 'with' statements are handled at the call site.) | 836 // Note that enclosing 'with' statements are handled at the call site.) |
| 837 if (!from_inner_function) | 837 if (!from_inner_scope) |
| 838 return var; | 838 return var; |
| 839 | 839 |
| 840 } else { | 840 } else { |
| 841 // We did not find a variable locally. Check against the function variable, | 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 | 842 // if any. We can do this for all scopes, since the function variable is |
| 843 // only present - if at all - for function scopes. | 843 // only present - if at all - for function scopes. |
| 844 // | 844 // |
| 845 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 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 | 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 | 847 // the name of named function literal is kept in an intermediate scope |
| 848 // in between this scope and the next outer scope.) | 848 // in between this scope and the next outer scope.) |
| 849 if (function_ != NULL && function_->name().is_identical_to(name)) { | 849 if (function_ != NULL && function_->name().is_identical_to(name)) { |
| 850 var = function_->var(); | 850 var = function_->var(); |
| 851 | 851 |
| 852 } else if (outer_scope_ != NULL) { | 852 } else if (outer_scope_ != NULL) { |
| 853 var = outer_scope_->LookupRecursive( | 853 var = outer_scope_->LookupRecursive( |
|
Rico
2011/09/14 13:43:25
now fits on one line
| |
| 854 name, | 854 name, |
| 855 is_function_scope() || from_inner_function, | 855 true, |
|
Steven
2011/09/14 13:30:17
The important change.
| |
| 856 invalidated_local); | 856 invalidated_local); |
| 857 // We may have found a variable in an outer scope. However, if | 857 // We may have found a variable in an outer scope. However, if |
| 858 // the current scope is inside a 'with', the actual variable may | 858 // the current scope is inside a 'with', the actual variable may |
| 859 // be a property introduced via the 'with' statement. Then, the | 859 // be a property introduced via the 'with' statement. Then, the |
| 860 // variable we may have found is just a guess. | 860 // variable we may have found is just a guess. |
| 861 if (scope_inside_with_) | 861 if (scope_inside_with_) |
| 862 guess = true; | 862 guess = true; |
| 863 } | 863 } |
| 864 | 864 |
| 865 // If we did not find a variable, we are done. | 865 // If we did not find a variable, we are done. |
| 866 if (var == NULL) | 866 if (var == NULL) |
| 867 return NULL; | 867 return NULL; |
| 868 } | 868 } |
| 869 | 869 |
| 870 ASSERT(var != NULL); | 870 ASSERT(var != NULL); |
| 871 | 871 |
| 872 // If this is a lookup from an inner scope, mark the variable. | 872 // If this is a lookup from an inner scope, mark the variable. |
| 873 if (from_inner_function) { | 873 if (from_inner_scope) { |
| 874 var->MarkAsAccessedFromInnerFunctionScope(); | 874 var->MarkAsAccessedFromInnerScope(); |
| 875 } | 875 } |
| 876 | 876 |
| 877 // If the variable we have found is just a guess, invalidate the | 877 // If the variable we have found is just a guess, invalidate the |
| 878 // result. If the found variable is local, record that fact so we | 878 // result. If the found variable is local, record that fact so we |
| 879 // can generate fast code to get it if it is not shadowed by eval. | 879 // can generate fast code to get it if it is not shadowed by eval. |
| 880 if (guess) { | 880 if (guess) { |
| 881 if (!var->is_global()) *invalidated_local = var; | 881 if (!var->is_global()) *invalidated_local = var; |
| 882 var = NULL; | 882 var = NULL; |
| 883 } | 883 } |
| 884 | 884 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1015 | 1015 |
| 1016 return scope_calls_eval_ || inner_scope_calls_eval_; | 1016 return scope_calls_eval_ || inner_scope_calls_eval_; |
| 1017 } | 1017 } |
| 1018 | 1018 |
| 1019 | 1019 |
| 1020 bool Scope::MustAllocate(Variable* var) { | 1020 bool Scope::MustAllocate(Variable* var) { |
| 1021 // Give var a read/write use if there is a chance it might be accessed | 1021 // Give var a read/write use if there is a chance it might be accessed |
| 1022 // via an eval() call. This is only possible if the variable has a | 1022 // via an eval() call. This is only possible if the variable has a |
| 1023 // visible name. | 1023 // visible name. |
| 1024 if ((var->is_this() || var->name()->length() > 0) && | 1024 if ((var->is_this() || var->name()->length() > 0) && |
| 1025 (var->is_accessed_from_inner_function_scope() || | 1025 (var->is_accessed_from_inner_scope() || |
| 1026 scope_calls_eval_ || | 1026 scope_calls_eval_ || |
| 1027 inner_scope_calls_eval_ || | 1027 inner_scope_calls_eval_ || |
| 1028 scope_contains_with_ || | 1028 scope_contains_with_ || |
| 1029 is_catch_scope() || | 1029 is_catch_scope() || |
| 1030 is_block_scope())) { | 1030 is_block_scope())) { |
| 1031 var->set_is_used(true); | 1031 var->set_is_used(true); |
| 1032 } | 1032 } |
| 1033 // Global variables do not need to be allocated. | 1033 // Global variables do not need to be allocated. |
| 1034 return !var->is_global() && var->is_used(); | 1034 return !var->is_global() && var->is_used(); |
| 1035 } | 1035 } |
| 1036 | 1036 |
| 1037 | 1037 |
| 1038 bool Scope::MustAllocateInContext(Variable* var) { | 1038 bool Scope::MustAllocateInContext(Variable* var) { |
| 1039 // If var is accessed from an inner scope, or if there is a possibility | 1039 // If var is accessed from an inner scope, or if there is a possibility |
| 1040 // that it might be accessed from the current or an inner scope (through | 1040 // that it might be accessed from the current or an inner scope (through |
| 1041 // an eval() call or a runtime with lookup), it must be allocated in the | 1041 // an eval() call or a runtime with lookup), it must be allocated in the |
| 1042 // context. | 1042 // context. |
| 1043 // | 1043 // |
| 1044 // Exceptions: temporary variables are never allocated in a context; | 1044 // Exceptions: temporary variables are never allocated in a context; |
| 1045 // catch-bound variables are always allocated in a context. | 1045 // catch-bound variables are always allocated in a context. |
| 1046 if (var->mode() == Variable::TEMPORARY) return false; | 1046 if (var->mode() == Variable::TEMPORARY) return false; |
| 1047 if (is_catch_scope() || is_block_scope()) return true; | 1047 if (is_catch_scope() || is_block_scope()) return true; |
| 1048 return var->is_accessed_from_inner_function_scope() || | 1048 return var->is_accessed_from_inner_scope() || |
| 1049 scope_calls_eval_ || | 1049 scope_calls_eval_ || |
| 1050 inner_scope_calls_eval_ || | 1050 inner_scope_calls_eval_ || |
| 1051 scope_contains_with_ || | 1051 scope_contains_with_ || |
| 1052 var->is_global(); | 1052 var->is_global(); |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 | 1055 |
| 1056 bool Scope::HasArgumentsParameter() { | 1056 bool Scope::HasArgumentsParameter() { |
| 1057 for (int i = 0; i < params_.length(); i++) { | 1057 for (int i = 0; i < params_.length(); i++) { |
| 1058 if (params_[i]->name().is_identical_to( | 1058 if (params_[i]->name().is_identical_to( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1104 // The same parameter may occur multiple times in the parameters_ list. | 1104 // The same parameter may occur multiple times in the parameters_ list. |
| 1105 // If it does, and if it is not copied into the context object, it must | 1105 // If it does, and if it is not copied into the context object, it must |
| 1106 // receive the highest parameter index for that parameter; thus iteration | 1106 // receive the highest parameter index for that parameter; thus iteration |
| 1107 // order is relevant! | 1107 // order is relevant! |
| 1108 for (int i = params_.length() - 1; i >= 0; --i) { | 1108 for (int i = params_.length() - 1; i >= 0; --i) { |
| 1109 Variable* var = params_[i]; | 1109 Variable* var = params_[i]; |
| 1110 ASSERT(var->scope() == this); | 1110 ASSERT(var->scope() == this); |
| 1111 if (uses_nonstrict_arguments) { | 1111 if (uses_nonstrict_arguments) { |
| 1112 // Give the parameter a use from an inner scope, to force allocation | 1112 // Give the parameter a use from an inner scope, to force allocation |
| 1113 // to the context. | 1113 // to the context. |
| 1114 var->MarkAsAccessedFromInnerFunctionScope(); | 1114 var->MarkAsAccessedFromInnerScope(); |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 if (MustAllocate(var)) { | 1117 if (MustAllocate(var)) { |
| 1118 if (MustAllocateInContext(var)) { | 1118 if (MustAllocateInContext(var)) { |
| 1119 ASSERT(var->IsUnallocated() || var->IsContextSlot()); | 1119 ASSERT(var->IsUnallocated() || var->IsContextSlot()); |
| 1120 if (var->IsUnallocated()) { | 1120 if (var->IsUnallocated()) { |
| 1121 AllocateHeapSlot(var); | 1121 AllocateHeapSlot(var); |
| 1122 } | 1122 } |
| 1123 } else { | 1123 } else { |
| 1124 ASSERT(var->IsUnallocated() || var->IsParameter()); | 1124 ASSERT(var->IsUnallocated() || var->IsParameter()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1202 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1202 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 1203 !must_have_local_context) { | 1203 !must_have_local_context) { |
| 1204 num_heap_slots_ = 0; | 1204 num_heap_slots_ = 0; |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 // Allocation done. | 1207 // Allocation done. |
| 1208 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1208 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1209 } | 1209 } |
| 1210 | 1210 |
| 1211 } } // namespace v8::internal | 1211 } } // namespace v8::internal |
| OLD | NEW |