Index: runtime/vm/intermediate_language.cc |
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc |
index 259419d2492ec7096d54fec2b2ae2a68b4d7ff69..2f4e978ab1182273aa789788a7ef61a83fe77e98 100644 |
--- a/runtime/vm/intermediate_language.cc |
+++ b/runtime/vm/intermediate_language.cc |
@@ -509,11 +509,11 @@ void Value::RemoveFromUseList() { |
bool Definition::HasOnlyUse(Value* use) const { |
- if (((input_use_list() == use) && (env_use_list() == NULL)) || |
- ((input_use_list() == NULL) && (env_use_list() == use))) { |
- return (use->next_use() == NULL); |
- } |
- return false; |
+ return (input_use_list() == use) && |
+ (use->next_use() == NULL) && |
+ ((env_use_list() == NULL) || |
+ ((env_use_list()->instruction() == use->instruction()) && |
+ (env_use_list()->next_use() == NULL))); |
} |
@@ -572,6 +572,28 @@ void Instruction::UnuseAllInputs() { |
} |
+void Instruction::InheritDeoptTargetAfter(Instruction* other) { |
+ ASSERT(other->env() != NULL); |
+ deopt_id_ = Isolate::ToDeoptAfter(other->deopt_id_); |
+ other->env()->DeepCopyTo(this); |
+ env()->set_deopt_id(deopt_id_); |
+} |
+ |
+ |
+void Instruction::InheritDeoptTarget(Instruction* other) { |
+ ASSERT(other->env() != NULL); |
+ deopt_id_ = other->deopt_id_; |
+ other->env()->DeepCopyTo(this); |
+ env()->set_deopt_id(deopt_id_); |
+} |
+ |
+ |
+void BranchInstr::InheritDeoptTarget(Instruction* other) { |
+ Instruction::InheritDeoptTarget(other); |
+ comparison()->SetDeoptId(GetDeoptId()); |
+} |
+ |
+ |
void Definition::ReplaceWith(Definition* other, |
ForwardInstructionIterator* iterator) { |
// Record other's input uses. |
@@ -1263,9 +1285,11 @@ Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
// Replace the comparison if the replacement is used at this branch, |
// and has exactly one use. |
- if ((comp->input_use_list()->instruction() == this) && |
- (comp->input_use_list()->next_use() == NULL) && |
- (comp->env_use_list() == NULL)) { |
+ Value* use = comp->input_use_list(); |
+ if ((use->instruction() == this) && comp->HasOnlyUse(use)) { |
+ RemoveEnvironment(); |
+ InheritDeoptTarget(comp); |
+ |
comp->RemoveFromGraph(); |
SetComparison(comp); |
if (FLAG_trace_optimization) { |
@@ -1381,6 +1405,11 @@ void GraphEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
+ if (!compiler->is_optimizing()) { |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
+ deopt_id_, |
+ Scanner::kDummyTokenIndex); |
+ } |
__ Bind(compiler->GetJumpLabel(this)); |
if (HasParallelMove()) { |
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
@@ -1389,6 +1418,11 @@ void JoinEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
void TargetEntryInstr::PrepareEntry(FlowGraphCompiler* compiler) { |
+ if (!compiler->is_optimizing()) { |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
+ deopt_id_, |
+ Scanner::kDummyTokenIndex); |
+ } |
__ Bind(compiler->GetJumpLabel(this)); |
if (HasParallelMove()) { |
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
@@ -1556,7 +1590,7 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
} else { |
// Unoptimized code. |
ASSERT(!HasICData()); |
- compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
deopt_id(), |
token_pos()); |
compiler->GenerateInstanceCall(deopt_id(), |
@@ -1579,7 +1613,7 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
if (!compiler->is_optimizing()) { |
// Some static calls can be optimized by the optimizing compiler (e.g. sqrt) |
// and therefore need a deoptimization descriptor. |
- compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
+ compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
deopt_id(), |
token_pos()); |
} |