| 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, Variable::Kind kind, |
| 35 Variable::Kind kind, | |
| 36 InitializationFlag initialization_flag, | 35 InitializationFlag initialization_flag, |
| 37 MaybeAssignedFlag maybe_assigned_flag) { | 36 MaybeAssignedFlag maybe_assigned_flag) { |
| 38 // AstRawStrings are unambiguous, i.e., the same string is always represented | 37 // AstRawStrings are unambiguous, i.e., the same string is always represented |
| 39 // by the same AstRawString*. | 38 // by the same AstRawString*. |
| 40 // FIXME(marja): fix the type of Lookup. | 39 // FIXME(marja): fix the type of Lookup. |
| 41 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 40 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
| 42 true, ZoneAllocationPolicy(zone())); | 41 true, ZoneAllocationPolicy(zone())); |
| 43 if (p->value == NULL) { | 42 if (p->value == NULL) { |
| 44 // The variable has not been declared yet -> insert it. | 43 // The variable has not been declared yet -> insert it. |
| 45 DCHECK(p->key == name); | 44 DCHECK(p->key == name); |
| 46 p->value = new (zone()) Variable(scope, name, mode, is_valid_lhs, kind, | 45 p->value = new (zone()) Variable(scope, name, mode, kind, |
| 47 initialization_flag, maybe_assigned_flag); | 46 initialization_flag, maybe_assigned_flag); |
| 48 } | 47 } |
| 49 return reinterpret_cast<Variable*>(p->value); | 48 return reinterpret_cast<Variable*>(p->value); |
| 50 } | 49 } |
| 51 | 50 |
| 52 | 51 |
| 53 Variable* VariableMap::Lookup(const AstRawString* name) { | 52 Variable* VariableMap::Lookup(const AstRawString* name) { |
| 54 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 53 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
| 55 false, ZoneAllocationPolicy(NULL)); | 54 false, ZoneAllocationPolicy(NULL)); |
| 56 if (p != NULL) { | 55 if (p != NULL) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 already_resolved_(true), | 123 already_resolved_(true), |
| 125 ast_value_factory_(value_factory), | 124 ast_value_factory_(value_factory), |
| 126 zone_(zone) { | 125 zone_(zone) { |
| 127 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); | 126 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
| 128 AddInnerScope(inner_scope); | 127 AddInnerScope(inner_scope); |
| 129 ++num_var_or_const_; | 128 ++num_var_or_const_; |
| 130 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 129 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 131 Variable* variable = variables_.Declare(this, | 130 Variable* variable = variables_.Declare(this, |
| 132 catch_variable_name, | 131 catch_variable_name, |
| 133 VAR, | 132 VAR, |
| 134 true, // Valid left-hand side. | |
| 135 Variable::NORMAL, | 133 Variable::NORMAL, |
| 136 kCreatedInitialized); | 134 kCreatedInitialized); |
| 137 AllocateHeapSlot(variable); | 135 AllocateHeapSlot(variable); |
| 138 } | 136 } |
| 139 | 137 |
| 140 | 138 |
| 141 void Scope::SetDefaults(ScopeType scope_type, | 139 void Scope::SetDefaults(ScopeType scope_type, |
| 142 Scope* outer_scope, | 140 Scope* outer_scope, |
| 143 Handle<ScopeInfo> scope_info) { | 141 Handle<ScopeInfo> scope_info) { |
| 144 outer_scope_ = outer_scope; | 142 outer_scope_ = outer_scope; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 // Declare convenience variables. | 291 // Declare convenience variables. |
| 294 // Declare and allocate receiver (even for the script scope, and even | 292 // Declare and allocate receiver (even for the script scope, and even |
| 295 // if naccesses_ == 0). | 293 // if naccesses_ == 0). |
| 296 // NOTE: When loading parameters in the script scope, we must take | 294 // NOTE: When loading parameters in the script scope, we must take |
| 297 // care not to access them as properties of the global object, but | 295 // care not to access them as properties of the global object, but |
| 298 // instead load them directly from the stack. Currently, the only | 296 // instead load them directly from the stack. Currently, the only |
| 299 // such parameter is 'this' which is passed on the stack when | 297 // such parameter is 'this' which is passed on the stack when |
| 300 // invoking scripts | 298 // invoking scripts |
| 301 if (is_declaration_scope()) { | 299 if (is_declaration_scope()) { |
| 302 DCHECK(!subclass_constructor || is_function_scope()); | 300 DCHECK(!subclass_constructor || is_function_scope()); |
| 303 Variable* var = variables_.Declare( | 301 if (has_this_declaration()) { |
| 304 this, ast_value_factory_->this_string(), | 302 Variable* var = variables_.Declare( |
| 305 subclass_constructor ? CONST : VAR, false, Variable::THIS, | 303 this, ast_value_factory_->this_string(), |
| 306 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); | 304 subclass_constructor ? CONST : VAR, Variable::THIS, |
| 307 var->AllocateTo(Variable::PARAMETER, -1); | 305 subclass_constructor ? kNeedsInitialization : kCreatedInitialized); |
| 308 receiver_ = var; | 306 receiver_ = var; |
| 307 } |
| 309 | 308 |
| 310 if (subclass_constructor) { | 309 if (subclass_constructor) { |
| 311 new_target_ = variables_.Declare( | 310 new_target_ = |
| 312 this, ast_value_factory_->new_target_string(), CONST, false, | 311 variables_.Declare(this, ast_value_factory_->new_target_string(), |
| 313 Variable::NEW_TARGET, kCreatedInitialized); | 312 CONST, Variable::NEW_TARGET, kCreatedInitialized); |
| 314 new_target_->AllocateTo(Variable::PARAMETER, -2); | 313 new_target_->AllocateTo(Variable::PARAMETER, -2); |
| 315 new_target_->set_is_used(); | 314 new_target_->set_is_used(); |
| 316 } | 315 } |
| 317 } else { | |
| 318 DCHECK(outer_scope() != NULL); | |
| 319 receiver_ = outer_scope()->receiver(); | |
| 320 } | 316 } |
| 321 | 317 |
| 322 if (is_function_scope()) { | 318 if (is_function_scope()) { |
| 323 // Declare 'arguments' variable which exists in all functions. | 319 // Declare 'arguments' variable which exists in all functions. |
| 324 // Note that it might never be accessed, in which case it won't be | 320 // Note that it might never be accessed, in which case it won't be |
| 325 // allocated during variable allocation. | 321 // allocated during variable allocation. |
| 326 variables_.Declare(this, | 322 variables_.Declare(this, |
| 327 ast_value_factory_->arguments_string(), | 323 ast_value_factory_->arguments_string(), |
| 328 VAR, | 324 VAR, |
| 329 true, | |
| 330 Variable::ARGUMENTS, | 325 Variable::ARGUMENTS, |
| 331 kCreatedInitialized); | 326 kCreatedInitialized); |
| 332 } | 327 } |
| 333 } | 328 } |
| 334 | 329 |
| 335 | 330 |
| 336 Scope* Scope::FinalizeBlockScope() { | 331 Scope* Scope::FinalizeBlockScope() { |
| 337 DCHECK(is_block_scope()); | 332 DCHECK(is_block_scope()); |
| 338 DCHECK(internals_.is_empty()); | 333 DCHECK(internals_.is_empty()); |
| 339 DCHECK(temps_.is_empty()); | 334 DCHECK(temps_.is_empty()); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 390 |
| 396 mode = DYNAMIC; | 391 mode = DYNAMIC; |
| 397 location = Variable::LOOKUP; | 392 location = Variable::LOOKUP; |
| 398 init_flag = kCreatedInitialized; | 393 init_flag = kCreatedInitialized; |
| 399 // Be conservative and flag parameters as maybe assigned. Better information | 394 // Be conservative and flag parameters as maybe assigned. Better information |
| 400 // would require ScopeInfo to serialize the maybe_assigned bit also for | 395 // would require ScopeInfo to serialize the maybe_assigned bit also for |
| 401 // parameters. | 396 // parameters. |
| 402 maybe_assigned_flag = kMaybeAssigned; | 397 maybe_assigned_flag = kMaybeAssigned; |
| 403 } | 398 } |
| 404 | 399 |
| 405 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 400 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
| 406 init_flag, maybe_assigned_flag); | 401 init_flag, maybe_assigned_flag); |
| 407 var->AllocateTo(location, index); | 402 var->AllocateTo(location, index); |
| 408 return var; | 403 return var; |
| 409 } | 404 } |
| 410 | 405 |
| 411 | 406 |
| 412 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 407 Variable* Scope::LookupFunctionVar(const AstRawString* name, |
| 413 AstNodeFactory* factory) { | 408 AstNodeFactory* factory) { |
| 414 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 409 if (function_ != NULL && function_->proxy()->raw_name() == name) { |
| 415 return function_->proxy()->var(); | 410 return function_->proxy()->var(); |
| 416 } else if (!scope_info_.is_null()) { | 411 } else if (!scope_info_.is_null()) { |
| 417 // If we are backed by a scope info, try to lookup the variable there. | 412 // If we are backed by a scope info, try to lookup the variable there. |
| 418 VariableMode mode; | 413 VariableMode mode; |
| 419 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 414 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
| 420 if (index < 0) return NULL; | 415 if (index < 0) return NULL; |
| 421 Variable* var = new(zone()) Variable( | 416 Variable* var = new (zone()) |
| 422 this, name, mode, true /* is valid LHS */, | 417 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); |
| 423 Variable::NORMAL, kCreatedInitialized); | |
| 424 VariableProxy* proxy = factory->NewVariableProxy(var); | 418 VariableProxy* proxy = factory->NewVariableProxy(var); |
| 425 VariableDeclaration* declaration = factory->NewVariableDeclaration( | 419 VariableDeclaration* declaration = factory->NewVariableDeclaration( |
| 426 proxy, mode, this, RelocInfo::kNoPosition); | 420 proxy, mode, this, RelocInfo::kNoPosition); |
| 427 DeclareFunctionVar(declaration); | 421 DeclareFunctionVar(declaration); |
| 428 var->AllocateTo(Variable::CONTEXT, index); | 422 var->AllocateTo(Variable::CONTEXT, index); |
| 429 return var; | 423 return var; |
| 430 } else { | 424 } else { |
| 431 return NULL; | 425 return NULL; |
| 432 } | 426 } |
| 433 } | 427 } |
| 434 | 428 |
| 435 | 429 |
| 436 Variable* Scope::Lookup(const AstRawString* name) { | 430 Variable* Scope::Lookup(const AstRawString* name) { |
| 437 for (Scope* scope = this; | 431 for (Scope* scope = this; |
| 438 scope != NULL; | 432 scope != NULL; |
| 439 scope = scope->outer_scope()) { | 433 scope = scope->outer_scope()) { |
| 440 Variable* var = scope->LookupLocal(name); | 434 Variable* var = scope->LookupLocal(name); |
| 441 if (var != NULL) return var; | 435 if (var != NULL) return var; |
| 442 } | 436 } |
| 443 return NULL; | 437 return NULL; |
| 444 } | 438 } |
| 445 | 439 |
| 446 | 440 |
| 447 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, | 441 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode, |
| 448 bool is_rest) { | 442 bool is_rest) { |
| 449 DCHECK(!already_resolved()); | 443 DCHECK(!already_resolved()); |
| 450 DCHECK(is_function_scope()); | 444 DCHECK(is_function_scope()); |
| 451 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 445 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
| 452 kCreatedInitialized); | 446 kCreatedInitialized); |
| 453 if (is_rest) { | 447 if (is_rest) { |
| 454 DCHECK_NULL(rest_parameter_); | 448 DCHECK_NULL(rest_parameter_); |
| 455 rest_parameter_ = var; | 449 rest_parameter_ = var; |
| 456 rest_index_ = num_parameters(); | 450 rest_index_ = num_parameters(); |
| 457 } | 451 } |
| 458 params_.Add(var, zone()); | 452 params_.Add(var, zone()); |
| 459 return var; | 453 return var; |
| 460 } | 454 } |
| 461 | 455 |
| 462 | 456 |
| 463 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 457 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
| 464 InitializationFlag init_flag, | 458 InitializationFlag init_flag, |
| 465 MaybeAssignedFlag maybe_assigned_flag) { | 459 MaybeAssignedFlag maybe_assigned_flag) { |
| 466 DCHECK(!already_resolved()); | 460 DCHECK(!already_resolved()); |
| 467 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 461 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
| 468 // introduces during variable allocation, INTERNAL variables are allocated | 462 // introduces during variable allocation, INTERNAL variables are allocated |
| 469 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 463 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
| 470 DCHECK(IsDeclaredVariableMode(mode)); | 464 DCHECK(IsDeclaredVariableMode(mode)); |
| 471 ++num_var_or_const_; | 465 ++num_var_or_const_; |
| 472 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 466 return variables_.Declare(this, name, mode, Variable::NORMAL, init_flag, |
| 473 maybe_assigned_flag); | 467 maybe_assigned_flag); |
| 474 } | 468 } |
| 475 | 469 |
| 476 | 470 |
| 477 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 471 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
| 478 DCHECK(is_script_scope()); | 472 DCHECK(is_script_scope()); |
| 479 return variables_.Declare(this, | 473 return variables_.Declare(this, |
| 480 name, | 474 name, |
| 481 DYNAMIC_GLOBAL, | 475 DYNAMIC_GLOBAL, |
| 482 true, | |
| 483 Variable::NORMAL, | 476 Variable::NORMAL, |
| 484 kCreatedInitialized); | 477 kCreatedInitialized); |
| 485 } | 478 } |
| 486 | 479 |
| 487 | 480 |
| 488 void Scope::RemoveUnresolved(VariableProxy* var) { | 481 void Scope::RemoveUnresolved(VariableProxy* var) { |
| 489 // Most likely (always?) any variable we want to remove | 482 // Most likely (always?) any variable we want to remove |
| 490 // was just added before, so we search backwards. | 483 // was just added before, so we search backwards. |
| 491 for (int i = unresolved_.length(); i-- > 0;) { | 484 for (int i = unresolved_.length(); i-- > 0;) { |
| 492 if (unresolved_[i] == var) { | 485 if (unresolved_[i] == var) { |
| 493 unresolved_.Remove(i); | 486 unresolved_.Remove(i); |
| 494 return; | 487 return; |
| 495 } | 488 } |
| 496 } | 489 } |
| 497 } | 490 } |
| 498 | 491 |
| 499 | 492 |
| 500 Variable* Scope::NewInternal(const AstRawString* name) { | 493 Variable* Scope::NewInternal(const AstRawString* name) { |
| 501 DCHECK(!already_resolved()); | 494 DCHECK(!already_resolved()); |
| 502 Variable* var = new(zone()) Variable(this, | 495 Variable* var = new(zone()) Variable(this, |
| 503 name, | 496 name, |
| 504 INTERNAL, | 497 INTERNAL, |
| 505 false, | |
| 506 Variable::NORMAL, | 498 Variable::NORMAL, |
| 507 kCreatedInitialized); | 499 kCreatedInitialized); |
| 508 internals_.Add(var, zone()); | 500 internals_.Add(var, zone()); |
| 509 return var; | 501 return var; |
| 510 } | 502 } |
| 511 | 503 |
| 512 | 504 |
| 513 Variable* Scope::NewTemporary(const AstRawString* name) { | 505 Variable* Scope::NewTemporary(const AstRawString* name) { |
| 514 DCHECK(!already_resolved()); | 506 DCHECK(!already_resolved()); |
| 515 Variable* var = new(zone()) Variable(this, | 507 Variable* var = new(zone()) Variable(this, |
| 516 name, | 508 name, |
| 517 TEMPORARY, | 509 TEMPORARY, |
| 518 true, | |
| 519 Variable::NORMAL, | 510 Variable::NORMAL, |
| 520 kCreatedInitialized); | 511 kCreatedInitialized); |
| 521 temps_.Add(var, zone()); | 512 temps_.Add(var, zone()); |
| 522 return var; | 513 return var; |
| 523 } | 514 } |
| 524 | 515 |
| 525 | 516 |
| 526 void Scope::AddDeclaration(Declaration* declaration) { | 517 void Scope::AddDeclaration(Declaration* declaration) { |
| 527 decls_.Add(declaration, zone()); | 518 decls_.Add(declaration, zone()); |
| 528 } | 519 } |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); | 946 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); |
| 956 VariableMap* map = dynamics_->GetMap(mode); | 947 VariableMap* map = dynamics_->GetMap(mode); |
| 957 Variable* var = map->Lookup(name); | 948 Variable* var = map->Lookup(name); |
| 958 if (var == NULL) { | 949 if (var == NULL) { |
| 959 // Declare a new non-local. | 950 // Declare a new non-local. |
| 960 InitializationFlag init_flag = (mode == VAR) | 951 InitializationFlag init_flag = (mode == VAR) |
| 961 ? kCreatedInitialized : kNeedsInitialization; | 952 ? kCreatedInitialized : kNeedsInitialization; |
| 962 var = map->Declare(NULL, | 953 var = map->Declare(NULL, |
| 963 name, | 954 name, |
| 964 mode, | 955 mode, |
| 965 true, | |
| 966 Variable::NORMAL, | 956 Variable::NORMAL, |
| 967 init_flag); | 957 init_flag); |
| 968 // Allocate it by giving it a dynamic lookup. | 958 // Allocate it by giving it a dynamic lookup. |
| 969 var->AllocateTo(Variable::LOOKUP, -1); | 959 var->AllocateTo(Variable::LOOKUP, -1); |
| 970 } | 960 } |
| 971 return var; | 961 return var; |
| 972 } | 962 } |
| 973 | 963 |
| 974 | 964 |
| 975 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 965 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 // via an eval() call. This is only possible if the variable has a | 1145 // via an eval() call. This is only possible if the variable has a |
| 1156 // visible name. | 1146 // visible name. |
| 1157 if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && | 1147 if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && |
| 1158 (var->has_forced_context_allocation() || scope_calls_eval_ || | 1148 (var->has_forced_context_allocation() || scope_calls_eval_ || |
| 1159 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || | 1149 inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || |
| 1160 is_block_scope() || is_module_scope() || is_script_scope())) { | 1150 is_block_scope() || is_module_scope() || is_script_scope())) { |
| 1161 var->set_is_used(); | 1151 var->set_is_used(); |
| 1162 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); | 1152 if (scope_calls_eval_ || inner_scope_calls_eval_) var->set_maybe_assigned(); |
| 1163 } | 1153 } |
| 1164 // Global variables do not need to be allocated. | 1154 // Global variables do not need to be allocated. |
| 1165 return !var->IsGlobalObjectProperty() && var->is_used(); | 1155 return var->is_this() || (var->is_used() && !var->IsGlobalObjectProperty()); |
| 1166 } | 1156 } |
| 1167 | 1157 |
| 1168 | 1158 |
| 1169 bool Scope::MustAllocateInContext(Variable* var) { | 1159 bool Scope::MustAllocateInContext(Variable* var) { |
| 1170 // If var is accessed from an inner scope, or if there is a possibility | 1160 // If var is accessed from an inner scope, or if there is a possibility |
| 1171 // that it might be accessed from the current or an inner scope (through | 1161 // that it might be accessed from the current or an inner scope (through |
| 1172 // an eval() call or a runtime with lookup), it must be allocated in the | 1162 // an eval() call or a runtime with lookup), it must be allocated in the |
| 1173 // context. | 1163 // context. |
| 1174 // | 1164 // |
| 1175 // Exceptions: If the scope as a whole has forced context allocation, all | 1165 // 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... |
| 1246 // order is relevant! | 1236 // order is relevant! |
| 1247 for (int i = params_.length() - 1; i >= 0; --i) { | 1237 for (int i = params_.length() - 1; i >= 0; --i) { |
| 1248 Variable* var = params_[i]; | 1238 Variable* var = params_[i]; |
| 1249 if (var == rest_parameter_) continue; | 1239 if (var == rest_parameter_) continue; |
| 1250 | 1240 |
| 1251 DCHECK(var->scope() == this); | 1241 DCHECK(var->scope() == this); |
| 1252 if (uses_sloppy_arguments || has_forced_context_allocation()) { | 1242 if (uses_sloppy_arguments || has_forced_context_allocation()) { |
| 1253 // Force context allocation of the parameter. | 1243 // Force context allocation of the parameter. |
| 1254 var->ForceContextAllocation(); | 1244 var->ForceContextAllocation(); |
| 1255 } | 1245 } |
| 1246 AllocateParameter(var, i); |
| 1247 } |
| 1248 } |
| 1256 | 1249 |
| 1257 if (MustAllocate(var)) { | 1250 |
| 1258 if (MustAllocateInContext(var)) { | 1251 void Scope::AllocateParameter(Variable* var, int index) { |
| 1259 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | 1252 if (MustAllocate(var)) { |
| 1260 if (var->IsUnallocated()) { | 1253 if (MustAllocateInContext(var)) { |
| 1261 AllocateHeapSlot(var); | 1254 DCHECK(var->IsUnallocated() || var->IsContextSlot()); |
| 1262 } | 1255 if (var->IsUnallocated()) { |
| 1263 } else { | 1256 AllocateHeapSlot(var); |
| 1264 DCHECK(var->IsUnallocated() || var->IsParameter()); | 1257 } |
| 1265 if (var->IsUnallocated()) { | 1258 } else { |
| 1266 var->AllocateTo(Variable::PARAMETER, i); | 1259 DCHECK(var->IsUnallocated() || var->IsParameter()); |
| 1267 } | 1260 if (var->IsUnallocated()) { |
| 1261 var->AllocateTo(Variable::PARAMETER, index); |
| 1268 } | 1262 } |
| 1269 } | 1263 } |
| 1270 } | 1264 } |
| 1271 } | 1265 } |
| 1272 | 1266 |
| 1273 | 1267 |
| 1268 void Scope::AllocateReceiver() { |
| 1269 DCHECK_EQ(receiver()->scope(), this); |
| 1270 |
| 1271 if (is_script_scope()) { |
| 1272 receiver()->AllocateTo(Variable::PARAMETER, -1); |
| 1273 } else { |
| 1274 if (has_forced_context_allocation()) { |
| 1275 receiver()->ForceContextAllocation(); |
| 1276 } |
| 1277 AllocateParameter(receiver(), -1); |
| 1278 } |
| 1279 } |
| 1280 |
| 1281 |
| 1274 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) { | 1282 void Scope::AllocateNonParameterLocal(Isolate* isolate, Variable* var) { |
| 1275 DCHECK(var->scope() == this); | 1283 DCHECK(var->scope() == this); |
| 1276 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || | 1284 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
| 1277 !var->IsStackLocal()); | 1285 !var->IsStackLocal()); |
| 1278 if (var->IsUnallocated() && MustAllocate(var)) { | 1286 if (var->IsUnallocated() && MustAllocate(var)) { |
| 1279 if (MustAllocateInContext(var)) { | 1287 if (MustAllocateInContext(var)) { |
| 1280 AllocateHeapSlot(var); | 1288 AllocateHeapSlot(var); |
| 1281 } else { | 1289 } else { |
| 1282 AllocateStackSlot(var); | 1290 AllocateStackSlot(var); |
| 1283 } | 1291 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 // If scope is already resolved, we still need to allocate | 1339 // If scope is already resolved, we still need to allocate |
| 1332 // variables in inner scopes which might not had been resolved yet. | 1340 // variables in inner scopes which might not had been resolved yet. |
| 1333 if (already_resolved()) return; | 1341 if (already_resolved()) return; |
| 1334 // The number of slots required for variables. | 1342 // The number of slots required for variables. |
| 1335 num_stack_slots_ = 0; | 1343 num_stack_slots_ = 0; |
| 1336 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1344 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 1337 | 1345 |
| 1338 // Allocate variables for this scope. | 1346 // Allocate variables for this scope. |
| 1339 // Parameters must be allocated first, if any. | 1347 // Parameters must be allocated first, if any. |
| 1340 if (is_function_scope()) AllocateParameterLocals(isolate); | 1348 if (is_function_scope()) AllocateParameterLocals(isolate); |
| 1349 if (has_this_declaration()) AllocateReceiver(); |
| 1341 AllocateNonParameterLocals(isolate); | 1350 AllocateNonParameterLocals(isolate); |
| 1342 | 1351 |
| 1343 // Force allocation of a context for this scope if necessary. For a 'with' | 1352 // Force allocation of a context for this scope if necessary. For a 'with' |
| 1344 // scope and for a function scope that makes an 'eval' call we need a context, | 1353 // scope and for a function scope that makes an 'eval' call we need a context, |
| 1345 // even if no local variables were statically allocated in the scope. | 1354 // even if no local variables were statically allocated in the scope. |
| 1346 // Likewise for modules. | 1355 // Likewise for modules. |
| 1347 bool must_have_context = is_with_scope() || is_module_scope() || | 1356 bool must_have_context = is_with_scope() || is_module_scope() || |
| 1348 (is_function_scope() && calls_eval()); | 1357 (is_function_scope() && calls_eval()); |
| 1349 | 1358 |
| 1350 // If we didn't allocate any locals in the local context, then we only | 1359 // If we didn't allocate any locals in the local context, then we only |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1381 } | 1390 } |
| 1382 | 1391 |
| 1383 | 1392 |
| 1384 int Scope::ContextLocalCount() const { | 1393 int Scope::ContextLocalCount() const { |
| 1385 if (num_heap_slots() == 0) return 0; | 1394 if (num_heap_slots() == 0) return 0; |
| 1386 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1395 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1387 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1396 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
| 1388 } | 1397 } |
| 1389 | 1398 |
| 1390 } } // namespace v8::internal | 1399 } } // namespace v8::internal |
| OLD | NEW |