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 3 // found in the LICENSE file. 4 5 #include "src/v8.h" 6 7 #include "src/scopes.h" 8 9 #include "src/accessors.h" 10 #include "src/bootstrapper.h" 11 #include "src/compiler.h" 12 #include "src/messages.h" 13 #include "src/scopeinfo.h" 14 15 namespace v8 { 16 namespace internal { 17 18 // ---------------------------------------------------------------------------- 19 // Implementation of LocalsMap 20 // 21 // Note: We are storing the handle locations as key values in the hash map. 22 // When inserting a new variable via Declare(), we rely on the fact that 23 // the handle location remains alive for the duration of that variable 24 // use. Because a Variable holding a handle with the same location exists 25 // this is ensured. 26 27 static bool Match(void* key1, void* key2) { 28 String* name1 = *reinterpret_cast<String**>(key1); 29 String* name2 = *reinterpret_cast<String**>(key2); 30 ASSERT(name1->IsInternalizedString()); 31 ASSERT(name2->IsInternalizedString()); 32 return name1 == name2; 33 } 34 35 36 VariableMap::VariableMap(Zone* zone) 37 : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)), 38 zone_(zone) {} 39 VariableMap::~VariableMap() {} 40 41 42 Variable* VariableMap::Declare( 43 Scope* scope, 44 Handle<String> name, 45 VariableMode mode, 46 bool is_valid_lhs, 47 Variable::Kind kind, 48 InitializationFlag initialization_flag, 49 Interface* interface) { 50 Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true, 51 ZoneAllocationPolicy(zone())); 52 if (p->value == NULL) { 53 // The variable has not been declared yet -> insert it. 54 ASSERT(p->key == name.location()); 55 p->value = new(zone()) Variable(scope, 56 name, 57 mode, 58 is_valid_lhs, 59 kind, 60 initialization_flag, 61 interface); 62 } 63 return reinterpret_cast<Variable*>(p->value); 64 } 65 66 67 Variable* VariableMap::Lookup(Handle<String> name) { 68 Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false, 69 ZoneAllocationPolicy(NULL)); 70 if (p != NULL) { 71 ASSERT(*reinterpret_cast<String**>(p->key) == *name); 72 ASSERT(p->value != NULL); 73 return reinterpret_cast<Variable*>(p->value); 74 } 75 return NULL; 76 } 77 78 79 // ---------------------------------------------------------------------------- 80 // Implementation of Scope 81 82 Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone) 83 : isolate_(zone->isolate()), 84 inner_scopes_(4, zone), 85 variables_(zone), 86 internals_(4, zone), 87 temps_(4, zone), 88 params_(4, zone), 89 unresolved_(16, zone), 90 decls_(4, zone), 91 interface_(FLAG_harmony_modules && 92 (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE) 93 ? Interface::NewModule(zone) : NULL), 94 already_resolved_(false), 95 zone_(zone) { 96 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); 97 // The outermost scope must be a global scope. 98 ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL); 99 ASSERT(!HasIllegalRedeclaration()); 100 } 101 102 103 Scope::Scope(Scope* inner_scope, 104 ScopeType scope_type, 105 Handle<ScopeInfo> scope_info, 106 Zone* zone) 107 : isolate_(zone->isolate()), 108 inner_scopes_(4, zone), 109 variables_(zone), 110 internals_(4, zone), 111 temps_(4, zone), 112 params_(4, zone), 113 unresolved_(16, zone), 114 decls_(4, zone), 115 interface_(NULL), 116 already_resolved_(true), 117 zone_(zone) { 118 SetDefaults(scope_type, NULL, scope_info); 119 if (!scope_info.is_null()) { 120 num_heap_slots_ = scope_info_->ContextLength(); 121 } 122 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. 123 num_heap_slots_ = Max(num_heap_slots_, 124 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); 125 AddInnerScope(inner_scope); 126 } 127 128 129 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone) 130 : isolate_(zone->isolate()), 131 inner_scopes_(1, zone), 132 variables_(zone), 133 internals_(0, zone), 134 temps_(0, zone), 135 params_(0, zone), 136 unresolved_(0, zone), 137 decls_(0, zone), 138 interface_(NULL), 139 already_resolved_(true), 140 zone_(zone) { 141 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); 142 AddInnerScope(inner_scope); 143 ++num_var_or_const_; 144 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 145 Variable* variable = variables_.Declare(this, 146 catch_variable_name, 147 VAR, 148 true, // Valid left-hand side. 149 Variable::NORMAL, 150 kCreatedInitialized); 151 AllocateHeapSlot(variable); 152 } 153 154 155 void Scope::SetDefaults(ScopeType scope_type, 156 Scope* outer_scope, 157 Handle<ScopeInfo> scope_info) { 158 outer_scope_ = outer_scope; 159 scope_type_ = scope_type; 160 scope_name_ = isolate_->factory()->empty_string(); 161 dynamics_ = NULL; 162 receiver_ = NULL; 163 function_ = NULL; 164 arguments_ = NULL; 165 illegal_redecl_ = NULL; 166 scope_inside_with_ = false; 167 scope_contains_with_ = false; 168 scope_calls_eval_ = false; 169 // Inherit the strict mode from the parent scope. 170 strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY; 171 outer_scope_calls_sloppy_eval_ = false; 172 inner_scope_calls_eval_ = false; 173 force_eager_compilation_ = false; 174 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) 175 ? outer_scope->has_forced_context_allocation() : false; 176 num_var_or_const_ = 0; 177 num_stack_slots_ = 0; 178 num_heap_slots_ = 0; 179 num_modules_ = 0; 180 module_var_ = NULL, 181 scope_info_ = scope_info; 182 start_position_ = RelocInfo::kNoPosition; 183 end_position_ = RelocInfo::kNoPosition; 184 if (!scope_info.is_null()) { 185 scope_calls_eval_ = scope_info->CallsEval(); 186 strict_mode_ = scope_info->strict_mode(); 187 } 188 } 189 190 191 Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope, 192 Zone* zone) { 193 // Reconstruct the outer scope chain from a closure's context chain. 194 Scope* current_scope = NULL; 195 Scope* innermost_scope = NULL; 196 bool contains_with = false; 197 while (!context->IsNativeContext()) { 198 if (context->IsWithContext()) { 199 Scope* with_scope = new(zone) Scope(current_scope, 200 WITH_SCOPE, 201 Handle<ScopeInfo>::null(), 202 zone); 203 current_scope = with_scope; 204 // All the inner scopes are inside a with. 205 contains_with = true; 206 for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) { 207 s->scope_inside_with_ = true; 208 } 209 } else if (context->IsGlobalContext()) { 210 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); 211 current_scope = new(zone) Scope(current_scope, 212 GLOBAL_SCOPE, 213 Handle<ScopeInfo>(scope_info), 214 zone); 215 } else if (context->IsModuleContext()) { 216 ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info()); 217 current_scope = new(zone) Scope(current_scope, 218 MODULE_SCOPE, 219 Handle<ScopeInfo>(scope_info), 220 zone); 221 } else if (context->IsFunctionContext()) { 222 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); 223 current_scope = new(zone) Scope(current_scope, 224 FUNCTION_SCOPE, 225 Handle<ScopeInfo>(scope_info), 226 zone); 227 } else if (context->IsBlockContext()) { 228 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); 229 current_scope = new(zone) Scope(current_scope, 230 BLOCK_SCOPE, 231 Handle<ScopeInfo>(scope_info), 232 zone); 233 } else { 234 ASSERT(context->IsCatchContext()); 235 String* name = String::cast(context->extension()); 236 current_scope = new(zone) Scope( 237 current_scope, Handle<String>(name), zone); 238 } 239 if (contains_with) current_scope->RecordWithStatement(); 240 if (innermost_scope == NULL) innermost_scope = current_scope; 241 242 // Forget about a with when we move to a context for a different function. 243 if (context->previous()->closure() != context->closure()) { 244 contains_with = false; 245 } 246 context = context->previous(); 247 } 248 249 global_scope->AddInnerScope(current_scope); 250 global_scope->PropagateScopeInfo(false); 251 return (innermost_scope == NULL) ? global_scope : innermost_scope; 252 } 253 254 255 bool Scope::Analyze(CompilationInfo* info) { 256 ASSERT(info->function() != NULL); 257 Scope* scope = info->function()->scope(); 258 Scope* top = scope; 259 260 // Traverse the scope tree up to the first unresolved scope or the global 261 // scope and start scope resolution and variable allocation from that scope. 262 while (!top->is_global_scope() && 263 !top->outer_scope()->already_resolved()) { 264 top = top->outer_scope(); 265 } 266 267 // Allocate the variables. 268 { 269 AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone()); 270 if (!top->AllocateVariables(info, &ast_node_factory)) return false; 271 } 272 273 #ifdef DEBUG 274 if (info->isolate()->bootstrapper()->IsActive() 275 ? FLAG_print_builtin_scopes 276 : FLAG_print_scopes) { 277 scope->Print(); 278 } 279 280 if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) { 281 PrintF("global : "); 282 top->interface()->Print(); 283 } 284 #endif 285 286 info->PrepareForCompilation(scope); 287 return true; 288 } 289 290 291 void Scope::Initialize() { 292 ASSERT(!already_resolved()); 293 294 // Add this scope as a new inner scope of the outer scope. 295 if (outer_scope_ != NULL) { 296 outer_scope_->inner_scopes_.Add(this, zone()); 297 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); 298 } else { 299 scope_inside_with_ = is_with_scope(); 300 } 301 302 // Declare convenience variables. 303 // Declare and allocate receiver (even for the global scope, and even 304 // if naccesses_ == 0). 305 // NOTE: When loading parameters in the global scope, we must take 306 // care not to access them as properties of the global object, but 307 // instead load them directly from the stack. Currently, the only 308 // such parameter is 'this' which is passed on the stack when 309 // invoking scripts 310 if (is_declaration_scope()) { 311 Variable* var = 312 variables_.Declare(this, 313 isolate_->factory()->this_string(), 314 VAR, 315 false, 316 Variable::THIS, 317 kCreatedInitialized); 318 var->AllocateTo(Variable::PARAMETER, -1); 319 receiver_ = var; 320 } else { 321 ASSERT(outer_scope() != NULL); 322 receiver_ = outer_scope()->receiver(); 323 } 324 325 if (is_function_scope()) { 326 // Declare 'arguments' variable which exists in all functions. 327 // Note that it might never be accessed, in which case it won't be 328 // allocated during variable allocation. 329 variables_.Declare(this, 330 isolate_->factory()->arguments_string(), 331 VAR, 332 true, 333 Variable::ARGUMENTS, 334 kCreatedInitialized); 335 } 336 } 337 338 339 Scope* Scope::FinalizeBlockScope() { 340 ASSERT(is_block_scope()); 341 ASSERT(internals_.is_empty()); 342 ASSERT(temps_.is_empty()); 343 ASSERT(params_.is_empty()); 344 345 if (num_var_or_const() > 0) return this; 346 347 // Remove this scope from outer scope. 348 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { 349 if (outer_scope_->inner_scopes_[i] == this) { 350 outer_scope_->inner_scopes_.Remove(i); 351 break; 352 } 353 } 354 355 // Reparent inner scopes. 356 for (int i = 0; i < inner_scopes_.length(); i++) { 357 outer_scope()->AddInnerScope(inner_scopes_[i]); 358 } 359 360 // Move unresolved variables 361 for (int i = 0; i < unresolved_.length(); i++) { 362 outer_scope()->unresolved_.Add(unresolved_[i], zone()); 363 } 364 365 return NULL; 366 } 367 368 369 Variable* Scope::LookupLocal(Handle<String> name) { 370 Variable* result = variables_.Lookup(name); 371 if (result != NULL || scope_info_.is_null()) { 372 return result; 373 } 374 // If we have a serialized scope info, we might find the variable there. 375 // There should be no local slot with the given name. 376 ASSERT(scope_info_->StackSlotIndex(*name) < 0); 377 378 // Check context slot lookup. 379 VariableMode mode; 380 Variable::Location location = Variable::CONTEXT; 381 InitializationFlag init_flag; 382 int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag); 383 if (index < 0) { 384 // Check parameters. 385 index = scope_info_->ParameterIndex(*name); 386 if (index < 0) return NULL; 387 388 mode = DYNAMIC; 389 location = Variable::LOOKUP; 390 init_flag = kCreatedInitialized; 391 } 392 393 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, 394 init_flag); 395 var->AllocateTo(location, index); 396 return var; 397 } 398 399 400 Variable* Scope::LookupFunctionVar(Handle<String> name, 401 AstNodeFactory<AstNullVisitor>* factory) { 402 if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) { 403 return function_->proxy()->var(); 404 } else if (!scope_info_.is_null()) { 405 // If we are backed by a scope info, try to lookup the variable there. 406 VariableMode mode; 407 int index = scope_info_->FunctionContextSlotIndex(*name, &mode); 408 if (index < 0) return NULL; 409 Variable* var = new(zone()) Variable( 410 this, name, mode, true /* is valid LHS */, 411 Variable::NORMAL, kCreatedInitialized); 412 VariableProxy* proxy = factory->NewVariableProxy(var); 413 VariableDeclaration* declaration = factory->NewVariableDeclaration( 414 proxy, mode, this, RelocInfo::kNoPosition); 415 DeclareFunctionVar(declaration); 416 var->AllocateTo(Variable::CONTEXT, index); 417 return var; 418 } else { 419 return NULL; 420 } 421 } 422 423 424 Variable* Scope::Lookup(Handle<String> name) { 425 for (Scope* scope = this; 426 scope != NULL; 427 scope = scope->outer_scope()) { 428 Variable* var = scope->LookupLocal(name); 429 if (var != NULL) return var; 430 } 431 return NULL; 432 } 433 434 435 void Scope::DeclareParameter(Handle<String> name, VariableMode mode) { 436 ASSERT(!already_resolved()); 437 ASSERT(is_function_scope()); 438 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, 439 kCreatedInitialized); 440 params_.Add(var, zone()); 441 } 442 443 444 Variable* Scope::DeclareLocal(Handle<String> name, 445 VariableMode mode, 446 InitializationFlag init_flag, 447 Interface* interface) { 448 ASSERT(!already_resolved()); 449 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are 450 // introduces during variable allocation, INTERNAL variables are allocated 451 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). 452 ASSERT(IsDeclaredVariableMode(mode)); 453 ++num_var_or_const_; 454 return variables_.Declare( 455 this, name, mode, true, Variable::NORMAL, init_flag, interface); 456 } 457 458 459 Variable* Scope::DeclareDynamicGlobal(Handle<String> name) { 460 ASSERT(is_global_scope()); 461 return variables_.Declare(this, 462 name, 463 DYNAMIC_GLOBAL, 464 true, 465 Variable::NORMAL, 466 kCreatedInitialized); 467 } 468 469 470 void Scope::RemoveUnresolved(VariableProxy* var) { 471 // Most likely (always?) any variable we want to remove 472 // was just added before, so we search backwards. 473 for (int i = unresolved_.length(); i-- > 0;) { 474 if (unresolved_[i] == var) { 475 unresolved_.Remove(i); 476 return; 477 } 478 } 479 } 480 481 482 Variable* Scope::NewInternal(Handle<String> name) { 483 ASSERT(!already_resolved()); 484 Variable* var = new(zone()) Variable(this, 485 name, 486 INTERNAL, 487 false, 488 Variable::NORMAL, 489 kCreatedInitialized); 490 internals_.Add(var, zone()); 491 return var; 492 } 493 494 495 Variable* Scope::NewTemporary(Handle<String> name) { 496 ASSERT(!already_resolved()); 497 Variable* var = new(zone()) Variable(this, 498 name, 499 TEMPORARY, 500 true, 501 Variable::NORMAL, 502 kCreatedInitialized); 503 temps_.Add(var, zone()); 504 return var; 505 } 506 507 508 void Scope::AddDeclaration(Declaration* declaration) { 509 decls_.Add(declaration, zone()); 510 } 511 512 513 void Scope::SetIllegalRedeclaration(Expression* expression) { 514 // Record only the first illegal redeclaration. 515 if (!HasIllegalRedeclaration()) { 516 illegal_redecl_ = expression; 517 } 518 ASSERT(HasIllegalRedeclaration()); 519 } 520 521 522 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { 523 ASSERT(HasIllegalRedeclaration()); 524 illegal_redecl_->Accept(visitor); 525 } 526 527 528 Declaration* Scope::CheckConflictingVarDeclarations() { 529 int length = decls_.length(); 530 for (int i = 0; i < length; i++) { 531 Declaration* decl = decls_[i]; 532 if (decl->mode() != VAR) continue; 533 Handle<String> name = decl->proxy()->name(); 534 535 // Iterate through all scopes until and including the declaration scope. 536 Scope* previous = NULL; 537 Scope* current = decl->scope(); 538 do { 539 // There is a conflict if there exists a non-VAR binding. 540 Variable* other_var = current->variables_.Lookup(name); 541 if (other_var != NULL && other_var->mode() != VAR) { 542 return decl; 543 } 544 previous = current; 545 current = current->outer_scope_; 546 } while (!previous->is_declaration_scope()); 547 } 548 return NULL; 549 } 550 551 552 class VarAndOrder { 553 public: 554 VarAndOrder(Variable* var, int order) : var_(var), order_(order) { } 555 Variable* var() const { return var_; } 556 int order() const { return order_; } 557 static int Compare(const VarAndOrder* a, const VarAndOrder* b) { 558 return a->order_ - b->order_; 559 } 560 561 private: 562 Variable* var_; 563 int order_; 564 }; 565 566 567 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, 568 ZoneList<Variable*>* context_locals) { 569 ASSERT(stack_locals != NULL); 570 ASSERT(context_locals != NULL); 571 572 // Collect internals which are always allocated on the heap. 573 for (int i = 0; i < internals_.length(); i++) { 574 Variable* var = internals_[i]; 575 if (var->is_used()) { 576 ASSERT(var->IsContextSlot()); 577 context_locals->Add(var, zone()); 578 } 579 } 580 581 // Collect temporaries which are always allocated on the stack, unless the 582 // context as a whole has forced context allocation. 583 for (int i = 0; i < temps_.length(); i++) { 584 Variable* var = temps_[i]; 585 if (var->is_used()) { 586 if (var->IsContextSlot()) { 587 ASSERT(has_forced_context_allocation()); 588 context_locals->Add(var, zone()); 589 } else { 590 ASSERT(var->IsStackLocal()); 591 stack_locals->Add(var, zone()); 592 } 593 } 594 } 595 596 // Collect declared local variables. 597 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); 598 for (VariableMap::Entry* p = variables_.Start(); 599 p != NULL; 600 p = variables_.Next(p)) { 601 Variable* var = reinterpret_cast<Variable*>(p->value); 602 if (var->is_used()) { 603 vars.Add(VarAndOrder(var, p->order), zone()); 604 } 605 } 606 vars.Sort(VarAndOrder::Compare); 607 int var_count = vars.length(); 608 for (int i = 0; i < var_count; i++) { 609 Variable* var = vars[i].var(); 610 if (var->IsStackLocal()) { 611 stack_locals->Add(var, zone()); 612 } else if (var->IsContextSlot()) { 613 context_locals->Add(var, zone()); 614 } 615 } 616 } 617 618 619 bool Scope::AllocateVariables(CompilationInfo* info, 620 AstNodeFactory<AstNullVisitor>* factory) { 621 // 1) Propagate scope information. 622 bool outer_scope_calls_sloppy_eval = false; 623 if (outer_scope_ != NULL) { 624 outer_scope_calls_sloppy_eval = 625 outer_scope_->outer_scope_calls_sloppy_eval() | 626 outer_scope_->calls_sloppy_eval(); 627 } 628 PropagateScopeInfo(outer_scope_calls_sloppy_eval); 629 630 // 2) Allocate module instances. 631 if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { 632 ASSERT(num_modules_ == 0); 633 AllocateModulesRecursively(this); 634 } 635 636 // 3) Resolve variables. 637 if (!ResolveVariablesRecursively(info, factory)) return false; 638 639 // 4) Allocate variables. 640 AllocateVariablesRecursively(); 641 642 return true; 643 } 644 645 646 bool Scope::HasTrivialContext() const { 647 // A function scope has a trivial context if it always is the global 648 // context. We iteratively scan out the context chain to see if 649 // there is anything that makes this scope non-trivial; otherwise we 650 // return true. 651 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { 652 if (scope->is_eval_scope()) return false; 653 if (scope->scope_inside_with_) return false; 654 if (scope->num_heap_slots_ > 0) return false; 655 } 656 return true; 657 } 658 659 660 bool Scope::HasTrivialOuterContext() const { 661 Scope* outer = outer_scope_; 662 if (outer == NULL) return true; 663 // Note that the outer context may be trivial in general, but the current 664 // scope may be inside a 'with' statement in which case the outer context 665 // for this scope is not trivial. 666 return !scope_inside_with_ && outer->HasTrivialContext(); 667 } 668 669 670 bool Scope::HasLazyCompilableOuterContext() const { 671 Scope* outer = outer_scope_; 672 if (outer == NULL) return true; 673 // We have to prevent lazy compilation if this scope is inside a with scope 674 // and all declaration scopes between them have empty contexts. Such 675 // declaration scopes may become invisible during scope info deserialization. 676 outer = outer->DeclarationScope(); 677 bool found_non_trivial_declarations = false; 678 for (const Scope* scope = outer; scope != NULL; scope = scope->outer_scope_) { 679 if (scope->is_with_scope() && !found_non_trivial_declarations) return false; 680 if (scope->is_declaration_scope() && scope->num_heap_slots() > 0) { 681 found_non_trivial_declarations = true; 682 } 683 } 684 return true; 685 } 686 687 688 bool Scope::AllowsLazyCompilation() const { 689 return !force_eager_compilation_ && HasLazyCompilableOuterContext(); 690 } 691 692 693 bool Scope::AllowsLazyCompilationWithoutContext() const { 694 return !force_eager_compilation_ && HasTrivialOuterContext(); 695 } 696 697 698 int Scope::ContextChainLength(Scope* scope) { 699 int n = 0; 700 for (Scope* s = this; s != scope; s = s->outer_scope_) { 701 ASSERT(s != NULL); // scope must be in the scope chain 702 if (s->is_with_scope() || s->num_heap_slots() > 0) n++; 703 // Catch and module scopes always have heap slots. 704 ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0); 705 ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0); 706 } 707 return n; 708 } 709 710 711 Scope* Scope::GlobalScope() { 712 Scope* scope = this; 713 while (!scope->is_global_scope()) { 714 scope = scope->outer_scope(); 715 } 716 return scope; 717 } 718 719 720 Scope* Scope::DeclarationScope() { 721 Scope* scope = this; 722 while (!scope->is_declaration_scope()) { 723 scope = scope->outer_scope(); 724 } 725 return scope; 726 } 727 728 729 Handle<ScopeInfo> Scope::GetScopeInfo() { 730 if (scope_info_.is_null()) { 731 scope_info_ = ScopeInfo::Create(this, zone()); 732 } 733 return scope_info_; 734 } 735 736 737 void Scope::GetNestedScopeChain( 738 List<Handle<ScopeInfo> >* chain, 739 int position) { 740 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo())); 741 742 for (int i = 0; i < inner_scopes_.length(); i++) { 743 Scope* scope = inner_scopes_[i]; 744 int beg_pos = scope->start_position(); 745 int end_pos = scope->end_position(); 746 ASSERT(beg_pos >= 0 && end_pos >= 0); 747 if (beg_pos <= position && position < end_pos) { 748 scope->GetNestedScopeChain(chain, position); 749 return; 750 } 751 } 752 } 753 754 755 #ifdef DEBUG 756 static const char* Header(ScopeType scope_type) { 757 switch (scope_type) { 758 case EVAL_SCOPE: return "eval"; 759 case FUNCTION_SCOPE: return "function"; 760 case MODULE_SCOPE: return "module"; 761 case GLOBAL_SCOPE: return "global"; 762 case CATCH_SCOPE: return "catch"; 763 case BLOCK_SCOPE: return "block"; 764 case WITH_SCOPE: return "with"; 765 } 766 UNREACHABLE(); 767 return NULL; 768 } 769 770 771 static void Indent(int n, const char* str) { 772 PrintF("%*s%s", n, "", str); 773 } 774 775 776 static void PrintName(Handle<String> name) { 777 SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS); 778 PrintF("%s", s.get()); 779 } 780 781 782 static void PrintLocation(Variable* var) { 783 switch (var->location()) { 784 case Variable::UNALLOCATED: 785 break; 786 case Variable::PARAMETER: 787 PrintF("parameter[%d]", var->index()); 788 break; 789 case Variable::LOCAL: 790 PrintF("local[%d]", var->index()); 791 break; 792 case Variable::CONTEXT: 793 PrintF("context[%d]", var->index()); 794 break; 795 case Variable::LOOKUP: 796 PrintF("lookup"); 797 break; 798 } 799 } 800 801 802 static void PrintVar(int indent, Variable* var) { 803 if (var->is_used() || !var->IsUnallocated()) { 804 Indent(indent, Variable::Mode2String(var->mode())); 805 PrintF(" "); 806 PrintName(var->name()); 807 PrintF("; // "); 808 PrintLocation(var); 809 if (var->has_forced_context_allocation()) { 810 if (!var->IsUnallocated()) PrintF(", "); 811 PrintF("forced context allocation"); 812 } 813 PrintF("\n"); 814 } 815 } 816 817 818 static void PrintMap(int indent, VariableMap* map) { 819 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { 820 Variable* var = reinterpret_cast<Variable*>(p->value); 821 PrintVar(indent, var); 822 } 823 } 824 825 826 void Scope::Print(int n) { 827 int n0 = (n > 0 ? n : 0); 828 int n1 = n0 + 2; // indentation 829 830 // Print header. 831 Indent(n0, Header(scope_type_)); 832 if (scope_name_->length() > 0) { 833 PrintF(" "); 834 PrintName(scope_name_); 835 } 836 837 // Print parameters, if any. 838 if (is_function_scope()) { 839 PrintF(" ("); 840 for (int i = 0; i < params_.length(); i++) { 841 if (i > 0) PrintF(", "); 842 PrintName(params_[i]->name()); 843 } 844 PrintF(")"); 845 } 846 847 PrintF(" { // (%d, %d)\n", start_position(), end_position()); 848 849 // Function name, if any (named function literals, only). 850 if (function_ != NULL) { 851 Indent(n1, "// (local) function name: "); 852 PrintName(function_->proxy()->name()); 853 PrintF("\n"); 854 } 855 856 // Scope info. 857 if (HasTrivialOuterContext()) { 858 Indent(n1, "// scope has trivial outer context\n"); 859 } 860 if (strict_mode() == STRICT) { 861 Indent(n1, "// strict mode scope\n"); 862 } 863 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 864 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); 865 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 866 if (outer_scope_calls_sloppy_eval_) { 867 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); 868 } 869 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 870 if (num_stack_slots_ > 0) { Indent(n1, "// "); 871 PrintF("%d stack slots\n", num_stack_slots_); } 872 if (num_heap_slots_ > 0) { Indent(n1, "// "); 873 PrintF("%d heap slots\n", num_heap_slots_); } 874 875 // Print locals. 876 if (function_ != NULL) { 877 Indent(n1, "// function var:\n"); 878 PrintVar(n1, function_->proxy()->var()); 879 } 880 881 if (temps_.length() > 0) { 882 Indent(n1, "// temporary vars:\n"); 883 for (int i = 0; i < temps_.length(); i++) { 884 PrintVar(n1, temps_[i]); 885 } 886 } 887 888 if (internals_.length() > 0) { 889 Indent(n1, "// internal vars:\n"); 890 for (int i = 0; i < internals_.length(); i++) { 891 PrintVar(n1, internals_[i]); 892 } 893 } 894 895 if (variables_.Start() != NULL) { 896 Indent(n1, "// local vars:\n"); 897 PrintMap(n1, &variables_); 898 } 899 900 if (dynamics_ != NULL) { 901 Indent(n1, "// dynamic vars:\n"); 902 PrintMap(n1, dynamics_->GetMap(DYNAMIC)); 903 PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL)); 904 PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL)); 905 } 906 907 // Print inner scopes (disable by providing negative n). 908 if (n >= 0) { 909 for (int i = 0; i < inner_scopes_.length(); i++) { 910 PrintF("\n"); 911 inner_scopes_[i]->Print(n1); 912 } 913 } 914 915 Indent(n0, "}\n"); 916 } 917 #endif // DEBUG 918 919 920 Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) { 921 if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone()); 922 VariableMap* map = dynamics_->GetMap(mode); 923 Variable* var = map->Lookup(name); 924 if (var == NULL) { 925 // Declare a new non-local. 926 InitializationFlag init_flag = (mode == VAR) 927 ? kCreatedInitialized : kNeedsInitialization; 928 var = map->Declare(NULL, 929 name, 930 mode, 931 true, 932 Variable::NORMAL, 933 init_flag); 934 // Allocate it by giving it a dynamic lookup. 935 var->AllocateTo(Variable::LOOKUP, -1); 936 } 937 return var; 938 } 939 940 941 Variable* Scope::LookupRecursive(Handle<String> name, 942 BindingKind* binding_kind, 943 AstNodeFactory<AstNullVisitor>* factory) { 944 ASSERT(binding_kind != NULL); 945 if (already_resolved() && is_with_scope()) { 946 // Short-cut: if the scope is deserialized from a scope info, variable 947 // allocation is already fixed. We can simply return with dynamic lookup. 948 *binding_kind = DYNAMIC_LOOKUP; 949 return NULL; 950 } 951 952 // Try to find the variable in this scope. 953 Variable* var = LookupLocal(name); 954 955 // We found a variable and we are done. (Even if there is an 'eval' in 956 // this scope which introduces the same variable again, the resulting 957 // variable remains the same.) 958 if (var != NULL) { 959 *binding_kind = BOUND; 960 return var; 961 } 962 963 // We did not find a variable locally. Check against the function variable, 964 // if any. We can do this for all scopes, since the function variable is 965 // only present - if at all - for function scopes. 966 *binding_kind = UNBOUND; 967 var = LookupFunctionVar(name, factory); 968 if (var != NULL) { 969 *binding_kind = BOUND; 970 } else if (outer_scope_ != NULL) { 971 var = outer_scope_->LookupRecursive(name, binding_kind, factory); 972 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { 973 var->ForceContextAllocation(); 974 } 975 } else { 976 ASSERT(is_global_scope()); 977 } 978 979 if (is_with_scope()) { 980 ASSERT(!already_resolved()); 981 // The current scope is a with scope, so the variable binding can not be 982 // statically resolved. However, note that it was necessary to do a lookup 983 // in the outer scope anyway, because if a binding exists in an outer scope, 984 // the associated variable has to be marked as potentially being accessed 985 // from inside of an inner with scope (the property may not be in the 'with' 986 // object). 987 *binding_kind = DYNAMIC_LOOKUP; 988 return NULL; 989 } else if (calls_sloppy_eval()) { 990 // A variable binding may have been found in an outer scope, but the current 991 // scope makes a sloppy 'eval' call, so the found variable may not be 992 // the correct one (the 'eval' may introduce a binding with the same name). 993 // In that case, change the lookup result to reflect this situation. 994 if (*binding_kind == BOUND) { 995 *binding_kind = BOUND_EVAL_SHADOWED; 996 } else if (*binding_kind == UNBOUND) { 997 *binding_kind = UNBOUND_EVAL_SHADOWED; 998 } 999 } 1000 return var; 1001 } 1002 1003 1004 bool Scope::ResolveVariable(CompilationInfo* info, 1005 VariableProxy* proxy, 1006 AstNodeFactory<AstNullVisitor>* factory) { 1007 ASSERT(info->global_scope()->is_global_scope()); 1008 1009 // If the proxy is already resolved there's nothing to do 1010 // (functions and consts may be resolved by the parser). 1011 if (proxy->var() != NULL) return true; 1012 1013 // Otherwise, try to resolve the variable. 1014 BindingKind binding_kind; 1015 Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory); 1016 switch (binding_kind) { 1017 case BOUND: 1018 // We found a variable binding. 1019 break; 1020 1021 case BOUND_EVAL_SHADOWED: 1022 // We either found a variable binding that might be shadowed by eval or 1023 // gave up on it (e.g. by encountering a local with the same in the outer 1024 // scope which was not promoted to a context, this can happen if we use 1025 // debugger to evaluate arbitrary expressions at a break point). 1026 if (var->IsGlobalObjectProperty()) { 1027 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); 1028 } else if (var->is_dynamic()) { 1029 var = NonLocal(proxy->name(), DYNAMIC); 1030 } else { 1031 Variable* invalidated = var; 1032 var = NonLocal(proxy->name(), DYNAMIC_LOCAL); 1033 var->set_local_if_not_shadowed(invalidated); 1034 } 1035 break; 1036 1037 case UNBOUND: 1038 // No binding has been found. Declare a variable on the global object. 1039 var = info->global_scope()->DeclareDynamicGlobal(proxy->name()); 1040 break; 1041 1042 case UNBOUND_EVAL_SHADOWED: 1043 // No binding has been found. But some scope makes a sloppy 'eval' call. 1044 var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); 1045 break; 1046 1047 case DYNAMIC_LOOKUP: 1048 // The variable could not be resolved statically. 1049 var = NonLocal(proxy->name(), DYNAMIC); 1050 break; 1051 } 1052 1053 ASSERT(var != NULL); 1054 1055 if (FLAG_harmony_scoping && strict_mode() == STRICT && 1056 var->is_const_mode() && proxy->IsLValue()) { 1057 // Assignment to const. Throw a syntax error. 1058 MessageLocation location( 1059 info->script(), proxy->position(), proxy->position()); 1060 Isolate* isolate = info->isolate(); 1061 Factory* factory = isolate->factory(); 1062 Handle<JSArray> array = factory->NewJSArray(0); 1063 Handle<Object> result = 1064 factory->NewSyntaxError("harmony_const_assign", array); 1065 isolate->Throw(*result, &location); 1066 return false; 1067 } 1068 1069 if (FLAG_harmony_modules) { 1070 bool ok; 1071 #ifdef DEBUG 1072 if (FLAG_print_interface_details) 1073 PrintF("# Resolve %s:\n", var->name()->ToAsciiArray()); 1074 #endif 1075 proxy->interface()->Unify(var->interface(), zone(), &ok); 1076 if (!ok) { 1077 #ifdef DEBUG 1078 if (FLAG_print_interfaces) { 1079 PrintF("SCOPES TYPE ERROR\n"); 1080 PrintF("proxy: "); 1081 proxy->interface()->Print(); 1082 PrintF("var: "); 1083 var->interface()->Print(); 1084 } 1085 #endif 1086 1087 // Inconsistent use of module. Throw a syntax error. 1088 // TODO(rossberg): generate more helpful error message. 1089 MessageLocation location( 1090 info->script(), proxy->position(), proxy->position()); 1091 Isolate* isolate = info->isolate(); 1092 Factory* factory = isolate->factory(); 1093 Handle<JSArray> array = factory->NewJSArray(1); 1094 JSObject::SetElement(array, 0, var->name(), NONE, STRICT).Assert(); 1095 Handle<Object> result = 1096 factory->NewSyntaxError("module_type_error", array); 1097 isolate->Throw(*result, &location); 1098 return false; 1099 } 1100 } 1101 1102 proxy->BindTo(var); 1103 1104 return true; 1105 } 1106 1107 1108 bool Scope::ResolveVariablesRecursively( 1109 CompilationInfo* info, 1110 AstNodeFactory<AstNullVisitor>* factory) { 1111 ASSERT(info->global_scope()->is_global_scope()); 1112 1113 // Resolve unresolved variables for this scope. 1114 for (int i = 0; i < unresolved_.length(); i++) { 1115 if (!ResolveVariable(info, unresolved_[i], factory)) return false; 1116 } 1117 1118 // Resolve unresolved variables for inner scopes. 1119 for (int i = 0; i < inner_scopes_.length(); i++) { 1120 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) 1121 return false; 1122 } 1123 1124 return true; 1125 } 1126 1127 1128 bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) { 1129 if (outer_scope_calls_sloppy_eval) { 1130 outer_scope_calls_sloppy_eval_ = true; 1131 } 1132 1133 bool calls_sloppy_eval = 1134 this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_; 1135 for (int i = 0; i < inner_scopes_.length(); i++) { 1136 Scope* inner_scope = inner_scopes_[i]; 1137 if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) { 1138 inner_scope_calls_eval_ = true; 1139 } 1140 if (inner_scope->force_eager_compilation_) { 1141 force_eager_compilation_ = true; 1142 } 1143 } 1144 1145 return scope_calls_eval_ || inner_scope_calls_eval_; 1146 } 1147 1148 1149 bool Scope::MustAllocate(Variable* var) { 1150 // Give var a read/write use if there is a chance it might be accessed 1151 // via an eval() call. This is only possible if the variable has a 1152 // visible name. 1153 if ((var->is_this() || var->name()->length() > 0) && 1154 (var->has_forced_context_allocation() || 1155 scope_calls_eval_ || 1156 inner_scope_calls_eval_ || 1157 scope_contains_with_ || 1158 is_catch_scope() || 1159 is_block_scope() || 1160 is_module_scope() || 1161 is_global_scope())) { 1162 var->set_is_used(true); 1163 } 1164 // Global variables do not need to be allocated. 1165 return !var->IsGlobalObjectProperty() && var->is_used(); 1166 } 1167 1168 1169 bool Scope::MustAllocateInContext(Variable* var) { 1170 // 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 1172 // an eval() call or a runtime with lookup), it must be allocated in the 1173 // context. 1174 // 1175 // Exceptions: If the scope as a whole has forced context allocation, all 1176 // variables will have context allocation, even temporaries. Otherwise 1177 // temporary variables are always stack-allocated. Catch-bound variables are 1178 // always context-allocated. 1179 if (has_forced_context_allocation()) return true; 1180 if (var->mode() == TEMPORARY) return false; 1181 if (var->mode() == INTERNAL) return true; 1182 if (is_catch_scope() || is_block_scope() || is_module_scope()) return true; 1183 if (is_global_scope() && IsLexicalVariableMode(var->mode())) return true; 1184 return var->has_forced_context_allocation() || 1185 scope_calls_eval_ || 1186 inner_scope_calls_eval_ || 1187 scope_contains_with_; 1188 } 1189 1190 1191 bool Scope::HasArgumentsParameter() { 1192 for (int i = 0; i < params_.length(); i++) { 1193 if (params_[i]->name().is_identical_to( 1194 isolate_->factory()->arguments_string())) { 1195 return true; 1196 } 1197 } 1198 return false; 1199 } 1200 1201 1202 void Scope::AllocateStackSlot(Variable* var) { 1203 var->AllocateTo(Variable::LOCAL, num_stack_slots_++); 1204 } 1205 1206 1207 void Scope::AllocateHeapSlot(Variable* var) { 1208 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++); 1209 } 1210 1211 1212 void Scope::AllocateParameterLocals() { 1213 ASSERT(is_function_scope()); 1214 Variable* arguments = LookupLocal(isolate_->factory()->arguments_string()); 1215 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly 1216 1217 bool uses_sloppy_arguments = false; 1218 1219 if (MustAllocate(arguments) && !HasArgumentsParameter()) { 1220 // 'arguments' is used. Unless there is also a parameter called 1221 // 'arguments', we must be conservative and allocate all parameters to 1222 // the context assuming they will be captured by the arguments object. 1223 // If we have a parameter named 'arguments', a (new) value is always 1224 // assigned to it via the function invocation. Then 'arguments' denotes 1225 // that specific parameter value and cannot be used to access the 1226 // parameters, which is why we don't need to allocate an arguments 1227 // object in that case. 1228 1229 // We are using 'arguments'. Tell the code generator that is needs to 1230 // allocate the arguments object by setting 'arguments_'. 1231 arguments_ = arguments; 1232 1233 // In strict mode 'arguments' does not alias formal parameters. 1234 // Therefore in strict mode we allocate parameters as if 'arguments' 1235 // were not used. 1236 uses_sloppy_arguments = strict_mode() == SLOPPY; 1237 } 1238 1239 // The same parameter may occur multiple times in the parameters_ list. 1240 // If it does, and if it is not copied into the context object, it must 1241 // receive the highest parameter index for that parameter; thus iteration 1242 // order is relevant! 1243 for (int i = params_.length() - 1; i >= 0; --i) { 1244 Variable* var = params_[i]; 1245 ASSERT(var->scope() == this); 1246 if (uses_sloppy_arguments || has_forced_context_allocation()) { 1247 // Force context allocation of the parameter. 1248 var->ForceContextAllocation(); 1249 } 1250 1251 if (MustAllocate(var)) { 1252 if (MustAllocateInContext(var)) { 1253 ASSERT(var->IsUnallocated() || var->IsContextSlot()); 1254 if (var->IsUnallocated()) { 1255 AllocateHeapSlot(var); 1256 } 1257 } else { 1258 ASSERT(var->IsUnallocated() || var->IsParameter()); 1259 if (var->IsUnallocated()) { 1260 var->AllocateTo(Variable::PARAMETER, i); 1261 } 1262 } 1263 } 1264 } 1265 } 1266 1267 1268 void Scope::AllocateNonParameterLocal(Variable* var) { 1269 ASSERT(var->scope() == this); 1270 ASSERT(!var->IsVariable(isolate_->factory()->dot_result_string()) || 1271 !var->IsStackLocal()); 1272 if (var->IsUnallocated() && MustAllocate(var)) { 1273 if (MustAllocateInContext(var)) { 1274 AllocateHeapSlot(var); 1275 } else { 1276 AllocateStackSlot(var); 1277 } 1278 } 1279 } 1280 1281 1282 void Scope::AllocateNonParameterLocals() { 1283 // All variables that have no rewrite yet are non-parameter locals. 1284 for (int i = 0; i < temps_.length(); i++) { 1285 AllocateNonParameterLocal(temps_[i]); 1286 } 1287 1288 for (int i = 0; i < internals_.length(); i++) { 1289 AllocateNonParameterLocal(internals_[i]); 1290 } 1291 1292 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); 1293 for (VariableMap::Entry* p = variables_.Start(); 1294 p != NULL; 1295 p = variables_.Next(p)) { 1296 Variable* var = reinterpret_cast<Variable*>(p->value); 1297 vars.Add(VarAndOrder(var, p->order), zone()); 1298 } 1299 vars.Sort(VarAndOrder::Compare); 1300 int var_count = vars.length(); 1301 for (int i = 0; i < var_count; i++) { 1302 AllocateNonParameterLocal(vars[i].var()); 1303 } 1304 1305 // For now, function_ must be allocated at the very end. If it gets 1306 // allocated in the context, it must be the last slot in the context, 1307 // because of the current ScopeInfo implementation (see 1308 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 1309 if (function_ != NULL) { 1310 AllocateNonParameterLocal(function_->proxy()->var()); 1311 } 1312 } 1313 1314 1315 void Scope::AllocateVariablesRecursively() { 1316 // Allocate variables for inner scopes. 1317 for (int i = 0; i < inner_scopes_.length(); i++) { 1318 inner_scopes_[i]->AllocateVariablesRecursively(); 1319 } 1320 1321 // If scope is already resolved, we still need to allocate 1322 // variables in inner scopes which might not had been resolved yet. 1323 if (already_resolved()) return; 1324 // The number of slots required for variables. 1325 num_stack_slots_ = 0; 1326 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1327 1328 // Allocate variables for this scope. 1329 // Parameters must be allocated first, if any. 1330 if (is_function_scope()) AllocateParameterLocals(); 1331 AllocateNonParameterLocals(); 1332 1333 // Force allocation of a context for this scope if necessary. For a 'with' 1334 // scope and for a function scope that makes an 'eval' call we need a context, 1335 // even if no local variables were statically allocated in the scope. 1336 // Likewise for modules. 1337 bool must_have_context = is_with_scope() || is_module_scope() || 1338 (is_function_scope() && calls_eval()); 1339 1340 // If we didn't allocate any locals in the local context, then we only 1341 // need the minimal number of slots if we must have a context. 1342 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { 1343 num_heap_slots_ = 0; 1344 } 1345 1346 // Allocation done. 1347 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1348 } 1349 1350 1351 void Scope::AllocateModulesRecursively(Scope* host_scope) { 1352 if (already_resolved()) return; 1353 if (is_module_scope()) { 1354 ASSERT(interface_->IsFrozen()); 1355 Handle<String> name = isolate_->factory()->InternalizeOneByteString( 1356 STATIC_ASCII_VECTOR(".module")); 1357 ASSERT(module_var_ == NULL); 1358 module_var_ = host_scope->NewInternal(name); 1359 ++host_scope->num_modules_; 1360 } 1361 1362 for (int i = 0; i < inner_scopes_.length(); i++) { 1363 Scope* inner_scope = inner_scopes_.at(i); 1364 inner_scope->AllocateModulesRecursively(host_scope); 1365 } 1366 } 1367 1368 1369 int Scope::StackLocalCount() const { 1370 return num_stack_slots() - 1371 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); 1372 } 1373 1374 1375 int Scope::ContextLocalCount() const { 1376 if (num_heap_slots() == 0) return 0; 1377 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - 1378 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); 1379 } 1380 1381 } } // namespace v8::internal 1382