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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 12457034: Ensure that all goto instructions have deoptimization target. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Delete UNREACHABLE Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
}
}
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698