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 } |
160 } | 181 } |
161 | 182 |
162 | 183 |
163 void Scope::SetDefaults(Type type, | 184 void Scope::SetDefaults(Type type, |
164 Scope* outer_scope, | 185 Scope* outer_scope, |
165 Handle<SerializedScopeInfo> scope_info) { | 186 Handle<SerializedScopeInfo> scope_info) { |
166 outer_scope_ = outer_scope; | 187 outer_scope_ = outer_scope; |
167 type_ = type; | 188 type_ = type; |
168 scope_name_ = FACTORY->empty_symbol(); | 189 scope_name_ = FACTORY->empty_symbol(); |
169 dynamics_ = NULL; | 190 dynamics_ = NULL; |
170 receiver_ = NULL; | 191 receiver_ = NULL; |
171 function_ = NULL; | 192 function_ = NULL; |
172 arguments_ = NULL; | 193 arguments_ = NULL; |
| 194 arguments_shadow_ = NULL; |
173 illegal_redecl_ = NULL; | 195 illegal_redecl_ = NULL; |
174 scope_inside_with_ = false; | 196 scope_inside_with_ = false; |
175 scope_contains_with_ = false; | 197 scope_contains_with_ = false; |
176 scope_calls_eval_ = false; | 198 scope_calls_eval_ = false; |
177 // Inherit the strict mode from the parent scope. | 199 // Inherit the strict mode from the parent scope. |
178 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; | 200 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; |
179 outer_scope_calls_eval_ = false; | 201 outer_scope_calls_eval_ = false; |
180 outer_scope_calls_non_strict_eval_ = false; | 202 outer_scope_calls_non_strict_eval_ = false; |
181 inner_scope_calls_eval_ = false; | 203 inner_scope_calls_eval_ = false; |
182 outer_scope_is_eval_scope_ = false; | 204 outer_scope_is_eval_scope_ = false; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 true, Variable::ARGUMENTS); | 292 true, Variable::ARGUMENTS); |
271 } | 293 } |
272 } | 294 } |
273 | 295 |
274 | 296 |
275 Variable* Scope::LocalLookup(Handle<String> name) { | 297 Variable* Scope::LocalLookup(Handle<String> name) { |
276 Variable* result = variables_.Lookup(name); | 298 Variable* result = variables_.Lookup(name); |
277 if (result != NULL || !resolved()) { | 299 if (result != NULL || !resolved()) { |
278 return result; | 300 return result; |
279 } | 301 } |
280 // If the scope is resolved, we can find a variable in serialized scope | 302 // If the scope is resolved, we can find a variable in serialized scope info. |
281 // info. | 303 |
282 // | 304 // We should never lookup 'arguments' in this scope |
283 // We should never lookup 'arguments' in this scope as it is implicitly | 305 // as it is implicitly present in any scope. |
284 // present in every scope. | |
285 ASSERT(*name != *FACTORY->arguments_symbol()); | 306 ASSERT(*name != *FACTORY->arguments_symbol()); |
286 // There should be no local slot with the given name. | 307 |
| 308 // Assert that there is no local slot with the given name. |
287 ASSERT(scope_info_->StackSlotIndex(*name) < 0); | 309 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
288 | 310 |
289 // Check context slot lookup. | 311 // Check context slot lookup. |
290 Variable::Mode mode; | 312 Variable::Mode mode; |
291 int index = scope_info_->ContextSlotIndex(*name, &mode); | 313 int index = scope_info_->ContextSlotIndex(*name, &mode); |
292 if (index < 0) { | 314 if (index >= 0) { |
293 // Check parameters. | 315 Variable* var = |
294 mode = Variable::VAR; | 316 variables_.Declare(this, name, mode, true, Variable::NORMAL); |
295 index = scope_info_->ParameterIndex(*name); | 317 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
296 if (index < 0) { | 318 return var; |
297 // Check the function name. | |
298 index = scope_info_->FunctionContextSlotIndex(*name); | |
299 if (index < 0) return NULL; | |
300 } | |
301 } | 319 } |
302 | 320 |
303 Variable* var = | 321 index = scope_info_->ParameterIndex(*name); |
304 variables_.Declare(this, name, mode, true, Variable::NORMAL); | 322 if (index >= 0) { |
305 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); | 323 // ".arguments" must be present in context slots. |
306 return var; | 324 ASSERT(arguments_shadow_ != NULL); |
| 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; |
307 } | 348 } |
308 | 349 |
309 | 350 |
310 Variable* Scope::Lookup(Handle<String> name) { | 351 Variable* Scope::Lookup(Handle<String> name) { |
311 for (Scope* scope = this; | 352 for (Scope* scope = this; |
312 scope != NULL; | 353 scope != NULL; |
313 scope = scope->outer_scope()) { | 354 scope = scope->outer_scope()) { |
314 Variable* var = scope->LocalLookup(name); | 355 Variable* var = scope->LocalLookup(name); |
315 if (var != NULL) return var; | 356 if (var != NULL) return var; |
316 } | 357 } |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
904 void Scope::AllocateHeapSlot(Variable* var) { | 945 void Scope::AllocateHeapSlot(Variable* var) { |
905 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); | 946 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); |
906 } | 947 } |
907 | 948 |
908 | 949 |
909 void Scope::AllocateParameterLocals() { | 950 void Scope::AllocateParameterLocals() { |
910 ASSERT(is_function_scope()); | 951 ASSERT(is_function_scope()); |
911 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); | 952 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); |
912 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 953 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
913 | 954 |
914 bool uses_nonstrict_arguments = false; | 955 // Parameters are rewritten to arguments[i] if 'arguments' is used in |
| 956 // a non-strict mode function. Strict mode code doesn't alias arguments. |
| 957 bool rewrite_parameters = false; |
915 | 958 |
916 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 959 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
917 // 'arguments' is used. Unless there is also a parameter called | 960 // 'arguments' is used. Unless there is also a parameter called |
918 // 'arguments', we must be conservative and allocate all parameters to | 961 // 'arguments', we must be conservative and access all parameters via |
919 // the context assuming they will be captured by the arguments object. | 962 // the arguments object: The i'th parameter is rewritten into |
920 // If we have a parameter named 'arguments', a (new) value is always | 963 // '.arguments[i]' (*). If we have a parameter named 'arguments', a |
921 // assigned to it via the function invocation. Then 'arguments' denotes | 964 // (new) value is always assigned to it via the function |
922 // that specific parameter value and cannot be used to access the | 965 // invocation. Then 'arguments' denotes that specific parameter value |
923 // parameters, which is why we don't need to allocate an arguments | 966 // and cannot be used to access the parameters, which is why we don't |
924 // object in that case. | 967 // need to rewrite 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. |
925 | 985 |
926 // We are using 'arguments'. Tell the code generator that is needs to | 986 // We are using 'arguments'. Tell the code generator that is needs to |
927 // allocate the arguments object by setting 'arguments_'. | 987 // allocate the arguments object by setting 'arguments_'. |
928 arguments_ = arguments; | 988 arguments_ = arguments; |
929 | 989 |
930 // In strict mode 'arguments' does not alias formal parameters. | 990 // In strict mode 'arguments' does not alias formal parameters. |
931 // Therefore in strict mode we allocate parameters as if 'arguments' | 991 // Therefore in strict mode we allocate parameters as if 'arguments' |
932 // were not used. | 992 // were not used. |
933 uses_nonstrict_arguments = !is_strict_mode(); | 993 rewrite_parameters = !is_strict_mode(); |
934 } | 994 } |
935 | 995 |
936 // The same parameter may occur multiple times in the parameters_ list. | 996 if (rewrite_parameters) { |
937 // If it does, and if it is not copied into the context object, it must | 997 // We also need the '.arguments' shadow variable. Declare it and create |
938 // receive the highest parameter index for that parameter; thus iteration | 998 // and bind the corresponding proxy. It's ok to declare it only now |
939 // order is relevant! | 999 // because it's a local variable that is allocated after the parameters |
940 for (int i = params_.length() - 1; i >= 0; --i) { | 1000 // have been allocated. |
941 Variable* var = params_[i]; | 1001 // |
942 ASSERT(var->scope() == this); | 1002 // Note: This is "almost" at temporary variable but we cannot use |
943 if (uses_nonstrict_arguments) { | 1003 // NewTemporary() because the mode needs to be INTERNAL since this |
944 // Give the parameter a use from an inner scope, to force allocation | 1004 // variable may be allocated in the heap-allocated context (temporaries |
945 // to the context. | 1005 // are never allocated in the context). |
946 var->MarkAsAccessedFromInnerScope(); | 1006 arguments_shadow_ = new Variable(this, |
| 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 } |
947 } | 1033 } |
948 | 1034 |
949 if (MustAllocate(var)) { | 1035 } else { |
950 if (MustAllocateInContext(var)) { | 1036 // The arguments object is not used, so we can access parameters directly. |
951 ASSERT(var->rewrite() == NULL || var->IsContextSlot()); | 1037 // The same parameter may occur multiple times in the parameters_ list. |
952 if (var->rewrite() == NULL) { | 1038 // If it does, and if it is not copied into the context object, it must |
953 AllocateHeapSlot(var); | 1039 // receive the highest parameter index for that parameter; thus iteration |
954 } | 1040 // order is relevant! |
955 } else { | 1041 for (int i = 0; i < params_.length(); i++) { |
956 ASSERT(var->rewrite() == NULL || var->IsParameter()); | 1042 Variable* var = params_[i]; |
957 if (var->rewrite() == NULL) { | 1043 ASSERT(var->scope() == this); |
| 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.) |
958 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); | 1062 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); |
959 } | 1063 } |
960 } | 1064 } |
961 } | 1065 } |
962 } | 1066 } |
963 } | 1067 } |
964 | 1068 |
965 | 1069 |
966 void Scope::AllocateNonParameterLocal(Variable* var) { | 1070 void Scope::AllocateNonParameterLocal(Variable* var) { |
967 ASSERT(var->scope() == this); | 1071 ASSERT(var->scope() == this); |
968 ASSERT(var->rewrite() == NULL || | 1072 ASSERT(var->rewrite() == NULL || |
969 !var->IsVariable(FACTORY->result_symbol()) || | 1073 (!var->IsVariable(FACTORY->result_symbol())) || |
970 var->AsSlot() == NULL || | 1074 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); |
971 var->AsSlot()->type() != Slot::LOCAL); | |
972 if (var->rewrite() == NULL && MustAllocate(var)) { | 1075 if (var->rewrite() == NULL && MustAllocate(var)) { |
973 if (MustAllocateInContext(var)) { | 1076 if (MustAllocateInContext(var)) { |
974 AllocateHeapSlot(var); | 1077 AllocateHeapSlot(var); |
975 } else { | 1078 } else { |
976 AllocateStackSlot(var); | 1079 AllocateStackSlot(var); |
977 } | 1080 } |
978 } | 1081 } |
979 } | 1082 } |
980 | 1083 |
981 | 1084 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1139 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
1037 !must_have_local_context) { | 1140 !must_have_local_context) { |
1038 num_heap_slots_ = 0; | 1141 num_heap_slots_ = 0; |
1039 } | 1142 } |
1040 | 1143 |
1041 // Allocation done. | 1144 // Allocation done. |
1042 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1145 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
1043 } | 1146 } |
1044 | 1147 |
1045 } } // namespace v8::internal | 1148 } } // namespace v8::internal |
OLD | NEW |