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