OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
11 #include "vm/code_generator.h" | 11 #include "vm/code_generator.h" |
12 #include "vm/disassembler.h" | 12 #include "vm/disassembler.h" |
13 #include "vm/longjump.h" | 13 #include "vm/longjump.h" |
14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
16 #include "vm/stub_code.h" | 16 #include "vm/stub_code.h" |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 DECLARE_FLAG(bool, print_ast); | 20 DECLARE_FLAG(bool, print_ast); |
21 DECLARE_FLAG(bool, print_scopes); | 21 DECLARE_FLAG(bool, print_scopes); |
22 DECLARE_FLAG(bool, trace_functions); | 22 DECLARE_FLAG(bool, trace_functions); |
23 | 23 |
24 FlowGraphCompiler::FlowGraphCompiler( | 24 FlowGraphCompiler::FlowGraphCompiler( |
25 Assembler* assembler, | 25 Assembler* assembler, |
26 const ParsedFunction& parsed_function, | 26 const ParsedFunction& parsed_function, |
27 const GrowableArray<BlockEntryInstr*>* blocks) | 27 const GrowableArray<BlockEntryInstr*>& block_order) |
28 : assembler_(assembler), | 28 : FlowGraphVisitor(block_order), |
| 29 assembler_(assembler), |
29 parsed_function_(parsed_function), | 30 parsed_function_(parsed_function), |
30 blocks_(blocks), | 31 block_info_(block_order.length()), |
31 block_info_(blocks->length()), | |
32 current_block_(NULL), | 32 current_block_(NULL), |
33 pc_descriptors_list_(new CodeGenerator::DescriptorList()) { | 33 pc_descriptors_list_(new CodeGenerator::DescriptorList()) { |
34 for (int i = 0; i < blocks->length(); ++i) { | 34 for (int i = 0; i < block_order.length(); ++i) { |
35 block_info_.Add(new BlockInfo()); | 35 block_info_.Add(new BlockInfo()); |
36 } | 36 } |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 FlowGraphCompiler::~FlowGraphCompiler() { | 40 FlowGraphCompiler::~FlowGraphCompiler() { |
41 // BlockInfos are zone-allocated, so their destructors are not called. | 41 // BlockInfos are zone-allocated, so their destructors are not called. |
42 // Verify the labels explicitly here. | 42 // Verify the labels explicitly here. |
43 for (int i = 0; i < block_info_.length(); ++i) { | 43 for (int i = 0; i < block_info_.length(); ++i) { |
44 ASSERT(!block_info_[i]->label.IsLinked()); | 44 ASSERT(!block_info_[i]->label.IsLinked()); |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 // instantiated type arguments, reset instantiator to null. | 723 // instantiated type arguments, reset instantiator to null. |
724 __ movq(RAX, raw_null); // Null instantiator. | 724 __ movq(RAX, raw_null); // Null instantiator. |
725 __ Bind(&use_instantiator); // Use instantiator in RAX. | 725 __ Bind(&use_instantiator); // Use instantiator in RAX. |
726 } | 726 } |
727 // In the non-factory case, we rely on the allocation stub to | 727 // In the non-factory case, we rely on the allocation stub to |
728 // instantiate the type arguments. | 728 // instantiate the type arguments. |
729 // RAX: instantiator or null. | 729 // RAX: instantiator or null. |
730 } | 730 } |
731 | 731 |
732 | 732 |
733 void FlowGraphCompiler::VisitBlocks( | 733 void FlowGraphCompiler::VisitBlocks() { |
734 const GrowableArray<BlockEntryInstr*>& blocks) { | 734 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
735 for (intptr_t i = blocks.length() - 1; i >= 0; --i) { | |
736 // Compile the block entry. | 735 // Compile the block entry. |
737 current_block_ = blocks[i]; | 736 current_block_ = block_order_[i]; |
738 Instruction* instr = current_block()->Accept(this); | 737 Instruction* instr = current_block()->Accept(this); |
739 // Compile all successors until an exit, branch, or a block entry. | 738 // Compile all successors until an exit, branch, or a block entry. |
740 while ((instr != NULL) && !instr->IsBlockEntry()) { | 739 while ((instr != NULL) && !instr->IsBlockEntry()) { |
741 instr = instr->Accept(this); | 740 instr = instr->Accept(this); |
742 } | 741 } |
743 | 742 |
744 BlockEntryInstr* successor = | 743 BlockEntryInstr* successor = |
745 (instr == NULL) ? NULL : instr->AsBlockEntry(); | 744 (instr == NULL) ? NULL : instr->AsBlockEntry(); |
746 if (successor != NULL) { | 745 if (successor != NULL) { |
747 // Block ended with a "goto". We can fall through if it is the | 746 // Block ended with a "goto". We can fall through if it is the |
748 // next block in the list. Otherwise, we need a jump. | 747 // next block in the list. Otherwise, we need a jump. |
749 if (i == 0 || (blocks[i - 1] != successor)) { | 748 if ((i == block_order_.length() - 1) || |
750 __ jmp(&block_info_[successor->block_number()]->label); | 749 (block_order_[i + 1] != successor)) { |
| 750 __ jmp(&block_info_[successor->postorder_number()]->label); |
751 } | 751 } |
752 } | 752 } |
753 } | 753 } |
754 } | 754 } |
755 | 755 |
756 | 756 |
757 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { | 757 void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
758 __ Bind(&block_info_[instr->block_number()]->label); | 758 __ Bind(&block_info_[instr->postorder_number()]->label); |
759 } | 759 } |
760 | 760 |
761 | 761 |
762 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { | 762 void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
763 __ Bind(&block_info_[instr->block_number()]->label); | 763 __ Bind(&block_info_[instr->postorder_number()]->label); |
764 } | 764 } |
765 | 765 |
766 | 766 |
767 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { | 767 void FlowGraphCompiler::VisitPickTemp(PickTempInstr* instr) { |
768 // Semantics is to copy a stack-allocated temporary to the top of stack. | 768 // Semantics is to copy a stack-allocated temporary to the top of stack. |
769 // Destination index d is assumed the new top of stack after the | 769 // Destination index d is assumed the new top of stack after the |
770 // operation, so d-1 is the current top of stack and so d-s-1 is the | 770 // operation, so d-1 is the current top of stack and so d-s-1 is the |
771 // offset to source index s. | 771 // offset to source index s. |
772 intptr_t offset = instr->destination() - instr->source() - 1; | 772 intptr_t offset = instr->destination() - instr->source() - 1; |
773 ASSERT(offset >= 0); | 773 ASSERT(offset >= 0); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 GenerateCallRuntime( | 860 GenerateCallRuntime( |
861 instr->node_id(), instr->token_index(), kReThrowRuntimeEntry); | 861 instr->node_id(), instr->token_index(), kReThrowRuntimeEntry); |
862 Bailout("ReThrow Untested"); | 862 Bailout("ReThrow Untested"); |
863 } | 863 } |
864 | 864 |
865 | 865 |
866 | 866 |
867 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { | 867 void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
868 // Determine if the true branch is fall through (!negated) or the false | 868 // Determine if the true branch is fall through (!negated) or the false |
869 // branch is. They cannot both be backwards branches. | 869 // branch is. They cannot both be backwards branches. |
870 intptr_t index = blocks_->length() - current_block()->block_number() - 1; | 870 intptr_t index = reverse_index(current_block()->postorder_number()); |
871 ASSERT(index > 0); | 871 bool negated = (block_order_[index + 1] == instr->false_successor()); |
872 | 872 ASSERT(!negated == (block_order_[index + 1] == instr->true_successor())); |
873 bool negated = ((*blocks_)[index - 1] == instr->false_successor()); | |
874 ASSERT(!negated == ((*blocks_)[index - 1] == instr->true_successor())); | |
875 | 873 |
876 LoadValue(RAX, instr->value()); | 874 LoadValue(RAX, instr->value()); |
877 __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); | 875 __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); |
878 __ cmpq(RAX, RDX); | 876 __ cmpq(RAX, RDX); |
879 if (negated) { | 877 if (negated) { |
880 __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); | 878 intptr_t target_index = instr->true_successor()->postorder_number(); |
| 879 __ j(EQUAL, &block_info_[target_index]->label); |
881 } else { | 880 } else { |
882 __ j(NOT_EQUAL, | 881 intptr_t target_index = instr->false_successor()->postorder_number(); |
883 &block_info_[instr->false_successor()->block_number()]->label); | 882 __ j(NOT_EQUAL, &block_info_[target_index]->label); |
884 } | 883 } |
885 } | 884 } |
886 | 885 |
887 | 886 |
888 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). | 887 // Coped from CodeGenerator::CopyParameters (CodeGenerator will be deprecated). |
889 void FlowGraphCompiler::CopyParameters() { | 888 void FlowGraphCompiler::CopyParameters() { |
890 const Function& function = parsed_function_.function(); | 889 const Function& function = parsed_function_.function(); |
891 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 890 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
892 const int num_fixed_params = function.num_fixed_parameters(); | 891 const int num_fixed_params = function.num_fixed_parameters(); |
893 const int num_opt_params = function.num_optional_parameters(); | 892 const int num_opt_params = function.num_optional_parameters(); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 if (FLAG_print_scopes) { | 1128 if (FLAG_print_scopes) { |
1130 // Print the function scope (again) after generating the prologue in order | 1129 // Print the function scope (again) after generating the prologue in order |
1131 // to see annotations such as allocation indices of locals. | 1130 // to see annotations such as allocation indices of locals. |
1132 if (FLAG_print_ast) { | 1131 if (FLAG_print_ast) { |
1133 // Second printing. | 1132 // Second printing. |
1134 OS::Print("Annotated "); | 1133 OS::Print("Annotated "); |
1135 } | 1134 } |
1136 AstPrinter::PrintFunctionScope(parsed_function_); | 1135 AstPrinter::PrintFunctionScope(parsed_function_); |
1137 } | 1136 } |
1138 | 1137 |
1139 VisitBlocks(*blocks_); | 1138 VisitBlocks(); |
1140 | 1139 |
1141 __ int3(); | 1140 __ int3(); |
1142 // Emit function patching code. This will be swapped with the first 13 bytes | 1141 // Emit function patching code. This will be swapped with the first 13 bytes |
1143 // at entry point. | 1142 // at entry point. |
1144 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 1143 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, |
1145 assembler_->CodeSize(), | 1144 assembler_->CodeSize(), |
1146 AstNode::kNoId, | 1145 AstNode::kNoId, |
1147 0, | 1146 0, |
1148 -1); | 1147 -1); |
1149 __ jmp(&StubCode::FixCallersTargetLabel()); | 1148 __ jmp(&StubCode::FixCallersTargetLabel()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { | 1197 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { |
1199 // We don't compile exception handlers yet. | 1198 // We don't compile exception handlers yet. |
1200 code.set_exception_handlers( | 1199 code.set_exception_handlers( |
1201 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); | 1200 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); |
1202 } | 1201 } |
1203 | 1202 |
1204 | 1203 |
1205 } // namespace dart | 1204 } // namespace dart |
1206 | 1205 |
1207 #endif // defined TARGET_ARCH_X64 | 1206 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |