Chromium Code Reviews| 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/flow_graph.h" | 5 #include "vm/flow_graph.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| 11 #include "vm/growable_array.h" | |
| 11 | 12 |
| 12 namespace dart { | 13 namespace dart { |
| 13 | 14 |
| 14 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, | 15 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, |
| 15 GraphEntryInstr* graph_entry) | 16 GraphEntryInstr* graph_entry) |
| 16 : parent_(), | 17 : parent_(), |
| 17 assigned_vars_(), | 18 assigned_vars_(), |
| 18 current_ssa_temp_index_(0), | 19 current_ssa_temp_index_(0), |
| 19 parsed_function_(builder.parsed_function()), | 20 parsed_function_(builder.parsed_function()), |
| 20 copied_parameter_count_(builder.copied_parameter_count()), | 21 copied_parameter_count_(builder.copied_parameter_count()), |
| 21 non_copied_parameter_count_(builder.non_copied_parameter_count()), | 22 non_copied_parameter_count_(builder.non_copied_parameter_count()), |
| 22 stack_local_count_(builder.stack_local_count()), | 23 stack_local_count_(builder.stack_local_count()), |
| 23 graph_entry_(graph_entry), | 24 graph_entry_(graph_entry), |
| 24 preorder_(), | 25 preorder_(), |
| 25 postorder_(), | 26 postorder_(), |
| 26 reverse_postorder_() { | 27 reverse_postorder_(), |
| 28 exits_(NULL) { | |
| 27 DiscoverBlocks(); | 29 DiscoverBlocks(); |
| 28 } | 30 } |
| 29 | 31 |
| 30 | 32 |
| 31 void FlowGraph::DiscoverBlocks() { | 33 void FlowGraph::DiscoverBlocks() { |
| 32 // Initialize state. | 34 // Initialize state. |
| 33 preorder_.TruncateTo(0); | 35 preorder_.TruncateTo(0); |
| 34 postorder_.TruncateTo(0); | 36 postorder_.TruncateTo(0); |
| 35 reverse_postorder_.TruncateTo(0); | 37 reverse_postorder_.TruncateTo(0); |
| 36 parent_.TruncateTo(0); | 38 parent_.TruncateTo(0); |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 InsertPhis(preorder_, assigned_vars_, dominance_frontier); | 292 InsertPhis(preorder_, assigned_vars_, dominance_frontier); |
| 291 GrowableArray<PhiInstr*> live_phis; | 293 GrowableArray<PhiInstr*> live_phis; |
| 292 // Rename uses to reference inserted phis where appropriate. | 294 // Rename uses to reference inserted phis where appropriate. |
| 293 // Collect phis that reach a non-environment use. | 295 // Collect phis that reach a non-environment use. |
| 294 Rename(&live_phis); | 296 Rename(&live_phis); |
| 295 // Propagate alive mark transitively from alive phis. | 297 // Propagate alive mark transitively from alive phis. |
| 296 MarkLivePhis(&live_phis); | 298 MarkLivePhis(&live_phis); |
| 297 } | 299 } |
| 298 | 300 |
| 299 | 301 |
| 302 void FlowGraph::ComputeSSAForInlining( | |
| 303 intptr_t callers_max_virtual_register_number) { | |
| 304 current_ssa_temp_index_ = callers_max_virtual_register_number; | |
| 305 ComputeSSA(); | |
| 306 } | |
| 307 | |
| 308 | |
| 300 // Compute immediate dominators and the dominance frontier for each basic | 309 // Compute immediate dominators and the dominance frontier for each basic |
| 301 // block. As a side effect of the algorithm, sets the immediate dominator | 310 // block. As a side effect of the algorithm, sets the immediate dominator |
| 302 // of each basic block. | 311 // of each basic block. |
| 303 // | 312 // |
| 304 // preorder: an input list of basic block entries in preorder. The | 313 // preorder: an input list of basic block entries in preorder. The |
| 305 // algorithm relies on the block ordering. | 314 // algorithm relies on the block ordering. |
| 306 // | 315 // |
| 307 // parent: an input parameter encoding a depth-first spanning tree of | 316 // parent: an input parameter encoding a depth-first spanning tree of |
| 308 // the control flow graph. The array maps the preorder block | 317 // the control flow graph. The array maps the preorder block |
| 309 // number of a block to the preorder block number of its spanning | 318 // number of a block to the preorder block number of its spanning |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 const char* function_name = parsed_function_.function().ToCString(); | 685 const char* function_name = parsed_function_.function().ToCString(); |
| 677 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 686 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 678 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 687 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 679 OS::SNPrint(chars, len, kFormat, function_name, reason); | 688 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 680 const Error& error = Error::Handle( | 689 const Error& error = Error::Handle( |
| 681 LanguageError::New(String::Handle(String::New(chars)))); | 690 LanguageError::New(String::Handle(String::New(chars)))); |
| 682 Isolate::Current()->long_jump_base()->Jump(1, error); | 691 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 683 } | 692 } |
| 684 | 693 |
| 685 | 694 |
| 695 // Helper to get the block-entry ancestor of an instruction. | |
|
Kevin Millikin (Google)
2012/08/29 14:01:04
'ancestor' makes me think of trees.
zerny-google
2012/08/30 07:31:40
Done.
| |
| 696 static BlockEntryInstr* GetBlockEntry(Instruction* instr) { | |
| 697 while (!instr->IsBlockEntry()) instr = instr->previous(); | |
| 698 return instr->AsBlockEntry(); | |
| 699 } | |
| 700 | |
| 701 | |
| 702 // Helper to link two instruction in the graph. | |
|
srdjan
2012/08/29 21:31:33
s/instruction/instructions/
zerny-google
2012/08/30 07:31:40
Done.
| |
| 703 static void Link(Instruction* prev, Instruction* next) { | |
| 704 ASSERT(prev != next); | |
| 705 prev->set_next(next); | |
| 706 next->set_previous(prev); | |
| 707 } | |
| 708 | |
| 709 | |
| 710 // Inline a flow graph at a call site. | |
| 711 // | |
| 712 // Assumes the callee graph was computed with BuildGraphForInlining and | |
| 713 // transformed to SSA with ComputeSSAForInlining, and that the use lists have | |
| 714 // been correctly computed. | |
| 715 // | |
| 716 // After inlining the caller graph will correctly have adjusted the pre/post | |
| 717 // orders, the dominator tree and the use lists. | |
| 718 void FlowGraph::InlineCall(BindInstr* caller_instr, | |
| 719 StaticCallComp* caller_comp, | |
| 720 FlowGraph* callee_graph) { | |
| 721 ASSERT(callee_graph->exits() != NULL); | |
| 722 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); | |
| 723 ASSERT(callee_graph->max_virtual_register_number() > | |
| 724 max_virtual_register_number()); | |
| 725 | |
| 726 // TODO(zerny): Implement support for callee graphs with control flow. | |
| 727 ASSERT(callee_graph->preorder().length() == 2); | |
| 728 | |
| 729 // Adjust the SSA temp index by the callee graph's index. | |
| 730 current_ssa_temp_index_ = callee_graph->max_virtual_register_number(); | |
| 731 | |
| 732 TargetEntryInstr* callee_entry = callee_graph->graph_entry()->normal_entry(); | |
| 733 ZoneGrowableArray<ReturnInstr*>* callee_exits = callee_graph->exits(); | |
| 734 | |
| 735 // 1. Insert the callee graph into the caller graph. | |
| 736 if (callee_exits->length() == 1) { | |
| 737 ReturnInstr* exit = (*callee_exits)[0]; | |
| 738 // TODO(zerny): Support one exit graph containing control flow. | |
| 739 ASSERT(callee_entry == GetBlockEntry(exit)); | |
| 740 // For just one exit, replace the uses and remove the call from the graph. | |
| 741 caller_instr->ReplaceUsesWith(exit->value()); | |
| 742 Link(caller_instr->previous(), callee_entry->next()); | |
| 743 Link(exit->previous(), caller_instr->next()); | |
| 744 } else { | |
| 745 // TODO(zerny): Support multiple exits. | |
| 746 UNREACHABLE(); | |
| 747 } | |
| 748 | |
| 749 // TODO(zerny): Adjust pre/post orders. | |
| 750 // TODO(zerny): Update dominator tree. | |
| 751 | |
| 752 // Remove original arguments to the call. | |
| 753 for (intptr_t i = 0; i < caller_comp->ArgumentCount(); ++i) { | |
| 754 PushArgumentInstr* push = caller_comp->ArgumentAt(i); | |
| 755 push->ReplaceUsesWith(push->value()); | |
| 756 push->RemoveFromGraph(); | |
| 757 } | |
| 758 } | |
| 759 | |
| 760 | |
| 686 } // namespace dart | 761 } // namespace dart |
| OLD | NEW |