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 |