Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index deba33399d1eb25c934b407bce8d2e979da82926..feb3b2ccb91f9969fdf922bcbe089a402f92806f 100644 |
--- a/runtime/vm/flow_graph_optimizer.cc |
+++ b/runtime/vm/flow_graph_optimizer.cc |
@@ -1830,7 +1830,8 @@ void FlowGraphOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { |
new Value(instantiator), |
new Value(type_args), |
type, |
- negate); |
+ negate, |
+ call->deopt_id()); |
ReplaceCall(call, instance_of); |
} |
@@ -1870,6 +1871,10 @@ void FlowGraphOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { |
new Value(type_args), |
type, |
dst_name); |
+ // Newly inserted instructions that can deoptimize or throw an exception |
+ // must have a deoptimization id that is valid for lookup in the unoptimized |
+ // code. |
+ assert_as->deopt_id_ = call->deopt_id(); |
ReplaceCall(call, assert_as); |
} |
@@ -4365,6 +4370,7 @@ void ConstantPropagator::Transform() { |
it.Current()->UnuseAllInputs(); |
} |
} |
+ block->UnuseAllInputs(); |
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
it.Current()->UnuseAllInputs(); |
} |
@@ -4457,11 +4463,15 @@ void ConstantPropagator::Transform() { |
ASSERT(if_false->parallel_move() == NULL); |
ASSERT(if_false->loop_info() == NULL); |
join = new JoinEntryInstr(if_false->block_id(), if_false->try_index()); |
+ join->InheritDeoptTarget(if_false); |
+ if_false->UnuseAllInputs(); |
next = if_false->next(); |
} else if (!reachable_->Contains(if_false->preorder_number())) { |
ASSERT(if_true->parallel_move() == NULL); |
ASSERT(if_true->loop_info() == NULL); |
join = new JoinEntryInstr(if_true->block_id(), if_true->try_index()); |
+ join->InheritDeoptTarget(if_true); |
+ if_true->UnuseAllInputs(); |
next = if_true->next(); |
} |
@@ -4471,9 +4481,12 @@ void ConstantPropagator::Transform() { |
// as it is a strict compare (the only one we can determine is |
// constant with the current analysis). |
GotoInstr* jump = new GotoInstr(join); |
+ jump->InheritDeoptTarget(branch); |
+ |
Instruction* previous = branch->previous(); |
branch->set_previous(NULL); |
previous->LinkTo(jump); |
+ |
// Replace the false target entry with the new join entry. We will |
// recompute the dominators after this pass. |
join->LinkTo(next); |
@@ -4494,6 +4507,28 @@ void ConstantPropagator::Transform() { |
} |
+// Returns true if the given phi has a single input use and |
+// is used in the environments either at the corresponding block entry or |
+// at the same instruction where input use is. |
+static bool PhiHasSingleUse(PhiInstr* phi, Value* use) { |
+ if ((use->next_use() != NULL) || (phi->input_use_list() != use)) { |
+ return false; |
+ } |
+ |
+ BlockEntryInstr* block = phi->block(); |
+ for (Value* env_use = phi->env_use_list(); |
+ env_use != NULL; |
+ env_use = env_use->next_use()) { |
+ if ((env_use->instruction() != block) && |
+ (env_use->instruction() != use->instruction())) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
bool BranchSimplifier::Match(JoinEntryInstr* block) { |
// Match the pattern of a branch on a comparison whose left operand is a |
// phi from the same block, and whose right operand is a constant. |
@@ -4515,7 +4550,7 @@ bool BranchSimplifier::Match(JoinEntryInstr* block) { |
return (phi != NULL) && |
(constant != NULL) && |
(phi->GetBlock() == block) && |
- phi->HasOnlyUse(left) && |
+ PhiHasSingleUse(phi, left) && |
constant->HasOnlyUse(right) && |
(block->next() == constant) && |
(constant->next() == branch) && |
@@ -4529,8 +4564,10 @@ JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { |
// from all the duplicated branches. |
JoinEntryInstr* join = |
new JoinEntryInstr(target->block_id(), target->try_index()); |
+ join->InheritDeoptTarget(target); |
join->LinkTo(target->next()); |
join->set_last_instruction(target->last_instruction()); |
+ target->UnuseAllInputs(); |
return join; |
} |
@@ -4551,18 +4588,24 @@ BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, |
if (comparison->IsStrictCompare()) { |
new_comparison = new StrictCompareInstr(comparison->kind(), left, right); |
} else if (comparison->IsEqualityCompare()) { |
- new_comparison = |
- new EqualityCompareInstr(comparison->AsEqualityCompare()->token_pos(), |
+ EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare(); |
+ EqualityCompareInstr* new_equality_compare = |
+ new EqualityCompareInstr(equality_compare->token_pos(), |
comparison->kind(), |
left, |
right); |
+ new_equality_compare->set_ic_data(equality_compare->ic_data()); |
+ new_comparison = new_equality_compare; |
} else { |
ASSERT(comparison->IsRelationalOp()); |
- new_comparison = |
- new RelationalOpInstr(comparison->AsRelationalOp()->token_pos(), |
+ RelationalOpInstr* relational_op = comparison->AsRelationalOp(); |
+ RelationalOpInstr* new_relational_op = |
+ new RelationalOpInstr(relational_op->token_pos(), |
comparison->kind(), |
left, |
right); |
+ new_relational_op->set_ic_data(relational_op->ic_data()); |
+ new_comparison = new_relational_op; |
} |
return new BranchInstr(new_comparison, branch->is_checked()); |
} |
@@ -4631,6 +4674,7 @@ void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
Value* new_left = phi->InputAt(i)->Copy(); |
Value* new_right = new Value(new_constant); |
BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); |
+ new_branch->InheritDeoptTarget(old_goto); |
new_branch->InsertBefore(old_goto); |
new_branch->set_next(NULL); // Detaching the goto from the graph. |
old_goto->UnuseAllInputs(); |
@@ -4646,16 +4690,20 @@ void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
TargetEntryInstr* true_target = |
new TargetEntryInstr(flow_graph->max_block_id() + 1, |
block->try_index()); |
+ true_target->InheritDeoptTarget(join_true); |
TargetEntryInstr* false_target = |
new TargetEntryInstr(flow_graph->max_block_id() + 2, |
block->try_index()); |
+ false_target->InheritDeoptTarget(join_false); |
flow_graph->set_max_block_id(flow_graph->max_block_id() + 2); |
*new_branch->true_successor_address() = true_target; |
*new_branch->false_successor_address() = false_target; |
GotoInstr* goto_true = new GotoInstr(join_true); |
+ goto_true->InheritDeoptTarget(join_true); |
true_target->LinkTo(goto_true); |
true_target->set_last_instruction(goto_true); |
GotoInstr* goto_false = new GotoInstr(join_false); |
+ goto_false->InheritDeoptTarget(join_false); |
false_target->LinkTo(goto_false); |
false_target->set_last_instruction(goto_false); |
} |
@@ -4663,6 +4711,7 @@ void BranchSimplifier::Simplify(FlowGraph* flow_graph) { |
// unreachable from the graph. |
phi->UnuseAllInputs(); |
branch->UnuseAllInputs(); |
+ block->UnuseAllInputs(); |
} |
} |