| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) { | 79 void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) { |
| 80 } | 80 } |
| 81 | 81 |
| 82 void BreakableStatementChecker::VisitModulePath(ModulePath* module) { | 82 void BreakableStatementChecker::VisitModulePath(ModulePath* module) { |
| 83 } | 83 } |
| 84 | 84 |
| 85 void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) { | 85 void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) { |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void BreakableStatementChecker::VisitModuleStatement(ModuleStatement* stmt) { |
| 90 } |
| 91 |
| 92 |
| 89 void BreakableStatementChecker::VisitBlock(Block* stmt) { | 93 void BreakableStatementChecker::VisitBlock(Block* stmt) { |
| 90 } | 94 } |
| 91 | 95 |
| 92 | 96 |
| 93 void BreakableStatementChecker::VisitExpressionStatement( | 97 void BreakableStatementChecker::VisitExpressionStatement( |
| 94 ExpressionStatement* stmt) { | 98 ExpressionStatement* stmt) { |
| 95 // Check if expression is breakable. | 99 // Check if expression is breakable. |
| 96 Visit(stmt->expression()); | 100 Visit(stmt->expression()); |
| 97 } | 101 } |
| 98 | 102 |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 | 579 |
| 576 | 580 |
| 577 void FullCodeGenerator::DoTest(const TestContext* context) { | 581 void FullCodeGenerator::DoTest(const TestContext* context) { |
| 578 DoTest(context->condition(), | 582 DoTest(context->condition(), |
| 579 context->true_label(), | 583 context->true_label(), |
| 580 context->false_label(), | 584 context->false_label(), |
| 581 context->fall_through()); | 585 context->fall_through()); |
| 582 } | 586 } |
| 583 | 587 |
| 584 | 588 |
| 589 void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) { |
| 590 ASSERT(scope_->is_global_scope()); |
| 591 |
| 592 for (int i = 0; i < declarations->length(); i++) { |
| 593 ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration(); |
| 594 if (declaration != NULL) { |
| 595 ModuleLiteral* module = declaration->module()->AsModuleLiteral(); |
| 596 if (module != NULL) { |
| 597 Comment cmnt(masm_, "[ Link nested modules"); |
| 598 Scope* scope = module->body()->scope(); |
| 599 Interface* interface = scope->interface(); |
| 600 ASSERT(interface->IsModule() && interface->IsFrozen()); |
| 601 |
| 602 interface->Allocate(scope->module_var()->index()); |
| 603 |
| 604 // Set up module context. |
| 605 ASSERT(scope->interface()->Index() >= 0); |
| 606 __ Push(Smi::FromInt(scope->interface()->Index())); |
| 607 __ Push(scope->GetScopeInfo()); |
| 608 __ CallRuntime(Runtime::kPushModuleContext, 2); |
| 609 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 610 context_register()); |
| 611 |
| 612 AllocateModules(scope->declarations()); |
| 613 |
| 614 // Pop module context. |
| 615 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 616 // Update local stack frame context field. |
| 617 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 618 context_register()); |
| 619 } |
| 620 } |
| 621 } |
| 622 } |
| 623 |
| 624 |
| 625 // Modules have their own local scope, represented by their own context. |
| 626 // Module instance objects have an accessor for every export that forwards |
| 627 // access to the respective slot from the module's context. (Exports that are |
| 628 // modules themselves, however, are simple data properties.) |
| 629 // |
| 630 // All modules have a _hosting_ scope/context, which (currently) is the |
| 631 // (innermost) enclosing global scope. To deal with recursion, nested modules |
| 632 // are hosted by the same scope as global ones. |
| 633 // |
| 634 // For every (global or nested) module literal, the hosting context has an |
| 635 // internal slot that points directly to the respective module context. This |
| 636 // enables quick access to (statically resolved) module members by 2-dimensional |
| 637 // access through the hosting context. For example, |
| 638 // |
| 639 // module A { |
| 640 // let x; |
| 641 // module B { let y; } |
| 642 // } |
| 643 // module C { let z; } |
| 644 // |
| 645 // allocates contexts as follows: |
| 646 // |
| 647 // [header| .A | .B | .C | A | C ] (global) |
| 648 // | | | |
| 649 // | | +-- [header| z ] (module) |
| 650 // | | |
| 651 // | +------- [header| y ] (module) |
| 652 // | |
| 653 // +------------ [header| x | B ] (module) |
| 654 // |
| 655 // Here, .A, .B, .C are the internal slots pointing to the hosted module |
| 656 // contexts, whereas A, B, C hold the actual instance objects (note that every |
| 657 // module context also points to the respective instance object through its |
| 658 // extension slot in the header). |
| 659 // |
| 660 // To deal with arbitrary recursion and aliases between modules, |
| 661 // they are created and initialized in several stages. Each stage applies to |
| 662 // all modules in the hosting global scope, including nested ones. |
| 663 // |
| 664 // 1. Allocate: for each module _literal_, allocate the module contexts and |
| 665 // respective instance object and wire them up. This happens in the |
| 666 // PushModuleContext runtime function, as generated by AllocateModules |
| 667 // (invoked by VisitDeclarations in the hosting scope). |
| 668 // |
| 669 // 2. Bind: for each module _declaration_ (i.e. literals as well as aliases), |
| 670 // assign the respective instance object to respective local variables. This |
| 671 // happens in VisitModuleDeclaration, and uses the instance objects created |
| 672 // in the previous stage. |
| 673 // For each module _literal_, this phase also constructs a module descriptor |
| 674 // for the next stage. This happens in VisitModuleLiteral. |
| 675 // |
| 676 // 3. Populate: invoke the DeclareModules runtime function to populate each |
| 677 // _instance_ object with accessors for it exports. This is generated by |
| 678 // DeclareModules (invoked by VisitDeclarations in the hosting scope again), |
| 679 // and uses the descriptors generated in the previous stage. |
| 680 // |
| 681 // 4. Initialize: execute the module bodies (and other code) in sequence. This |
| 682 // happens by the separate statements generated for module bodies. To reenter |
| 683 // the module scopes properly, the parser inserted ModuleStatements. |
| 684 |
| 585 void FullCodeGenerator::VisitDeclarations( | 685 void FullCodeGenerator::VisitDeclarations( |
| 586 ZoneList<Declaration*>* declarations) { | 686 ZoneList<Declaration*>* declarations) { |
| 687 Handle<FixedArray> saved_modules = modules_; |
| 688 int saved_module_index = module_index_; |
| 587 ZoneList<Handle<Object> >* saved_globals = globals_; | 689 ZoneList<Handle<Object> >* saved_globals = globals_; |
| 588 ZoneList<Handle<Object> > inner_globals(10, zone()); | 690 ZoneList<Handle<Object> > inner_globals(10, zone()); |
| 589 globals_ = &inner_globals; | 691 globals_ = &inner_globals; |
| 590 | 692 |
| 693 if (scope_->num_modules() != 0) { |
| 694 // This is a scope hosting modules. Allocate a descriptor array to pass |
| 695 // to the runtime for initialization. |
| 696 Comment cmnt(masm_, "[ Allocate modules"); |
| 697 ASSERT(scope_->is_global_scope()); |
| 698 modules_ = |
| 699 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED); |
| 700 module_index_ = 0; |
| 701 |
| 702 // Generate code for allocating all modules, including nested ones. |
| 703 // The allocated contexts are stored in internal variables in this scope. |
| 704 AllocateModules(declarations); |
| 705 } |
| 706 |
| 591 AstVisitor::VisitDeclarations(declarations); | 707 AstVisitor::VisitDeclarations(declarations); |
| 708 |
| 709 if (scope_->num_modules() != 0) { |
| 710 // Initialize modules from descriptor array. |
| 711 ASSERT(module_index_ == modules_->length()); |
| 712 DeclareModules(modules_); |
| 713 modules_ = saved_modules; |
| 714 module_index_ = saved_module_index; |
| 715 } |
| 716 |
| 592 if (!globals_->is_empty()) { | 717 if (!globals_->is_empty()) { |
| 593 // Invoke the platform-dependent code generator to do the actual | 718 // Invoke the platform-dependent code generator to do the actual |
| 594 // declaration the global functions and variables. | 719 // declaration of the global functions and variables. |
| 595 Handle<FixedArray> array = | 720 Handle<FixedArray> array = |
| 596 isolate()->factory()->NewFixedArray(globals_->length(), TENURED); | 721 isolate()->factory()->NewFixedArray(globals_->length(), TENURED); |
| 597 for (int i = 0; i < globals_->length(); ++i) | 722 for (int i = 0; i < globals_->length(); ++i) |
| 598 array->set(i, *globals_->at(i)); | 723 array->set(i, *globals_->at(i)); |
| 599 DeclareGlobals(array); | 724 DeclareGlobals(array); |
| 600 } | 725 } |
| 601 | 726 |
| 602 globals_ = saved_globals; | 727 globals_ = saved_globals; |
| 603 } | 728 } |
| 604 | 729 |
| 605 | 730 |
| 606 void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) { | 731 void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) { |
| 607 // Allocate a module context statically. | |
| 608 Block* block = module->body(); | 732 Block* block = module->body(); |
| 609 Scope* saved_scope = scope(); | 733 Scope* saved_scope = scope(); |
| 610 scope_ = block->scope(); | 734 scope_ = block->scope(); |
| 611 Interface* interface = module->interface(); | 735 Interface* interface = scope_->interface(); |
| 612 Handle<JSModule> instance = interface->Instance(); | |
| 613 | 736 |
| 614 Comment cmnt(masm_, "[ ModuleLiteral"); | 737 Comment cmnt(masm_, "[ ModuleLiteral"); |
| 615 SetStatementPosition(block); | 738 SetStatementPosition(block); |
| 616 | 739 |
| 740 ASSERT(!modules_.is_null()); |
| 741 ASSERT(module_index_ < modules_->length()); |
| 742 int index = module_index_++; |
| 743 |
| 617 // Set up module context. | 744 // Set up module context. |
| 618 __ Push(instance); | 745 ASSERT(interface->Index() >= 0); |
| 619 __ CallRuntime(Runtime::kPushModuleContext, 1); | 746 __ Push(Smi::FromInt(interface->Index())); |
| 747 __ Push(Smi::FromInt(0)); |
| 748 __ CallRuntime(Runtime::kPushModuleContext, 2); |
| 620 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 749 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 621 | 750 |
| 622 { | 751 { |
| 623 Comment cmnt(masm_, "[ Declarations"); | 752 Comment cmnt(masm_, "[ Declarations"); |
| 624 VisitDeclarations(scope_->declarations()); | 753 VisitDeclarations(scope_->declarations()); |
| 625 } | 754 } |
| 626 | 755 |
| 756 // Populate the module description. |
| 757 Handle<ModuleInfo> description = |
| 758 ModuleInfo::Create(isolate(), interface, scope_); |
| 759 modules_->set(index, *description); |
| 760 |
| 627 scope_ = saved_scope; | 761 scope_ = saved_scope; |
| 628 // Pop module context. | 762 // Pop module context. |
| 629 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 763 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 630 // Update local stack frame context field. | 764 // Update local stack frame context field. |
| 631 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 765 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
| 632 } | 766 } |
| 633 | 767 |
| 634 | 768 |
| 635 void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) { | 769 void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) { |
| 636 // Nothing to do. | 770 // Nothing to do. |
| 637 // The instance object is resolved statically through the module's interface. | 771 // The instance object is resolved statically through the module's interface. |
| 638 } | 772 } |
| 639 | 773 |
| 640 | 774 |
| 641 void FullCodeGenerator::VisitModulePath(ModulePath* module) { | 775 void FullCodeGenerator::VisitModulePath(ModulePath* module) { |
| 642 // Nothing to do. | 776 // Nothing to do. |
| 643 // The instance object is resolved statically through the module's interface. | 777 // The instance object is resolved statically through the module's interface. |
| 644 } | 778 } |
| 645 | 779 |
| 646 | 780 |
| 647 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* decl) { | 781 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) { |
| 648 // TODO(rossberg) | 782 // TODO(rossberg): dummy allocation for now. |
| 783 Scope* scope = module->body()->scope(); |
| 784 Interface* interface = scope_->interface(); |
| 785 |
| 786 ASSERT(interface->IsModule() && interface->IsFrozen()); |
| 787 ASSERT(!modules_.is_null()); |
| 788 ASSERT(module_index_ < modules_->length()); |
| 789 interface->Allocate(scope->module_var()->index()); |
| 790 int index = module_index_++; |
| 791 |
| 792 Handle<ModuleInfo> description = |
| 793 ModuleInfo::Create(isolate(), interface, scope_); |
| 794 modules_->set(index, *description); |
| 649 } | 795 } |
| 650 | 796 |
| 651 | 797 |
| 652 int FullCodeGenerator::DeclareGlobalsFlags() { | 798 int FullCodeGenerator::DeclareGlobalsFlags() { |
| 653 ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode())); | 799 ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode())); |
| 654 return DeclareGlobalsEvalFlag::encode(is_eval()) | | 800 return DeclareGlobalsEvalFlag::encode(is_eval()) | |
| 655 DeclareGlobalsNativeFlag::encode(is_native()) | | 801 DeclareGlobalsNativeFlag::encode(is_native()) | |
| 656 DeclareGlobalsLanguageMode::encode(language_mode()); | 802 DeclareGlobalsLanguageMode::encode(language_mode()); |
| 657 } | 803 } |
| 658 | 804 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 | 1043 |
| 898 void FullCodeGenerator::VisitBlock(Block* stmt) { | 1044 void FullCodeGenerator::VisitBlock(Block* stmt) { |
| 899 Comment cmnt(masm_, "[ Block"); | 1045 Comment cmnt(masm_, "[ Block"); |
| 900 NestedBlock nested_block(this, stmt); | 1046 NestedBlock nested_block(this, stmt); |
| 901 SetStatementPosition(stmt); | 1047 SetStatementPosition(stmt); |
| 902 | 1048 |
| 903 Scope* saved_scope = scope(); | 1049 Scope* saved_scope = scope(); |
| 904 // Push a block context when entering a block with block scoped variables. | 1050 // Push a block context when entering a block with block scoped variables. |
| 905 if (stmt->scope() != NULL) { | 1051 if (stmt->scope() != NULL) { |
| 906 scope_ = stmt->scope(); | 1052 scope_ = stmt->scope(); |
| 907 if (scope_->is_module_scope()) { | 1053 ASSERT(!scope_->is_module_scope()); |
| 908 // If this block is a module body, then we have already allocated and | 1054 { Comment cmnt(masm_, "[ Extend block context"); |
| 909 // initialized the declarations earlier. Just push the context. | 1055 Handle<ScopeInfo> scope_info = scope_->GetScopeInfo(); |
| 910 ASSERT(!scope_->interface()->Instance().is_null()); | 1056 int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS; |
| 911 __ Push(scope_->interface()->Instance()); | 1057 __ Push(scope_info); |
| 912 __ CallRuntime(Runtime::kPushModuleContext, 1); | 1058 PushFunctionArgumentForContextAllocation(); |
| 913 StoreToFrameField( | 1059 if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) { |
| 914 StandardFrameConstants::kContextOffset, context_register()); | 1060 FastNewBlockContextStub stub(heap_slots); |
| 915 } else { | 1061 __ CallStub(&stub); |
| 916 { Comment cmnt(masm_, "[ Extend block context"); | 1062 } else { |
| 917 Handle<ScopeInfo> scope_info = scope_->GetScopeInfo(); | 1063 __ CallRuntime(Runtime::kPushBlockContext, 2); |
| 918 int heap_slots = | 1064 } |
| 919 scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS; | |
| 920 __ Push(scope_info); | |
| 921 PushFunctionArgumentForContextAllocation(); | |
| 922 if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) { | |
| 923 FastNewBlockContextStub stub(heap_slots); | |
| 924 __ CallStub(&stub); | |
| 925 } else { | |
| 926 __ CallRuntime(Runtime::kPushBlockContext, 2); | |
| 927 } | |
| 928 | 1065 |
| 929 // Replace the context stored in the frame. | 1066 // Replace the context stored in the frame. |
| 930 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1067 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 931 context_register()); | 1068 context_register()); |
| 932 } | 1069 } |
| 933 { Comment cmnt(masm_, "[ Declarations"); | 1070 { Comment cmnt(masm_, "[ Declarations"); |
| 934 VisitDeclarations(scope_->declarations()); | 1071 VisitDeclarations(scope_->declarations()); |
| 935 } | |
| 936 } | 1072 } |
| 937 } | 1073 } |
| 1074 |
| 938 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 1075 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
| 939 VisitStatements(stmt->statements()); | 1076 VisitStatements(stmt->statements()); |
| 940 scope_ = saved_scope; | 1077 scope_ = saved_scope; |
| 941 __ bind(nested_block.break_label()); | 1078 __ bind(nested_block.break_label()); |
| 942 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1079 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 943 | 1080 |
| 944 // Pop block context if necessary. | 1081 // Pop block context if necessary. |
| 945 if (stmt->scope() != NULL) { | 1082 if (stmt->scope() != NULL) { |
| 946 LoadContextField(context_register(), Context::PREVIOUS_INDEX); | 1083 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 947 // Update local stack frame context field. | 1084 // Update local stack frame context field. |
| 948 StoreToFrameField(StandardFrameConstants::kContextOffset, | 1085 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 949 context_register()); | 1086 context_register()); |
| 950 } | 1087 } |
| 951 } | 1088 } |
| 952 | 1089 |
| 953 | 1090 |
| 1091 void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) { |
| 1092 Comment cmnt(masm_, "[ Module context"); |
| 1093 |
| 1094 __ Push(Smi::FromInt(stmt->proxy()->interface()->Index())); |
| 1095 __ Push(Smi::FromInt(0)); |
| 1096 __ CallRuntime(Runtime::kPushModuleContext, 2); |
| 1097 StoreToFrameField( |
| 1098 StandardFrameConstants::kContextOffset, context_register()); |
| 1099 |
| 1100 Scope* saved_scope = scope_; |
| 1101 scope_ = stmt->body()->scope(); |
| 1102 VisitStatements(stmt->body()->statements()); |
| 1103 scope_ = saved_scope; |
| 1104 LoadContextField(context_register(), Context::PREVIOUS_INDEX); |
| 1105 // Update local stack frame context field. |
| 1106 StoreToFrameField(StandardFrameConstants::kContextOffset, |
| 1107 context_register()); |
| 1108 } |
| 1109 |
| 1110 |
| 954 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 1111 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 955 Comment cmnt(masm_, "[ ExpressionStatement"); | 1112 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 956 SetStatementPosition(stmt); | 1113 SetStatementPosition(stmt); |
| 957 VisitForEffect(stmt->expression()); | 1114 VisitForEffect(stmt->expression()); |
| 958 } | 1115 } |
| 959 | 1116 |
| 960 | 1117 |
| 961 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 1118 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 962 Comment cmnt(masm_, "[ EmptyStatement"); | 1119 Comment cmnt(masm_, "[ EmptyStatement"); |
| 963 SetStatementPosition(stmt); | 1120 SetStatementPosition(stmt); |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 } | 1578 } |
| 1422 | 1579 |
| 1423 return false; | 1580 return false; |
| 1424 } | 1581 } |
| 1425 | 1582 |
| 1426 | 1583 |
| 1427 #undef __ | 1584 #undef __ |
| 1428 | 1585 |
| 1429 | 1586 |
| 1430 } } // namespace v8::internal | 1587 } } // namespace v8::internal |
| OLD | NEW |