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

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 9429056: Recognize basic block entries in the flow graph. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 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
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/flags.h" 7 #include "vm/flags.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/os.h" 9 #include "vm/os.h"
10 #include "vm/parser.h" 10 #include "vm/parser.h"
11 11
12 namespace dart { 12 namespace dart {
13 13
14 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from graph builder."); 14 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from graph builder.");
15 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); 15 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
16 DECLARE_FLAG(bool, enable_type_checks); 16 DECLARE_FLAG(bool, enable_type_checks);
17 17
18 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { 18 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
19 ASSERT(is_open()); 19 ASSERT(is_open());
20 if (other_fragment.is_empty()) return; 20 if (other_fragment.is_empty()) return;
21 if (is_empty()) { 21 if (is_empty()) {
22 entry_ = other_fragment.entry(); 22 entry_ = other_fragment.entry();
23 exit_ = other_fragment.exit(); 23 exit_ = other_fragment.exit();
24 } else { 24 } else {
25 exit()->set_successor(other_fragment.entry()); 25 exit()->SetSuccessor(other_fragment.entry());
26 exit_ = other_fragment.exit(); 26 exit_ = other_fragment.exit();
27 } 27 }
28 } 28 }
29 29
30 30
31 void EffectGraphVisitor::AddInstruction(Instruction* instruction) { 31 void EffectGraphVisitor::AddInstruction(Instruction* instruction) {
32 ASSERT(is_open()); 32 ASSERT(is_open());
33 if (is_empty()) { 33 if (is_empty()) {
34 entry_ = exit_ = instruction; 34 entry_ = exit_ = instruction;
35 } else { 35 } else {
36 exit()->set_successor(instruction); 36 exit()->SetSuccessor(instruction);
37 exit_ = instruction; 37 exit_ = instruction;
38 } 38 }
39 } 39 }
40 40
41 41
42 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, 42 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
43 const EffectGraphVisitor& true_fragment, 43 const EffectGraphVisitor& true_fragment,
44 const EffectGraphVisitor& false_fragment) { 44 const EffectGraphVisitor& false_fragment) {
45 // We have: a test graph fragment with zero, one, or two available exits; 45 // We have: a test graph fragment with zero, one, or two available exits;
46 // and a pair of effect graph fragments with zero or one available exits. 46 // and a pair of effect graph fragments with zero or one available exits.
47 // We want to append the branch and (if necessary) a join node to this 47 // We want to append the branch and (if necessary) a join node to this
48 // graph fragment. 48 // graph fragment.
49 ASSERT(is_open()); 49 ASSERT(is_open());
50 50
51 // 1. Connect the test to this graph. 51 // 1. Connect the test to this graph.
52 Append(test_fragment); 52 Append(test_fragment);
53 53
54 // 2. Connect the true and false bodies to the test if they are reachable, 54 // 2. Connect the true and false bodies to the test if they are reachable,
55 // and if so record their exits (if any). 55 // and if so record their exits (if any).
56 if (test_fragment.can_be_true()) { 56 if (test_fragment.can_be_true()) {
57 Instruction* true_exit = NULL; 57 Instruction* true_exit = NULL;
58 Instruction* false_exit = NULL; 58 Instruction* false_exit = NULL;
59 TargetEntryInstr* true_entry = new TargetEntryInstr(); 59 TargetEntryInstr* true_entry = new TargetEntryInstr();
60 *test_fragment.true_successor_address() = true_entry; 60 *test_fragment.true_successor_address() = true_entry;
61 true_entry->set_successor(true_fragment.entry()); 61 true_entry->SetSuccessor(true_fragment.entry());
62 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); 62 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit();
63 63
64 TargetEntryInstr* false_entry = new TargetEntryInstr(); 64 TargetEntryInstr* false_entry = new TargetEntryInstr();
65 *test_fragment.false_successor_address() = false_entry; 65 *test_fragment.false_successor_address() = false_entry;
66 false_entry->set_successor(false_fragment.entry()); 66 false_entry->SetSuccessor(false_fragment.entry());
67 false_exit = 67 false_exit =
68 false_fragment.is_empty() ? false_entry : false_fragment.exit(); 68 false_fragment.is_empty() ? false_entry : false_fragment.exit();
69 69
70 exit_ = new JoinEntryInstr(); 70 exit_ = new JoinEntryInstr();
71 true_exit->set_successor(exit_); 71 true_exit->SetSuccessor(exit_);
72 false_exit->set_successor(exit_); 72 false_exit->SetSuccessor(exit_);
73 } 73 }
74 } 74 }
75 75
76 76
77 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, 77 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment,
78 const EffectGraphVisitor& body_fragment) { 78 const EffectGraphVisitor& body_fragment) {
79 // We have: a test graph fragment with zero, one, or two available exits; 79 // We have: a test graph fragment with zero, one, or two available exits;
80 // and an effect graph fragment with zero or one available exits. We want 80 // and an effect graph fragment with zero or one available exits. We want
81 // to append the 'while loop' consisting of the test graph fragment as 81 // to append the 'while loop' consisting of the test graph fragment as
82 // condition and the effect graph fragment as body. 82 // condition and the effect graph fragment as body.
83 ASSERT(is_open()); 83 ASSERT(is_open());
84 84
85 // 1. Connect the body to the test if it is reachable, and if so record 85 // 1. Connect the body to the test if it is reachable, and if so record
86 // its exit (if any). 86 // its exit (if any).
87 Instruction* body_exit = NULL; 87 Instruction* body_exit = NULL;
88 if (test_fragment.can_be_true()) { 88 if (test_fragment.can_be_true()) {
89 TargetEntryInstr* body_entry = new TargetEntryInstr(); 89 TargetEntryInstr* body_entry = new TargetEntryInstr();
90 *test_fragment.true_successor_address() = body_entry; 90 *test_fragment.true_successor_address() = body_entry;
91 body_entry->set_successor(body_fragment.entry()); 91 body_entry->SetSuccessor(body_fragment.entry());
92 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); 92 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit();
93 } 93 }
94 94
95 // 2. Connect the test to this graph, including the body if reachable and 95 // 2. Connect the test to this graph, including the body if reachable and
96 // using a fresh join node if the body is reachable and has an open exit. 96 // using a fresh join node if the body is reachable and has an open exit.
97 if (body_exit == NULL) { 97 if (body_exit == NULL) {
98 Append(test_fragment); 98 Append(test_fragment);
99 } else { 99 } else {
100 JoinEntryInstr* join = new JoinEntryInstr(); 100 JoinEntryInstr* join = new JoinEntryInstr();
101 AddInstruction(join); 101 AddInstruction(join);
102 join->set_successor(test_fragment.entry()); 102 join->SetSuccessor(test_fragment.entry());
103 body_exit->set_successor(join); 103 body_exit->SetSuccessor(join);
104 } 104 }
105 105
106 // 3. Set the exit to the graph to be empty or a fresh target node 106 // 3. Set the exit to the graph to be empty or a fresh target node
107 // depending on whether the false branch of the test is reachable. 107 // depending on whether the false branch of the test is reachable.
108 if (test_fragment.can_be_false()) { 108 if (test_fragment.can_be_false()) {
109 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); 109 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr();
110 } else { 110 } else {
111 exit_ = NULL; 111 exit_ = NULL;
112 } 112 }
113 } 113 }
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 } 864 }
865 } 865 }
866 866
867 867
868 void FlowGraphBuilder::PrintGraph() const { 868 void FlowGraphBuilder::PrintGraph() const {
869 if (!FLAG_print_flow_graph || HasBailedOut()) return; 869 if (!FLAG_print_flow_graph || HasBailedOut()) return;
870 870
871 OS::Print("==== %s\n", 871 OS::Print("==== %s\n",
872 parsed_function().function().ToFullyQualifiedCString()); 872 parsed_function().function().ToFullyQualifiedCString());
873 873
874 for (intptr_t i = postorder_.length() - 1; i >= 0; --i) { 874 for (intptr_t i = postorder_block_entries_.length() - 1; i >= 0; --i) {
875 OS::Print("%8d: ", postorder_.length() - i); 875 // Print the block entry.
876 postorder_[i]->Print(i, postorder_); 876 Instruction* current = postorder_block_entries_[i]->Print();
877 // And all the successors until an exit, branch, or a block entry.
878 while (current != NULL && !current->IsBlockEntry()) {
srdjan 2012/02/22 17:41:10 More parenthesis, please
Kevin Millikin (Google) 2012/02/23 09:08:04 Thanks for the reminder.
879 OS::Print("\n");
880 current = current->Print();
881 }
882 if (current != NULL && current->IsBlockEntry()) {
883 OS::Print(" goto %d", current->GetBlockNumber());
884 }
877 OS::Print("\n"); 885 OS::Print("\n");
878 } 886 }
879 OS::Print("\n");
880 } 887 }
881 888
882 889
883 void FlowGraphBuilder::BuildGraph() { 890 void FlowGraphBuilder::BuildGraph() {
884 EffectGraphVisitor for_effect(this, 0); 891 EffectGraphVisitor for_effect(this, 0);
892 for_effect.AddInstruction(new TargetEntryInstr());
885 parsed_function().node_sequence()->Visit(&for_effect); 893 parsed_function().node_sequence()->Visit(&for_effect);
886 TraceBailout(); 894 TraceBailout();
887 if (!HasBailedOut() && (for_effect.entry() != NULL)) { 895 if (!HasBailedOut() && (for_effect.entry() != NULL)) {
888 for_effect.entry()->Postorder(&postorder_); 896 // Accumulate basic block entries via postorder traversal.
897 for_effect.entry()->Postorder(&postorder_block_entries_);
898 // Number the blocks in reverse postorder starting with 0.
899 intptr_t index = postorder_block_entries_.length() - 1;
srdjan 2012/02/22 17:41:10 AS a for loop maybe? intptr_t number = 0; for (in
Kevin Millikin (Google) 2012/02/23 09:08:04 Done.
900 intptr_t number = 0;
901 while (index >= 0) {
902 postorder_block_entries_[index--]->SetBlockNumber(number++);
903 }
889 } 904 }
890 PrintGraph(); 905 PrintGraph();
891 } 906 }
892 907
893 } // namespace dart 908 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698