OLD | NEW |
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 13 matching lines...) Expand all Loading... |
24 // use. Because a Variable holding a handle with the same location exists | 24 // use. Because a Variable holding a handle with the same location exists |
25 // this is ensured. | 25 // this is ensured. |
26 | 26 |
27 VariableMap::VariableMap(Zone* zone) | 27 VariableMap::VariableMap(Zone* zone) |
28 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), | 28 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), |
29 zone_(zone) {} | 29 zone_(zone) {} |
30 VariableMap::~VariableMap() {} | 30 VariableMap::~VariableMap() {} |
31 | 31 |
32 | 32 |
33 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, | 33 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, |
34 VariableMode mode, bool is_valid_lhs, | 34 VariableMode mode, |
35 Variable::Kind kind, | 35 Variable::Kind kind, |
36 InitializationFlag initialization_flag, | 36 InitializationFlag initialization_flag, |
37 MaybeAssignedFlag maybe_assigned_flag, | 37 MaybeAssignedFlag maybe_assigned_flag, |
38 Interface* interface) { | 38 Interface* interface) { |
39 // AstRawStrings are unambiguous, i.e., the same string is always represented | 39 // AstRawStrings are unambiguous, i.e., the same string is always represented |
40 // by the same AstRawString*. | 40 // by the same AstRawString*. |
41 // FIXME(marja): fix the type of Lookup. | 41 // FIXME(marja): fix the type of Lookup. |
42 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 42 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
43 true, ZoneAllocationPolicy(zone())); | 43 true, ZoneAllocationPolicy(zone())); |
44 if (p->value == NULL) { | 44 if (p->value == NULL) { |
45 // The variable has not been declared yet -> insert it. | 45 // The variable has not been declared yet -> insert it. |
46 DCHECK(p->key == name); | 46 DCHECK(p->key == name); |
47 p->value = new (zone()) | 47 p->value = new (zone()) |
48 Variable(scope, name, mode, is_valid_lhs, kind, initialization_flag, | 48 Variable(scope, name, mode, kind, initialization_flag, |
49 maybe_assigned_flag, interface); | 49 maybe_assigned_flag, interface); |
50 } | 50 } |
51 return reinterpret_cast<Variable*>(p->value); | 51 return reinterpret_cast<Variable*>(p->value); |
52 } | 52 } |
53 | 53 |
54 | 54 |
55 Variable* VariableMap::Lookup(const AstRawString* name) { | 55 Variable* VariableMap::Lookup(const AstRawString* name) { |
56 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 56 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
57 false, ZoneAllocationPolicy(NULL)); | 57 false, ZoneAllocationPolicy(NULL)); |
58 if (p != NULL) { | 58 if (p != NULL) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 already_resolved_(true), | 130 already_resolved_(true), |
131 ast_value_factory_(value_factory), | 131 ast_value_factory_(value_factory), |
132 zone_(zone) { | 132 zone_(zone) { |
133 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); | 133 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
134 AddInnerScope(inner_scope); | 134 AddInnerScope(inner_scope); |
135 ++num_var_or_const_; | 135 ++num_var_or_const_; |
136 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 136 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
137 Variable* variable = variables_.Declare(this, | 137 Variable* variable = variables_.Declare(this, |
138 catch_variable_name, | 138 catch_variable_name, |
139 VAR, | 139 VAR, |
140 true, // Valid left-hand side. | |
141 Variable::NORMAL, | 140 Variable::NORMAL, |
142 kCreatedInitialized); | 141 kCreatedInitialized); |
143 AllocateHeapSlot(variable); | 142 AllocateHeapSlot(variable); |
144 } | 143 } |
145 | 144 |
146 | 145 |
147 void Scope::SetDefaults(ScopeType scope_type, | 146 void Scope::SetDefaults(ScopeType scope_type, |
148 Scope* outer_scope, | 147 Scope* outer_scope, |
149 Handle<ScopeInfo> scope_info) { | 148 Handle<ScopeInfo> scope_info) { |
150 outer_scope_ = outer_scope; | 149 outer_scope_ = outer_scope; |
151 scope_type_ = scope_type; | 150 scope_type_ = scope_type; |
152 scope_name_ = ast_value_factory_->empty_string(); | 151 scope_name_ = ast_value_factory_->empty_string(); |
153 dynamics_ = NULL; | 152 dynamics_ = NULL; |
154 receiver_ = NULL; | 153 receiver_ = NULL; |
155 function_ = NULL; | 154 function_ = NULL; |
156 arguments_ = NULL; | 155 arguments_ = NULL; |
157 illegal_redecl_ = NULL; | 156 illegal_redecl_ = NULL; |
158 scope_inside_with_ = false; | 157 scope_inside_with_ = false; |
159 scope_contains_with_ = false; | 158 scope_contains_with_ = false; |
160 scope_calls_eval_ = false; | 159 scope_calls_eval_ = false; |
161 scope_uses_arguments_ = false; | 160 scope_uses_arguments_ = false; |
162 scope_uses_super_property_ = false; | 161 scope_uses_super_property_ = false; |
163 scope_uses_super_constructor_call_ = false; | 162 scope_uses_super_constructor_call_ = false; |
164 scope_uses_this_ = false; | |
165 asm_module_ = false; | 163 asm_module_ = false; |
166 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; | 164 asm_function_ = outer_scope != NULL && outer_scope->asm_module_; |
167 // Inherit the strict mode from the parent scope. | 165 // Inherit the strict mode from the parent scope. |
168 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; | 166 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; |
169 outer_scope_calls_sloppy_eval_ = false; | 167 outer_scope_calls_sloppy_eval_ = false; |
170 inner_scope_calls_eval_ = false; | 168 inner_scope_calls_eval_ = false; |
171 inner_scope_uses_arguments_ = false; | 169 inner_scope_uses_arguments_ = false; |
172 inner_scope_uses_this_ = false; | |
173 inner_scope_uses_super_property_ = false; | 170 inner_scope_uses_super_property_ = false; |
174 inner_scope_uses_super_constructor_call_ = false; | 171 inner_scope_uses_super_constructor_call_ = false; |
175 force_eager_compilation_ = false; | 172 force_eager_compilation_ = false; |
176 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) | 173 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) |
177 ? outer_scope->has_forced_context_allocation() : false; | 174 ? outer_scope->has_forced_context_allocation() : false; |
178 num_var_or_const_ = 0; | 175 num_var_or_const_ = 0; |
179 num_stack_slots_ = 0; | 176 num_stack_slots_ = 0; |
180 num_heap_slots_ = 0; | 177 num_heap_slots_ = 0; |
181 num_modules_ = 0; | 178 num_modules_ = 0; |
182 module_var_ = NULL, | 179 module_var_ = NULL, |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 } | 300 } |
304 | 301 |
305 // Declare convenience variables. | 302 // Declare convenience variables. |
306 // Declare and allocate receiver (even for the script scope, and even | 303 // Declare and allocate receiver (even for the script scope, and even |
307 // if naccesses_ == 0). | 304 // if naccesses_ == 0). |
308 // NOTE: When loading parameters in the script scope, we must take | 305 // NOTE: When loading parameters in the script scope, we must take |
309 // care not to access them as properties of the global object, but | 306 // care not to access them as properties of the global object, but |
310 // instead load them directly from the stack. Currently, the only | 307 // instead load them directly from the stack. Currently, the only |
311 // such parameter is 'this' which is passed on the stack when | 308 // such parameter is 'this' which is passed on the stack when |
312 // invoking scripts | 309 // invoking scripts |
313 if (is_declaration_scope()) { | 310 if (has_this_declaration()) { |
314 Variable* var = | 311 Variable* var = |
315 variables_.Declare(this, | 312 variables_.Declare(this, |
316 ast_value_factory_->this_string(), | 313 ast_value_factory_->this_string(), |
317 VAR, | 314 VAR, |
318 false, | |
319 Variable::THIS, | 315 Variable::THIS, |
320 kCreatedInitialized); | 316 kCreatedInitialized); |
321 var->AllocateTo(Variable::PARAMETER, -1); | |
322 receiver_ = var; | 317 receiver_ = var; |
323 } else { | |
324 DCHECK(outer_scope() != NULL); | |
325 receiver_ = outer_scope()->receiver(); | |
326 } | 318 } |
327 | 319 |
328 if (is_function_scope()) { | 320 if (is_function_scope()) { |
329 // Declare 'arguments' variable which exists in all functions. | 321 // Declare 'arguments' variable which exists in all functions. |
330 // Note that it might never be accessed, in which case it won't be | 322 // Note that it might never be accessed, in which case it won't be |
331 // allocated during variable allocation. | 323 // allocated during variable allocation. |
332 variables_.Declare(this, | 324 variables_.Declare(this, |
333 ast_value_factory_->arguments_string(), | 325 ast_value_factory_->arguments_string(), |
334 VAR, | 326 VAR, |
335 true, | |
336 Variable::ARGUMENTS, | 327 Variable::ARGUMENTS, |
337 kCreatedInitialized); | 328 kCreatedInitialized); |
338 } | 329 } |
339 } | 330 } |
340 | 331 |
341 | 332 |
342 Scope* Scope::FinalizeBlockScope() { | 333 Scope* Scope::FinalizeBlockScope() { |
343 DCHECK(is_block_scope()); | 334 DCHECK(is_block_scope()); |
344 DCHECK(internals_.is_empty()); | 335 DCHECK(internals_.is_empty()); |
345 DCHECK(temps_.is_empty()); | 336 DCHECK(temps_.is_empty()); |
(...skipping 17 matching lines...) Expand all Loading... |
363 // Move unresolved variables | 354 // Move unresolved variables |
364 for (int i = 0; i < unresolved_.length(); i++) { | 355 for (int i = 0; i < unresolved_.length(); i++) { |
365 outer_scope()->unresolved_.Add(unresolved_[i], zone()); | 356 outer_scope()->unresolved_.Add(unresolved_[i], zone()); |
366 } | 357 } |
367 | 358 |
368 // Propagate usage flags to outer scope. | 359 // Propagate usage flags to outer scope. |
369 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); | 360 if (uses_arguments()) outer_scope_->RecordArgumentsUsage(); |
370 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); | 361 if (uses_super_property()) outer_scope_->RecordSuperPropertyUsage(); |
371 if (uses_super_constructor_call()) | 362 if (uses_super_constructor_call()) |
372 outer_scope_->RecordSuperConstructorCallUsage(); | 363 outer_scope_->RecordSuperConstructorCallUsage(); |
373 if (uses_this()) outer_scope_->RecordThisUsage(); | |
374 | 364 |
375 return NULL; | 365 return NULL; |
376 } | 366 } |
377 | 367 |
378 | 368 |
379 Variable* Scope::LookupLocal(const AstRawString* name) { | 369 Variable* Scope::LookupLocal(const AstRawString* name) { |
380 Variable* result = variables_.Lookup(name); | 370 Variable* result = variables_.Lookup(name); |
381 if (result != NULL || scope_info_.is_null()) { | 371 if (result != NULL || scope_info_.is_null()) { |
382 return result; | 372 return result; |
383 } | 373 } |
(...skipping 19 matching lines...) Expand all Loading... |
403 | 393 |
404 mode = DYNAMIC; | 394 mode = DYNAMIC; |
405 location = Variable::LOOKUP; | 395 location = Variable::LOOKUP; |
406 init_flag = kCreatedInitialized; | 396 init_flag = kCreatedInitialized; |
407 // Be conservative and flag parameters as maybe assigned. Better information | 397 // Be conservative and flag parameters as maybe assigned. Better information |
408 // would require ScopeInfo to serialize the maybe_assigned bit also for | 398 // would require ScopeInfo to serialize the maybe_assigned bit also for |
409 // parameters. | 399 // parameters. |
410 maybe_assigned_flag = kMaybeAssigned; | 400 maybe_assigned_flag = kMaybeAssigned; |
411 } | 401 } |
412 | 402 |
413 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 403 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
414 init_flag, maybe_assigned_flag); | 404 init_flag, maybe_assigned_flag); |
415 var->AllocateTo(location, index); | 405 var->AllocateTo(location, index); |
416 return var; | 406 return var; |
417 } | 407 } |
418 | 408 |
419 | 409 |
420 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 410 Variable* Scope::LookupFunctionVar(const AstRawString* name, |
421 AstNodeFactory* factory) { | 411 AstNodeFactory* factory) { |
422 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 412 if (function_ != NULL && function_->proxy()->raw_name() == name) { |
423 return function_->proxy()->var(); | 413 return function_->proxy()->var(); |
424 } else if (!scope_info_.is_null()) { | 414 } else if (!scope_info_.is_null()) { |
425 // If we are backed by a scope info, try to lookup the variable there. | 415 // If we are backed by a scope info, try to lookup the variable there. |
426 VariableMode mode; | 416 VariableMode mode; |
427 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 417 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
428 if (index < 0) return NULL; | 418 if (index < 0) return NULL; |
429 Variable* var = new(zone()) Variable( | 419 Variable* var = new(zone()) Variable(this, name, |
430 this, name, mode, true /* is valid LHS */, | 420 mode, Variable::NORMAL, kCreatedInitialized); |
431 Variable::NORMAL, kCreatedInitialized); | |
432 VariableProxy* proxy = factory->NewVariableProxy(var); | 421 VariableProxy* proxy = factory->NewVariableProxy(var); |
433 VariableDeclaration* declaration = factory->NewVariableDeclaration( | 422 VariableDeclaration* declaration = factory->NewVariableDeclaration( |
434 proxy, mode, this, RelocInfo::kNoPosition); | 423 proxy, mode, this, RelocInfo::kNoPosition); |
435 DeclareFunctionVar(declaration); | 424 DeclareFunctionVar(declaration); |
436 var->AllocateTo(Variable::CONTEXT, index); | 425 var->AllocateTo(Variable::CONTEXT, index); |
437 return var; | 426 return var; |
438 } else { | 427 } else { |
439 return NULL; | 428 return NULL; |
440 } | 429 } |
441 } | 430 } |
442 | 431 |
443 | 432 |
444 Variable* Scope::Lookup(const AstRawString* name) { | 433 Variable* Scope::Lookup(const AstRawString* name) { |
445 for (Scope* scope = this; | 434 for (Scope* scope = this; |
446 scope != NULL; | 435 scope != NULL; |
447 scope = scope->outer_scope()) { | 436 scope = scope->outer_scope()) { |
448 Variable* var = scope->LookupLocal(name); | 437 Variable* var = scope->LookupLocal(name); |
449 if (var != NULL) return var; | 438 if (var != NULL) return var; |
450 } | 439 } |
451 return NULL; | 440 return NULL; |
452 } | 441 } |
453 | 442 |
454 | 443 |
455 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, | 444 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, |
456 bool is_rest) { | 445 bool is_rest) { |
457 DCHECK(!already_resolved()); | 446 DCHECK(!already_resolved()); |
458 DCHECK(is_function_scope()); | 447 DCHECK(is_function_scope()); |
459 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 448 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
460 kCreatedInitialized); | 449 kCreatedInitialized); |
461 if (is_rest) { | 450 if (is_rest) { |
462 DCHECK_NULL(rest_parameter_); | 451 DCHECK_NULL(rest_parameter_); |
463 rest_parameter_ = var; | 452 rest_parameter_ = var; |
464 rest_index_ = num_parameters(); | 453 rest_index_ = num_parameters(); |
465 } | 454 } |
466 params_.Add(var, zone()); | 455 params_.Add(var, zone()); |
467 return var; | 456 return var; |
468 } | 457 } |
469 | 458 |
470 | 459 |
471 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 460 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
472 InitializationFlag init_flag, | 461 InitializationFlag init_flag, |
473 MaybeAssignedFlag maybe_assigned_flag, | 462 MaybeAssignedFlag maybe_assigned_flag, |
474 Interface* interface) { | 463 Interface* interface) { |
475 DCHECK(!already_resolved()); | 464 DCHECK(!already_resolved()); |
476 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 465 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
477 // introduces during variable allocation, INTERNAL variables are allocated | 466 // introduces during variable allocation, INTERNAL variables are allocated |
478 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 467 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
479 DCHECK(IsDeclaredVariableMode(mode)); | 468 DCHECK(IsDeclaredVariableMode(mode)); |
480 ++num_var_or_const_; | 469 ++num_var_or_const_; |
481 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 470 return variables_.Declare(this, name, mode, Variable::NORMAL, init_flag, |
482 maybe_assigned_flag, interface); | 471 maybe_assigned_flag, interface); |
483 } | 472 } |
484 | 473 |
485 | 474 |
486 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 475 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
487 DCHECK(is_script_scope()); | 476 DCHECK(is_script_scope()); |
488 return variables_.Declare(this, | 477 return variables_.Declare(this, |
489 name, | 478 name, |
490 DYNAMIC_GLOBAL, | 479 DYNAMIC_GLOBAL, |
491 true, | |
492 Variable::NORMAL, | 480 Variable::NORMAL, |
493 kCreatedInitialized); | 481 kCreatedInitialized); |
494 } | 482 } |
495 | 483 |
496 | 484 |
497 void Scope::RemoveUnresolved(VariableProxy* var) { | 485 void Scope::RemoveUnresolved(VariableProxy* var) { |
498 // Most likely (always?) any variable we want to remove | 486 // Most likely (always?) any variable we want to remove |
499 // was just added before, so we search backwards. | 487 // was just added before, so we search backwards. |
500 for (int i = unresolved_.length(); i-- > 0;) { | 488 for (int i = unresolved_.length(); i-- > 0;) { |
501 if (unresolved_[i] == var) { | 489 if (unresolved_[i] == var) { |
502 unresolved_.Remove(i); | 490 unresolved_.Remove(i); |
503 return; | 491 return; |
504 } | 492 } |
505 } | 493 } |
506 } | 494 } |
507 | 495 |
508 | 496 |
509 Variable* Scope::NewInternal(const AstRawString* name) { | 497 Variable* Scope::NewInternal(const AstRawString* name) { |
510 DCHECK(!already_resolved()); | 498 DCHECK(!already_resolved()); |
511 Variable* var = new(zone()) Variable(this, | 499 Variable* var = new(zone()) Variable(this, |
512 name, | 500 name, |
513 INTERNAL, | 501 INTERNAL, |
514 false, | |
515 Variable::NORMAL, | 502 Variable::NORMAL, |
516 kCreatedInitialized); | 503 kCreatedInitialized); |
517 internals_.Add(var, zone()); | 504 internals_.Add(var, zone()); |
518 return var; | 505 return var; |
519 } | 506 } |
520 | 507 |
521 | 508 |
522 Variable* Scope::NewTemporary(const AstRawString* name) { | 509 Variable* Scope::NewTemporary(const AstRawString* name) { |
523 DCHECK(!already_resolved()); | 510 DCHECK(!already_resolved()); |
524 Variable* var = new(zone()) Variable(this, | 511 Variable* var = new(zone()) Variable(this, |
525 name, | 512 name, |
526 TEMPORARY, | 513 TEMPORARY, |
527 true, | |
528 Variable::NORMAL, | 514 Variable::NORMAL, |
529 kCreatedInitialized); | 515 kCreatedInitialized); |
530 temps_.Add(var, zone()); | 516 temps_.Add(var, zone()); |
531 return var; | 517 return var; |
532 } | 518 } |
533 | 519 |
534 | 520 |
535 void Scope::AddDeclaration(Declaration* declaration) { | 521 void Scope::AddDeclaration(Declaration* declaration) { |
536 decls_.Add(declaration, zone()); | 522 decls_.Add(declaration, zone()); |
537 } | 523 } |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 Indent(n1, "// strict mode scope\n"); | 879 Indent(n1, "// strict mode scope\n"); |
894 } | 880 } |
895 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); | 881 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); |
896 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); | 882 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); |
897 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); | 883 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); |
898 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); | 884 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); |
899 if (scope_uses_super_property_) | 885 if (scope_uses_super_property_) |
900 Indent(n1, "// scope uses 'super' property\n"); | 886 Indent(n1, "// scope uses 'super' property\n"); |
901 if (scope_uses_super_constructor_call_) | 887 if (scope_uses_super_constructor_call_) |
902 Indent(n1, "// scope uses 'super' constructor\n"); | 888 Indent(n1, "// scope uses 'super' constructor\n"); |
903 if (scope_uses_this_) Indent(n1, "// scope uses 'this'\n"); | |
904 if (inner_scope_uses_arguments_) { | 889 if (inner_scope_uses_arguments_) { |
905 Indent(n1, "// inner scope uses 'arguments'\n"); | 890 Indent(n1, "// inner scope uses 'arguments'\n"); |
906 } | 891 } |
907 if (inner_scope_uses_super_property_) | 892 if (inner_scope_uses_super_property_) |
908 Indent(n1, "// inner scope uses 'super' property\n"); | 893 Indent(n1, "// inner scope uses 'super' property\n"); |
909 if (inner_scope_uses_super_constructor_call_) { | 894 if (inner_scope_uses_super_constructor_call_) { |
910 Indent(n1, "// inner scope uses 'super' constructor\n"); | 895 Indent(n1, "// inner scope uses 'super' constructor\n"); |
911 } | 896 } |
912 if (inner_scope_uses_this_) Indent(n1, "// inner scope uses 'this'\n"); | |
913 if (outer_scope_calls_sloppy_eval_) { | 897 if (outer_scope_calls_sloppy_eval_) { |
914 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); | 898 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
915 } | 899 } |
916 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 900 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
917 if (num_stack_slots_ > 0) { Indent(n1, "// "); | 901 if (num_stack_slots_ > 0) { Indent(n1, "// "); |
918 PrintF("%d stack slots\n", num_stack_slots_); } | 902 PrintF("%d stack slots\n", num_stack_slots_); } |
919 if (num_heap_slots_ > 0) { Indent(n1, "// "); | 903 if (num_heap_slots_ > 0) { Indent(n1, "// "); |
920 PrintF("%d heap slots\n", num_heap_slots_); } | 904 PrintF("%d heap slots\n", num_heap_slots_); } |
921 | 905 |
922 // Print locals. | 906 // Print locals. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); | 952 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); |
969 VariableMap* map = dynamics_->GetMap(mode); | 953 VariableMap* map = dynamics_->GetMap(mode); |
970 Variable* var = map->Lookup(name); | 954 Variable* var = map->Lookup(name); |
971 if (var == NULL) { | 955 if (var == NULL) { |
972 // Declare a new non-local. | 956 // Declare a new non-local. |
973 InitializationFlag init_flag = (mode == VAR) | 957 InitializationFlag init_flag = (mode == VAR) |
974 ? kCreatedInitialized : kNeedsInitialization; | 958 ? kCreatedInitialized : kNeedsInitialization; |
975 var = map->Declare(NULL, | 959 var = map->Declare(NULL, |
976 name, | 960 name, |
977 mode, | 961 mode, |
978 true, | |
979 Variable::NORMAL, | 962 Variable::NORMAL, |
980 init_flag); | 963 init_flag); |
981 // Allocate it by giving it a dynamic lookup. | 964 // Allocate it by giving it a dynamic lookup. |
982 var->AllocateTo(Variable::LOOKUP, -1); | 965 var->AllocateTo(Variable::LOOKUP, -1); |
983 } | 966 } |
984 return var; | 967 return var; |
985 } | 968 } |
986 | 969 |
987 | 970 |
988 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 971 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 inner_scope_uses_arguments_ = true; | 1165 inner_scope_uses_arguments_ = true; |
1183 } | 1166 } |
1184 if (inner->scope_uses_super_property_ || | 1167 if (inner->scope_uses_super_property_ || |
1185 inner->inner_scope_uses_super_property_) { | 1168 inner->inner_scope_uses_super_property_) { |
1186 inner_scope_uses_super_property_ = true; | 1169 inner_scope_uses_super_property_ = true; |
1187 } | 1170 } |
1188 if (inner->uses_super_constructor_call() || | 1171 if (inner->uses_super_constructor_call() || |
1189 inner->inner_scope_uses_super_constructor_call_) { | 1172 inner->inner_scope_uses_super_constructor_call_) { |
1190 inner_scope_uses_super_constructor_call_ = true; | 1173 inner_scope_uses_super_constructor_call_ = true; |
1191 } | 1174 } |
1192 if (inner->scope_uses_this_ || inner->inner_scope_uses_this_) { | |
1193 inner_scope_uses_this_ = true; | |
1194 } | |
1195 } | 1175 } |
1196 if (inner->force_eager_compilation_) { | 1176 if (inner->force_eager_compilation_) { |
1197 force_eager_compilation_ = true; | 1177 force_eager_compilation_ = true; |
1198 } | 1178 } |
1199 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { | 1179 if (asm_module_ && inner->scope_type() == FUNCTION_SCOPE) { |
1200 inner->asm_function_ = true; | 1180 inner->asm_function_ = true; |
1201 } | 1181 } |
1202 } | 1182 } |
1203 } | 1183 } |
1204 | 1184 |
1205 | 1185 |
1206 bool Scope::MustAllocate(Variable* var) { | 1186 bool Scope::MustAllocate(Variable* var) { |
1207 // Give var a read/write use if there is a chance it might be accessed | 1187 // Give var a read/write use if there is a chance it might be accessed |
1208 // via an eval() call. This is only possible if the variable has a | 1188 // via an eval() call. This is only possible if the variable has a |
1209 // visible name. | 1189 // visible name. |
1210 if ((var->is_this() || !var->raw_name()->IsEmpty()) && | 1190 if ((var->is_this() || !var->raw_name()->IsEmpty()) && |
1211 (var->has_forced_context_allocation() || | 1191 (var->has_forced_context_allocation() || |
1212 scope_calls_eval_ || | 1192 scope_calls_eval_ || |
1213 inner_scope_calls_eval_ || | 1193 inner_scope_calls_eval_ || |
1214 scope_contains_with_ || | 1194 scope_contains_with_ || |
1215 is_catch_scope() || | 1195 is_catch_scope() || |
1216 is_block_scope() || | 1196 is_block_scope() || |
1217 is_module_scope() || | 1197 is_module_scope() || |
1218 is_script_scope())) { | 1198 is_script_scope())) { |
1219 var->set_is_used(); | 1199 var->set_is_used(); |
1220 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1200 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
1221 } | 1201 } |
1222 // Global variables do not need to be allocated. | 1202 // Global variables do not need to be allocated. |
1223 return !var->IsGlobalObjectProperty() && var->is_used(); | 1203 return var->is_this() || (var->is_used() && !var->IsGlobalObjectProperty()); |
1224 } | 1204 } |
1225 | 1205 |
1226 | 1206 |
1227 bool Scope::MustAllocateInContext(Variable* var) { | 1207 bool Scope::MustAllocateInContext(Variable* var) { |
1228 // If var is accessed from an inner scope, or if there is a possibility | 1208 // If var is accessed from an inner scope, or if there is a possibility |
1229 // that it might be accessed from the current or an inner scope (through | 1209 // that it might be accessed from the current or an inner scope (through |
1230 // an eval() call or a runtime with lookup), it must be allocated in the | 1210 // an eval() call or a runtime with lookup), it must be allocated in the |
1231 // context. | 1211 // context. |
1232 // | 1212 // |
1233 // Exceptions: If the scope as a whole has forced context allocation, all | 1213 // Exceptions: If the scope as a whole has forced context allocation, all |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1304 // order is relevant! | 1284 // order is relevant! |
1305 for (int i = params_.length() - 1; i >= 0; --i) { | 1285 for (int i = params_.length() - 1; i >= 0; --i) { |
1306 Variable* var = params_[i]; | 1286 Variable* var = params_[i]; |
1307 if (var == rest_parameter_) continue; | 1287 if (var == rest_parameter_) continue; |
1308 | 1288 |
1309 DCHECK(var->scope() == this); | 1289 DCHECK(var->scope() == this); |
1310 if (uses_sloppy_arguments || has_forced_context_allocation()) { | 1290 if (uses_sloppy_arguments || has_forced_context_allocation()) { |
1311 // Force context allocation of the parameter. | 1291 // Force context allocation of the parameter. |
1312 var->ForceContextAllocation(); | 1292 var->ForceContextAllocation(); |
1313 } | 1293 } |
| 1294 AllocateParameter(var, i); |
| 1295 } |
| 1296 } |
1314 | 1297 |
1315 if (MustAllocate(var)) { | 1298 |
1316 if (MustAllocateInContext(var)) { | 1299 void Scope::AllocateReceiver() { |
1317 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | 1300 DCHECK_EQ(receiver()->scope(), this); |
1318 if (var->IsUnallocated()) { | 1301 |
1319 AllocateHeapSlot(var); | 1302 if (has_forced_context_allocation()) { |
1320 } | 1303 // Force context allocation of the receiver. |
1321 } else { | 1304 receiver()->ForceContextAllocation(); |
1322 DCHECK(var->IsUnallocated() || var->IsParameter()); | 1305 } |
1323 if (var->IsUnallocated()) { | 1306 AllocateParameter(receiver(), -1); |
1324 var->AllocateTo(Variable::PARAMETER, i); | 1307 } |
1325 } | 1308 |
| 1309 |
| 1310 void Scope::AllocateParameter(Variable* var, int index) { |
| 1311 if (MustAllocate(var)) { |
| 1312 if (MustAllocateInContext(var)) { |
| 1313 DCHECK(var->IsUnallocated() || var->IsContextSlot()); |
| 1314 if (var->IsUnallocated()) { |
| 1315 AllocateHeapSlot(var); |
| 1316 } |
| 1317 } else { |
| 1318 DCHECK(var->IsUnallocated() || var->IsParameter()); |
| 1319 if (var->IsUnallocated()) { |
| 1320 var->AllocateTo(Variable::PARAMETER, index); |
1326 } | 1321 } |
1327 } | 1322 } |
1328 } | 1323 } |
1329 } | 1324 } |
1330 | 1325 |
1331 | 1326 |
1332 void Scope::AllocateNonParameterLocal(Variable* var) { | 1327 void Scope::AllocateNonParameterLocal(Variable* var) { |
1333 DCHECK(var->scope() == this); | 1328 DCHECK(var->scope() == this); |
1334 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || | 1329 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || |
1335 !var->IsStackLocal()); | 1330 !var->IsStackLocal()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 | 1383 |
1389 // If scope is already resolved, we still need to allocate | 1384 // If scope is already resolved, we still need to allocate |
1390 // variables in inner scopes which might not had been resolved yet. | 1385 // variables in inner scopes which might not had been resolved yet. |
1391 if (already_resolved()) return; | 1386 if (already_resolved()) return; |
1392 // The number of slots required for variables. | 1387 // The number of slots required for variables. |
1393 num_stack_slots_ = 0; | 1388 num_stack_slots_ = 0; |
1394 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1389 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
1395 | 1390 |
1396 // Allocate variables for this scope. | 1391 // Allocate variables for this scope. |
1397 // Parameters must be allocated first, if any. | 1392 // Parameters must be allocated first, if any. |
| 1393 if (has_this_declaration()) AllocateReceiver(); |
1398 if (is_function_scope()) AllocateParameterLocals(); | 1394 if (is_function_scope()) AllocateParameterLocals(); |
1399 AllocateNonParameterLocals(); | 1395 AllocateNonParameterLocals(); |
1400 | 1396 |
1401 // Force allocation of a context for this scope if necessary. For a 'with' | 1397 // Force allocation of a context for this scope if necessary. For a 'with' |
1402 // scope and for a function scope that makes an 'eval' call we need a context, | 1398 // scope and for a function scope that makes an 'eval' call we need a context, |
1403 // even if no local variables were statically allocated in the scope. | 1399 // even if no local variables were statically allocated in the scope. |
1404 // Likewise for modules. | 1400 // Likewise for modules. |
1405 bool must_have_context = is_with_scope() || is_module_scope() || | 1401 bool must_have_context = is_with_scope() || is_module_scope() || |
1406 (is_function_scope() && calls_eval()); | 1402 (is_function_scope() && calls_eval()); |
1407 | 1403 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 } | 1435 } |
1440 | 1436 |
1441 | 1437 |
1442 int Scope::ContextLocalCount() const { | 1438 int Scope::ContextLocalCount() const { |
1443 if (num_heap_slots() == 0) return 0; | 1439 if (num_heap_slots() == 0) return 0; |
1444 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1440 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1445 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1441 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1446 } | 1442 } |
1447 | 1443 |
1448 } } // namespace v8::internal | 1444 } } // namespace v8::internal |
OLD | NEW |