| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "scopes.h" | 30 #include "scopes.h" |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "compiler.h" | 33 #include "compiler.h" |
| 34 #include "prettyprinter.h" | |
| 35 #include "scopeinfo.h" | 34 #include "scopeinfo.h" |
| 36 | 35 |
| 37 #include "allocation-inl.h" | 36 #include "allocation-inl.h" |
| 38 | 37 |
| 39 namespace v8 { | 38 namespace v8 { |
| 40 namespace internal { | 39 namespace internal { |
| 41 | 40 |
| 42 // ---------------------------------------------------------------------------- | 41 // ---------------------------------------------------------------------------- |
| 43 // A Zone allocator for use with LocalsMap. | 42 // A Zone allocator for use with LocalsMap. |
| 44 | 43 |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 } else { | 306 } else { |
| 308 ASSERT(is_function_scope() || | 307 ASSERT(is_function_scope() || |
| 309 is_global_scope() || | 308 is_global_scope() || |
| 310 is_eval_scope()); | 309 is_eval_scope()); |
| 311 Variable* var = | 310 Variable* var = |
| 312 variables_.Declare(this, | 311 variables_.Declare(this, |
| 313 isolate_->factory()->this_symbol(), | 312 isolate_->factory()->this_symbol(), |
| 314 Variable::VAR, | 313 Variable::VAR, |
| 315 false, | 314 false, |
| 316 Variable::THIS); | 315 Variable::THIS); |
| 317 var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1)); | 316 var->AllocateTo(Variable::PARAMETER, -1); |
| 318 receiver_ = var; | 317 receiver_ = var; |
| 319 } | 318 } |
| 320 | 319 |
| 321 if (is_function_scope()) { | 320 if (is_function_scope()) { |
| 322 // Declare 'arguments' variable which exists in all functions. | 321 // Declare 'arguments' variable which exists in all functions. |
| 323 // Note that it might never be accessed, in which case it won't be | 322 // Note that it might never be accessed, in which case it won't be |
| 324 // allocated during variable allocation. | 323 // allocated during variable allocation. |
| 325 variables_.Declare(this, | 324 variables_.Declare(this, |
| 326 isolate_->factory()->arguments_symbol(), | 325 isolate_->factory()->arguments_symbol(), |
| 327 Variable::VAR, | 326 Variable::VAR, |
| 328 true, | 327 true, |
| 329 Variable::ARGUMENTS); | 328 Variable::ARGUMENTS); |
| 330 } | 329 } |
| 331 } | 330 } |
| 332 | 331 |
| 333 | 332 |
| 333 Scope* Scope::FinalizeBlockScope() { |
| 334 ASSERT(is_block_scope()); |
| 335 ASSERT(temps_.is_empty()); |
| 336 ASSERT(params_.is_empty()); |
| 337 |
| 338 if (num_var_or_const() > 0) return this; |
| 339 |
| 340 // Remove this scope from outer scope. |
| 341 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { |
| 342 if (outer_scope_->inner_scopes_[i] == this) { |
| 343 outer_scope_->inner_scopes_.Remove(i); |
| 344 break; |
| 345 } |
| 346 } |
| 347 |
| 348 // Reparent inner scopes. |
| 349 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 350 outer_scope()->AddInnerScope(inner_scopes_[i]); |
| 351 } |
| 352 |
| 353 // Move unresolved variables |
| 354 for (int i = 0; i < unresolved_.length(); i++) { |
| 355 outer_scope()->unresolved_.Add(unresolved_[i]); |
| 356 } |
| 357 |
| 358 return NULL; |
| 359 } |
| 360 |
| 361 |
| 334 Variable* Scope::LocalLookup(Handle<String> name) { | 362 Variable* Scope::LocalLookup(Handle<String> name) { |
| 335 Variable* result = variables_.Lookup(name); | 363 Variable* result = variables_.Lookup(name); |
| 336 if (result != NULL || scope_info_.is_null()) { | 364 if (result != NULL || scope_info_.is_null()) { |
| 337 return result; | 365 return result; |
| 338 } | 366 } |
| 339 // If we have a serialized scope info, we might find the variable there. | 367 // If we have a serialized scope info, we might find the variable there. |
| 340 // | 368 // |
| 341 // We should never lookup 'arguments' in this scope as it is implicitly | 369 // We should never lookup 'arguments' in this scope as it is implicitly |
| 342 // present in every scope. | 370 // present in every scope. |
| 343 ASSERT(*name != *isolate_->factory()->arguments_symbol()); | 371 ASSERT(*name != *isolate_->factory()->arguments_symbol()); |
| 344 // There should be no local slot with the given name. | 372 // There should be no local slot with the given name. |
| 345 ASSERT(scope_info_->StackSlotIndex(*name) < 0); | 373 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
| 346 | 374 |
| 347 // Check context slot lookup. | 375 // Check context slot lookup. |
| 348 Variable::Mode mode; | 376 Variable::Mode mode; |
| 349 int index = scope_info_->ContextSlotIndex(*name, &mode); | 377 int index = scope_info_->ContextSlotIndex(*name, &mode); |
| 350 if (index < 0) { | 378 if (index < 0) { |
| 351 // Check parameters. | 379 // Check parameters. |
| 352 mode = Variable::VAR; | 380 mode = Variable::VAR; |
| 353 index = scope_info_->ParameterIndex(*name); | 381 index = scope_info_->ParameterIndex(*name); |
| 354 if (index < 0) { | 382 if (index < 0) { |
| 355 // Check the function name. | 383 // Check the function name. |
| 356 index = scope_info_->FunctionContextSlotIndex(*name); | 384 index = scope_info_->FunctionContextSlotIndex(*name); |
| 357 if (index < 0) return NULL; | 385 if (index < 0) return NULL; |
| 358 } | 386 } |
| 359 } | 387 } |
| 360 | 388 |
| 361 Variable* var = | 389 Variable* var = |
| 362 variables_.Declare(this, name, mode, true, Variable::NORMAL); | 390 variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 363 var->set_rewrite(NewSlot(var, Slot::CONTEXT, index)); | 391 var->AllocateTo(Variable::CONTEXT, index); |
| 364 return var; | 392 return var; |
| 365 } | 393 } |
| 366 | 394 |
| 367 | 395 |
| 368 Variable* Scope::Lookup(Handle<String> name) { | 396 Variable* Scope::Lookup(Handle<String> name) { |
| 369 for (Scope* scope = this; | 397 for (Scope* scope = this; |
| 370 scope != NULL; | 398 scope != NULL; |
| 371 scope = scope->outer_scope()) { | 399 scope = scope->outer_scope()) { |
| 372 Variable* var = scope->LocalLookup(name); | 400 Variable* var = scope->LocalLookup(name); |
| 373 if (var != NULL) return var; | 401 if (var != NULL) return var; |
| 374 } | 402 } |
| 375 return NULL; | 403 return NULL; |
| 376 } | 404 } |
| 377 | 405 |
| 378 | 406 |
| 379 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 407 Variable* Scope::DeclareFunctionVar(Handle<String> name) { |
| 380 ASSERT(is_function_scope() && function_ == NULL); | 408 ASSERT(is_function_scope() && function_ == NULL); |
| 381 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 409 Variable* function_var = |
| 382 return function_; | 410 new Variable(this, name, Variable::CONST, true, Variable::NORMAL); |
| 411 function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var); |
| 412 return function_var; |
| 383 } | 413 } |
| 384 | 414 |
| 385 | 415 |
| 386 void Scope::DeclareParameter(Handle<String> name) { | 416 void Scope::DeclareParameter(Handle<String> name, Variable::Mode mode) { |
| 387 ASSERT(!already_resolved()); | 417 ASSERT(!already_resolved()); |
| 388 ASSERT(is_function_scope()); | 418 ASSERT(is_function_scope()); |
| 389 Variable* var = | 419 Variable* var = |
| 390 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); | 420 variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 391 params_.Add(var); | 421 params_.Add(var); |
| 392 } | 422 } |
| 393 | 423 |
| 394 | 424 |
| 395 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { | 425 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { |
| 396 ASSERT(!already_resolved()); | 426 ASSERT(!already_resolved()); |
| 397 // This function handles VAR and CONST modes. DYNAMIC variables are | 427 // This function handles VAR and CONST modes. DYNAMIC variables are |
| 398 // introduces during variable allocation, INTERNAL variables are allocated | 428 // introduces during variable allocation, INTERNAL variables are allocated |
| 399 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 429 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
| 400 ASSERT(mode == Variable::VAR || | 430 ASSERT(mode == Variable::VAR || |
| 401 mode == Variable::CONST || | 431 mode == Variable::CONST || |
| 402 mode == Variable::LET); | 432 mode == Variable::LET); |
| 403 ++num_var_or_const_; | 433 ++num_var_or_const_; |
| 404 return variables_.Declare(this, name, mode, true, Variable::NORMAL); | 434 return variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 405 } | 435 } |
| 406 | 436 |
| 407 | 437 |
| 408 Variable* Scope::DeclareGlobal(Handle<String> name) { | 438 Variable* Scope::DeclareGlobal(Handle<String> name) { |
| 409 ASSERT(is_global_scope()); | 439 ASSERT(is_global_scope()); |
| 410 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, | 440 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, |
| 441 true, |
| 411 Variable::NORMAL); | 442 Variable::NORMAL); |
| 412 } | 443 } |
| 413 | 444 |
| 414 | 445 |
| 415 VariableProxy* Scope::NewUnresolved(Handle<String> name, | 446 VariableProxy* Scope::NewUnresolved(Handle<String> name, |
| 416 bool inside_with, | 447 bool inside_with, |
| 417 int position) { | 448 int position) { |
| 418 // Note that we must not share the unresolved variables with | 449 // Note that we must not share the unresolved variables with |
| 419 // the same name because they may be removed selectively via | 450 // the same name because they may be removed selectively via |
| 420 // RemoveUnresolved(). | 451 // RemoveUnresolved(). |
| (...skipping 12 matching lines...) Expand all Loading... |
| 433 if (unresolved_[i] == var) { | 464 if (unresolved_[i] == var) { |
| 434 unresolved_.Remove(i); | 465 unresolved_.Remove(i); |
| 435 return; | 466 return; |
| 436 } | 467 } |
| 437 } | 468 } |
| 438 } | 469 } |
| 439 | 470 |
| 440 | 471 |
| 441 Variable* Scope::NewTemporary(Handle<String> name) { | 472 Variable* Scope::NewTemporary(Handle<String> name) { |
| 442 ASSERT(!already_resolved()); | 473 ASSERT(!already_resolved()); |
| 443 Variable* var = | 474 Variable* var = new Variable(this, |
| 444 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); | 475 name, |
| 476 Variable::TEMPORARY, |
| 477 true, |
| 478 Variable::NORMAL); |
| 445 temps_.Add(var); | 479 temps_.Add(var); |
| 446 return var; | 480 return var; |
| 447 } | 481 } |
| 448 | 482 |
| 449 | 483 |
| 450 void Scope::AddDeclaration(Declaration* declaration) { | 484 void Scope::AddDeclaration(Declaration* declaration) { |
| 451 decls_.Add(declaration); | 485 decls_.Add(declaration); |
| 452 } | 486 } |
| 453 | 487 |
| 454 | 488 |
| 455 void Scope::SetIllegalRedeclaration(Expression* expression) { | 489 void Scope::SetIllegalRedeclaration(Expression* expression) { |
| 456 // Record only the first illegal redeclaration. | 490 // Record only the first illegal redeclaration. |
| 457 if (!HasIllegalRedeclaration()) { | 491 if (!HasIllegalRedeclaration()) { |
| 458 illegal_redecl_ = expression; | 492 illegal_redecl_ = expression; |
| 459 } | 493 } |
| 460 ASSERT(HasIllegalRedeclaration()); | 494 ASSERT(HasIllegalRedeclaration()); |
| 461 } | 495 } |
| 462 | 496 |
| 463 | 497 |
| 464 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { | 498 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { |
| 465 ASSERT(HasIllegalRedeclaration()); | 499 ASSERT(HasIllegalRedeclaration()); |
| 466 illegal_redecl_->Accept(visitor); | 500 illegal_redecl_->Accept(visitor); |
| 467 } | 501 } |
| 468 | 502 |
| 469 | 503 |
| 504 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 505 int length = decls_.length(); |
| 506 for (int i = 0; i < length; i++) { |
| 507 Declaration* decl = decls_[i]; |
| 508 if (decl->mode() != Variable::VAR) continue; |
| 509 Handle<String> name = decl->proxy()->name(); |
| 510 bool cond = true; |
| 511 for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) { |
| 512 // There is a conflict if there exists a non-VAR binding. |
| 513 Variable* other_var = scope->variables_.Lookup(name); |
| 514 if (other_var != NULL && other_var->mode() != Variable::VAR) { |
| 515 return decl; |
| 516 } |
| 517 |
| 518 // Include declaration scope in the iteration but stop after. |
| 519 if (!scope->is_block_scope() && !scope->is_catch_scope()) cond = false; |
| 520 } |
| 521 } |
| 522 return NULL; |
| 523 } |
| 524 |
| 525 |
| 470 template<class Allocator> | 526 template<class Allocator> |
| 471 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { | 527 void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { |
| 472 // Collect variables in this scope. | 528 // Collect variables in this scope. |
| 473 // Note that the function_ variable - if present - is not | 529 // Note that the function_ variable - if present - is not |
| 474 // collected here but handled separately in ScopeInfo | 530 // collected here but handled separately in ScopeInfo |
| 475 // which is the current user of this function). | 531 // which is the current user of this function). |
| 476 for (int i = 0; i < temps_.length(); i++) { | 532 for (int i = 0; i < temps_.length(); i++) { |
| 477 Variable* var = temps_[i]; | 533 Variable* var = temps_[i]; |
| 478 if (var->is_used()) { | 534 if (var->is_used()) { |
| 479 locals->Add(var); | 535 locals->Add(var); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 PrintF("%*s%s", n, "", str); | 661 PrintF("%*s%s", n, "", str); |
| 606 } | 662 } |
| 607 | 663 |
| 608 | 664 |
| 609 static void PrintName(Handle<String> name) { | 665 static void PrintName(Handle<String> name) { |
| 610 SmartPointer<char> s = name->ToCString(DISALLOW_NULLS); | 666 SmartPointer<char> s = name->ToCString(DISALLOW_NULLS); |
| 611 PrintF("%s", *s); | 667 PrintF("%s", *s); |
| 612 } | 668 } |
| 613 | 669 |
| 614 | 670 |
| 615 static void PrintVar(PrettyPrinter* printer, int indent, Variable* var) { | 671 static void PrintLocation(Variable* var) { |
| 616 if (var->is_used() || var->rewrite() != NULL) { | 672 switch (var->location()) { |
| 673 case Variable::UNALLOCATED: |
| 674 break; |
| 675 case Variable::PARAMETER: |
| 676 PrintF("parameter[%d]", var->index()); |
| 677 break; |
| 678 case Variable::LOCAL: |
| 679 PrintF("local[%d]", var->index()); |
| 680 break; |
| 681 case Variable::CONTEXT: |
| 682 PrintF("context[%d]", var->index()); |
| 683 break; |
| 684 case Variable::LOOKUP: |
| 685 PrintF("lookup"); |
| 686 break; |
| 687 } |
| 688 } |
| 689 |
| 690 |
| 691 static void PrintVar(int indent, Variable* var) { |
| 692 if (var->is_used() || !var->IsUnallocated()) { |
| 617 Indent(indent, Variable::Mode2String(var->mode())); | 693 Indent(indent, Variable::Mode2String(var->mode())); |
| 618 PrintF(" "); | 694 PrintF(" "); |
| 619 PrintName(var->name()); | 695 PrintName(var->name()); |
| 620 PrintF("; // "); | 696 PrintF("; // "); |
| 621 if (var->rewrite() != NULL) { | 697 PrintLocation(var); |
| 622 PrintF("%s, ", printer->Print(var->rewrite())); | |
| 623 if (var->is_accessed_from_inner_function_scope()) PrintF(", "); | |
| 624 } | |
| 625 if (var->is_accessed_from_inner_function_scope()) { | 698 if (var->is_accessed_from_inner_function_scope()) { |
| 699 if (!var->IsUnallocated()) PrintF(", "); |
| 626 PrintF("inner scope access"); | 700 PrintF("inner scope access"); |
| 627 } | 701 } |
| 628 PrintF("\n"); | 702 PrintF("\n"); |
| 629 } | 703 } |
| 630 } | 704 } |
| 631 | 705 |
| 632 | 706 |
| 633 static void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) { | 707 static void PrintMap(int indent, VariableMap* map) { |
| 634 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 708 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| 635 Variable* var = reinterpret_cast<Variable*>(p->value); | 709 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 636 PrintVar(printer, indent, var); | 710 PrintVar(indent, var); |
| 637 } | 711 } |
| 638 } | 712 } |
| 639 | 713 |
| 640 | 714 |
| 641 void Scope::Print(int n) { | 715 void Scope::Print(int n) { |
| 642 int n0 = (n > 0 ? n : 0); | 716 int n0 = (n > 0 ? n : 0); |
| 643 int n1 = n0 + 2; // indentation | 717 int n1 = n0 + 2; // indentation |
| 644 | 718 |
| 645 // Print header. | 719 // Print header. |
| 646 Indent(n0, Header(type_)); | 720 Indent(n0, Header(type_)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 757 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
| 684 if (outer_scope_is_eval_scope_) { | 758 if (outer_scope_is_eval_scope_) { |
| 685 Indent(n1, "// outer scope is 'eval' scope\n"); | 759 Indent(n1, "// outer scope is 'eval' scope\n"); |
| 686 } | 760 } |
| 687 if (num_stack_slots_ > 0) { Indent(n1, "// "); | 761 if (num_stack_slots_ > 0) { Indent(n1, "// "); |
| 688 PrintF("%d stack slots\n", num_stack_slots_); } | 762 PrintF("%d stack slots\n", num_stack_slots_); } |
| 689 if (num_heap_slots_ > 0) { Indent(n1, "// "); | 763 if (num_heap_slots_ > 0) { Indent(n1, "// "); |
| 690 PrintF("%d heap slots\n", num_heap_slots_); } | 764 PrintF("%d heap slots\n", num_heap_slots_); } |
| 691 | 765 |
| 692 // Print locals. | 766 // Print locals. |
| 693 PrettyPrinter printer; | |
| 694 Indent(n1, "// function var\n"); | 767 Indent(n1, "// function var\n"); |
| 695 if (function_ != NULL) { | 768 if (function_ != NULL) { |
| 696 PrintVar(&printer, n1, function_); | 769 PrintVar(n1, function_->var()); |
| 697 } | 770 } |
| 698 | 771 |
| 699 Indent(n1, "// temporary vars\n"); | 772 Indent(n1, "// temporary vars\n"); |
| 700 for (int i = 0; i < temps_.length(); i++) { | 773 for (int i = 0; i < temps_.length(); i++) { |
| 701 PrintVar(&printer, n1, temps_[i]); | 774 PrintVar(n1, temps_[i]); |
| 702 } | 775 } |
| 703 | 776 |
| 704 Indent(n1, "// local vars\n"); | 777 Indent(n1, "// local vars\n"); |
| 705 PrintMap(&printer, n1, &variables_); | 778 PrintMap(n1, &variables_); |
| 706 | 779 |
| 707 Indent(n1, "// dynamic vars\n"); | 780 Indent(n1, "// dynamic vars\n"); |
| 708 if (dynamics_ != NULL) { | 781 if (dynamics_ != NULL) { |
| 709 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC)); | 782 PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC)); |
| 710 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); | 783 PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL)); |
| 711 PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); | 784 PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL)); |
| 712 } | 785 } |
| 713 | 786 |
| 714 // Print inner scopes (disable by providing negative n). | 787 // Print inner scopes (disable by providing negative n). |
| 715 if (n >= 0) { | 788 if (n >= 0) { |
| 716 for (int i = 0; i < inner_scopes_.length(); i++) { | 789 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 717 PrintF("\n"); | 790 PrintF("\n"); |
| 718 inner_scopes_[i]->Print(n1); | 791 inner_scopes_[i]->Print(n1); |
| 719 } | 792 } |
| 720 } | 793 } |
| 721 | 794 |
| 722 Indent(n0, "}\n"); | 795 Indent(n0, "}\n"); |
| 723 } | 796 } |
| 724 #endif // DEBUG | 797 #endif // DEBUG |
| 725 | 798 |
| 726 | 799 |
| 727 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 800 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
| 728 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 801 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); |
| 729 VariableMap* map = dynamics_->GetMap(mode); | 802 VariableMap* map = dynamics_->GetMap(mode); |
| 730 Variable* var = map->Lookup(name); | 803 Variable* var = map->Lookup(name); |
| 731 if (var == NULL) { | 804 if (var == NULL) { |
| 732 // Declare a new non-local. | 805 // Declare a new non-local. |
| 733 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 806 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
| 734 // Allocate it by giving it a dynamic lookup. | 807 // Allocate it by giving it a dynamic lookup. |
| 735 var->set_rewrite(NewSlot(var, Slot::LOOKUP, -1)); | 808 var->AllocateTo(Variable::LOOKUP, -1); |
| 736 } | 809 } |
| 737 return var; | 810 return var; |
| 738 } | 811 } |
| 739 | 812 |
| 740 | 813 |
| 741 // Lookup a variable starting with this scope. The result is either | 814 // Lookup a variable starting with this scope. The result is either |
| 742 // the statically resolved variable belonging to an outer scope, or | 815 // the statically resolved variable belonging to an outer scope, or |
| 743 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 816 // NULL. It may be NULL because a) we couldn't find a variable, or b) |
| 744 // because the variable is just a guess (and may be shadowed by | 817 // because the variable is just a guess (and may be shadowed by |
| 745 // another variable that is introduced dynamically via an 'eval' call | 818 // another variable that is introduced dynamically via an 'eval' call |
| (...skipping 21 matching lines...) Expand all Loading... |
| 767 } else { | 840 } else { |
| 768 // We did not find a variable locally. Check against the function variable, | 841 // We did not find a variable locally. Check against the function variable, |
| 769 // if any. We can do this for all scopes, since the function variable is | 842 // if any. We can do this for all scopes, since the function variable is |
| 770 // only present - if at all - for function scopes. | 843 // only present - if at all - for function scopes. |
| 771 // | 844 // |
| 772 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 845 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| 773 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 846 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
| 774 // the name of named function literal is kept in an intermediate scope | 847 // the name of named function literal is kept in an intermediate scope |
| 775 // in between this scope and the next outer scope.) | 848 // in between this scope and the next outer scope.) |
| 776 if (function_ != NULL && function_->name().is_identical_to(name)) { | 849 if (function_ != NULL && function_->name().is_identical_to(name)) { |
| 777 var = function_; | 850 var = function_->var(); |
| 778 | 851 |
| 779 } else if (outer_scope_ != NULL) { | 852 } else if (outer_scope_ != NULL) { |
| 780 var = outer_scope_->LookupRecursive( | 853 var = outer_scope_->LookupRecursive( |
| 781 name, | 854 name, |
| 782 is_function_scope() || from_inner_function, | 855 is_function_scope() || from_inner_function, |
| 783 invalidated_local); | 856 invalidated_local); |
| 784 // We may have found a variable in an outer scope. However, if | 857 // We may have found a variable in an outer scope. However, if |
| 785 // the current scope is inside a 'with', the actual variable may | 858 // the current scope is inside a 'with', the actual variable may |
| 786 // be a property introduced via the 'with' statement. Then, the | 859 // be a property introduced via the 'with' statement. Then, the |
| 787 // variable we may have found is just a guess. | 860 // variable we may have found is just a guess. |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 if (params_[i]->name().is_identical_to( | 1058 if (params_[i]->name().is_identical_to( |
| 986 isolate_->factory()->arguments_symbol())) { | 1059 isolate_->factory()->arguments_symbol())) { |
| 987 return true; | 1060 return true; |
| 988 } | 1061 } |
| 989 } | 1062 } |
| 990 return false; | 1063 return false; |
| 991 } | 1064 } |
| 992 | 1065 |
| 993 | 1066 |
| 994 void Scope::AllocateStackSlot(Variable* var) { | 1067 void Scope::AllocateStackSlot(Variable* var) { |
| 995 var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++)); | 1068 var->AllocateTo(Variable::LOCAL, num_stack_slots_++); |
| 996 } | 1069 } |
| 997 | 1070 |
| 998 | 1071 |
| 999 void Scope::AllocateHeapSlot(Variable* var) { | 1072 void Scope::AllocateHeapSlot(Variable* var) { |
| 1000 var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++)); | 1073 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++); |
| 1001 } | 1074 } |
| 1002 | 1075 |
| 1003 | 1076 |
| 1004 void Scope::AllocateParameterLocals() { | 1077 void Scope::AllocateParameterLocals() { |
| 1005 ASSERT(is_function_scope()); | 1078 ASSERT(is_function_scope()); |
| 1006 Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol()); | 1079 Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol()); |
| 1007 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 1080 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
| 1008 | 1081 |
| 1009 bool uses_nonstrict_arguments = false; | 1082 bool uses_nonstrict_arguments = false; |
| 1010 | 1083 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1036 Variable* var = params_[i]; | 1109 Variable* var = params_[i]; |
| 1037 ASSERT(var->scope() == this); | 1110 ASSERT(var->scope() == this); |
| 1038 if (uses_nonstrict_arguments) { | 1111 if (uses_nonstrict_arguments) { |
| 1039 // Give the parameter a use from an inner scope, to force allocation | 1112 // Give the parameter a use from an inner scope, to force allocation |
| 1040 // to the context. | 1113 // to the context. |
| 1041 var->MarkAsAccessedFromInnerFunctionScope(); | 1114 var->MarkAsAccessedFromInnerFunctionScope(); |
| 1042 } | 1115 } |
| 1043 | 1116 |
| 1044 if (MustAllocate(var)) { | 1117 if (MustAllocate(var)) { |
| 1045 if (MustAllocateInContext(var)) { | 1118 if (MustAllocateInContext(var)) { |
| 1046 ASSERT(var->rewrite() == NULL || var->IsContextSlot()); | 1119 ASSERT(var->IsUnallocated() || var->IsContextSlot()); |
| 1047 if (var->rewrite() == NULL) { | 1120 if (var->IsUnallocated()) { |
| 1048 AllocateHeapSlot(var); | 1121 AllocateHeapSlot(var); |
| 1049 } | 1122 } |
| 1050 } else { | 1123 } else { |
| 1051 ASSERT(var->rewrite() == NULL || var->IsParameter()); | 1124 ASSERT(var->IsUnallocated() || var->IsParameter()); |
| 1052 if (var->rewrite() == NULL) { | 1125 if (var->IsUnallocated()) { |
| 1053 var->set_rewrite(NewSlot(var, Slot::PARAMETER, i)); | 1126 var->AllocateTo(Variable::PARAMETER, i); |
| 1054 } | 1127 } |
| 1055 } | 1128 } |
| 1056 } | 1129 } |
| 1057 } | 1130 } |
| 1058 } | 1131 } |
| 1059 | 1132 |
| 1060 | 1133 |
| 1061 void Scope::AllocateNonParameterLocal(Variable* var) { | 1134 void Scope::AllocateNonParameterLocal(Variable* var) { |
| 1062 ASSERT(var->scope() == this); | 1135 ASSERT(var->scope() == this); |
| 1063 ASSERT(var->rewrite() == NULL || | 1136 ASSERT(!var->IsVariable(isolate_->factory()->result_symbol()) || |
| 1064 !var->IsVariable(isolate_->factory()->result_symbol()) || | 1137 !var->IsStackLocal()); |
| 1065 var->AsSlot() == NULL || | 1138 if (var->IsUnallocated() && MustAllocate(var)) { |
| 1066 var->AsSlot()->type() != Slot::LOCAL); | |
| 1067 if (var->rewrite() == NULL && MustAllocate(var)) { | |
| 1068 if (MustAllocateInContext(var)) { | 1139 if (MustAllocateInContext(var)) { |
| 1069 AllocateHeapSlot(var); | 1140 AllocateHeapSlot(var); |
| 1070 } else { | 1141 } else { |
| 1071 AllocateStackSlot(var); | 1142 AllocateStackSlot(var); |
| 1072 } | 1143 } |
| 1073 } | 1144 } |
| 1074 } | 1145 } |
| 1075 | 1146 |
| 1076 | 1147 |
| 1077 void Scope::AllocateNonParameterLocals() { | 1148 void Scope::AllocateNonParameterLocals() { |
| 1078 // All variables that have no rewrite yet are non-parameter locals. | 1149 // All variables that have no rewrite yet are non-parameter locals. |
| 1079 for (int i = 0; i < temps_.length(); i++) { | 1150 for (int i = 0; i < temps_.length(); i++) { |
| 1080 AllocateNonParameterLocal(temps_[i]); | 1151 AllocateNonParameterLocal(temps_[i]); |
| 1081 } | 1152 } |
| 1082 | 1153 |
| 1083 for (VariableMap::Entry* p = variables_.Start(); | 1154 for (VariableMap::Entry* p = variables_.Start(); |
| 1084 p != NULL; | 1155 p != NULL; |
| 1085 p = variables_.Next(p)) { | 1156 p = variables_.Next(p)) { |
| 1086 Variable* var = reinterpret_cast<Variable*>(p->value); | 1157 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 1087 AllocateNonParameterLocal(var); | 1158 AllocateNonParameterLocal(var); |
| 1088 } | 1159 } |
| 1089 | 1160 |
| 1090 // For now, function_ must be allocated at the very end. If it gets | 1161 // For now, function_ must be allocated at the very end. If it gets |
| 1091 // allocated in the context, it must be the last slot in the context, | 1162 // allocated in the context, it must be the last slot in the context, |
| 1092 // because of the current ScopeInfo implementation (see | 1163 // because of the current ScopeInfo implementation (see |
| 1093 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1164 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
| 1094 if (function_ != NULL) { | 1165 if (function_ != NULL) { |
| 1095 AllocateNonParameterLocal(function_); | 1166 AllocateNonParameterLocal(function_->var()); |
| 1096 } | 1167 } |
| 1097 } | 1168 } |
| 1098 | 1169 |
| 1099 | 1170 |
| 1100 void Scope::AllocateVariablesRecursively() { | 1171 void Scope::AllocateVariablesRecursively() { |
| 1101 // Allocate variables for inner scopes. | 1172 // Allocate variables for inner scopes. |
| 1102 for (int i = 0; i < inner_scopes_.length(); i++) { | 1173 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 1103 inner_scopes_[i]->AllocateVariablesRecursively(); | 1174 inner_scopes_[i]->AllocateVariablesRecursively(); |
| 1104 } | 1175 } |
| 1105 | 1176 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1131 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1202 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 1132 !must_have_local_context) { | 1203 !must_have_local_context) { |
| 1133 num_heap_slots_ = 0; | 1204 num_heap_slots_ = 0; |
| 1134 } | 1205 } |
| 1135 | 1206 |
| 1136 // Allocation done. | 1207 // Allocation done. |
| 1137 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1208 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1138 } | 1209 } |
| 1139 | 1210 |
| 1140 } } // namespace v8::internal | 1211 } } // namespace v8::internal |
| OLD | NEW |