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_builder.h" | 5 #include "vm/flow_graph_builder.h" |
6 | 6 |
7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 } | 44 } |
45 | 45 |
46 | 46 |
47 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { | 47 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { |
48 ASSERT(is_open()); | 48 ASSERT(is_open()); |
49 if (other_fragment.is_empty()) return; | 49 if (other_fragment.is_empty()) return; |
50 if (is_empty()) { | 50 if (is_empty()) { |
51 entry_ = other_fragment.entry(); | 51 entry_ = other_fragment.entry(); |
52 exit_ = other_fragment.exit(); | 52 exit_ = other_fragment.exit(); |
53 } else { | 53 } else { |
54 exit()->SetSuccessor(other_fragment.entry()); | 54 exit()->set_successor(other_fragment.entry()); |
55 exit_ = other_fragment.exit(); | 55 exit_ = other_fragment.exit(); |
56 } | 56 } |
57 temp_index_ = other_fragment.temp_index(); | 57 temp_index_ = other_fragment.temp_index(); |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 void EffectGraphVisitor::AddInstruction(Instruction* instruction) { | 61 void EffectGraphVisitor::AddInstruction(Instruction* instruction) { |
62 ASSERT(is_open()); | 62 ASSERT(is_open()); |
63 DeallocateTempIndex(instruction->InputCount()); | 63 DeallocateTempIndex(instruction->InputCount()); |
64 if (instruction->IsDefinition()) { | 64 if (instruction->IsDefinition()) { |
65 instruction->AsDefinition()->set_temp_index(AllocateTempIndex()); | 65 instruction->AsDefinition()->set_temp_index(AllocateTempIndex()); |
66 } | 66 } |
67 if (is_empty()) { | 67 if (is_empty()) { |
68 entry_ = exit_ = instruction; | 68 entry_ = exit_ = instruction; |
69 } else { | 69 } else { |
70 exit()->SetSuccessor(instruction); | 70 exit()->set_successor(instruction); |
71 exit_ = instruction; | 71 exit_ = instruction; |
72 } | 72 } |
73 } | 73 } |
74 | 74 |
75 | 75 |
| 76 // Appends a graph fragment to a block entry instruction and returns the exit |
| 77 // of the resulting graph fragment. |
| 78 static Instruction* AppendFragment(BlockEntryInstr* entry, |
| 79 const EffectGraphVisitor& fragment) { |
| 80 if (fragment.is_empty()) return entry; |
| 81 entry->set_successor(fragment.entry()); |
| 82 return fragment.exit(); |
| 83 } |
| 84 |
| 85 |
76 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, | 86 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, |
77 const EffectGraphVisitor& true_fragment, | 87 const EffectGraphVisitor& true_fragment, |
78 const EffectGraphVisitor& false_fragment) { | 88 const EffectGraphVisitor& false_fragment) { |
79 // We have: a test graph fragment with zero, one, or two available exits; | 89 // We have: a test graph fragment with zero, one, or two available exits; |
80 // and a pair of effect graph fragments with zero or one available exits. | 90 // and a pair of effect graph fragments with zero or one available exits. |
81 // We want to append the branch and (if necessary) a join node to this | 91 // We want to append the branch and (if necessary) a join node to this |
82 // graph fragment. | 92 // graph fragment. |
83 ASSERT(is_open()); | 93 ASSERT(is_open()); |
84 | 94 |
85 // 1. Connect the test to this graph. | 95 // 1. Connect the test to this graph. |
86 Append(test_fragment); | 96 Append(test_fragment); |
87 | 97 |
88 // 2. Connect the true and false bodies to the test and record their exits | 98 // 2. Connect the true and false bodies to the test and record their exits |
89 // (if any). | 99 // (if any). |
90 Instruction* true_exit = NULL; | |
91 Instruction* false_exit = NULL; | |
92 TargetEntryInstr* true_entry = new TargetEntryInstr(); | 100 TargetEntryInstr* true_entry = new TargetEntryInstr(); |
93 *test_fragment.true_successor_address() = true_entry; | 101 *test_fragment.true_successor_address() = true_entry; |
94 true_entry->SetSuccessor(true_fragment.entry()); | 102 Instruction* true_exit = AppendFragment(true_entry, true_fragment); |
95 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); | |
96 | 103 |
97 TargetEntryInstr* false_entry = new TargetEntryInstr(); | 104 TargetEntryInstr* false_entry = new TargetEntryInstr(); |
98 *test_fragment.false_successor_address() = false_entry; | 105 *test_fragment.false_successor_address() = false_entry; |
99 false_entry->SetSuccessor(false_fragment.entry()); | 106 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
100 false_exit = false_fragment.is_empty() ? false_entry : false_fragment.exit(); | |
101 | 107 |
102 // 3. Add a join or select one (or neither) of the arms as exit. | 108 // 3. Add a join or select one (or neither) of the arms as exit. |
103 if (true_exit == NULL) { | 109 if (true_exit == NULL) { |
104 exit_ = false_exit; // May be NULL. | 110 exit_ = false_exit; // May be NULL. |
105 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); | 111 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); |
106 } else if (false_exit == NULL) { | 112 } else if (false_exit == NULL) { |
107 exit_ = true_exit; | 113 exit_ = true_exit; |
108 temp_index_ = true_fragment.temp_index(); | 114 temp_index_ = true_fragment.temp_index(); |
109 } else { | 115 } else { |
110 exit_ = new JoinEntryInstr(); | 116 exit_ = new JoinEntryInstr(); |
111 true_exit->SetSuccessor(exit_); | 117 true_exit->set_successor(exit_); |
112 false_exit->SetSuccessor(exit_); | 118 false_exit->set_successor(exit_); |
113 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); | 119 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); |
114 temp_index_ = true_fragment.temp_index(); | 120 temp_index_ = true_fragment.temp_index(); |
115 } | 121 } |
116 } | 122 } |
117 | 123 |
118 | 124 |
119 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 125 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
120 const EffectGraphVisitor& body_fragment) { | 126 const EffectGraphVisitor& body_fragment) { |
121 // We have: a test graph fragment with zero, one, or two available exits; | 127 // We have: a test graph fragment with zero, one, or two available exits; |
122 // and an effect graph fragment with zero or one available exits. We want | 128 // and an effect graph fragment with zero or one available exits. We want |
123 // to append the 'while loop' consisting of the test graph fragment as | 129 // to append the 'while loop' consisting of the test graph fragment as |
124 // condition and the effect graph fragment as body. | 130 // condition and the effect graph fragment as body. |
125 ASSERT(is_open()); | 131 ASSERT(is_open()); |
126 | 132 |
127 // 1. Connect the body to the test if it is reachable, and if so record | 133 // 1. Connect the body to the test if it is reachable, and if so record |
128 // its exit (if any). | 134 // its exit (if any). |
129 Instruction* body_exit = NULL; | |
130 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 135 TargetEntryInstr* body_entry = new TargetEntryInstr(); |
131 *test_fragment.true_successor_address() = body_entry; | 136 *test_fragment.true_successor_address() = body_entry; |
132 body_entry->SetSuccessor(body_fragment.entry()); | 137 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
133 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); | |
134 | 138 |
135 // 2. Connect the test to this graph, including the body if reachable and | 139 // 2. Connect the test to this graph, including the body if reachable and |
136 // using a fresh join node if the body is reachable and has an open exit. | 140 // using a fresh join node if the body is reachable and has an open exit. |
137 if (body_exit == NULL) { | 141 if (body_exit == NULL) { |
138 Append(test_fragment); | 142 Append(test_fragment); |
139 } else { | 143 } else { |
140 JoinEntryInstr* join = new JoinEntryInstr(); | 144 JoinEntryInstr* join = new JoinEntryInstr(); |
141 AddInstruction(join); | 145 AddInstruction(join); |
142 join->SetSuccessor(test_fragment.entry()); | 146 join->set_successor(test_fragment.entry()); |
143 body_exit->SetSuccessor(join); | 147 body_exit->set_successor(join); |
144 } | 148 } |
145 | 149 |
146 // 3. Set the exit to the graph to be the false successor of the test, a | 150 // 3. Set the exit to the graph to be the false successor of the test, a |
147 // fresh target node | 151 // fresh target node |
148 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); | 152 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); |
149 } | 153 } |
150 | 154 |
151 | 155 |
152 Computation* EffectGraphVisitor::BuildStoreLocal( | 156 Computation* EffectGraphVisitor::BuildStoreLocal( |
153 const LocalVariable& local, Value* value) { | 157 const LocalVariable& local, Value* value) { |
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 | 1055 |
1052 // Once a test fragment has been added, this fragment is closed. | 1056 // Once a test fragment has been added, this fragment is closed. |
1053 ASSERT(!is_open()); | 1057 ASSERT(!is_open()); |
1054 | 1058 |
1055 // Connect all test cases except the last one. | 1059 // Connect all test cases except the last one. |
1056 for (intptr_t i = 0; i < (len - 1); i++) { | 1060 for (intptr_t i = 0; i < (len - 1); i++) { |
1057 ASSERT(needs_join_at_statement_entry); | 1061 ASSERT(needs_join_at_statement_entry); |
1058 *case_false_addresses[i] = case_entries[i + 1]; | 1062 *case_false_addresses[i] = case_entries[i + 1]; |
1059 TargetEntryInstr* true_target = new TargetEntryInstr(); | 1063 TargetEntryInstr* true_target = new TargetEntryInstr(); |
1060 *case_true_addresses[i] = true_target; | 1064 *case_true_addresses[i] = true_target; |
1061 true_target->SetSuccessor(statement_start); | 1065 true_target->set_successor(statement_start); |
1062 } | 1066 } |
1063 | 1067 |
1064 BlockEntryInstr* exit_instruction = NULL; | 1068 BlockEntryInstr* exit_instruction = NULL; |
1065 // Handle last (or only) case: false goes to exit or to statement if this | 1069 // Handle last (or only) case: false goes to exit or to statement if this |
1066 // node contains default. | 1070 // node contains default. |
1067 if (len > 0) { | 1071 if (len > 0) { |
1068 if (statement_start->IsTargetEntry()) { | 1072 if (statement_start->IsTargetEntry()) { |
1069 *case_true_addresses[len - 1] = statement_start->AsTargetEntry(); | 1073 *case_true_addresses[len - 1] = statement_start->AsTargetEntry(); |
1070 } else { | 1074 } else { |
1071 TargetEntryInstr* true_target = new TargetEntryInstr(); | 1075 TargetEntryInstr* true_target = new TargetEntryInstr(); |
1072 *case_true_addresses[len - 1] = true_target; | 1076 *case_true_addresses[len - 1] = true_target; |
1073 true_target->SetSuccessor(statement_start); | 1077 true_target->set_successor(statement_start); |
1074 } | 1078 } |
1075 TargetEntryInstr* false_target = new TargetEntryInstr(); | 1079 TargetEntryInstr* false_target = new TargetEntryInstr(); |
1076 *case_false_addresses[len - 1] = false_target; | 1080 *case_false_addresses[len - 1] = false_target; |
1077 if (node->contains_default()) { | 1081 if (node->contains_default()) { |
1078 // True and false go to statement start. | 1082 // True and false go to statement start. |
1079 false_target->SetSuccessor(statement_start); | 1083 false_target->set_successor(statement_start); |
1080 if (for_case_statements.is_open()) { | 1084 if (for_case_statements.is_open()) { |
1081 exit_instruction = new TargetEntryInstr(); | 1085 exit_instruction = new TargetEntryInstr(); |
1082 for_case_statements.exit()->SetSuccessor(exit_instruction); | 1086 for_case_statements.exit()->set_successor(exit_instruction); |
1083 } | 1087 } |
1084 } else { | 1088 } else { |
1085 if (for_case_statements.is_open()) { | 1089 if (for_case_statements.is_open()) { |
1086 exit_instruction = new JoinEntryInstr(); | 1090 exit_instruction = new JoinEntryInstr(); |
1087 for_case_statements.exit()->SetSuccessor(exit_instruction); | 1091 for_case_statements.exit()->set_successor(exit_instruction); |
1088 } else { | 1092 } else { |
1089 exit_instruction = new TargetEntryInstr(); | 1093 exit_instruction = new TargetEntryInstr(); |
1090 } | 1094 } |
1091 false_target->SetSuccessor(exit_instruction); | 1095 false_target->set_successor(exit_instruction); |
1092 } | 1096 } |
1093 } else { | 1097 } else { |
1094 // A CaseNode without case expressions must contain default. | 1098 // A CaseNode without case expressions must contain default. |
1095 ASSERT(node->contains_default()); | 1099 ASSERT(node->contains_default()); |
1096 AddInstruction(statement_start); | 1100 AddInstruction(statement_start); |
1097 } | 1101 } |
1098 | 1102 |
1099 ASSERT(!is_open()); | 1103 ASSERT(!is_open()); |
1100 exit_ = exit_instruction; | 1104 exit_ = exit_instruction; |
1101 } | 1105 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 | 1160 |
1157 TestGraphVisitor for_test(owner(), | 1161 TestGraphVisitor for_test(owner(), |
1158 temp_index(), | 1162 temp_index(), |
1159 node->condition()->token_pos()); | 1163 node->condition()->token_pos()); |
1160 node->condition()->Visit(&for_test); | 1164 node->condition()->Visit(&for_test); |
1161 ASSERT(is_open()); | 1165 ASSERT(is_open()); |
1162 | 1166 |
1163 // Tie do-while loop (test is after the body). | 1167 // Tie do-while loop (test is after the body). |
1164 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); | 1168 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); |
1165 AddInstruction(body_entry_join); | 1169 AddInstruction(body_entry_join); |
1166 body_entry_join->SetSuccessor(for_body.entry()); | 1170 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
1167 Instruction* body_exit = | |
1168 for_body.is_empty() ? body_entry_join : for_body.exit(); | |
1169 | 1171 |
1170 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { | 1172 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { |
1171 BlockEntryInstr* test_entry = NULL; | 1173 BlockEntryInstr* test_entry = NULL; |
1172 if (node->label()->join_for_continue() == NULL) { | 1174 if (node->label()->join_for_continue() == NULL) { |
1173 test_entry = new TargetEntryInstr(); | 1175 test_entry = new TargetEntryInstr(); |
1174 } else { | 1176 } else { |
1175 test_entry = node->label()->join_for_continue(); | 1177 test_entry = node->label()->join_for_continue(); |
1176 } | 1178 } |
1177 test_entry->SetSuccessor(for_test.entry()); | 1179 test_entry->set_successor(for_test.entry()); |
1178 if (body_exit != NULL) { | 1180 if (body_exit != NULL) { |
1179 body_exit->SetSuccessor(test_entry); | 1181 body_exit->set_successor(test_entry); |
1180 } | 1182 } |
1181 } | 1183 } |
1182 | 1184 |
1183 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); | 1185 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); |
1184 *for_test.true_successor_address() = back_target_entry; | 1186 *for_test.true_successor_address() = back_target_entry; |
1185 back_target_entry->SetSuccessor(body_entry_join); | 1187 back_target_entry->set_successor(body_entry_join); |
1186 TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); | 1188 TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); |
1187 *for_test.false_successor_address() = loop_exit_target; | 1189 *for_test.false_successor_address() = loop_exit_target; |
1188 if (node->label()->join_for_break() == NULL) { | 1190 if (node->label()->join_for_break() == NULL) { |
1189 exit_ = loop_exit_target; | 1191 exit_ = loop_exit_target; |
1190 } else { | 1192 } else { |
1191 loop_exit_target->SetSuccessor(node->label()->join_for_break()); | 1193 loop_exit_target->set_successor(node->label()->join_for_break()); |
1192 exit_ = node->label()->join_for_break(); | 1194 exit_ = node->label()->join_for_break(); |
1193 } | 1195 } |
1194 } | 1196 } |
1195 | 1197 |
1196 | 1198 |
1197 // A ForNode can contain break and continue jumps. 'break' joins to | 1199 // A ForNode can contain break and continue jumps. 'break' joins to |
1198 // ForNode exit, 'continue' joins at increment entry. The fragment is composed | 1200 // ForNode exit, 'continue' joins at increment entry. The fragment is composed |
1199 // as follows: | 1201 // as follows: |
1200 // a) [ initializer ] | 1202 // a) [ initializer ] |
1201 // b) loop-join | 1203 // b) loop-join |
(...skipping 26 matching lines...) Expand all Loading... |
1228 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { | 1230 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { |
1229 // Do not insert an extra basic block. | 1231 // Do not insert an extra basic block. |
1230 node->increment()->Visit(&for_increment); | 1232 node->increment()->Visit(&for_increment); |
1231 for_body.Append(for_increment); | 1233 for_body.Append(for_increment); |
1232 loop_increment_end = for_body.exit(); | 1234 loop_increment_end = for_body.exit(); |
1233 // 'for_body' contains at least the TargetInstruction 'body_entry'. | 1235 // 'for_body' contains at least the TargetInstruction 'body_entry'. |
1234 ASSERT(loop_increment_end != NULL); | 1236 ASSERT(loop_increment_end != NULL); |
1235 } else if (node->label()->join_for_continue() != NULL) { | 1237 } else if (node->label()->join_for_continue() != NULL) { |
1236 // Insert join between body and increment. | 1238 // Insert join between body and increment. |
1237 if (for_body.is_open()) { | 1239 if (for_body.is_open()) { |
1238 for_body.exit()->SetSuccessor(node->label()->join_for_continue()); | 1240 for_body.exit()->set_successor(node->label()->join_for_continue()); |
1239 } | 1241 } |
1240 for_increment.AddInstruction(node->label()->join_for_continue()); | 1242 for_increment.AddInstruction(node->label()->join_for_continue()); |
1241 node->increment()->Visit(&for_increment); | 1243 node->increment()->Visit(&for_increment); |
1242 loop_increment_end = for_increment.exit(); | 1244 loop_increment_end = for_increment.exit(); |
1243 ASSERT(loop_increment_end != NULL); | 1245 ASSERT(loop_increment_end != NULL); |
1244 } else { | 1246 } else { |
1245 loop_increment_end = NULL; | 1247 loop_increment_end = NULL; |
1246 ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL); | 1248 ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL); |
1247 } | 1249 } |
1248 | 1250 |
1249 // 'loop_increment_end' is NULL only if there is no join for continue and the | 1251 // 'loop_increment_end' is NULL only if there is no join for continue and the |
1250 // body is not open, i.e., no backward branch exists. | 1252 // body is not open, i.e., no backward branch exists. |
1251 if (loop_increment_end != NULL) { | 1253 if (loop_increment_end != NULL) { |
1252 JoinEntryInstr* loop_start = new JoinEntryInstr(); | 1254 JoinEntryInstr* loop_start = new JoinEntryInstr(); |
1253 AddInstruction(loop_start); | 1255 AddInstruction(loop_start); |
1254 loop_increment_end->SetSuccessor(loop_start); | 1256 loop_increment_end->set_successor(loop_start); |
1255 } | 1257 } |
1256 | 1258 |
1257 if (node->condition() == NULL) { | 1259 if (node->condition() == NULL) { |
1258 // Endless loop, no test. | 1260 // Endless loop, no test. |
1259 Append(for_body); | 1261 Append(for_body); |
1260 if (node->label()->join_for_break() == NULL) { | 1262 if (node->label()->join_for_break() == NULL) { |
1261 CloseFragment(); | 1263 CloseFragment(); |
1262 } else { | 1264 } else { |
1263 // Control flow of ForLoop continues into join_for_break. | 1265 // Control flow of ForLoop continues into join_for_break. |
1264 exit_ = node->label()->join_for_break(); | 1266 exit_ = node->label()->join_for_break(); |
1265 } | 1267 } |
1266 } else { | 1268 } else { |
1267 TargetEntryInstr* loop_exit = new TargetEntryInstr(); | 1269 TargetEntryInstr* loop_exit = new TargetEntryInstr(); |
1268 TestGraphVisitor for_test(owner(), | 1270 TestGraphVisitor for_test(owner(), |
1269 temp_index(), | 1271 temp_index(), |
1270 node->condition()->token_pos()); | 1272 node->condition()->token_pos()); |
1271 node->condition()->Visit(&for_test); | 1273 node->condition()->Visit(&for_test); |
1272 Append(for_test); | 1274 Append(for_test); |
1273 *for_test.true_successor_address() = body_entry; | 1275 *for_test.true_successor_address() = body_entry; |
1274 *for_test.false_successor_address() = loop_exit; | 1276 *for_test.false_successor_address() = loop_exit; |
1275 if (node->label()->join_for_break() == NULL) { | 1277 if (node->label()->join_for_break() == NULL) { |
1276 exit_ = loop_exit; | 1278 exit_ = loop_exit; |
1277 } else { | 1279 } else { |
1278 loop_exit->SetSuccessor(node->label()->join_for_break()); | 1280 loop_exit->set_successor(node->label()->join_for_break()); |
1279 exit_ = node->label()->join_for_break(); | 1281 exit_ = node->label()->join_for_break(); |
1280 } | 1282 } |
1281 } | 1283 } |
1282 } | 1284 } |
1283 | 1285 |
1284 | 1286 |
1285 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 1287 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
1286 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1288 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
1287 EffectGraphVisitor for_effect(owner(), temp_index()); | 1289 EffectGraphVisitor for_effect(owner(), temp_index()); |
1288 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 1290 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
(...skipping 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2381 &postorder_block_entries_, | 2383 &postorder_block_entries_, |
2382 &parent, | 2384 &parent, |
2383 &assigned_vars, | 2385 &assigned_vars, |
2384 variable_count); | 2386 variable_count); |
2385 // Number blocks in reverse postorder. | 2387 // Number blocks in reverse postorder. |
2386 intptr_t block_count = postorder_block_entries_.length(); | 2388 intptr_t block_count = postorder_block_entries_.length(); |
2387 for (intptr_t i = 0; i < block_count; ++i) { | 2389 for (intptr_t i = 0; i < block_count; ++i) { |
2388 postorder_block_entries_[i]->set_block_id(block_count - i - 1); | 2390 postorder_block_entries_[i]->set_block_id(block_count - i - 1); |
2389 } | 2391 } |
2390 if (for_optimized && use_ssa) { | 2392 if (for_optimized && use_ssa) { |
| 2393 // Link instructions backwards for optimized compilation. |
| 2394 for (intptr_t i = 0; i < block_count; ++i) { |
| 2395 Instruction* prev = postorder_block_entries_[i]; |
| 2396 Instruction* current = prev->successor(); |
| 2397 while (current != NULL && !current->IsBlockEntry()) { |
| 2398 current->set_previous(prev); |
| 2399 prev = current; |
| 2400 current = current->successor(); |
| 2401 } |
| 2402 } |
2391 GrowableArray<BitVector*> dominance_frontier; | 2403 GrowableArray<BitVector*> dominance_frontier; |
2392 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); | 2404 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); |
2393 InsertPhis(preorder_block_entries_, | 2405 InsertPhis(preorder_block_entries_, |
2394 assigned_vars, | 2406 assigned_vars, |
2395 variable_count, | 2407 variable_count, |
2396 dominance_frontier); | 2408 dominance_frontier); |
2397 Rename(variable_count); | 2409 Rename(variable_count); |
2398 } | 2410 } |
2399 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { | 2411 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { |
2400 intptr_t length = postorder_block_entries_.length(); | 2412 intptr_t length = postorder_block_entries_.length(); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2648 PhiInstr* phi = (*join->phis())[i]; | 2660 PhiInstr* phi = (*join->phis())[i]; |
2649 if (phi != NULL) { | 2661 if (phi != NULL) { |
2650 (*env)[i] = new UseVal(phi); | 2662 (*env)[i] = new UseVal(phi); |
2651 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. | 2663 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. |
2652 } | 2664 } |
2653 } | 2665 } |
2654 } | 2666 } |
2655 } | 2667 } |
2656 | 2668 |
2657 // 2. Process normal instructions. | 2669 // 2. Process normal instructions. |
2658 Instruction* current = block_entry->StraightLineSuccessor(); | 2670 Instruction* current = block_entry->successor(); |
2659 Instruction* prev = block_entry; | |
2660 while ((current != NULL) && !current->IsBlockEntry()) { | 2671 while ((current != NULL) && !current->IsBlockEntry()) { |
2661 // 2a. Handle uses of LoadLocal / StoreLocal | 2672 // 2a. Handle uses of LoadLocal / StoreLocal |
2662 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 2673 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
2663 // from the environment. | 2674 // from the environment. |
2664 for (intptr_t i = 0; i < current->InputCount(); ++i) { | 2675 for (intptr_t i = 0; i < current->InputCount(); ++i) { |
2665 Value* v = current->InputAt(i); | 2676 Value* v = current->InputAt(i); |
2666 if (v->IsUse() && | 2677 if (v->IsUse() && |
2667 v->AsUse()->definition()->IsBind() && | 2678 v->AsUse()->definition()->IsBind() && |
2668 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { | 2679 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { |
2669 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2680 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2705 if (current->IsDo() && | 2716 if (current->IsDo() && |
2706 current->AsDo()->computation()->IsStoreLocal()) { | 2717 current->AsDo()->computation()->IsStoreLocal()) { |
2707 store = current->AsDo()->computation()->AsStoreLocal(); | 2718 store = current->AsDo()->computation()->AsStoreLocal(); |
2708 } else if (current->IsBind() && | 2719 } else if (current->IsBind() && |
2709 current->AsBind()->computation()->IsStoreLocal()) { | 2720 current->AsBind()->computation()->IsStoreLocal()) { |
2710 store = current->AsBind()->computation()->AsStoreLocal(); | 2721 store = current->AsBind()->computation()->AsStoreLocal(); |
2711 } | 2722 } |
2712 | 2723 |
2713 if (load != NULL) { | 2724 if (load != NULL) { |
2714 // Remove instruction. | 2725 // Remove instruction. |
2715 prev->SetSuccessor(current->StraightLineSuccessor()); | 2726 current->RemoveFromGraph(); |
2716 } else if (store != NULL) { | 2727 } else if (store != NULL) { |
2717 // Remove instruction and update renaming environment. | 2728 // Remove instruction and update renaming environment. |
2718 prev->SetSuccessor(current->StraightLineSuccessor()); | 2729 current->RemoveFromGraph(); |
2719 (*env)[store->local().BitIndexIn(var_count)] = store->value(); | 2730 (*env)[store->local().BitIndexIn(var_count)] = store->value(); |
2720 } else { | 2731 } else if (current->IsBind()) { |
2721 // Assign new SSA temporary. | 2732 // Assign new SSA temporary. |
2722 if (current->IsBind()) { | 2733 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); |
2723 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); | |
2724 } | |
2725 // Update previous only if no instruction was removed from the graph. | |
2726 prev = current; | |
2727 } | 2734 } |
2728 current = current->StraightLineSuccessor(); | 2735 current = current->successor(); |
2729 } | 2736 } |
2730 | 2737 |
2731 // 3. Process dominated blocks. | 2738 // 3. Process dominated blocks. |
2732 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { | 2739 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { |
2733 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; | 2740 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; |
2734 ZoneGrowableArray<Value*>* new_env = | 2741 ZoneGrowableArray<Value*>* new_env = |
2735 new ZoneGrowableArray<Value*>(var_count); | 2742 new ZoneGrowableArray<Value*>(var_count); |
2736 new_env->AddArray(*env); | 2743 new_env->AddArray(*env); |
2737 RenameRecursive(block, new_env, var_count); | 2744 RenameRecursive(block, new_env, var_count); |
2738 } | 2745 } |
(...skipping 28 matching lines...) Expand all Loading... |
2767 char* chars = reinterpret_cast<char*>( | 2774 char* chars = reinterpret_cast<char*>( |
2768 Isolate::Current()->current_zone()->Allocate(len)); | 2775 Isolate::Current()->current_zone()->Allocate(len)); |
2769 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2776 OS::SNPrint(chars, len, kFormat, function_name, reason); |
2770 const Error& error = Error::Handle( | 2777 const Error& error = Error::Handle( |
2771 LanguageError::New(String::Handle(String::New(chars)))); | 2778 LanguageError::New(String::Handle(String::New(chars)))); |
2772 Isolate::Current()->long_jump_base()->Jump(1, error); | 2779 Isolate::Current()->long_jump_base()->Jump(1, error); |
2773 } | 2780 } |
2774 | 2781 |
2775 | 2782 |
2776 } // namespace dart | 2783 } // namespace dart |
OLD | NEW |