| 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 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 | 613 |
| 614 | 614 |
| 615 static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { | 615 static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { |
| 616 if (var->is_used() || var->rewrite() != NULL) { | 616 if (var->is_used() || var->rewrite() != NULL) { |
| 617 Indent(indent, Variable::Mode2String(var->mode())); | 617 Indent(indent, Variable::Mode2String(var->mode())); |
| 618 PrintF(" "); | 618 PrintF(" "); |
| 619 PrintName(var->name()); | 619 PrintName(var->name()); |
| 620 PrintF("; // "); | 620 PrintF("; // "); |
| 621 if (var->rewrite() != NULL) { | 621 if (var->rewrite() != NULL) { |
| 622 PrintF("%s, ", printer->Print(var->rewrite())); | 622 PrintF("%s, ", printer->Print(var->rewrite())); |
| 623 if (var->is_accessed_from_inner_function_scope()) PrintF(", "); | 623 if (var->is_accessed_from_inner_scope()) PrintF(", "); |
| 624 } | 624 } |
| 625 if (var->is_accessed_from_inner_function_scope()) { | 625 if (var->is_accessed_from_inner_scope()) { |
| 626 PrintF("inner scope access"); | 626 PrintF("inner scope access"); |
| 627 } | 627 } |
| 628 PrintF("\n"); | 628 PrintF("\n"); |
| 629 } | 629 } |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { | 633 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { |
| 634 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 634 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| 635 Variable* var = reinterpret_cast<Variable*>(p->value); | 635 Variable* var = reinterpret_cast<Variable*>(p->value); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 } | 738 } |
| 739 | 739 |
| 740 | 740 |
| 741 // Lookup a variable starting with this scope. The result is either | 741 // Lookup a variable starting with this scope. The result is either |
| 742 // the statically resolved variable belonging to an outer scope, or | 742 // the statically resolved variable belonging to an outer scope, or |
| 743 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 743 // NULL. It may be NULL because a) we couldn't find a variable, or b) |
| 744 // because the variable is just a guess (and may be shadowed by | 744 // because the variable is just a guess (and may be shadowed by |
| 745 // another variable that is introduced dynamically via an 'eval' call | 745 // another variable that is introduced dynamically via an 'eval' call |
| 746 // or a 'with' statement). | 746 // or a 'with' statement). |
| 747 Variable* Scope::LookupRecursive(Handle<String> name, | 747 Variable* Scope::LookupRecursive(Handle<String> name, |
| 748 bool from_inner_function, | 748 bool from_inner_scope, |
| 749 Variable** invalidated_local) { | 749 Variable** invalidated_local) { |
| 750 // If we find a variable, but the current scope calls 'eval', the found | 750 // If we find a variable, but the current scope calls 'eval', the found |
| 751 // variable may not be the correct one (the 'eval' may introduce a | 751 // variable may not be the correct one (the 'eval' may introduce a |
| 752 // property with the same name). In that case, remember that the variable | 752 // property with the same name). In that case, remember that the variable |
| 753 // found is just a guess. | 753 // found is just a guess. |
| 754 bool guess = scope_calls_eval_; | 754 bool guess = scope_calls_eval_; |
| 755 | 755 |
| 756 // Try to find the variable in this scope. | 756 // Try to find the variable in this scope. |
| 757 Variable* var = LocalLookup(name); | 757 Variable* var = LocalLookup(name); |
| 758 | 758 |
| 759 if (var != NULL) { | 759 if (var != NULL) { |
| 760 // We found a variable. If this is not an inner lookup, we are done. | 760 // We found a variable. If this is not an inner lookup, we are done. |
| 761 // (Even if there is an 'eval' in this scope which introduces the | 761 // (Even if there is an 'eval' in this scope which introduces the |
| 762 // same variable again, the resulting variable remains the same. | 762 // same variable again, the resulting variable remains the same. |
| 763 // Note that enclosing 'with' statements are handled at the call site.) | 763 // Note that enclosing 'with' statements are handled at the call site.) |
| 764 if (!from_inner_function) | 764 if (!from_inner_scope) |
| 765 return var; | 765 return var; |
| 766 | 766 |
| 767 } else { | 767 } else { |
| 768 // We did not find a variable locally. Check against the function variable, | 768 // We did not find a variable locally. Check against the function variable, |
| 769 // if any. We can do this for all scopes, since the function variable is | 769 // if any. We can do this for all scopes, since the function variable is |
| 770 // only present - if at all - for function scopes. | 770 // only present - if at all - for function scopes. |
| 771 // | 771 // |
| 772 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 772 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| 773 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 773 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
| 774 // the name of named function literal is kept in an intermediate scope | 774 // the name of named function literal is kept in an intermediate scope |
| 775 // in between this scope and the next outer scope.) | 775 // in between this scope and the next outer scope.) |
| 776 if (function_ != NULL && function_->name().is_identical_to(name)) { | 776 if (function_ != NULL && function_->name().is_identical_to(name)) { |
| 777 var = function_; | 777 var = function_; |
| 778 | 778 |
| 779 } else if (outer_scope_ != NULL) { | 779 } else if (outer_scope_ != NULL) { |
| 780 var = outer_scope_->LookupRecursive( | 780 var = outer_scope_->LookupRecursive(name, true, invalidated_local); |
| 781 name, | |
| 782 is_function_scope() || from_inner_function, | |
| 783 invalidated_local); | |
| 784 // We may have found a variable in an outer scope. However, if | 781 // We may have found a variable in an outer scope. However, if |
| 785 // the current scope is inside a 'with', the actual variable may | 782 // the current scope is inside a 'with', the actual variable may |
| 786 // be a property introduced via the 'with' statement. Then, the | 783 // be a property introduced via the 'with' statement. Then, the |
| 787 // variable we may have found is just a guess. | 784 // variable we may have found is just a guess. |
| 788 if (scope_inside_with_) | 785 if (scope_inside_with_) |
| 789 guess = true; | 786 guess = true; |
| 790 } | 787 } |
| 791 | 788 |
| 792 // If we did not find a variable, we are done. | 789 // If we did not find a variable, we are done. |
| 793 if (var == NULL) | 790 if (var == NULL) |
| 794 return NULL; | 791 return NULL; |
| 795 } | 792 } |
| 796 | 793 |
| 797 ASSERT(var != NULL); | 794 ASSERT(var != NULL); |
| 798 | 795 |
| 799 // If this is a lookup from an inner scope, mark the variable. | 796 // If this is a lookup from an inner scope, mark the variable. |
| 800 if (from_inner_function) { | 797 if (from_inner_scope) { |
| 801 var->MarkAsAccessedFromInnerFunctionScope(); | 798 var->MarkAsAccessedFromInnerScope(); |
| 802 } | 799 } |
| 803 | 800 |
| 804 // If the variable we have found is just a guess, invalidate the | 801 // If the variable we have found is just a guess, invalidate the |
| 805 // result. If the found variable is local, record that fact so we | 802 // result. If the found variable is local, record that fact so we |
| 806 // can generate fast code to get it if it is not shadowed by eval. | 803 // can generate fast code to get it if it is not shadowed by eval. |
| 807 if (guess) { | 804 if (guess) { |
| 808 if (!var->is_global()) *invalidated_local = var; | 805 if (!var->is_global()) *invalidated_local = var; |
| 809 var = NULL; | 806 var = NULL; |
| 810 } | 807 } |
| 811 | 808 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 | 939 |
| 943 return scope_calls_eval_ || inner_scope_calls_eval_; | 940 return scope_calls_eval_ || inner_scope_calls_eval_; |
| 944 } | 941 } |
| 945 | 942 |
| 946 | 943 |
| 947 bool Scope::MustAllocate(Variable* var) { | 944 bool Scope::MustAllocate(Variable* var) { |
| 948 // Give var a read/write use if there is a chance it might be accessed | 945 // Give var a read/write use if there is a chance it might be accessed |
| 949 // via an eval() call. This is only possible if the variable has a | 946 // via an eval() call. This is only possible if the variable has a |
| 950 // visible name. | 947 // visible name. |
| 951 if ((var->is_this() || var->name()->length() > 0) && | 948 if ((var->is_this() || var->name()->length() > 0) && |
| 952 (var->is_accessed_from_inner_function_scope() || | 949 (var->is_accessed_from_inner_scope() || |
| 953 scope_calls_eval_ || | 950 scope_calls_eval_ || |
| 954 inner_scope_calls_eval_ || | 951 inner_scope_calls_eval_ || |
| 955 scope_contains_with_ || | 952 scope_contains_with_ || |
| 956 is_catch_scope() || | 953 is_catch_scope() || |
| 957 is_block_scope())) { | 954 is_block_scope())) { |
| 958 var->set_is_used(true); | 955 var->set_is_used(true); |
| 959 } | 956 } |
| 960 // Global variables do not need to be allocated. | 957 // Global variables do not need to be allocated. |
| 961 return !var->is_global() && var->is_used(); | 958 return !var->is_global() && var->is_used(); |
| 962 } | 959 } |
| 963 | 960 |
| 964 | 961 |
| 965 bool Scope::MustAllocateInContext(Variable* var) { | 962 bool Scope::MustAllocateInContext(Variable* var) { |
| 966 // If var is accessed from an inner scope, or if there is a possibility | 963 // If var is accessed from an inner scope, or if there is a possibility |
| 967 // that it might be accessed from the current or an inner scope (through | 964 // that it might be accessed from the current or an inner scope (through |
| 968 // an eval() call or a runtime with lookup), it must be allocated in the | 965 // an eval() call or a runtime with lookup), it must be allocated in the |
| 969 // context. | 966 // context. |
| 970 // | 967 // |
| 971 // Exceptions: temporary variables are never allocated in a context; | 968 // Exceptions: temporary variables are never allocated in a context; |
| 972 // catch-bound variables are always allocated in a context. | 969 // catch-bound variables are always allocated in a context. |
| 973 if (var->mode() == Variable::TEMPORARY) return false; | 970 if (var->mode() == Variable::TEMPORARY) return false; |
| 974 if (is_catch_scope() || is_block_scope()) return true; | 971 if (is_catch_scope() || is_block_scope()) return true; |
| 975 return var->is_accessed_from_inner_function_scope() || | 972 return var->is_accessed_from_inner_scope() || |
| 976 scope_calls_eval_ || | 973 scope_calls_eval_ || |
| 977 inner_scope_calls_eval_ || | 974 inner_scope_calls_eval_ || |
| 978 scope_contains_with_ || | 975 scope_contains_with_ || |
| 979 var->is_global(); | 976 var->is_global(); |
| 980 } | 977 } |
| 981 | 978 |
| 982 | 979 |
| 983 bool Scope::HasArgumentsParameter() { | 980 bool Scope::HasArgumentsParameter() { |
| 984 for (int i = 0; i < params_.length(); i++) { | 981 for (int i = 0; i < params_.length(); i++) { |
| 985 if (params_[i]->name().is_identical_to( | 982 if (params_[i]->name().is_identical_to( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 // The same parameter may occur multiple times in the parameters_ list. | 1028 // The same parameter may occur multiple times in the parameters_ list. |
| 1032 // If it does, and if it is not copied into the context object, it must | 1029 // If it does, and if it is not copied into the context object, it must |
| 1033 // receive the highest parameter index for that parameter; thus iteration | 1030 // receive the highest parameter index for that parameter; thus iteration |
| 1034 // order is relevant! | 1031 // order is relevant! |
| 1035 for (int i = params_.length() - 1; i >= 0; --i) { | 1032 for (int i = params_.length() - 1; i >= 0; --i) { |
| 1036 Variable* var = params_[i]; | 1033 Variable* var = params_[i]; |
| 1037 ASSERT(var->scope() == this); | 1034 ASSERT(var->scope() == this); |
| 1038 if (uses_nonstrict_arguments) { | 1035 if (uses_nonstrict_arguments) { |
| 1039 // Give the parameter a use from an inner scope, to force allocation | 1036 // Give the parameter a use from an inner scope, to force allocation |
| 1040 // to the context. | 1037 // to the context. |
| 1041 var->MarkAsAccessedFromInnerFunctionScope(); | 1038 var->MarkAsAccessedFromInnerScope(); |
| 1042 } | 1039 } |
| 1043 | 1040 |
| 1044 if (MustAllocate(var)) { | 1041 if (MustAllocate(var)) { |
| 1045 if (MustAllocateInContext(var)) { | 1042 if (MustAllocateInContext(var)) { |
| 1046 ASSERT(var->rewrite() == NULL || var->IsContextSlot()); | 1043 ASSERT(var->rewrite() == NULL || var->IsContextSlot()); |
| 1047 if (var->rewrite() == NULL) { | 1044 if (var->rewrite() == NULL) { |
| 1048 AllocateHeapSlot(var); | 1045 AllocateHeapSlot(var); |
| 1049 } | 1046 } |
| 1050 } else { | 1047 } else { |
| 1051 ASSERT(var->rewrite() == NULL || var->IsParameter()); | 1048 ASSERT(var->rewrite() == NULL || var->IsParameter()); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1128 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 1132 !must_have_local_context) { | 1129 !must_have_local_context) { |
| 1133 num_heap_slots_ = 0; | 1130 num_heap_slots_ = 0; |
| 1134 } | 1131 } |
| 1135 | 1132 |
| 1136 // Allocation done. | 1133 // Allocation done. |
| 1137 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1134 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1138 } | 1135 } |
| 1139 | 1136 |
| 1140 } } // namespace v8::internal | 1137 } } // namespace v8::internal |
| OLD | NEW |