| 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 |