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