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

Side by Side Diff: src/scopes.cc

Issue 883823002: Implement proper scoping for "this" in arrow functions Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make sure an unresolved VariableProxy for "this" is not considered a valid LHS Created 5 years, 11 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/scopes.h" 7 #include "src/scopes.h"
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 receiver_ = NULL; 156 receiver_ = NULL;
157 function_ = NULL; 157 function_ = NULL;
158 arguments_ = NULL; 158 arguments_ = NULL;
159 illegal_redecl_ = NULL; 159 illegal_redecl_ = NULL;
160 scope_inside_with_ = false; 160 scope_inside_with_ = false;
161 scope_contains_with_ = false; 161 scope_contains_with_ = false;
162 scope_calls_eval_ = false; 162 scope_calls_eval_ = false;
163 scope_uses_arguments_ = false; 163 scope_uses_arguments_ = false;
164 scope_uses_super_property_ = false; 164 scope_uses_super_property_ = false;
165 scope_uses_super_constructor_call_ = false; 165 scope_uses_super_constructor_call_ = false;
166 scope_uses_this_ = false;
167 asm_module_ = false; 166 asm_module_ = false;
168 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; 167 asm_function_ = outer_scope != NULL && outer_scope->asm_module_;
169 // Inherit the strict mode from the parent scope. 168 // Inherit the strict mode from the parent scope.
170 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; 169 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
171 outer_scope_calls_sloppy_eval_ = false; 170 outer_scope_calls_sloppy_eval_ = false;
172 inner_scope_calls_eval_ = false; 171 inner_scope_calls_eval_ = false;
173 inner_scope_uses_arguments_ = false; 172 inner_scope_uses_arguments_ = false;
174 inner_scope_uses_this_ = false;
175 inner_scope_uses_super_property_ = false; 173 inner_scope_uses_super_property_ = false;
176 inner_scope_uses_super_constructor_call_ = false; 174 inner_scope_uses_super_constructor_call_ = false;
177 force_eager_compilation_ = false; 175 force_eager_compilation_ = false;
178 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) 176 force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
179 ? outer_scope->has_forced_context_allocation() : false; 177 ? outer_scope->has_forced_context_allocation() : false;
180 num_var_or_const_ = 0; 178 num_var_or_const_ = 0;
181 num_stack_slots_ = 0; 179 num_stack_slots_ = 0;
182 num_heap_slots_ = 0; 180 num_heap_slots_ = 0;
183 num_modules_ = 0; 181 num_modules_ = 0;
184 module_var_ = NULL, 182 module_var_ = NULL,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 301 }
304 302
305 // Declare convenience variables. 303 // Declare convenience variables.
306 // Declare and allocate receiver (even for the script scope, and even 304 // Declare and allocate receiver (even for the script scope, and even
307 // if naccesses_ == 0). 305 // if naccesses_ == 0).
308 // NOTE: When loading parameters in the script scope, we must take 306 // NOTE: When loading parameters in the script scope, we must take
309 // care not to access them as properties of the global object, but 307 // care not to access them as properties of the global object, but
310 // instead load them directly from the stack. Currently, the only 308 // instead load them directly from the stack. Currently, the only
311 // such parameter is 'this' which is passed on the stack when 309 // such parameter is 'this' which is passed on the stack when
312 // invoking scripts 310 // invoking scripts
313 if (is_declaration_scope()) { 311 if (has_this_declaration()) {
314 Variable* var = 312 Variable* var =
315 variables_.Declare(this, 313 variables_.Declare(this,
316 ast_value_factory_->this_string(), 314 ast_value_factory_->this_string(),
317 VAR, 315 VAR,
318 false, 316 false,
319 Variable::THIS, 317 Variable::THIS,
320 kCreatedInitialized); 318 kCreatedInitialized);
321 var->AllocateTo(Variable::PARAMETER, -1);
322 receiver_ = var; 319 receiver_ = var;
323 } else {
324 DCHECK(outer_scope() != NULL);
325 receiver_ = outer_scope()->receiver();
326 } 320 }
327 321
328 if (is_function_scope()) { 322 if (is_function_scope()) {
329 // Declare 'arguments' variable which exists in all functions. 323 // Declare 'arguments' variable which exists in all functions.
330 // Note that it might never be accessed, in which case it won't be 324 // Note that it might never be accessed, in which case it won't be
331 // allocated during variable allocation. 325 // allocated during variable allocation.
332 variables_.Declare(this, 326 variables_.Declare(this,
333 ast_value_factory_->arguments_string(), 327 ast_value_factory_->arguments_string(),
334 VAR, 328 VAR,
335 true, 329 true,
(...skipping 27 matching lines...) Expand all
363 // Move unresolved variables 357 // Move unresolved variables
364 for (int i = 0; i < unresolved_.length(); i++) { 358 for (int i = 0; i < unresolved_.length(); i++) {
365 outer_scope()->unresolved_.Add(unresolved_[i], zone()); 359 outer_scope()->unresolved_.Add(unresolved_[i], zone());
366 } 360 }
367 361
368 // Propagate usage flags to outer scope. 362 // Propagate usage flags to outer scope.
369 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); 363 if (uses_arguments()) outer_scope_->RecordArgumentsUsage();
370 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); 364 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage();
371 if (uses_super_constructor_call()) 365 if (uses_super_constructor_call())
372 outer_scope_->RecordSuperConstructorCallUsage(); 366 outer_scope_->RecordSuperConstructorCallUsage();
373 if (uses_this()) outer_scope_->RecordThisUsage();
374 367
375 return NULL; 368 return NULL;
376 } 369 }
377 370
378 371
379 Variable* Scope::LookupLocal(const AstRawString* name) { 372 Variable* Scope::LookupLocal(const AstRawString* name) {
380 Variable* result = variables_.Lookup(name); 373 Variable* result = variables_.Lookup(name);
381 if (result != NULL || scope_info_.is_null()) { 374 if (result != NULL || scope_info_.is_null()) {
382 return result; 375 return result;
383 } 376 }
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 Indent(n1, "// strict mode scope\n"); 880 Indent(n1, "// strict mode scope\n");
888 } 881 }
889 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 882 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
890 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); 883 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
891 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 884 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
892 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); 885 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n");
893 if (scope_uses_super_property_) 886 if (scope_uses_super_property_)
894 Indent(n1, "// scope uses 'super' property\n"); 887 Indent(n1, "// scope uses 'super' property\n");
895 if (scope_uses_super_constructor_call_) 888 if (scope_uses_super_constructor_call_)
896 Indent(n1, "// scope uses 'super' constructor\n"); 889 Indent(n1, "// scope uses 'super' constructor\n");
897 if (scope_uses_this_) Indent(n1, "// scope uses 'this'\n");
898 if (inner_scope_uses_arguments_) { 890 if (inner_scope_uses_arguments_) {
899 Indent(n1, "// inner scope uses 'arguments'\n"); 891 Indent(n1, "// inner scope uses 'arguments'\n");
900 } 892 }
901 if (inner_scope_uses_super_property_) 893 if (inner_scope_uses_super_property_)
902 Indent(n1, "// inner scope uses 'super' property\n"); 894 Indent(n1, "// inner scope uses 'super' property\n");
903 if (inner_scope_uses_super_constructor_call_) { 895 if (inner_scope_uses_super_constructor_call_) {
904 Indent(n1, "// inner scope uses 'super' constructor\n"); 896 Indent(n1, "// inner scope uses 'super' constructor\n");
905 } 897 }
906 if (inner_scope_uses_this_) Indent(n1, "// inner scope uses 'this'\n");
907 if (outer_scope_calls_sloppy_eval_) { 898 if (outer_scope_calls_sloppy_eval_) {
908 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); 899 Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
909 } 900 }
910 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 901 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
911 if (num_stack_slots_ > 0) { Indent(n1, "// "); 902 if (num_stack_slots_ > 0) { Indent(n1, "// ");
912 PrintF("%d stack slots\n", num_stack_slots_); } 903 PrintF("%d stack slots\n", num_stack_slots_); }
913 if (num_heap_slots_ > 0) { Indent(n1, "// "); 904 if (num_heap_slots_ > 0) { Indent(n1, "// ");
914 PrintF("%d heap slots\n", num_heap_slots_); } 905 PrintF("%d heap slots\n", num_heap_slots_); }
915 906
916 // Print locals. 907 // Print locals.
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 inner_scope_uses_arguments_ = true; 1167 inner_scope_uses_arguments_ = true;
1177 } 1168 }
1178 if (inner->scope_uses_super_property_ || 1169 if (inner->scope_uses_super_property_ ||
1179 inner->inner_scope_uses_super_property_) { 1170 inner->inner_scope_uses_super_property_) {
1180 inner_scope_uses_super_property_ = true; 1171 inner_scope_uses_super_property_ = true;
1181 } 1172 }
1182 if (inner->uses_super_constructor_call() || 1173 if (inner->uses_super_constructor_call() ||
1183 inner->inner_scope_uses_super_constructor_call_) { 1174 inner->inner_scope_uses_super_constructor_call_) {
1184 inner_scope_uses_super_constructor_call_ = true; 1175 inner_scope_uses_super_constructor_call_ = true;
1185 } 1176 }
1186 if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) {
1187 inner_scope_uses_this_ = true;
1188 }
1189 } 1177 }
1178
wingo 2015/02/04 10:02:13 extra whitespace
aperez 2015/02/04 21:00:42 Acknowledged.
1190 if (inner->force_eager_compilation_) { 1179 if (inner->force_eager_compilation_) {
1191 force_eager_compilation_ = true; 1180 force_eager_compilation_ = true;
1192 } 1181 }
1193 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { 1182 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) {
1194 inner->asm_function_ = true; 1183 inner->asm_function_ = true;
1195 } 1184 }
1196 } 1185 }
1197 } 1186 }
1198 1187
1199 1188
1200 bool Scope::MustAllocate(Variable* var) { 1189 bool Scope::MustAllocate(Variable* var) {
1201 // Give var a read/write use if there is a chance it might be accessed 1190 // Give var a read/write use if there is a chance it might be accessed
1202 // via an eval() call. This is only possible if the variable has a 1191 // via an eval() call. This is only possible if the variable has a
1203 // visible name. 1192 // visible name.
1204 if ((var->is_this() || !var->raw_name()->IsEmpty()) && 1193 if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
1205 (var->has_forced_context_allocation() || 1194 (var->has_forced_context_allocation() ||
1206 scope_calls_eval_ || 1195 scope_calls_eval_ ||
1207 inner_scope_calls_eval_ || 1196 inner_scope_calls_eval_ ||
1208 scope_contains_with_ || 1197 scope_contains_with_ ||
1209 is_catch_scope() || 1198 is_catch_scope() ||
1210 is_block_scope() || 1199 is_block_scope() ||
1211 is_module_scope() || 1200 is_module_scope() ||
1212 is_script_scope())) { 1201 is_script_scope())) {
1213 var->set_is_used(); 1202 var->set_is_used();
1214 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); 1203 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned();
1215 } 1204 }
1216 // Global variables do not need to be allocated. 1205 // Global variables do not need to be allocated, except the receiver
1217 return !var->IsGlobalObjectProperty() && var->is_used(); 1206 // which is not preallocated.
wingo 2015/02/04 10:02:13 Confusing comment. Also I think the conditional
aperez 2015/02/04 21:00:42 Acknowledged.
1207 return (var->is_this() || !var->IsGlobalObjectProperty()) && var->is_used();
1218 } 1208 }
1219 1209
1220 1210
1221 bool Scope::MustAllocateInContext(Variable* var) { 1211 bool Scope::MustAllocateInContext(Variable* var) {
1222 // If var is accessed from an inner scope, or if there is a possibility 1212 // If var is accessed from an inner scope, or if there is a possibility
1223 // that it might be accessed from the current or an inner scope (through 1213 // that it might be accessed from the current or an inner scope (through
1224 // an eval() call or a runtime with lookup), it must be allocated in the 1214 // an eval() call or a runtime with lookup), it must be allocated in the
1225 // context. 1215 // context.
1226 // 1216 //
1227 // Exceptions: If the scope as a whole has forced context allocation, all 1217 // Exceptions: If the scope as a whole has forced context allocation, all
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 // If it does, and if it is not copied into the context object, it must 1282 // If it does, and if it is not copied into the context object, it must
1293 // receive the highest parameter index for that parameter; thus iteration 1283 // receive the highest parameter index for that parameter; thus iteration
1294 // order is relevant! 1284 // order is relevant!
1295 for (int i = params_.length() - 1; i >= 0; --i) { 1285 for (int i = params_.length() - 1; i >= 0; --i) {
1296 Variable* var = params_[i]; 1286 Variable* var = params_[i];
1297 DCHECK(var->scope() == this); 1287 DCHECK(var->scope() == this);
1298 if (uses_sloppy_arguments || has_forced_context_allocation()) { 1288 if (uses_sloppy_arguments || has_forced_context_allocation()) {
1299 // Force context allocation of the parameter. 1289 // Force context allocation of the parameter.
1300 var->ForceContextAllocation(); 1290 var->ForceContextAllocation();
1301 } 1291 }
1292 AllocateParameter(var, i);
1293 }
1294 }
1302 1295
1303 if (MustAllocate(var)) { 1296
1304 if (MustAllocateInContext(var)) { 1297 void Scope::AllocateReceiver() {
1305 DCHECK(var->IsUnallocated() || var->IsContextSlot()); 1298 DCHECK(receiver());
1306 if (var->IsUnallocated()) { 1299 DCHECK(receiver()->scope() == this);
wingo 2015/02/04 10:02:13 the second DCHECK is sufficient, I think, if we ad
aperez 2015/02/04 21:00:42 Acknowledged.
1307 AllocateHeapSlot(var); 1300
1308 } 1301 if (has_forced_context_allocation()) {
1309 } else { 1302 // Force context allocation of the receiver.
1310 DCHECK(var->IsUnallocated() || var->IsParameter()); 1303 receiver()->ForceContextAllocation();
1311 if (var->IsUnallocated()) { 1304 }
1312 var->AllocateTo(Variable::PARAMETER, i); 1305 AllocateParameter(receiver(), -1);
1313 } 1306 }
1307
1308
1309 void Scope::AllocateParameter(Variable* var, int index) {
1310 if (MustAllocate(var)) {
1311 if (MustAllocateInContext(var)) {
1312 DCHECK(var->IsUnallocated() || var->IsContextSlot());
1313 if (var->IsUnallocated()) {
1314 AllocateHeapSlot(var);
1315 }
1316 } else {
1317 DCHECK(var->IsUnallocated() || var->IsParameter());
1318 if (var->IsUnallocated()) {
1319 var->AllocateTo(Variable::PARAMETER, index);
1314 } 1320 }
1315 } 1321 }
1316 } 1322 }
1317 } 1323 }
1318 1324
1319 1325
1320 void Scope::AllocateNonParameterLocal(Variable* var) { 1326 void Scope::AllocateNonParameterLocal(Variable* var) {
1321 DCHECK(var->scope() == this); 1327 DCHECK(var->scope() == this);
1322 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || 1328 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) ||
1323 !var->IsStackLocal()); 1329 !var->IsStackLocal());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 1378
1373 // If scope is already resolved, we still need to allocate 1379 // If scope is already resolved, we still need to allocate
1374 // variables in inner scopes which might not had been resolved yet. 1380 // variables in inner scopes which might not had been resolved yet.
1375 if (already_resolved()) return; 1381 if (already_resolved()) return;
1376 // The number of slots required for variables. 1382 // The number of slots required for variables.
1377 num_stack_slots_ = 0; 1383 num_stack_slots_ = 0;
1378 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1384 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1379 1385
1380 // Allocate variables for this scope. 1386 // Allocate variables for this scope.
1381 // Parameters must be allocated first, if any. 1387 // Parameters must be allocated first, if any.
1388 if (has_this_declaration()) AllocateReceiver();
1382 if (is_function_scope()) AllocateParameterLocals(); 1389 if (is_function_scope()) AllocateParameterLocals();
1383 AllocateNonParameterLocals(); 1390 AllocateNonParameterLocals();
1384 1391
1385 // Force allocation of a context for this scope if necessary. For a 'with' 1392 // Force allocation of a context for this scope if necessary. For a 'with'
1386 // scope and for a function scope that makes an 'eval' call we need a context, 1393 // scope and for a function scope that makes an 'eval' call we need a context,
1387 // even if no local variables were statically allocated in the scope. 1394 // even if no local variables were statically allocated in the scope.
1388 // Likewise for modules. 1395 // Likewise for modules.
1389 bool must_have_context = is_with_scope() || is_module_scope() || 1396 bool must_have_context = is_with_scope() || is_module_scope() ||
1390 (is_function_scope() && calls_eval()); 1397 (is_function_scope() && calls_eval());
1391 1398
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 } 1430 }
1424 1431
1425 1432
1426 int Scope::ContextLocalCount() const { 1433 int Scope::ContextLocalCount() const {
1427 if (num_heap_slots() == 0) return 0; 1434 if (num_heap_slots() == 0) return 0;
1428 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1435 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS -
1429 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); 1436 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0);
1430 } 1437 }
1431 1438
1432 } } // namespace v8::internal 1439 } } // namespace v8::internal
OLDNEW
« src/scopes.h ('K') | « src/scopes.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698