Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: src/full-codegen.cc

Issue 11093074: Get rid of static module allocation, do it in code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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(Immediate(Smi::FromInt(scope->interface()->Index())));
607 __ push(Immediate(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(Immediate(Smi::FromInt(interface->Index())));
Michael Starzinger 2012/11/20 12:05:05 See comment further down the file.
rossberg 2012/11/20 17:23:45 Done.
747 __ push(Immediate(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. The format is:
757 //
758 // Index, (Name, VariableMode, Index)*
759 //
760 // That is, the first slot is the index of the module's context in the
761 // host context, then a sequence of triples follows that describes its
762 // exports. Index is either the slot index in the module context, or
763 // (for exported modules) the slot index of the referred module's
764 // context in the host context.
Sven Panne 2012/11/20 14:39:13 Can we abstract this index magic into a separate c
rossberg 2012/11/20 17:23:45 Done. Of course, in C++ that means thrice as much
765 // TODO(rossberg): Cannot yet handle exports of modules declared in
766 // earlier scripts.
767 Handle<FixedArray> description =
768 isolate()->factory()->NewFixedArray(1 + 3 * interface->Length());
769 description->set(0, Smi::FromInt(interface->Index()));
770 int i = 1;
771 for (Interface::Iterator it = interface->iterator();
772 !it.done(); it.Advance()) {
773 Variable* var = scope_->LocalLookup(it.name());
774 description->set(i++, *it.name());
775 description->set(i++, Smi::FromInt(var->mode()));
776 ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
777 if (var->mode() == MODULE) {
778 ASSERT(it.interface()->IsFrozen());
779 ASSERT(it.interface()->Index() >= 0);
780 description->set(i++, Smi::FromInt(it.interface()->Index()));
781 } else {
782 ASSERT(var->index() >= 0);
783 description->set(i++, Smi::FromInt(var->index()));
784 }
785 }
786 ASSERT(i == description->length());
787 modules_->set(index, *description);
788
627 scope_ = saved_scope; 789 scope_ = saved_scope;
628 // Pop module context. 790 // Pop module context.
629 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 791 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
630 // Update local stack frame context field. 792 // Update local stack frame context field.
631 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 793 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
632 } 794 }
633 795
634 796
635 void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) { 797 void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) {
636 // Nothing to do. 798 // Nothing to do.
637 // The instance object is resolved statically through the module's interface. 799 // The instance object is resolved statically through the module's interface.
638 } 800 }
639 801
640 802
641 void FullCodeGenerator::VisitModulePath(ModulePath* module) { 803 void FullCodeGenerator::VisitModulePath(ModulePath* module) {
642 // Nothing to do. 804 // Nothing to do.
643 // The instance object is resolved statically through the module's interface. 805 // The instance object is resolved statically through the module's interface.
644 } 806 }
645 807
646 808
647 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* decl) { 809 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) {
648 // TODO(rossberg) 810 // TODO(rossberg): dummy allocation for now.
811 Scope* scope = module->body()->scope();
812 Interface* interface = scope_->interface();
813
814 ASSERT(interface->IsModule() && interface->IsFrozen());
815 ASSERT(!modules_.is_null());
816 ASSERT(module_index_ < modules_->length());
817 interface->Allocate(scope->module_var()->index());
818 int index = module_index_++;
819
820 Handle<FixedArray> description = isolate()->factory()->NewFixedArray(2);
821 description->set(0, Smi::FromInt(interface->Index()));
822 description->set(1, *scope->GetScopeInfo());
Michael Starzinger 2012/11/20 12:05:05 Pattern is not GC-safe.
Sven Panne 2012/11/20 14:39:13 See my comment above about FixedArray. The descrip
rossberg 2012/11/20 17:23:45 Obsolete.
rossberg 2012/11/20 17:23:45 That was actually a bug (leftover from earlier for
823 modules_->set(index, *description);
649 } 824 }
650 825
651 826
652 int FullCodeGenerator::DeclareGlobalsFlags() { 827 int FullCodeGenerator::DeclareGlobalsFlags() {
653 ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode())); 828 ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
654 return DeclareGlobalsEvalFlag::encode(is_eval()) | 829 return DeclareGlobalsEvalFlag::encode(is_eval()) |
655 DeclareGlobalsNativeFlag::encode(is_native()) | 830 DeclareGlobalsNativeFlag::encode(is_native()) |
656 DeclareGlobalsLanguageMode::encode(language_mode()); 831 DeclareGlobalsLanguageMode::encode(language_mode());
657 } 832 }
658 833
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 1072
898 void FullCodeGenerator::VisitBlock(Block* stmt) { 1073 void FullCodeGenerator::VisitBlock(Block* stmt) {
899 Comment cmnt(masm_, "[ Block"); 1074 Comment cmnt(masm_, "[ Block");
900 NestedBlock nested_block(this, stmt); 1075 NestedBlock nested_block(this, stmt);
901 SetStatementPosition(stmt); 1076 SetStatementPosition(stmt);
902 1077
903 Scope* saved_scope = scope(); 1078 Scope* saved_scope = scope();
904 // Push a block context when entering a block with block scoped variables. 1079 // Push a block context when entering a block with block scoped variables.
905 if (stmt->scope() != NULL) { 1080 if (stmt->scope() != NULL) {
906 scope_ = stmt->scope(); 1081 scope_ = stmt->scope();
907 if (scope_->is_module_scope()) { 1082 ASSERT(!scope_->is_module_scope());
908 // If this block is a module body, then we have already allocated and 1083 { Comment cmnt(masm_, "[ Extend block context");
909 // initialized the declarations earlier. Just push the context. 1084 Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
910 ASSERT(!scope_->interface()->Instance().is_null()); 1085 int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
911 __ Push(scope_->interface()->Instance()); 1086 __ Push(scope_info);
912 __ CallRuntime(Runtime::kPushModuleContext, 1); 1087 PushFunctionArgumentForContextAllocation();
913 StoreToFrameField( 1088 if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
914 StandardFrameConstants::kContextOffset, context_register()); 1089 FastNewBlockContextStub stub(heap_slots);
915 } else { 1090 __ CallStub(&stub);
916 { Comment cmnt(masm_, "[ Extend block context"); 1091 } else {
917 Handle<ScopeInfo> scope_info = scope_->GetScopeInfo(); 1092 __ CallRuntime(Runtime::kPushBlockContext, 2);
918 int heap_slots = 1093 }
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 1094
929 // Replace the context stored in the frame. 1095 // Replace the context stored in the frame.
930 StoreToFrameField(StandardFrameConstants::kContextOffset, 1096 StoreToFrameField(StandardFrameConstants::kContextOffset,
931 context_register()); 1097 context_register());
932 } 1098 }
933 { Comment cmnt(masm_, "[ Declarations"); 1099 { Comment cmnt(masm_, "[ Declarations");
934 VisitDeclarations(scope_->declarations()); 1100 VisitDeclarations(scope_->declarations());
935 }
936 } 1101 }
937 } 1102 }
1103
938 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 1104 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
939 VisitStatements(stmt->statements()); 1105 VisitStatements(stmt->statements());
940 scope_ = saved_scope; 1106 scope_ = saved_scope;
941 __ bind(nested_block.break_label()); 1107 __ bind(nested_block.break_label());
942 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1108 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
943 1109
944 // Pop block context if necessary. 1110 // Pop block context if necessary.
945 if (stmt->scope() != NULL) { 1111 if (stmt->scope() != NULL) {
946 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 1112 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
947 // Update local stack frame context field. 1113 // Update local stack frame context field.
948 StoreToFrameField(StandardFrameConstants::kContextOffset, 1114 StoreToFrameField(StandardFrameConstants::kContextOffset,
949 context_register()); 1115 context_register());
950 } 1116 }
951 } 1117 }
952 1118
953 1119
1120 void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
1121 Comment cmnt(masm_, "[ Module context");
1122
1123 __ push(Immediate(Smi::FromInt(stmt->proxy()->interface()->Index())));
Michael Starzinger 2012/11/20 12:05:05 You will have a hard time porting this to other ar
rossberg 2012/11/20 17:23:45 Done.
1124 __ push(Immediate(Smi::FromInt(0)));
1125 __ CallRuntime(Runtime::kPushModuleContext, 2);
1126 StoreToFrameField(
1127 StandardFrameConstants::kContextOffset, context_register());
1128
1129 Scope* saved_scope = scope_;
1130 scope_ = stmt->body()->scope();
1131 VisitStatements(stmt->body()->statements());
1132 scope_ = saved_scope;
1133 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1134 // Update local stack frame context field.
1135 StoreToFrameField(StandardFrameConstants::kContextOffset,
1136 context_register());
1137 }
1138
1139
954 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 1140 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
955 Comment cmnt(masm_, "[ ExpressionStatement"); 1141 Comment cmnt(masm_, "[ ExpressionStatement");
956 SetStatementPosition(stmt); 1142 SetStatementPosition(stmt);
957 VisitForEffect(stmt->expression()); 1143 VisitForEffect(stmt->expression());
958 } 1144 }
959 1145
960 1146
961 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 1147 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
962 Comment cmnt(masm_, "[ EmptyStatement"); 1148 Comment cmnt(masm_, "[ EmptyStatement");
963 SetStatementPosition(stmt); 1149 SetStatementPosition(stmt);
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
1421 } 1607 }
1422 1608
1423 return false; 1609 return false;
1424 } 1610 }
1425 1611
1426 1612
1427 #undef __ 1613 #undef __
1428 1614
1429 1615
1430 } } // namespace v8::internal 1616 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/heap.cc » ('j') | src/ia32/full-codegen-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698