1 // Copyright 2010 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 "bootstrapper.h" 33 #include "compiler.h" 34 #include "prettyprinter.h" 35 #include "scopeinfo.h" 36 37 namespace v8 { 38 namespace internal { 39 40 // ---------------------------------------------------------------------------- 41 // A Zone allocator for use with LocalsMap. 42 43 // TODO(isolates): It is probably worth it to change the Allocator class to 44 // take a pointer to an isolate. 45 class ZoneAllocator: public Allocator { 46 public: 47 /* nothing to do */ 48 virtual ~ZoneAllocator() {} 49 50 virtual void* New(size_t size) { return ZONE->New(static_cast<int>(size)); } 51 52 /* ignored - Zone is freed in one fell swoop */ 53 virtual void Delete(void* p) {} 54 }; 55 56 57 static ZoneAllocator LocalsMapAllocator; 58 59 60 // ---------------------------------------------------------------------------- 61 // Implementation of LocalsMap 62 // 63 // Note: We are storing the handle locations as key values in the hash map. 64 // When inserting a new variable via Declare(), we rely on the fact that 65 // the handle location remains alive for the duration of that variable 66 // use. Because a Variable holding a handle with the same location exists 67 // this is ensured. 68 69 static bool Match(void* key1, void* key2) { 70 String* name1 = *reinterpret_cast<String**>(key1); 71 String* name2 = *reinterpret_cast<String**>(key2); 72 ASSERT(name1->IsSymbol()); 73 ASSERT(name2->IsSymbol()); 74 return name1 == name2; 75 } 76 77 78 // Dummy constructor 79 VariableMap::VariableMap(bool gotta_love_static_overloading) : HashMap() {} 80 81 VariableMap::VariableMap() : HashMap(Match, &LocalsMapAllocator, 8) {} 82 VariableMap::~VariableMap() {} 83 84 85 Variable* VariableMap::Declare(Scope* scope, 86 Handle<String> name, 87 Variable::Mode mode, 88 bool is_valid_lhs, 89 Variable::Kind kind) { 90 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); 91 if (p->value == NULL) { 92 // The variable has not been declared yet -> insert it. 93 ASSERT(p->key == name.location()); 94 p->value = new Variable(scope, name, mode, is_valid_lhs, kind); 95 } 96 return reinterpret_cast<Variable*>(p->value); 97 } 98 99 100 Variable* VariableMap::Lookup(Handle<String> name) { 101 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); 102 if (p != NULL) { 103 ASSERT(*reinterpret_cast<String**>(p->key) == *name); 104 ASSERT(p->value != NULL); 105 return reinterpret_cast<Variable*>(p->value); 106 } 107 return NULL; 108 } 109 110 111 // ---------------------------------------------------------------------------- 112 // Implementation of Scope 113 114 115 // Dummy constructor 116 Scope::Scope(Type type) 117 : inner_scopes_(0), 118 variables_(false), 119 temps_(0), 120 params_(0), 121 unresolved_(0), 122 decls_(0) { 123 SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null()); 124 ASSERT(!resolved()); 125 } 126 127 128 Scope::Scope(Scope* outer_scope, Type type) 129 : inner_scopes_(4), 130 variables_(), 131 temps_(4), 132 params_(4), 133 unresolved_(16), 134 decls_(4) { 135 SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null()); 136 // At some point we might want to provide outer scopes to 137 // eval scopes (by walking the stack and reading the scope info). 138 // In that case, the ASSERT below needs to be adjusted. 139 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); 140 ASSERT(!HasIllegalRedeclaration()); 141 ASSERT(!resolved()); 142 } 143 144 145 Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info) 146 : inner_scopes_(4), 147 variables_(), 148 temps_(4), 149 params_(4), 150 unresolved_(16), 151 decls_(4) { 152 ASSERT(!scope_info.is_null()); 153 SetDefaults(FUNCTION_SCOPE, NULL, scope_info); 154 ASSERT(resolved()); 155 if (scope_info->HasHeapAllocatedLocals()) { 156 num_heap_slots_ = scope_info_->NumberOfContextSlots(); 157 } 158 159 AddInnerScope(inner_scope); 160 161 // This scope's arguments shadow (if present) is context-allocated if an inner 162 // scope accesses this one's parameters. Allocate the arguments_shadow_ 163 // variable if necessary. 164 Isolate* isolate = Isolate::Current(); 165 Variable::Mode mode; 166 int arguments_shadow_index = 167 scope_info_->ContextSlotIndex( 168 isolate->heap()->arguments_shadow_symbol(), &mode); 169 if (arguments_shadow_index >= 0) { 170 ASSERT(mode == Variable::INTERNAL); 171 arguments_shadow_ = new Variable( 172 this, 173 isolate->factory()->arguments_shadow_symbol(), 174 Variable::INTERNAL, 175 true, 176 Variable::ARGUMENTS); 177 arguments_shadow_->set_rewrite( 178 new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index)); 179 arguments_shadow_->set_is_used(true); 180 } 181 } 182 183 184 void Scope::SetDefaults(Type type, 185 Scope* outer_scope, 186 Handle<SerializedScopeInfo> scope_info) { 187 outer_scope_ = outer_scope; 188 type_ = type; 189 scope_name_ = FACTORY->empty_symbol(); 190 dynamics_ = NULL; 191 receiver_ = NULL; 192 function_ = NULL; 193 arguments_ = NULL; 194 arguments_shadow_ = NULL; 195 illegal_redecl_ = NULL; 196 scope_inside_with_ = false; 197 scope_contains_with_ = false; 198 scope_calls_eval_ = false; 199 // Inherit the strict mode from the parent scope. 200 strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; 201 outer_scope_calls_eval_ = false; 202 inner_scope_calls_eval_ = false; 203 outer_scope_is_eval_scope_ = false; 204 force_eager_compilation_ = false; 205 num_var_or_const_ = 0; 206 num_stack_slots_ = 0; 207 num_heap_slots_ = 0; 208 scope_info_ = scope_info; 209 } 210 211 212 Scope* Scope::DeserializeScopeChain(CompilationInfo* info, 213 Scope* global_scope) { 214 ASSERT(!info->closure().is_null()); 215 // If we have a serialized scope info, reuse it. 216 Scope* innermost_scope = NULL; 217 Scope* scope = NULL; 218 219 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); 220 if (scope_info != SerializedScopeInfo::Empty()) { 221 JSFunction* current = *info->closure(); 222 do { 223 current = current->context()->closure(); 224 Handle<SerializedScopeInfo> scope_info(current->shared()->scope_info()); 225 if (*scope_info != SerializedScopeInfo::Empty()) { 226 scope = new Scope(scope, scope_info); 227 if (innermost_scope == NULL) innermost_scope = scope; 228 } else { 229 ASSERT(current->context()->IsGlobalContext()); 230 } 231 } while (!current->context()->IsGlobalContext()); 232 } 233 234 global_scope->AddInnerScope(scope); 235 if (innermost_scope == NULL) innermost_scope = global_scope; 236 237 return innermost_scope; 238 } 239 240 241 bool Scope::Analyze(CompilationInfo* info) { 242 ASSERT(info->function() != NULL); 243 Scope* top = info->function()->scope(); 244 245 while (top->outer_scope() != NULL) top = top->outer_scope(); 246 top->AllocateVariables(info->calling_context()); 247 248 #ifdef DEBUG 249 if (info->isolate()->bootstrapper()->IsActive() 250 ? FLAG_print_builtin_scopes 251 : FLAG_print_scopes) { 252 info->function()->scope()->Print(); 253 } 254 #endif 255 256 info->SetScope(info->function()->scope()); 257 return true; // Can not fail. 258 } 259 260 261 void Scope::Initialize(bool inside_with) { 262 ASSERT(!resolved()); 263 264 // Add this scope as a new inner scope of the outer scope. 265 if (outer_scope_ != NULL) { 266 outer_scope_->inner_scopes_.Add(this); 267 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; 268 } else { 269 scope_inside_with_ = inside_with; 270 } 271 272 // Declare convenience variables. 273 // Declare and allocate receiver (even for the global scope, and even 274 // if naccesses_ == 0). 275 // NOTE: When loading parameters in the global scope, we must take 276 // care not to access them as properties of the global object, but 277 // instead load them directly from the stack. Currently, the only 278 // such parameter is 'this' which is passed on the stack when 279 // invoking scripts 280 Variable* var = 281 variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR, 282 false, Variable::THIS); 283 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1)); 284 receiver_ = var; 285 286 if (is_function_scope()) { 287 // Declare 'arguments' variable which exists in all functions. 288 // Note that it might never be accessed, in which case it won't be 289 // allocated during variable allocation. 290 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR, 291 true, Variable::ARGUMENTS); 292 } 293 } 294 295 296 Variable* Scope::LocalLookup(Handle<String> name) { 297 Variable* result = variables_.Lookup(name); 298 if (result != NULL || !resolved()) { 299 return result; 300 } 301 // If the scope is resolved, we can find a variable in serialized scope info. 302 303 // We should never lookup 'arguments' in this scope 304 // as it is implicitly present in any scope. 305 ASSERT(*name != *FACTORY->arguments_symbol()); 306 307 // Assert that there is no local slot with the given name. 308 ASSERT(scope_info_->StackSlotIndex(*name) < 0); 309 310 // Check context slot lookup. 311 Variable::Mode mode; 312 int index = scope_info_->ContextSlotIndex(*name, &mode); 313 if (index >= 0) { 314 Variable* var = 315 variables_.Declare(this, name, mode, true, Variable::NORMAL); 316 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); 317 return var; 318 } 319 320 index = scope_info_->ParameterIndex(*name); 321 if (index >= 0) { 322 // ".arguments" must be present in context slots. 323 ASSERT(arguments_shadow_ != NULL); 324 Variable* var = 325 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); 326 Property* rewrite = 327 new Property(new VariableProxy(arguments_shadow_), 328 new Literal(Handle<Object>(Smi::FromInt(index))), 329 RelocInfo::kNoPosition, 330 Property::SYNTHETIC); 331 rewrite->set_is_arguments_access(true); 332 var->set_rewrite(rewrite); 333 return var; 334 } 335 336 index = scope_info_->FunctionContextSlotIndex(*name); 337 if (index >= 0) { 338 // Check that there is no local slot with the given name. 339 ASSERT(scope_info_->StackSlotIndex(*name) < 0); 340 Variable* var = 341 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); 342 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); 343 return var; 344 } 345 346 return NULL; 347 } 348 349 350 Variable* Scope::Lookup(Handle<String> name) { 351 for (Scope* scope = this; 352 scope != NULL; 353 scope = scope->outer_scope()) { 354 Variable* var = scope->LocalLookup(name); 355 if (var != NULL) return var; 356 } 357 return NULL; 358 } 359 360 361 Variable* Scope::DeclareFunctionVar(Handle<String> name) { 362 ASSERT(is_function_scope() && function_ == NULL); 363 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); 364 return function_; 365 } 366 367 368 Variable* Scope::DeclareLocal(Handle<String> name, 369 Variable::Mode mode, 370 LocalType type) { 371 // DYNAMIC variables are introduces during variable allocation, 372 // INTERNAL variables are allocated explicitly, and TEMPORARY 373 // variables are allocated via NewTemporary(). 374 ASSERT(!resolved()); 375 ASSERT(mode == Variable::VAR || mode == Variable::CONST); 376 if (type == VAR_OR_CONST) { 377 num_var_or_const_++; 378 } 379 return variables_.Declare(this, name, mode, true, Variable::NORMAL); 380 } 381 382 383 Variable* Scope::DeclareGlobal(Handle<String> name) { 384 ASSERT(is_global_scope()); 385 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, 386 Variable::NORMAL); 387 } 388 389 390 void Scope::AddParameter(Variable* var) { 391 ASSERT(is_function_scope()); 392 ASSERT(LocalLookup(var->name()) == var); 393 params_.Add(var); 394 } 395 396 397 VariableProxy* Scope::NewUnresolved(Handle<String> name, 398 bool inside_with, 399 int position) { 400 // Note that we must not share the unresolved variables with 401 // the same name because they may be removed selectively via 402 // RemoveUnresolved(). 403 ASSERT(!resolved()); 404 VariableProxy* proxy = new VariableProxy(name, false, inside_with, position); 405 unresolved_.Add(proxy); 406 return proxy; 407 } 408 409 410 void Scope::RemoveUnresolved(VariableProxy* var) { 411 // Most likely (always?) any variable we want to remove 412 // was just added before, so we search backwards. 413 for (int i = unresolved_.length(); i-- > 0;) { 414 if (unresolved_[i] == var) { 415 unresolved_.Remove(i); 416 return; 417 } 418 } 419 } 420 421 422 Variable* Scope::NewTemporary(Handle<String> name) { 423 ASSERT(!resolved()); 424 Variable* var = 425 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); 426 temps_.Add(var); 427 return var; 428 } 429 430 431 void Scope::AddDeclaration(Declaration* declaration) { 432 decls_.Add(declaration); 433 } 434 435 436 void Scope::SetIllegalRedeclaration(Expression* expression) { 437 // Record only the first illegal redeclaration. 438 if (!HasIllegalRedeclaration()) { 439 illegal_redecl_ = expression; 440 } 441 ASSERT(HasIllegalRedeclaration()); 442 } 443 444 445 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { 446 ASSERT(HasIllegalRedeclaration()); 447 illegal_redecl_->Accept(visitor); 448 } 449 450 451 template<class Allocator> 452 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { 453 // Collect variables in this scope. 454 // Note that the function_ variable - if present - is not 455 // collected here but handled separately in ScopeInfo 456 // which is the current user of this function). 457 for (int i = 0; i < temps_.length(); i++) { 458 Variable* var = temps_[i]; 459 if (var->is_used()) { 460 locals->Add(var); 461 } 462 } 463 for (VariableMap::Entry* p = variables_.Start(); 464 p != NULL; 465 p = variables_.Next(p)) { 466 Variable* var = reinterpret_cast<Variable*>(p->value); 467 if (var->is_used()) { 468 locals->Add(var); 469 } 470 } 471 } 472 473 474 // Make sure the method gets instantiated by the template system. 475 template void Scope::CollectUsedVariables( 476 List<Variable*, FreeStoreAllocationPolicy>* locals); 477 template void Scope::CollectUsedVariables( 478 List<Variable*, PreallocatedStorage>* locals); 479 template void Scope::CollectUsedVariables( 480 List<Variable*, ZoneListAllocationPolicy>* locals); 481 482 483 void Scope::AllocateVariables(Handle<Context> context) { 484 ASSERT(outer_scope_ == NULL); // eval or global scopes only 485 486 // 1) Propagate scope information. 487 // If we are in an eval scope, we may have other outer scopes about 488 // which we don't know anything at this point. Thus we must be conservative 489 // and assume they may invoke eval themselves. Eventually we could capture 490 // this information in the ScopeInfo and then use it here (by traversing 491 // the call chain stack, at compile time). 492 bool eval_scope = is_eval_scope(); 493 PropagateScopeInfo(eval_scope, eval_scope); 494 495 // 2) Resolve variables. 496 Scope* global_scope = NULL; 497 if (is_global_scope()) global_scope = this; 498 ResolveVariablesRecursively(global_scope, context); 499 500 // 3) Allocate variables. 501 AllocateVariablesRecursively(); 502 } 503 504 505 bool Scope::AllowsLazyCompilation() const { 506 return !force_eager_compilation_ && HasTrivialOuterContext(); 507 } 508 509 510 bool Scope::HasTrivialContext() const { 511 // A function scope has a trivial context if it always is the global 512 // context. We iteratively scan out the context chain to see if 513 // there is anything that makes this scope non-trivial; otherwise we 514 // return true. 515 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { 516 if (scope->is_eval_scope()) return false; 517 if (scope->scope_inside_with_) return false; 518 if (scope->num_heap_slots_ > 0) return false; 519 } 520 return true; 521 } 522 523 524 bool Scope::HasTrivialOuterContext() const { 525 Scope* outer = outer_scope_; 526 if (outer == NULL) return true; 527 // Note that the outer context may be trivial in general, but the current 528 // scope may be inside a 'with' statement in which case the outer context 529 // for this scope is not trivial. 530 return !scope_inside_with_ && outer->HasTrivialContext(); 531 } 532 533 534 int Scope::ContextChainLength(Scope* scope) { 535 int n = 0; 536 for (Scope* s = this; s != scope; s = s->outer_scope_) { 537 ASSERT(s != NULL); // scope must be in the scope chain 538 if (s->num_heap_slots() > 0) n++; 539 } 540 return n; 541 } 542 543 544 #ifdef DEBUG 545 static const char* Header(Scope::Type type) { 546 switch (type) { 547 case Scope::EVAL_SCOPE: return "eval"; 548 case Scope::FUNCTION_SCOPE: return "function"; 549 case Scope::GLOBAL_SCOPE: return "global"; 550 } 551 UNREACHABLE(); 552 return NULL; 553 } 554 555 556 static void Indent(int n, const char* str) { 557 PrintF("%*s%s", n, "", str); 558 } 559 560 561 static void PrintName(Handle<String> name) { 562 SmartPointer<char> s = name->ToCString(DISALLOW_NULLS); 563 PrintF("%s", *s); 564 } 565 566 567 static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { 568 if (var->is_used() || var->rewrite() != NULL) { 569 Indent(indent, Variable::Mode2String(var->mode())); 570 PrintF(" "); 571 PrintName(var->name()); 572 PrintF("; // "); 573 if (var->rewrite() != NULL) { 574 PrintF("%s, ", printer->Print(var->rewrite())); 575 if (var->is_accessed_from_inner_scope()) PrintF(", "); 576 } 577 if (var->is_accessed_from_inner_scope()) PrintF("inner scope access"); 578 PrintF("\n"); 579 } 580 } 581 582 583 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { 584 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { 585 Variable* var = reinterpret_cast<Variable*>(p->value); 586 PrintVar(printer, indent, var); 587 } 588 } 589 590 591 void Scope::Print(int n) { 592 int n0 = (n > 0 ? n : 0); 593 int n1 = n0 + 2; // indentation 594 595 // Print header. 596 Indent(n0, Header(type_)); 597 if (scope_name_->length() > 0) { 598 PrintF(" "); 599 PrintName(scope_name_); 600 } 601 602 // Print parameters, if any. 603 if (is_function_scope()) { 604 PrintF(" ("); 605 for (int i = 0; i < params_.length(); i++) { 606 if (i > 0) PrintF(", "); 607 PrintName(params_[i]->name()); 608 } 609 PrintF(")"); 610 } 611 612 PrintF(" {\n"); 613 614 // Function name, if any (named function literals, only). 615 if (function_ != NULL) { 616 Indent(n1, "// (local) function name: "); 617 PrintName(function_->name()); 618 PrintF("\n"); 619 } 620 621 // Scope info. 622 if (HasTrivialOuterContext()) { 623 Indent(n1, "// scope has trivial outer context\n"); 624 } 625 if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n"); 626 if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n"); 627 if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); 628 if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n"); 629 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); 630 if (outer_scope_is_eval_scope_) { 631 Indent(n1, "// outer scope is 'eval' scope\n"); 632 } 633 if (num_stack_slots_ > 0) { Indent(n1, "// "); 634 PrintF("%d stack slots\n", num_stack_slots_); } 635 if (num_heap_slots_ > 0) { Indent(n1, "// "); 636 PrintF("%d heap slots\n", num_heap_slots_); } 637 638 // Print locals. 639 PrettyPrinter printer; 640 Indent(n1, "// function var\n"); 641 if (function_ != NULL) { 642 PrintVar(&printer, n1, function_); 643 } 644 645 Indent(n1, "// temporary vars\n"); 646 for (int i = 0; i < temps_.length(); i++) { 647 PrintVar(&printer, n1, temps_[i]); 648 } 649 650 Indent(n1, "// local vars\n"); 651 PrintMap(&printer, n1, &variables_); 652 653 Indent(n1, "// dynamic vars\n"); 654 if (dynamics_ != NULL) { 655 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC)); 656 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); 657 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); 658 } 659 660 // Print inner scopes (disable by providing negative n). 661 if (n >= 0) { 662 for (int i = 0; i < inner_scopes_.length(); i++) { 663 PrintF("\n"); 664 inner_scopes_[i]->Print(n1); 665 } 666 } 667 668 Indent(n0, "}\n"); 669 } 670 #endif // DEBUG 671 672 673 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { 674 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); 675 VariableMap* map = dynamics_->GetMap(mode); 676 Variable* var = map->Lookup(name); 677 if (var == NULL) { 678 // Declare a new non-local. 679 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); 680 // Allocate it by giving it a dynamic lookup. 681 var->set_rewrite(new Slot(var, Slot::LOOKUP, -1)); 682 } 683 return var; 684 } 685 686 687 // Lookup a variable starting with this scope. The result is either 688 // the statically resolved variable belonging to an outer scope, or 689 // NULL. It may be NULL because a) we couldn't find a variable, or b) 690 // because the variable is just a guess (and may be shadowed by 691 // another variable that is introduced dynamically via an 'eval' call 692 // or a 'with' statement). 693 Variable* Scope::LookupRecursive(Handle<String> name, 694 bool inner_lookup, 695 Variable** invalidated_local) { 696 // If we find a variable, but the current scope calls 'eval', the found 697 // variable may not be the correct one (the 'eval' may introduce a 698 // property with the same name). In that case, remember that the variable 699 // found is just a guess. 700 bool guess = scope_calls_eval_; 701 702 // Try to find the variable in this scope. 703 Variable* var = LocalLookup(name); 704 705 if (var != NULL) { 706 // We found a variable. If this is not an inner lookup, we are done. 707 // (Even if there is an 'eval' in this scope which introduces the 708 // same variable again, the resulting variable remains the same. 709 // Note that enclosing 'with' statements are handled at the call site.) 710 if (!inner_lookup) 711 return var; 712 713 } else { 714 // We did not find a variable locally. Check against the function variable, 715 // if any. We can do this for all scopes, since the function variable is 716 // only present - if at all - for function scopes. 717 // 718 // This lookup corresponds to a lookup in the "intermediate" scope sitting 719 // between this scope and the outer scope. (ECMA-262, 3rd., requires that 720 // the name of named function literal is kept in an intermediate scope 721 // in between this scope and the next outer scope.) 722 if (function_ != NULL && function_->name().is_identical_to(name)) { 723 var = function_; 724 725 } else if (outer_scope_ != NULL) { 726 var = outer_scope_->LookupRecursive(name, true, invalidated_local); 727 // We may have found a variable in an outer scope. However, if 728 // the current scope is inside a 'with', the actual variable may 729 // be a property introduced via the 'with' statement. Then, the 730 // variable we may have found is just a guess. 731 if (scope_inside_with_) 732 guess = true; 733 } 734 735 // If we did not find a variable, we are done. 736 if (var == NULL) 737 return NULL; 738 } 739 740 ASSERT(var != NULL); 741 742 // If this is a lookup from an inner scope, mark the variable. 743 if (inner_lookup) { 744 var->MarkAsAccessedFromInnerScope(); 745 } 746 747 // If the variable we have found is just a guess, invalidate the 748 // result. If the found variable is local, record that fact so we 749 // can generate fast code to get it if it is not shadowed by eval. 750 if (guess) { 751 if (!var->is_global()) *invalidated_local = var; 752 var = NULL; 753 } 754 755 return var; 756 } 757 758 759 void Scope::ResolveVariable(Scope* global_scope, 760 Handle<Context> context, 761 VariableProxy* proxy) { 762 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 763 764 // If the proxy is already resolved there's nothing to do 765 // (functions and consts may be resolved by the parser). 766 if (proxy->var() != NULL) return; 767 768 // Otherwise, try to resolve the variable. 769 Variable* invalidated_local = NULL; 770 Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local); 771 772 if (proxy->inside_with()) { 773 // If we are inside a local 'with' statement, all bets are off 774 // and we cannot resolve the proxy to a local variable even if 775 // we found an outer matching variable. 776 // Note that we must do a lookup anyway, because if we find one, 777 // we must mark that variable as potentially accessed from this 778 // inner scope (the property may not be in the 'with' object). 779 var = NonLocal(proxy->name(), Variable::DYNAMIC); 780 781 } else { 782 // We are not inside a local 'with' statement. 783 784 if (var == NULL) { 785 // We did not find the variable. We have a global variable 786 // if we are in the global scope (we know already that we 787 // are outside a 'with' statement) or if there is no way 788 // that the variable might be introduced dynamically (through 789 // a local or outer eval() call, or an outer 'with' statement), 790 // or we don't know about the outer scope (because we are 791 // in an eval scope). 792 if (is_global_scope() || 793 !(scope_inside_with_ || outer_scope_is_eval_scope_ || 794 scope_calls_eval_ || outer_scope_calls_eval_)) { 795 // We must have a global variable. 796 ASSERT(global_scope != NULL); 797 var = global_scope->DeclareGlobal(proxy->name()); 798 799 } else if (scope_inside_with_) { 800 // If we are inside a with statement we give up and look up 801 // the variable at runtime. 802 var = NonLocal(proxy->name(), Variable::DYNAMIC); 803 804 } else if (invalidated_local != NULL) { 805 // No with statements are involved and we found a local 806 // variable that might be shadowed by eval introduced 807 // variables. 808 var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL); 809 var->set_local_if_not_shadowed(invalidated_local); 810 811 } else if (outer_scope_is_eval_scope_) { 812 // No with statements and we did not find a local and the code 813 // is executed with a call to eval. The context contains 814 // scope information that we can use to determine if the 815 // variable is global if it is not shadowed by eval-introduced 816 // variables. 817 if (context->GlobalIfNotShadowedByEval(proxy->name())) { 818 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); 819 820 } else { 821 var = NonLocal(proxy->name(), Variable::DYNAMIC); 822 } 823 824 } else { 825 // No with statements and we did not find a local and the code 826 // is not executed with a call to eval. We know that this 827 // variable is global unless it is shadowed by eval-introduced 828 // variables. 829 var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); 830 } 831 } 832 } 833 834 proxy->BindTo(var); 835 } 836 837 838 void Scope::ResolveVariablesRecursively(Scope* global_scope, 839 Handle<Context> context) { 840 ASSERT(global_scope == NULL || global_scope->is_global_scope()); 841 842 // Resolve unresolved variables for this scope. 843 for (int i = 0; i < unresolved_.length(); i++) { 844 ResolveVariable(global_scope, context, unresolved_[i]); 845 } 846 847 // Resolve unresolved variables for inner scopes. 848 for (int i = 0; i < inner_scopes_.length(); i++) { 849 inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context); 850 } 851 } 852 853 854 bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval, 855 bool outer_scope_is_eval_scope) { 856 if (outer_scope_calls_eval) { 857 outer_scope_calls_eval_ = true; 858 } 859 860 if (outer_scope_is_eval_scope) { 861 outer_scope_is_eval_scope_ = true; 862 } 863 864 bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_; 865 bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_; 866 for (int i = 0; i < inner_scopes_.length(); i++) { 867 Scope* inner_scope = inner_scopes_[i]; 868 if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) { 869 inner_scope_calls_eval_ = true; 870 } 871 if (inner_scope->force_eager_compilation_) { 872 force_eager_compilation_ = true; 873 } 874 } 875 876 return scope_calls_eval_ || inner_scope_calls_eval_; 877 } 878 879 880 bool Scope::MustAllocate(Variable* var) { 881 // Give var a read/write use if there is a chance it might be accessed 882 // via an eval() call. This is only possible if the variable has a 883 // visible name. 884 if ((var->is_this() || var->name()->length() > 0) && 885 (var->is_accessed_from_inner_scope() || 886 scope_calls_eval_ || inner_scope_calls_eval_ || 887 scope_contains_with_)) { 888 var->set_is_used(true); 889 } 890 // Global variables do not need to be allocated. 891 return !var->is_global() && var->is_used(); 892 } 893 894 895 bool Scope::MustAllocateInContext(Variable* var) { 896 // If var is accessed from an inner scope, or if there is a 897 // possibility that it might be accessed from the current or an inner 898 // scope (through an eval() call), it must be allocated in the 899 // context. Exception: temporary variables are not allocated in the 900 // context. 901 return 902 var->mode() != Variable::TEMPORARY && 903 (var->is_accessed_from_inner_scope() || 904 scope_calls_eval_ || inner_scope_calls_eval_ || 905 scope_contains_with_ || var->is_global()); 906 } 907 908 909 bool Scope::HasArgumentsParameter() { 910 for (int i = 0; i < params_.length(); i++) { 911 if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol())) 912 return true; 913 } 914 return false; 915 } 916 917 918 void Scope::AllocateStackSlot(Variable* var) { 919 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++)); 920 } 921 922 923 void Scope::AllocateHeapSlot(Variable* var) { 924 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); 925 } 926 927 928 void Scope::AllocateParameterLocals() { 929 ASSERT(is_function_scope()); 930 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); 931 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly 932 933 // Parameters are rewritten to arguments[i] if 'arguments' is used in 934 // a non-strict mode function. Strict mode code doesn't alias arguments. 935 bool rewrite_parameters = false; 936 937 if (MustAllocate(arguments) && !HasArgumentsParameter()) { 938 // 'arguments' is used. Unless there is also a parameter called 939 // 'arguments', we must be conservative and access all parameters via 940 // the arguments object: The i'th parameter is rewritten into 941 // '.arguments[i]' (*). If we have a parameter named 'arguments', a 942 // (new) value is always assigned to it via the function 943 // invocation. Then 'arguments' denotes that specific parameter value 944 // and cannot be used to access the parameters, which is why we don't 945 // need to rewrite in that case. 946 // 947 // (*) Instead of having a parameter called 'arguments', we may have an 948 // assignment to 'arguments' in the function body, at some arbitrary 949 // point in time (possibly through an 'eval()' call!). After that 950 // assignment any re-write of parameters would be invalid (was bug 951 // 881452). Thus, we introduce a shadow '.arguments' 952 // variable which also points to the arguments object. For rewrites we 953 // use '.arguments' which remains valid even if we assign to 954 // 'arguments'. To summarize: If we need to rewrite, we allocate an 955 // 'arguments' object dynamically upon function invocation. The compiler 956 // introduces 2 local variables 'arguments' and '.arguments', both of 957 // which originally point to the arguments object that was 958 // allocated. All parameters are rewritten into property accesses via 959 // the '.arguments' variable. Thus, any changes to properties of 960 // 'arguments' are reflected in the variables and vice versa. If the 961 // 'arguments' variable is changed, '.arguments' still points to the 962 // correct arguments object and the rewrites still work. 963 964 // We are using 'arguments'. Tell the code generator that is needs to 965 // allocate the arguments object by setting 'arguments_'. 966 arguments_ = arguments; 967 968 // In strict mode 'arguments' does not alias formal parameters. 969 // Therefore in strict mode we allocate parameters as if 'arguments' 970 // were not used. 971 rewrite_parameters = !is_strict_mode(); 972 } 973 974 if (rewrite_parameters) { 975 // We also need the '.arguments' shadow variable. Declare it and create 976 // and bind the corresponding proxy. It's ok to declare it only now 977 // because it's a local variable that is allocated after the parameters 978 // have been allocated. 979 // 980 // Note: This is "almost" at temporary variable but we cannot use 981 // NewTemporary() because the mode needs to be INTERNAL since this 982 // variable may be allocated in the heap-allocated context (temporaries 983 // are never allocated in the context). 984 arguments_shadow_ = new Variable(this, 985 FACTORY->arguments_shadow_symbol(), 986 Variable::INTERNAL, 987 true, 988 Variable::ARGUMENTS); 989 arguments_shadow_->set_is_used(true); 990 temps_.Add(arguments_shadow_); 991 992 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. 993 for (int i = 0; i < params_.length(); i++) { 994 Variable* var = params_[i]; 995 ASSERT(var->scope() == this); 996 if (MustAllocate(var)) { 997 if (MustAllocateInContext(var)) { 998 // It is ok to set this only now, because arguments is a local 999 // variable that is allocated after the parameters have been 1000 // allocated. 1001 arguments_shadow_->MarkAsAccessedFromInnerScope(); 1002 } 1003 Property* rewrite = 1004 new Property(new VariableProxy(arguments_shadow_), 1005 new Literal(Handle<Object>(Smi::FromInt(i))), 1006 RelocInfo::kNoPosition, 1007 Property::SYNTHETIC); 1008 rewrite->set_is_arguments_access(true); 1009 var->set_rewrite(rewrite); 1010 } 1011 } 1012 1013 } else { 1014 // The arguments object is not used, so we can access parameters directly. 1015 // The same parameter may occur multiple times in the parameters_ list. 1016 // If it does, and if it is not copied into the context object, it must 1017 // receive the highest parameter index for that parameter; thus iteration 1018 // order is relevant! 1019 for (int i = 0; i < params_.length(); i++) { 1020 Variable* var = params_[i]; 1021 ASSERT(var->scope() == this); 1022 if (MustAllocate(var)) { 1023 if (MustAllocateInContext(var)) { 1024 ASSERT(var->rewrite() == NULL || 1025 (var->AsSlot() != NULL && 1026 var->AsSlot()->type() == Slot::CONTEXT)); 1027 if (var->rewrite() == NULL) { 1028 // Only set the heap allocation if the parameter has not 1029 // been allocated yet. 1030 AllocateHeapSlot(var); 1031 } 1032 } else { 1033 ASSERT(var->rewrite() == NULL || 1034 (var->AsSlot() != NULL && 1035 var->AsSlot()->type() == Slot::PARAMETER)); 1036 // Set the parameter index always, even if the parameter 1037 // was seen before! (We need to access the actual parameter 1038 // supplied for the last occurrence of a multiply declared 1039 // parameter.) 1040 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); 1041 } 1042 } 1043 } 1044 } 1045 } 1046 1047 1048 void Scope::AllocateNonParameterLocal(Variable* var) { 1049 ASSERT(var->scope() == this); 1050 ASSERT(var->rewrite() == NULL || 1051 (!var->IsVariable(FACTORY->result_symbol())) || 1052 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); 1053 if (var->rewrite() == NULL && MustAllocate(var)) { 1054 if (MustAllocateInContext(var)) { 1055 AllocateHeapSlot(var); 1056 } else { 1057 AllocateStackSlot(var); 1058 } 1059 } 1060 } 1061 1062 1063 void Scope::AllocateNonParameterLocals() { 1064 // All variables that have no rewrite yet are non-parameter locals. 1065 for (int i = 0; i < temps_.length(); i++) { 1066 AllocateNonParameterLocal(temps_[i]); 1067 } 1068 1069 for (VariableMap::Entry* p = variables_.Start(); 1070 p != NULL; 1071 p = variables_.Next(p)) { 1072 Variable* var = reinterpret_cast<Variable*>(p->value); 1073 AllocateNonParameterLocal(var); 1074 } 1075 1076 // For now, function_ must be allocated at the very end. If it gets 1077 // allocated in the context, it must be the last slot in the context, 1078 // because of the current ScopeInfo implementation (see 1079 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 1080 if (function_ != NULL) { 1081 AllocateNonParameterLocal(function_); 1082 } 1083 } 1084 1085 1086 void Scope::AllocateVariablesRecursively() { 1087 // Allocate variables for inner scopes. 1088 for (int i = 0; i < inner_scopes_.length(); i++) { 1089 inner_scopes_[i]->AllocateVariablesRecursively(); 1090 } 1091 1092 // If scope is already resolved, we still need to allocate 1093 // variables in inner scopes which might not had been resolved yet. 1094 if (resolved()) return; 1095 // The number of slots required for variables. 1096 num_stack_slots_ = 0; 1097 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; 1098 1099 // Allocate variables for this scope. 1100 // Parameters must be allocated first, if any. 1101 if (is_function_scope()) AllocateParameterLocals(); 1102 AllocateNonParameterLocals(); 1103 1104 // Allocate context if necessary. 1105 bool must_have_local_context = false; 1106 if (scope_calls_eval_ || scope_contains_with_) { 1107 // The context for the eval() call or 'with' statement in this scope. 1108 // Unless we are in the global or an eval scope, we need a local 1109 // context even if we didn't statically allocate any locals in it, 1110 // and the compiler will access the context variable. If we are 1111 // not in an inner scope, the scope is provided from the outside. 1112 must_have_local_context = is_function_scope(); 1113 } 1114 1115 // If we didn't allocate any locals in the local context, then we only 1116 // need the minimal number of slots if we must have a local context. 1117 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 1118 !must_have_local_context) { 1119 num_heap_slots_ = 0; 1120 } 1121 1122 // Allocation done. 1123 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 1124 } 1125 1126 } } // namespace v8::internal 1127