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 |