| 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)
|
|
|