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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 // Insert the callee graph into the caller graph. First sort the list of | 126 // Insert the callee graph into the caller graph. First sort the list of |
127 // exits by block id (recording block entries as a side effect). | 127 // exits by block id (recording block entries as a side effect). |
128 SortExits(); | 128 SortExits(); |
129 intptr_t num_exits = exits_.length(); | 129 intptr_t num_exits = exits_.length(); |
130 if (num_exits == 0) { | 130 if (num_exits == 0) { |
131 // TODO(zerny): Add support for non-local exits, such as throw. | 131 // TODO(zerny): Add support for non-local exits, such as throw. |
132 UNREACHABLE(); | 132 UNREACHABLE(); |
133 } else if (num_exits == 1) { | 133 } else if (num_exits == 1) { |
134 // For just one exit, replace the uses and remove the call from the graph. | 134 // For just one exit, replace the uses and remove the call from the graph. |
135 call->ReplaceUsesWith(ValueAt(0)->definition()); | 135 call->ReplaceUsesWith(ValueAt(0)->definition()); |
136 ValueAt(0)->RemoveFromUseList(); | 136 ReturnAt(0)->UnuseAllInputs(); |
137 call->previous()->LinkTo(callee_entry->next()); | 137 call->previous()->LinkTo(callee_entry->next()); |
138 LastInstructionAt(0)->LinkTo(call->next()); | 138 LastInstructionAt(0)->LinkTo(call->next()); |
139 // In case of control flow, locally update the predecessors, phis and | 139 // In case of control flow, locally update the predecessors, phis and |
140 // dominator tree. | 140 // dominator tree. |
141 // TODO(zerny): should we leave the dominator tree since we recompute it | 141 // TODO(zerny): should we leave the dominator tree since we recompute it |
142 // after a full inlining pass? | 142 // after a full inlining pass? |
143 if (callee_graph->preorder().length() > 2) { | 143 if (callee_graph->preorder().length() > 2) { |
144 BlockEntryInstr* exit_block = ExitBlockAt(0); | 144 BlockEntryInstr* exit_block = ExitBlockAt(0); |
145 // Pictorially, the graph structure is: | 145 // Pictorially, the graph structure is: |
146 // | 146 // |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 block->set_dominator(caller_entry); | 179 block->set_dominator(caller_entry); |
180 caller_entry->AddDominatedBlock(block); | 180 caller_entry->AddDominatedBlock(block); |
181 } | 181 } |
182 } | 182 } |
183 } else { | 183 } else { |
184 // Create a join of the returns. | 184 // Create a join of the returns. |
185 intptr_t join_id = caller_graph->max_block_id() + 1; | 185 intptr_t join_id = caller_graph->max_block_id() + 1; |
186 caller_graph->set_max_block_id(join_id); | 186 caller_graph->set_max_block_id(join_id); |
187 JoinEntryInstr* join = | 187 JoinEntryInstr* join = |
188 new JoinEntryInstr(join_id, CatchClauseNode::kInvalidTryIndex); | 188 new JoinEntryInstr(join_id, CatchClauseNode::kInvalidTryIndex); |
| 189 join->InheritDeoptTarget(call); |
189 for (intptr_t i = 0; i < num_exits; ++i) { | 190 for (intptr_t i = 0; i < num_exits; ++i) { |
190 LastInstructionAt(i)->Goto(join); | 191 GotoInstr* goto_instr = new GotoInstr(join); |
| 192 goto_instr->InheritDeoptTarget(ReturnAt(i)); |
| 193 LastInstructionAt(i)->LinkTo(goto_instr); |
191 // Directly add the predecessors of the join in ascending block id order. | 194 // Directly add the predecessors of the join in ascending block id order. |
192 join->predecessors_.Add(ExitBlockAt(i)); | 195 join->predecessors_.Add(ExitBlockAt(i)); |
193 } | 196 } |
194 // If the call has uses, create a phi of the returns. | 197 // If the call has uses, create a phi of the returns. |
195 if (call->HasUses()) { | 198 if (call->HasUses()) { |
196 // Add a phi of the return values. | 199 // Add a phi of the return values. |
197 PhiInstr* phi = new PhiInstr(join, num_exits); | 200 PhiInstr* phi = new PhiInstr(join, num_exits); |
198 phi->set_ssa_temp_index(caller_graph->alloc_ssa_temp_index()); | 201 phi->set_ssa_temp_index(caller_graph->alloc_ssa_temp_index()); |
199 phi->mark_alive(); | 202 phi->mark_alive(); |
200 for (intptr_t i = 0; i < num_exits; ++i) { | 203 for (intptr_t i = 0; i < num_exits; ++i) { |
| 204 ReturnAt(i)->RemoveEnvironment(); |
201 phi->SetInputAt(i, ValueAt(i)); | 205 phi->SetInputAt(i, ValueAt(i)); |
202 } | 206 } |
203 join->InsertPhi(phi); | 207 join->InsertPhi(phi); |
204 // Replace uses of the call with the phi. | 208 // Replace uses of the call with the phi. |
205 call->ReplaceUsesWith(phi); | 209 call->ReplaceUsesWith(phi); |
206 } else { | 210 } else { |
207 // In the case that the result is unused, remove the return value uses | 211 // In the case that the result is unused, remove the return value uses |
208 // from their definition's use list. | 212 // from their definition's use list. |
209 for (intptr_t i = 0; i < num_exits; ++i) { | 213 for (intptr_t i = 0; i < num_exits; ++i) { |
210 ValueAt(i)->RemoveFromUseList(); | 214 ReturnAt(i)->UnuseAllInputs(); |
211 } | 215 } |
212 } | 216 } |
213 // Remove the call from the graph. | 217 // Remove the call from the graph. |
214 call->previous()->LinkTo(callee_entry->next()); | 218 call->previous()->LinkTo(callee_entry->next()); |
215 join->LinkTo(call->next()); | 219 join->LinkTo(call->next()); |
216 // Replace the blocks after splitting (see comment in the len=1 case above). | 220 // Replace the blocks after splitting (see comment in the len=1 case above). |
217 caller_entry->ReplaceAsPredecessorWith(join); | 221 caller_entry->ReplaceAsPredecessorWith(join); |
218 callee_entry->ReplaceAsPredecessorWith(caller_entry); | 222 callee_entry->ReplaceAsPredecessorWith(caller_entry); |
219 // Update the last instruction pointers on each exit block to the new goto. | 223 // Update the last instruction pointers on each exit block to the new goto. |
220 for (intptr_t i = 0; i < num_exits; ++i) { | 224 for (intptr_t i = 0; i < num_exits; ++i) { |
(...skipping 3123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3344 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 3348 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
3345 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 3349 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
3346 OS::SNPrint(chars, len, kFormat, function_name, reason); | 3350 OS::SNPrint(chars, len, kFormat, function_name, reason); |
3347 const Error& error = Error::Handle( | 3351 const Error& error = Error::Handle( |
3348 LanguageError::New(String::Handle(String::New(chars)))); | 3352 LanguageError::New(String::Handle(String::New(chars)))); |
3349 Isolate::Current()->long_jump_base()->Jump(1, error); | 3353 Isolate::Current()->long_jump_base()->Jump(1, error); |
3350 } | 3354 } |
3351 | 3355 |
3352 | 3356 |
3353 } // namespace dart | 3357 } // namespace dart |
OLD | NEW |