| 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 |