Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/scopes.cc

Issue 7167006: Merge arguments branch to bleeding merge. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix test arguments.js." Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/scopes.h ('k') | src/stub-cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/scopes.h ('k') | src/stub-cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698