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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 unresolved_(16), | 150 unresolved_(16), |
151 decls_(4) { | 151 decls_(4) { |
152 ASSERT(!scope_info.is_null()); | 152 ASSERT(!scope_info.is_null()); |
153 SetDefaults(FUNCTION_SCOPE, NULL, scope_info); | 153 SetDefaults(FUNCTION_SCOPE, NULL, scope_info); |
154 ASSERT(resolved()); | 154 ASSERT(resolved()); |
155 if (scope_info->HasHeapAllocatedLocals()) { | 155 if (scope_info->HasHeapAllocatedLocals()) { |
156 num_heap_slots_ = scope_info_->NumberOfContextSlots(); | 156 num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
157 } | 157 } |
158 | 158 |
159 AddInnerScope(inner_scope); | 159 AddInnerScope(inner_scope); |
160 | |
161 // This scope's arguments shadow (if present) is context-allocated if an inner | |
162 // scope accesses this one's parameters. Allocate the arguments_shadow_ | |
163 // variable if necessary. | |
164 Isolate* isolate = Isolate::Current(); | |
165 Variable::Mode mode; | |
166 int arguments_shadow_index = | |
167 scope_info_->ContextSlotIndex( | |
168 isolate->heap()->arguments_shadow_symbol(), &mode); | |
169 if (arguments_shadow_index >= 0) { | |
170 ASSERT(mode == Variable::INTERNAL); | |
171 arguments_shadow_ = new Variable( | |
172 this, | |
173 isolate->factory()->arguments_shadow_symbol(), | |
174 Variable::INTERNAL, | |
175 true, | |
176 Variable::ARGUMENTS); | |
177 arguments_shadow_->set_rewrite( | |
178 new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index)); | |
179 arguments_shadow_->set_is_used(true); | |
180 } | |
181 } | 160 } |
182 | 161 |
183 | 162 |
184 void Scope::SetDefaults(Type type, | 163 void Scope::SetDefaults(Type type, |
185 Scope* outer_scope, | 164 Scope* outer_scope, |
186 Handle<SerializedScopeInfo> scope_info) { | 165 Handle<SerializedScopeInfo> scope_info) { |
187 outer_scope_ = outer_scope; | 166 outer_scope_ = outer_scope; |
188 type_ = type; | 167 type_ = type; |
189 scope_name_ = FACTORY->empty_symbol(); | 168 scope_name_ = FACTORY->empty_symbol(); |
190 dynamics_ = NULL; | 169 dynamics_ = NULL; |
191 receiver_ = NULL; | 170 receiver_ = NULL; |
192 function_ = NULL; | 171 function_ = NULL; |
193 arguments_ = NULL; | 172 arguments_ = NULL; |
194 arguments_shadow_ = NULL; | |
195 illegal_redecl_ = NULL; | 173 illegal_redecl_ = NULL; |
196 scope_inside_with_ = false; | 174 scope_inside_with_ = false; |
197 scope_contains_with_ = false; | 175 scope_contains_with_ = false; |
198 scope_calls_eval_ = false; | 176 scope_calls_eval_ = false; |
199 // Inherit the strict mode from the parent scope. | 177 // Inherit the strict mode from the parent scope. |
200 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; | 178 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; |
201 outer_scope_calls_eval_ = false; | 179 outer_scope_calls_eval_ = false; |
202 outer_scope_calls_non_strict_eval_ = false; | 180 outer_scope_calls_non_strict_eval_ = false; |
203 inner_scope_calls_eval_ = false; | 181 inner_scope_calls_eval_ = false; |
204 outer_scope_is_eval_scope_ = false; | 182 outer_scope_is_eval_scope_ = false; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 true, Variable::ARGUMENTS); | 270 true, Variable::ARGUMENTS); |
293 } | 271 } |
294 } | 272 } |
295 | 273 |
296 | 274 |
297 Variable* Scope::LocalLookup(Handle<String> name) { | 275 Variable* Scope::LocalLookup(Handle<String> name) { |
298 Variable* result = variables_.Lookup(name); | 276 Variable* result = variables_.Lookup(name); |
299 if (result != NULL || !resolved()) { | 277 if (result != NULL || !resolved()) { |
300 return result; | 278 return result; |
301 } | 279 } |
302 // If the scope is resolved, we can find a variable in serialized scope info. | 280 // If the scope is resolved, we can find a variable in serialized scope |
303 | 281 // info. |
304 // We should never lookup 'arguments' in this scope | 282 // |
305 // as it is implicitly present in any scope. | 283 // We should never lookup 'arguments' in this scope as it is implicitly |
| 284 // present in every scope. |
306 ASSERT(*name != *FACTORY->arguments_symbol()); | 285 ASSERT(*name != *FACTORY->arguments_symbol()); |
307 | 286 // There should be no local slot with the given name. |
308 // Assert that there is no local slot with the given name. | |
309 ASSERT(scope_info_->StackSlotIndex(*name) < 0); | 287 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
310 | 288 |
311 // Check context slot lookup. | 289 // Check context slot lookup. |
312 Variable::Mode mode; | 290 Variable::Mode mode; |
313 int index = scope_info_->ContextSlotIndex(*name, &mode); | 291 int index = scope_info_->ContextSlotIndex(*name, &mode); |
314 if (index >= 0) { | 292 if (index < 0) { |
315 Variable* var = | 293 // Check parameters. |
316 variables_.Declare(this, name, mode, true, Variable::NORMAL); | 294 mode = Variable::VAR; |
317 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); | 295 index = scope_info_->ParameterIndex(*name); |
318 return var; | 296 if (index < 0) { |
| 297 // Check the function name. |
| 298 index = scope_info_->FunctionContextSlotIndex(*name); |
| 299 if (index < 0) return NULL; |
| 300 } |
319 } | 301 } |
320 | 302 |
321 index = scope_info_->ParameterIndex(*name); | 303 Variable* var = |
322 if (index >= 0) { | 304 variables_.Declare(this, name, mode, true, Variable::NORMAL); |
323 // ".arguments" must be present in context slots. | 305 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
324 ASSERT(arguments_shadow_ != NULL); | 306 return var; |
325 Variable* var = | |
326 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); | |
327 Property* rewrite = | |
328 new Property(new VariableProxy(arguments_shadow_), | |
329 new Literal(Handle<Object>(Smi::FromInt(index))), | |
330 RelocInfo::kNoPosition, | |
331 Property::SYNTHETIC); | |
332 rewrite->set_is_arguments_access(true); | |
333 var->set_rewrite(rewrite); | |
334 return var; | |
335 } | |
336 | |
337 index = scope_info_->FunctionContextSlotIndex(*name); | |
338 if (index >= 0) { | |
339 // Check that there is no local slot with the given name. | |
340 ASSERT(scope_info_->StackSlotIndex(*name) < 0); | |
341 Variable* var = | |
342 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); | |
343 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); | |
344 return var; | |
345 } | |
346 | |
347 return NULL; | |
348 } | 307 } |
349 | 308 |
350 | 309 |
351 Variable* Scope::Lookup(Handle<String> name) { | 310 Variable* Scope::Lookup(Handle<String> name) { |
352 for (Scope* scope = this; | 311 for (Scope* scope = this; |
353 scope != NULL; | 312 scope != NULL; |
354 scope = scope->outer_scope()) { | 313 scope = scope->outer_scope()) { |
355 Variable* var = scope->LocalLookup(name); | 314 Variable* var = scope->LocalLookup(name); |
356 if (var != NULL) return var; | 315 if (var != NULL) return var; |
357 } | 316 } |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 void Scope::AllocateHeapSlot(Variable* var) { | 904 void Scope::AllocateHeapSlot(Variable* var) { |
946 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); | 905 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); |
947 } | 906 } |
948 | 907 |
949 | 908 |
950 void Scope::AllocateParameterLocals() { | 909 void Scope::AllocateParameterLocals() { |
951 ASSERT(is_function_scope()); | 910 ASSERT(is_function_scope()); |
952 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); | 911 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); |
953 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 912 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
954 | 913 |
955 // Parameters are rewritten to arguments[i] if 'arguments' is used in | 914 bool uses_nonstrict_arguments = false; |
956 // a non-strict mode function. Strict mode code doesn't alias arguments. | |
957 bool rewrite_parameters = false; | |
958 | 915 |
959 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 916 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
960 // 'arguments' is used. Unless there is also a parameter called | 917 // 'arguments' is used. Unless there is also a parameter called |
961 // 'arguments', we must be conservative and access all parameters via | 918 // 'arguments', we must be conservative and allocate all parameters to |
962 // the arguments object: The i'th parameter is rewritten into | 919 // the context assuming they will be captured by the arguments object. |
963 // '.arguments[i]' (*). If we have a parameter named 'arguments', a | 920 // If we have a parameter named 'arguments', a (new) value is always |
964 // (new) value is always assigned to it via the function | 921 // assigned to it via the function invocation. Then 'arguments' denotes |
965 // invocation. Then 'arguments' denotes that specific parameter value | 922 // that specific parameter value and cannot be used to access the |
966 // and cannot be used to access the parameters, which is why we don't | 923 // parameters, which is why we don't need to allocate an arguments |
967 // need to rewrite in that case. | 924 // object in that case. |
968 // | |
969 // (*) Instead of having a parameter called 'arguments', we may have an | |
970 // assignment to 'arguments' in the function body, at some arbitrary | |
971 // point in time (possibly through an 'eval()' call!). After that | |
972 // assignment any re-write of parameters would be invalid (was bug | |
973 // 881452). Thus, we introduce a shadow '.arguments' | |
974 // variable which also points to the arguments object. For rewrites we | |
975 // use '.arguments' which remains valid even if we assign to | |
976 // 'arguments'. To summarize: If we need to rewrite, we allocate an | |
977 // 'arguments' object dynamically upon function invocation. The compiler | |
978 // introduces 2 local variables 'arguments' and '.arguments', both of | |
979 // which originally point to the arguments object that was | |
980 // allocated. All parameters are rewritten into property accesses via | |
981 // the '.arguments' variable. Thus, any changes to properties of | |
982 // 'arguments' are reflected in the variables and vice versa. If the | |
983 // 'arguments' variable is changed, '.arguments' still points to the | |
984 // correct arguments object and the rewrites still work. | |
985 | 925 |
986 // We are using 'arguments'. Tell the code generator that is needs to | 926 // We are using 'arguments'. Tell the code generator that is needs to |
987 // allocate the arguments object by setting 'arguments_'. | 927 // allocate the arguments object by setting 'arguments_'. |
988 arguments_ = arguments; | 928 arguments_ = arguments; |
989 | 929 |
990 // In strict mode 'arguments' does not alias formal parameters. | 930 // In strict mode 'arguments' does not alias formal parameters. |
991 // Therefore in strict mode we allocate parameters as if 'arguments' | 931 // Therefore in strict mode we allocate parameters as if 'arguments' |
992 // were not used. | 932 // were not used. |
993 rewrite_parameters = !is_strict_mode(); | 933 uses_nonstrict_arguments = !is_strict_mode(); |
994 } | 934 } |
995 | 935 |
996 if (rewrite_parameters) { | 936 // The same parameter may occur multiple times in the parameters_ list. |
997 // We also need the '.arguments' shadow variable. Declare it and create | 937 // If it does, and if it is not copied into the context object, it must |
998 // and bind the corresponding proxy. It's ok to declare it only now | 938 // receive the highest parameter index for that parameter; thus iteration |
999 // because it's a local variable that is allocated after the parameters | 939 // order is relevant! |
1000 // have been allocated. | 940 for (int i = params_.length() - 1; i >= 0; --i) { |
1001 // | 941 Variable* var = params_[i]; |
1002 // Note: This is "almost" at temporary variable but we cannot use | 942 ASSERT(var->scope() == this); |
1003 // NewTemporary() because the mode needs to be INTERNAL since this | 943 if (uses_nonstrict_arguments) { |
1004 // variable may be allocated in the heap-allocated context (temporaries | 944 // Give the parameter a use from an inner scope, to force allocation |
1005 // are never allocated in the context). | 945 // to the context. |
1006 arguments_shadow_ = new Variable(this, | 946 var->MarkAsAccessedFromInnerScope(); |
1007 FACTORY->arguments_shadow_symbol(), | |
1008 Variable::INTERNAL, | |
1009 true, | |
1010 Variable::ARGUMENTS); | |
1011 arguments_shadow_->set_is_used(true); | |
1012 temps_.Add(arguments_shadow_); | |
1013 | |
1014 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. | |
1015 for (int i = 0; i < params_.length(); i++) { | |
1016 Variable* var = params_[i]; | |
1017 ASSERT(var->scope() == this); | |
1018 if (MustAllocate(var)) { | |
1019 if (MustAllocateInContext(var)) { | |
1020 // It is ok to set this only now, because arguments is a local | |
1021 // variable that is allocated after the parameters have been | |
1022 // allocated. | |
1023 arguments_shadow_->MarkAsAccessedFromInnerScope(); | |
1024 } | |
1025 Property* rewrite = | |
1026 new Property(new VariableProxy(arguments_shadow_), | |
1027 new Literal(Handle<Object>(Smi::FromInt(i))), | |
1028 RelocInfo::kNoPosition, | |
1029 Property::SYNTHETIC); | |
1030 rewrite->set_is_arguments_access(true); | |
1031 var->set_rewrite(rewrite); | |
1032 } | |
1033 } | 947 } |
1034 | 948 |
1035 } else { | 949 if (MustAllocate(var)) { |
1036 // The arguments object is not used, so we can access parameters directly. | 950 if (MustAllocateInContext(var)) { |
1037 // The same parameter may occur multiple times in the parameters_ list. | 951 ASSERT(var->rewrite() == NULL || var->IsContextSlot()); |
1038 // If it does, and if it is not copied into the context object, it must | 952 if (var->rewrite() == NULL) { |
1039 // receive the highest parameter index for that parameter; thus iteration | 953 AllocateHeapSlot(var); |
1040 // order is relevant! | 954 } |
1041 for (int i = 0; i < params_.length(); i++) { | 955 } else { |
1042 Variable* var = params_[i]; | 956 ASSERT(var->rewrite() == NULL || var->IsParameter()); |
1043 ASSERT(var->scope() == this); | 957 if (var->rewrite() == NULL) { |
1044 if (MustAllocate(var)) { | |
1045 if (MustAllocateInContext(var)) { | |
1046 ASSERT(var->rewrite() == NULL || | |
1047 (var->AsSlot() != NULL && | |
1048 var->AsSlot()->type() == Slot::CONTEXT)); | |
1049 if (var->rewrite() == NULL) { | |
1050 // Only set the heap allocation if the parameter has not | |
1051 // been allocated yet. | |
1052 AllocateHeapSlot(var); | |
1053 } | |
1054 } else { | |
1055 ASSERT(var->rewrite() == NULL || | |
1056 (var->AsSlot() != NULL && | |
1057 var->AsSlot()->type() == Slot::PARAMETER)); | |
1058 // Set the parameter index always, even if the parameter | |
1059 // was seen before! (We need to access the actual parameter | |
1060 // supplied for the last occurrence of a multiply declared | |
1061 // parameter.) | |
1062 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); | 958 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); |
1063 } | 959 } |
1064 } | 960 } |
1065 } | 961 } |
1066 } | 962 } |
1067 } | 963 } |
1068 | 964 |
1069 | 965 |
1070 void Scope::AllocateNonParameterLocal(Variable* var) { | 966 void Scope::AllocateNonParameterLocal(Variable* var) { |
1071 ASSERT(var->scope() == this); | 967 ASSERT(var->scope() == this); |
1072 ASSERT(var->rewrite() == NULL || | 968 ASSERT(var->rewrite() == NULL || |
1073 (!var->IsVariable(FACTORY->result_symbol())) || | 969 !var->IsVariable(FACTORY->result_symbol()) || |
1074 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); | 970 var->AsSlot() == NULL || |
| 971 var->AsSlot()->type() != Slot::LOCAL); |
1075 if (var->rewrite() == NULL && MustAllocate(var)) { | 972 if (var->rewrite() == NULL && MustAllocate(var)) { |
1076 if (MustAllocateInContext(var)) { | 973 if (MustAllocateInContext(var)) { |
1077 AllocateHeapSlot(var); | 974 AllocateHeapSlot(var); |
1078 } else { | 975 } else { |
1079 AllocateStackSlot(var); | 976 AllocateStackSlot(var); |
1080 } | 977 } |
1081 } | 978 } |
1082 } | 979 } |
1083 | 980 |
1084 | 981 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1036 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
1140 !must_have_local_context) { | 1037 !must_have_local_context) { |
1141 num_heap_slots_ = 0; | 1038 num_heap_slots_ = 0; |
1142 } | 1039 } |
1143 | 1040 |
1144 // Allocation done. | 1041 // Allocation done. |
1145 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1042 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
1146 } | 1043 } |
1147 | 1044 |
1148 } } // namespace v8::internal | 1045 } } // namespace v8::internal |
OLD | NEW |