| 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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 } | 700 } |
| 701 | 701 |
| 702 | 702 |
| 703 static void PrintVar(int indent, Variable* var) { | 703 static void PrintVar(int indent, Variable* var) { |
| 704 if (var->is_used() || !var->IsUnallocated()) { | 704 if (var->is_used() || !var->IsUnallocated()) { |
| 705 Indent(indent, Variable::Mode2String(var->mode())); | 705 Indent(indent, Variable::Mode2String(var->mode())); |
| 706 PrintF(" "); | 706 PrintF(" "); |
| 707 PrintName(var->name()); | 707 PrintName(var->name()); |
| 708 PrintF("; // "); | 708 PrintF("; // "); |
| 709 PrintLocation(var); | 709 PrintLocation(var); |
| 710 if (var->is_accessed_from_inner_scope()) { | 710 if (var->has_forced_context_allocation()) { |
| 711 if (!var->IsUnallocated()) PrintF(", "); | 711 if (!var->IsUnallocated()) PrintF(", "); |
| 712 PrintF("inner scope access"); | 712 PrintF("forced context allocation"); |
| 713 } | 713 } |
| 714 PrintF("\n"); | 714 PrintF("\n"); |
| 715 } | 715 } |
| 716 } | 716 } |
| 717 | 717 |
| 718 | 718 |
| 719 static void PrintMap(int indent, VariableMap* map) { | 719 static void PrintMap(int indent, VariableMap* map) { |
| 720 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 720 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| 721 Variable* var = reinterpret_cast<Variable*>(p->value); | 721 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 722 PrintVar(indent, var); | 722 PrintVar(indent, var); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 841 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| 842 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 842 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
| 843 // the name of named function literal is kept in an intermediate scope | 843 // the name of named function literal is kept in an intermediate scope |
| 844 // in between this scope and the next outer scope.) | 844 // in between this scope and the next outer scope.) |
| 845 *binding_kind = UNBOUND; | 845 *binding_kind = UNBOUND; |
| 846 if (function_ != NULL && function_->name().is_identical_to(name)) { | 846 if (function_ != NULL && function_->name().is_identical_to(name)) { |
| 847 var = function_->var(); | 847 var = function_->var(); |
| 848 *binding_kind = BOUND; | 848 *binding_kind = BOUND; |
| 849 } else if (outer_scope_ != NULL) { | 849 } else if (outer_scope_ != NULL) { |
| 850 var = outer_scope_->LookupRecursive(name, context, binding_kind); | 850 var = outer_scope_->LookupRecursive(name, context, binding_kind); |
| 851 if (*binding_kind == BOUND) var->MarkAsAccessedFromInnerScope(); | 851 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
| 852 var->ForceContextAllocation(); |
| 853 } |
| 852 } | 854 } |
| 853 | 855 |
| 854 if (is_with_scope()) { | 856 if (is_with_scope()) { |
| 855 // The current scope is a with scope, so the variable binding can not be | 857 // The current scope is a with scope, so the variable binding can not be |
| 856 // statically resolved. However, note that it was necessary to do a lookup | 858 // statically resolved. However, note that it was necessary to do a lookup |
| 857 // in the outer scope anyway, because if a binding exists in an outer scope, | 859 // in the outer scope anyway, because if a binding exists in an outer scope, |
| 858 // the associated variable has to be marked as potentially being accessed | 860 // the associated variable has to be marked as potentially being accessed |
| 859 // from inside of an inner with scope (the property may not be in the 'with' | 861 // from inside of an inner with scope (the property may not be in the 'with' |
| 860 // object). | 862 // object). |
| 861 *binding_kind = DYNAMIC_LOOKUP; | 863 *binding_kind = DYNAMIC_LOOKUP; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 973 | 975 |
| 974 return scope_calls_eval_ || inner_scope_calls_eval_; | 976 return scope_calls_eval_ || inner_scope_calls_eval_; |
| 975 } | 977 } |
| 976 | 978 |
| 977 | 979 |
| 978 bool Scope::MustAllocate(Variable* var) { | 980 bool Scope::MustAllocate(Variable* var) { |
| 979 // Give var a read/write use if there is a chance it might be accessed | 981 // Give var a read/write use if there is a chance it might be accessed |
| 980 // via an eval() call. This is only possible if the variable has a | 982 // via an eval() call. This is only possible if the variable has a |
| 981 // visible name. | 983 // visible name. |
| 982 if ((var->is_this() || var->name()->length() > 0) && | 984 if ((var->is_this() || var->name()->length() > 0) && |
| 983 (var->is_accessed_from_inner_scope() || | 985 (var->has_forced_context_allocation() || |
| 984 scope_calls_eval_ || | 986 scope_calls_eval_ || |
| 985 inner_scope_calls_eval_ || | 987 inner_scope_calls_eval_ || |
| 986 scope_contains_with_ || | 988 scope_contains_with_ || |
| 987 is_catch_scope() || | 989 is_catch_scope() || |
| 988 is_block_scope())) { | 990 is_block_scope())) { |
| 989 var->set_is_used(true); | 991 var->set_is_used(true); |
| 990 } | 992 } |
| 991 // Global variables do not need to be allocated. | 993 // Global variables do not need to be allocated. |
| 992 return !var->is_global() && var->is_used(); | 994 return !var->is_global() && var->is_used(); |
| 993 } | 995 } |
| 994 | 996 |
| 995 | 997 |
| 996 bool Scope::MustAllocateInContext(Variable* var) { | 998 bool Scope::MustAllocateInContext(Variable* var) { |
| 997 // If var is accessed from an inner scope, or if there is a possibility | 999 // If var is accessed from an inner scope, or if there is a possibility |
| 998 // that it might be accessed from the current or an inner scope (through | 1000 // that it might be accessed from the current or an inner scope (through |
| 999 // an eval() call or a runtime with lookup), it must be allocated in the | 1001 // an eval() call or a runtime with lookup), it must be allocated in the |
| 1000 // context. | 1002 // context. |
| 1001 // | 1003 // |
| 1002 // Exceptions: temporary variables are never allocated in a context; | 1004 // Exceptions: temporary variables are never allocated in a context; |
| 1003 // catch-bound variables are always allocated in a context. | 1005 // catch-bound variables are always allocated in a context. |
| 1004 if (var->mode() == TEMPORARY) return false; | 1006 if (var->mode() == TEMPORARY) return false; |
| 1005 if (is_catch_scope() || is_block_scope()) return true; | 1007 if (is_catch_scope() || is_block_scope()) return true; |
| 1006 return var->is_accessed_from_inner_scope() || | 1008 return var->has_forced_context_allocation() || |
| 1007 scope_calls_eval_ || | 1009 scope_calls_eval_ || |
| 1008 inner_scope_calls_eval_ || | 1010 inner_scope_calls_eval_ || |
| 1009 scope_contains_with_ || | 1011 scope_contains_with_ || |
| 1010 var->is_global(); | 1012 var->is_global(); |
| 1011 } | 1013 } |
| 1012 | 1014 |
| 1013 | 1015 |
| 1014 bool Scope::HasArgumentsParameter() { | 1016 bool Scope::HasArgumentsParameter() { |
| 1015 for (int i = 0; i < params_.length(); i++) { | 1017 for (int i = 0; i < params_.length(); i++) { |
| 1016 if (params_[i]->name().is_identical_to( | 1018 if (params_[i]->name().is_identical_to( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 } | 1062 } |
| 1061 | 1063 |
| 1062 // The same parameter may occur multiple times in the parameters_ list. | 1064 // The same parameter may occur multiple times in the parameters_ list. |
| 1063 // If it does, and if it is not copied into the context object, it must | 1065 // If it does, and if it is not copied into the context object, it must |
| 1064 // receive the highest parameter index for that parameter; thus iteration | 1066 // receive the highest parameter index for that parameter; thus iteration |
| 1065 // order is relevant! | 1067 // order is relevant! |
| 1066 for (int i = params_.length() - 1; i >= 0; --i) { | 1068 for (int i = params_.length() - 1; i >= 0; --i) { |
| 1067 Variable* var = params_[i]; | 1069 Variable* var = params_[i]; |
| 1068 ASSERT(var->scope() == this); | 1070 ASSERT(var->scope() == this); |
| 1069 if (uses_nonstrict_arguments) { | 1071 if (uses_nonstrict_arguments) { |
| 1070 // Give the parameter a use from an inner scope, to force allocation | 1072 // Force context allocation of the parameter. |
| 1071 // to the context. | 1073 var->ForceContextAllocation(); |
| 1072 var->MarkAsAccessedFromInnerScope(); | |
| 1073 } | 1074 } |
| 1074 | 1075 |
| 1075 if (MustAllocate(var)) { | 1076 if (MustAllocate(var)) { |
| 1076 if (MustAllocateInContext(var)) { | 1077 if (MustAllocateInContext(var)) { |
| 1077 ASSERT(var->IsUnallocated() || var->IsContextSlot()); | 1078 ASSERT(var->IsUnallocated() || var->IsContextSlot()); |
| 1078 if (var->IsUnallocated()) { | 1079 if (var->IsUnallocated()) { |
| 1079 AllocateHeapSlot(var); | 1080 AllocateHeapSlot(var); |
| 1080 } | 1081 } |
| 1081 } else { | 1082 } else { |
| 1082 ASSERT(var->IsUnallocated() || var->IsParameter()); | 1083 ASSERT(var->IsUnallocated() || var->IsParameter()); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1161 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 1161 !must_have_local_context) { | 1162 !must_have_local_context) { |
| 1162 num_heap_slots_ = 0; | 1163 num_heap_slots_ = 0; |
| 1163 } | 1164 } |
| 1164 | 1165 |
| 1165 // Allocation done. | 1166 // Allocation done. |
| 1166 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1167 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1167 } | 1168 } |
| 1168 | 1169 |
| 1169 } } // namespace v8::internal | 1170 } } // namespace v8::internal |
| OLD | NEW |