Index: runtime/vm/intermediate_language.h |
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
index 94f2b5d86ab0e007b75012fbf579c4fe68c712db..828b19f4464860c8432280cef6058b59d58e0f6c 100644 |
--- a/runtime/vm/intermediate_language.h |
+++ b/runtime/vm/intermediate_language.h |
@@ -535,7 +535,7 @@ class Instruction : public ZoneAllocated { |
virtual Tag tag() const = 0; |
intptr_t deopt_id() const { |
- ASSERT(CanDeoptimize()); |
+ ASSERT(CanDeoptimize() || CanBeDeoptimizationTarget()); |
return deopt_id_; |
} |
@@ -728,6 +728,18 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
return false; |
} |
+ virtual void InheritDeoptTarget(Instruction* other); |
+ |
+ bool NeedsEnvironment() const { |
+ return CanDeoptimize() || CanBeDeoptimizationTarget(); |
+ } |
+ |
+ virtual bool CanBeDeoptimizationTarget() const { |
+ return false; |
+ } |
+ |
+ void InheritDeoptTargetAfter(Instruction* other); |
+ |
protected: |
// Fetch deopt id without checking if this computation can deoptimize. |
intptr_t GetDeoptId() const { |
@@ -760,6 +772,11 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
friend class LoadIndexedInstr; |
friend class StoreIndexedInstr; |
friend class StoreInstanceFieldInstr; |
+ friend class ControlInstruction; |
+ friend class ComparisonInstr; |
+ friend class TargetEntryInstr; |
+ friend class JoinEntryInstr; |
+ friend class InstanceOfInstr; |
virtual void RawSetInputAt(intptr_t i, Value* value) = 0; |
@@ -981,6 +998,12 @@ class BlockEntryInstr : public Instruction { |
virtual intptr_t ArgumentCount() const { return 0; } |
+ virtual bool CanBeDeoptimizationTarget() const { |
+ // BlockEntry environment is copied to Goto and Branch instructions |
+ // when we insert new blocks targeting this block. |
+ return true; |
+ } |
+ |
virtual bool CanDeoptimize() const { return false; } |
virtual bool HasSideEffect() const { return false; } |
@@ -1653,6 +1676,12 @@ class ReturnInstr : public TemplateInstruction<1> { |
intptr_t token_pos() const { return token_pos_; } |
Value* value() const { return inputs_[0]; } |
+ virtual bool CanBeDeoptimizationTarget() const { |
+ // Return instruction might turn into a Goto instruction after inlining. |
+ // Every Goto must have an environment. |
+ return true; |
+ } |
+ |
virtual bool CanDeoptimize() const { return false; } |
virtual bool HasSideEffect() const { return false; } |
@@ -1721,6 +1750,12 @@ class GotoInstr : public TemplateInstruction<0> { |
virtual intptr_t SuccessorCount() const; |
virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
+ virtual bool CanBeDeoptimizationTarget() const { |
+ // Goto instruction can be used as a deoptimization target when LICM |
+ // hoists instructions out of the loop. |
+ return true; |
+ } |
+ |
virtual bool CanDeoptimize() const { return false; } |
virtual bool HasSideEffect() const { return false; } |
@@ -1789,6 +1824,7 @@ class BranchInstr : public ControlInstruction { |
intptr_t InputCount() const; |
Value* InputAt(intptr_t i) const; |
virtual bool CanDeoptimize() const; |
+ virtual bool CanBeDeoptimizationTarget() const; |
virtual bool HasSideEffect() const; |
@@ -1825,6 +1861,8 @@ class BranchInstr : public ControlInstruction { |
return constrained_type_; |
} |
+ virtual void InheritDeoptTarget(Instruction* other); |
+ |
private: |
virtual void RawSetInputAt(intptr_t i, Value* value); |
@@ -2422,6 +2460,10 @@ class ComparisonInstr : public TemplateDefinition<2> { |
virtual void EmitBranchCode(FlowGraphCompiler* compiler, |
BranchInstr* branch) = 0; |
+ void SetDeoptId(intptr_t deopt_id) { |
+ deopt_id_ = deopt_id; |
+ } |
+ |
protected: |
Token::Kind kind_; |
}; |
@@ -2450,6 +2492,11 @@ inline bool BranchInstr::CanDeoptimize() const { |
} |
+inline bool BranchInstr::CanBeDeoptimizationTarget() const { |
+ return comparison()->CanBeDeoptimizationTarget(); |
+} |
+ |
+ |
inline bool BranchInstr::HasSideEffect() const { |
return comparison()->HasSideEffect(); |
} |
@@ -2486,6 +2533,11 @@ class StrictCompareInstr : public ComparisonInstr { |
virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ virtual bool CanBeDeoptimizationTarget() const { |
+ // StrictCompare can be merged into Branch and thus needs an environment. |
+ return true; |
+ } |
+ |
virtual bool CanDeoptimize() const { return false; } |
virtual bool HasSideEffect() const { return false; } |
@@ -2533,6 +2585,7 @@ class EqualityCompareInstr : public ComparisonInstr { |
bool HasICData() const { |
return (ic_data() != NULL) && !ic_data()->IsNull(); |
} |
+ void set_ic_data(const ICData* value) { ic_data_ = value; } |
intptr_t token_pos() const { return token_pos_; } |
@@ -2603,6 +2656,7 @@ class RelationalOpInstr : public ComparisonInstr { |
bool HasICData() const { |
return (ic_data() != NULL) && !ic_data()->IsNull(); |
} |
+ void set_ic_data(const ICData* value) { ic_data_ = value; } |
intptr_t token_pos() const { return token_pos_; } |
@@ -3110,7 +3164,8 @@ class InstanceOfInstr : public TemplateDefinition<3> { |
Value* instantiator, |
Value* instantiator_type_arguments, |
const AbstractType& type, |
- bool negate_result) |
+ bool negate_result, |
+ intptr_t deopt_id) |
: token_pos_(token_pos), |
type_(type), |
negate_result_(negate_result) { |
@@ -3118,6 +3173,7 @@ class InstanceOfInstr : public TemplateDefinition<3> { |
SetInputAt(0, value); |
SetInputAt(1, instantiator); |
SetInputAt(2, instantiator_type_arguments); |
+ deopt_id_ = deopt_id; |
} |
DECLARE_INSTRUCTION(InstanceOf) |