Index: vm/flow_graph_builder.cc |
=================================================================== |
--- vm/flow_graph_builder.cc (revision 9281) |
+++ vm/flow_graph_builder.cc (working copy) |
@@ -51,7 +51,7 @@ |
entry_ = other_fragment.entry(); |
exit_ = other_fragment.exit(); |
} else { |
- exit()->SetSuccessor(other_fragment.entry()); |
+ exit()->set_successor(other_fragment.entry()); |
exit_ = other_fragment.exit(); |
} |
temp_index_ = other_fragment.temp_index(); |
@@ -67,12 +67,22 @@ |
if (is_empty()) { |
entry_ = exit_ = instruction; |
} else { |
- exit()->SetSuccessor(instruction); |
+ exit()->set_successor(instruction); |
exit_ = instruction; |
} |
} |
+// Appends a graph fragment to a block entry instruction and returns the exit |
+// of the resulting graph fragment. |
+static Instruction* AppendFragment(BlockEntryInstr* entry, |
+ const EffectGraphVisitor& fragment) { |
+ if (fragment.is_empty()) return entry; |
+ entry->set_successor(fragment.entry()); |
+ return fragment.exit(); |
+} |
+ |
+ |
void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, |
const EffectGraphVisitor& true_fragment, |
const EffectGraphVisitor& false_fragment) { |
@@ -87,17 +97,13 @@ |
// 2. Connect the true and false bodies to the test and record their exits |
// (if any). |
- Instruction* true_exit = NULL; |
- Instruction* false_exit = NULL; |
TargetEntryInstr* true_entry = new TargetEntryInstr(); |
*test_fragment.true_successor_address() = true_entry; |
- true_entry->SetSuccessor(true_fragment.entry()); |
- true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); |
+ Instruction* true_exit = AppendFragment(true_entry, true_fragment); |
TargetEntryInstr* false_entry = new TargetEntryInstr(); |
*test_fragment.false_successor_address() = false_entry; |
- false_entry->SetSuccessor(false_fragment.entry()); |
- false_exit = false_fragment.is_empty() ? false_entry : false_fragment.exit(); |
+ Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
// 3. Add a join or select one (or neither) of the arms as exit. |
if (true_exit == NULL) { |
@@ -108,8 +114,8 @@ |
temp_index_ = true_fragment.temp_index(); |
} else { |
exit_ = new JoinEntryInstr(); |
- true_exit->SetSuccessor(exit_); |
- false_exit->SetSuccessor(exit_); |
+ true_exit->set_successor(exit_); |
+ false_exit->set_successor(exit_); |
ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); |
temp_index_ = true_fragment.temp_index(); |
} |
@@ -126,11 +132,9 @@ |
// 1. Connect the body to the test if it is reachable, and if so record |
// its exit (if any). |
- Instruction* body_exit = NULL; |
TargetEntryInstr* body_entry = new TargetEntryInstr(); |
*test_fragment.true_successor_address() = body_entry; |
- body_entry->SetSuccessor(body_fragment.entry()); |
- body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); |
+ Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
// 2. Connect the test to this graph, including the body if reachable and |
// using a fresh join node if the body is reachable and has an open exit. |
@@ -139,8 +143,8 @@ |
} else { |
JoinEntryInstr* join = new JoinEntryInstr(); |
AddInstruction(join); |
- join->SetSuccessor(test_fragment.entry()); |
- body_exit->SetSuccessor(join); |
+ join->set_successor(test_fragment.entry()); |
+ body_exit->set_successor(join); |
} |
// 3. Set the exit to the graph to be the false successor of the test, a |
@@ -1058,7 +1062,7 @@ |
*case_false_addresses[i] = case_entries[i + 1]; |
TargetEntryInstr* true_target = new TargetEntryInstr(); |
*case_true_addresses[i] = true_target; |
- true_target->SetSuccessor(statement_start); |
+ true_target->set_successor(statement_start); |
} |
BlockEntryInstr* exit_instruction = NULL; |
@@ -1070,25 +1074,25 @@ |
} else { |
TargetEntryInstr* true_target = new TargetEntryInstr(); |
*case_true_addresses[len - 1] = true_target; |
- true_target->SetSuccessor(statement_start); |
+ true_target->set_successor(statement_start); |
} |
TargetEntryInstr* false_target = new TargetEntryInstr(); |
*case_false_addresses[len - 1] = false_target; |
if (node->contains_default()) { |
// True and false go to statement start. |
- false_target->SetSuccessor(statement_start); |
+ false_target->set_successor(statement_start); |
if (for_case_statements.is_open()) { |
exit_instruction = new TargetEntryInstr(); |
- for_case_statements.exit()->SetSuccessor(exit_instruction); |
+ for_case_statements.exit()->set_successor(exit_instruction); |
} |
} else { |
if (for_case_statements.is_open()) { |
exit_instruction = new JoinEntryInstr(); |
- for_case_statements.exit()->SetSuccessor(exit_instruction); |
+ for_case_statements.exit()->set_successor(exit_instruction); |
} else { |
exit_instruction = new TargetEntryInstr(); |
} |
- false_target->SetSuccessor(exit_instruction); |
+ false_target->set_successor(exit_instruction); |
} |
} else { |
// A CaseNode without case expressions must contain default. |
@@ -1163,9 +1167,7 @@ |
// Tie do-while loop (test is after the body). |
JoinEntryInstr* body_entry_join = new JoinEntryInstr(); |
AddInstruction(body_entry_join); |
- body_entry_join->SetSuccessor(for_body.entry()); |
- Instruction* body_exit = |
- for_body.is_empty() ? body_entry_join : for_body.exit(); |
+ Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { |
BlockEntryInstr* test_entry = NULL; |
@@ -1174,21 +1176,21 @@ |
} else { |
test_entry = node->label()->join_for_continue(); |
} |
- test_entry->SetSuccessor(for_test.entry()); |
+ test_entry->set_successor(for_test.entry()); |
if (body_exit != NULL) { |
- body_exit->SetSuccessor(test_entry); |
+ body_exit->set_successor(test_entry); |
} |
} |
TargetEntryInstr* back_target_entry = new TargetEntryInstr(); |
*for_test.true_successor_address() = back_target_entry; |
- back_target_entry->SetSuccessor(body_entry_join); |
+ back_target_entry->set_successor(body_entry_join); |
TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); |
*for_test.false_successor_address() = loop_exit_target; |
if (node->label()->join_for_break() == NULL) { |
exit_ = loop_exit_target; |
} else { |
- loop_exit_target->SetSuccessor(node->label()->join_for_break()); |
+ loop_exit_target->set_successor(node->label()->join_for_break()); |
exit_ = node->label()->join_for_break(); |
} |
} |
@@ -1235,7 +1237,7 @@ |
} else if (node->label()->join_for_continue() != NULL) { |
// Insert join between body and increment. |
if (for_body.is_open()) { |
- for_body.exit()->SetSuccessor(node->label()->join_for_continue()); |
+ for_body.exit()->set_successor(node->label()->join_for_continue()); |
} |
for_increment.AddInstruction(node->label()->join_for_continue()); |
node->increment()->Visit(&for_increment); |
@@ -1251,7 +1253,7 @@ |
if (loop_increment_end != NULL) { |
JoinEntryInstr* loop_start = new JoinEntryInstr(); |
AddInstruction(loop_start); |
- loop_increment_end->SetSuccessor(loop_start); |
+ loop_increment_end->set_successor(loop_start); |
} |
if (node->condition() == NULL) { |
@@ -1275,7 +1277,7 @@ |
if (node->label()->join_for_break() == NULL) { |
exit_ = loop_exit; |
} else { |
- loop_exit->SetSuccessor(node->label()->join_for_break()); |
+ loop_exit->set_successor(node->label()->join_for_break()); |
exit_ = node->label()->join_for_break(); |
} |
} |
@@ -2388,6 +2390,16 @@ |
postorder_block_entries_[i]->set_block_id(block_count - i - 1); |
} |
if (for_optimized && use_ssa) { |
+ // Link instructions backwards for optimized compilation. |
+ for (intptr_t i = 0; i < block_count; ++i) { |
+ Instruction* prev = postorder_block_entries_[i]; |
+ Instruction* current = prev->successor(); |
+ while (current != NULL && !current->IsBlockEntry()) { |
+ current->set_previous(prev); |
+ prev = current; |
+ current = current->successor(); |
+ } |
+ } |
GrowableArray<BitVector*> dominance_frontier; |
ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); |
InsertPhis(preorder_block_entries_, |
@@ -2655,8 +2667,7 @@ |
} |
// 2. Process normal instructions. |
- Instruction* current = block_entry->StraightLineSuccessor(); |
- Instruction* prev = block_entry; |
+ Instruction* current = block_entry->successor(); |
while ((current != NULL) && !current->IsBlockEntry()) { |
// 2a. Handle uses of LoadLocal / StoreLocal |
// For each use of a LoadLocal or StoreLocal: Replace it with the value |
@@ -2712,20 +2723,16 @@ |
if (load != NULL) { |
// Remove instruction. |
- prev->SetSuccessor(current->StraightLineSuccessor()); |
+ current->RemoveFromGraph(); |
} else if (store != NULL) { |
// Remove instruction and update renaming environment. |
- prev->SetSuccessor(current->StraightLineSuccessor()); |
+ current->RemoveFromGraph(); |
(*env)[store->local().BitIndexIn(var_count)] = store->value(); |
- } else { |
+ } else if (current->IsBind()) { |
// Assign new SSA temporary. |
- if (current->IsBind()) { |
- current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); |
- } |
- // Update previous only if no instruction was removed from the graph. |
- prev = current; |
+ current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); |
} |
- current = current->StraightLineSuccessor(); |
+ current = current->successor(); |
} |
// 3. Process dominated blocks. |