Chromium Code Reviews| Index: runtime/vm/flow_graph_compiler_x64.cc |
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
| index cd0580c12eddcfc2914cb5a654553215baa11e69..862f4f20d4f597d892045b41dc2a0380ed4c6b2e 100644 |
| --- a/runtime/vm/flow_graph_compiler_x64.cc |
| +++ b/runtime/vm/flow_graph_compiler_x64.cc |
| @@ -20,6 +20,23 @@ DECLARE_FLAG(bool, print_ast); |
| DECLARE_FLAG(bool, print_scopes); |
| DECLARE_FLAG(bool, trace_functions); |
| +FlowGraphCompiler::FlowGraphCompiler( |
| + Assembler* assembler, |
| + const ParsedFunction& parsed_function, |
| + const GrowableArray<BlockEntryInstr*>* blocks) |
| + : assembler_(assembler), |
| + parsed_function_(parsed_function), |
| + blocks_(blocks), |
| + block_info_(blocks->length()), |
| + current_block_(NULL), |
| + pc_descriptors_list_(new CodeGenerator::DescriptorList()), |
| + stack_local_count_(0) { |
| + for (int i = 0; i < blocks->length(); ++i) { |
| + block_info_.Add(new BlockInfo()); |
| + } |
| +} |
| + |
| + |
| void FlowGraphCompiler::Bailout(const char* reason) { |
| const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| const char* function_name = parsed_function_.function().ToCString(); |
| @@ -260,13 +277,36 @@ void FlowGraphCompiler::VisitInstanceSetter(InstanceSetterComp* comp) { |
| } |
| +void FlowGraphCompiler::VisitBlocks( |
| + const GrowableArray<BlockEntryInstr*>& blocks) { |
| + for (intptr_t i = blocks.length() - 1; i >= 0; --i) { |
| + // Compile the block entry. |
| + current_block_ = blocks[i]; |
| + Instruction* instr = current_block()->Accept(this); |
| + // Compile all successors until an exit, branch, or a block entry. |
| + while ((instr != NULL) && !instr->IsBlockEntry()) { |
| + instr = instr->Accept(this); |
| + } |
| + |
| + if ((instr != NULL) && instr->IsBlockEntry()) { |
| + // Block ended with a "goto". We can fall through if it is the |
| + // next block in the list. Otherwise, we need a jump. |
| + if (i == 0 || (blocks[i - 1] != instr)) { |
| + int number = BlockEntryInstr::cast(instr)->block_number(); |
|
srdjan
2012/03/07 22:23:06
Discussed in the team and talked with Ivan: Please
Kevin Millikin (Google)
2012/03/08 09:59:53
Removed the static member function from class Bloc
|
| + __ jmp(&block_info_[number]->label); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| void FlowGraphCompiler::VisitJoinEntry(JoinEntryInstr* instr) { |
| - Bailout("JoinEntryInstr"); |
| + __ Bind(&block_info_[instr->block_number()]->label); |
| } |
| void FlowGraphCompiler::VisitTargetEntry(TargetEntryInstr* instr) { |
| - // Since we don't handle branching control flow yet, there is nothing to do. |
| + __ Bind(&block_info_[instr->block_number()]->label); |
| } |
| @@ -349,7 +389,24 @@ void FlowGraphCompiler::VisitReturn(ReturnInstr* instr) { |
| void FlowGraphCompiler::VisitBranch(BranchInstr* instr) { |
| - Bailout("BranchInstr"); |
| + // Determine if the true branch is fall through (!negated) or the false |
| + // branch is. They cannot both be backwards branches. |
| + int index = blocks_->length() - current_block()->block_number() - 1; |
|
srdjan
2012/03/07 22:23:06
intptr_t
Kevin Millikin (Google)
2012/03/08 09:59:53
Done.
|
| + ASSERT(index != 0); |
|
srdjan
2012/03/07 22:23:06
Maybe safer: (index > 0).
Kevin Millikin (Google)
2012/03/08 09:59:53
Done.
|
| + |
| + bool negated = ((*blocks_)[index - 1] == instr->false_successor()); |
| + ASSERT(!negated == ((*blocks_)[index - 1] == instr->true_successor())); |
| + |
| + LoadValue(instr->value()); |
| + __ LoadObject(RDX, Bool::ZoneHandle(Bool::True())); |
| + __ cmpq(RAX, RDX); |
| + if (negated) { |
| + __ j(EQUAL, &block_info_[instr->true_successor()->block_number()]->label); |
| + |
|
srdjan
2012/03/07 22:23:06
Empty line?
Kevin Millikin (Google)
2012/03/08 09:59:53
Deleted.
|
| + } else { |
| + __ j(NOT_EQUAL, |
| + &block_info_[instr->false_successor()->block_number()]->label); |
| + } |
| } |
| @@ -371,8 +428,6 @@ void FlowGraphCompiler::CompileGraph() { |
| &context_owner); |
| set_stack_local_count(first_local_index - first_free_frame_index); |
| - if (blocks_->length() != 1) Bailout("more than 1 basic block"); |
| - |
| // Specialized version of entry code from CodeGenerator::GenerateEntryCode. |
| __ EnterFrame(stack_local_count() * kWordSize); |
| #ifdef DEBUG |