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