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 |