Chromium Code Reviews| Index: runtime/vm/intermediate_language.h |
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
| index fcbabad1424f20c6753ee46d94323b432854fdfd..5313c250f2a063d362a1a889ed87fd47f7599d2a 100644 |
| --- a/runtime/vm/intermediate_language.h |
| +++ b/runtime/vm/intermediate_language.h |
| @@ -556,7 +556,7 @@ class EmbeddedArray<T, 0> { |
| M(BoxInt32) \ |
| M(UnboxInt32) \ |
| M(UnboxedIntConverter) \ |
| - |
| + M(Deoptimize) |
| #define FORWARD_DECLARATION(type) class type##Instr; |
| FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) |
| @@ -873,12 +873,7 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
| friend class Int32x4ToFloat32x4Instr; |
| friend class BinaryInt32x4OpInstr; |
| friend class BinaryFloat64x2OpInstr; |
| - friend class BinaryMintOpInstr; |
| - friend class BinarySmiOpInstr; |
| - friend class UnarySmiOpInstr; |
| friend class UnaryDoubleOpInstr; |
| - friend class ShiftMintOpInstr; |
| - friend class UnaryMintOpInstr; |
| friend class MathUnaryInstr; |
| friend class MathMinMaxInstr; |
| friend class CheckClassInstr; |
| @@ -910,14 +905,13 @@ FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) |
| friend class RelationalOpInstr; |
| friend class EqualityCompareInstr; |
| friend class TestCidsInstr; |
| - friend class BinaryUint32OpInstr; |
| - friend class UnaryUint32OpInstr; |
| - friend class ShiftUint32OpInstr; |
| friend class UnboxIntNInstr; |
| friend class UnboxInt32Instr; |
| friend class UnboxUint32Instr; |
| - friend class BinaryInt32OpInstr; |
| friend class UnboxedIntConverterInstr; |
| + friend class UnaryIntegerOpInstr; |
| + friend class BinaryIntegerOpInstr; |
| + friend class DeoptimizeInstr; |
| virtual void RawSetInputAt(intptr_t i, Value* value) = 0; |
| @@ -2325,6 +2319,35 @@ class StoreContextInstr : public TemplateInstruction<1> { |
| }; |
| +class DeoptimizeInstr : public TemplateInstruction<0> { |
| + public: |
| + DeoptimizeInstr(ICData::DeoptReasonId deopt_reason, intptr_t deopt_id) |
| + : deopt_reason_(deopt_reason) { |
| + deopt_id_ = deopt_id; |
| + } |
| + |
| + virtual intptr_t ArgumentCount() const { return 0; } |
| + |
| + virtual bool CanDeoptimize() const { return true; } |
| + |
| + virtual bool AllowsCSE() const { return true; } |
| + virtual EffectSet Effects() const { return EffectSet::None(); } |
| + virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| + virtual bool AttributesEqual(Instruction* other) const { |
| + return true; |
| + } |
| + |
| + virtual bool MayThrow() const { return false; } |
| + |
| + DECLARE_INSTRUCTION(Deoptimize) |
| + |
| + private: |
| + const ICData::DeoptReasonId deopt_reason_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(DeoptimizeInstr); |
| +}; |
| + |
| + |
| class RedefinitionInstr : public TemplateDefinition<1> { |
| public: |
| explicit RedefinitionInstr(Value* value) { |
| @@ -6668,43 +6691,33 @@ class BinaryFloat64x2OpInstr : public TemplateDefinition<2> { |
| }; |
| -class BinaryMintOpInstr : public TemplateDefinition<2> { |
| +class UnaryIntegerOpInstr : public TemplateDefinition<1> { |
| public: |
| - BinaryMintOpInstr(Token::Kind op_kind, |
| - Value* left, |
| - Value* right, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind), can_overflow_(true) { |
| - SetInputAt(0, left); |
| - SetInputAt(1, right); |
| + UnaryIntegerOpInstr(Token::Kind op_kind, |
| + Value* value, |
| + intptr_t deopt_id) |
| + : op_kind_(op_kind) { |
| + ASSERT((op_kind == Token::kNEGATE) || |
| + (op_kind == Token::kBIT_NOT)); |
| + SetInputAt(0, value); |
| // Override generated deopt-id. |
| deopt_id_ = deopt_id; |
| } |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| + static UnaryIntegerOpInstr* Make(Representation representation, |
| + Token::Kind op_kind, |
| + Value* value, |
| + intptr_t deopt_id, |
| + Range* range); |
| + Value* value() const { return inputs_[0]; } |
| Token::Kind op_kind() const { return op_kind_; } |
| - bool can_overflow() const { return can_overflow_; } |
| - void set_can_overflow(bool value) { can_overflow_ = value; } |
| - |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| - |
| - virtual bool CanDeoptimize() const { |
| - return FLAG_throw_on_javascript_int_overflow |
| - || (can_overflow() && ((op_kind() == Token::kADD) || |
| - (op_kind() == Token::kSUB))) |
| - || (op_kind() == Token::kMUL); // Deopt if inputs are not int32. |
| - } |
| - |
| - virtual Representation representation() const { |
| - return kUnboxedMint; |
| - } |
| - |
| - virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| - ASSERT((idx == 0) || (idx == 1)); |
| - return kUnboxedMint; |
| + virtual bool AllowsCSE() const { return true; } |
| + virtual EffectSet Effects() const { return EffectSet::None(); } |
| + virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| + virtual bool AttributesEqual(Instruction* other) const { |
| + return static_cast<UnaryIntegerOpInstr*>(other)->op_kind() == op_kind(); |
|
srdjan
2014/09/11 17:38:12
Why static_cast instead of other->AsUnary... ?
Vyacheslav Egorov (Google)
2014/09/11 19:50:47
That would require manually introducing AsUnary...
|
| } |
| virtual intptr_t DeoptimizationTarget() const { |
| @@ -6713,121 +6726,77 @@ class BinaryMintOpInstr : public TemplateDefinition<2> { |
| return deopt_id_; |
| } |
| - virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| - |
| - virtual Definition* Canonicalize(FlowGraph* flow_graph); |
| - |
| - DECLARE_INSTRUCTION(BinaryMintOp) |
| - virtual CompileType ComputeType() const; |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - ASSERT(other->IsBinaryMintOp()); |
| - return op_kind() == other->AsBinaryMintOp()->op_kind(); |
| - } |
| - |
| virtual bool MayThrow() const { return false; } |
| + virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + |
| private: |
| const Token::Kind op_kind_; |
| - bool can_overflow_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr); |
| }; |
| -class ShiftMintOpInstr : public TemplateDefinition<2> { |
| +// Handles both Smi operations: BIT_OR and NEGATE. |
| +class UnarySmiOpInstr : public UnaryIntegerOpInstr { |
| public: |
| - ShiftMintOpInstr(Token::Kind op_kind, |
| - Value* left, |
| - Value* right, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind), can_overflow_(true) { |
| - ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL); |
| - SetInputAt(0, left); |
| - SetInputAt(1, right); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| + UnarySmiOpInstr(Token::Kind op_kind, |
| + Value* value, |
| + intptr_t deopt_id) |
| + : UnaryIntegerOpInstr(op_kind, value, deopt_id) { |
| } |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| + virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; } |
| - Token::Kind op_kind() const { return op_kind_; } |
| + virtual CompileType ComputeType() const; |
| - bool can_overflow() const { return can_overflow_; } |
| - void set_can_overflow(bool value) { can_overflow_ = value; } |
| + DECLARE_INSTRUCTION(UnarySmiOp) |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(UnarySmiOpInstr); |
| +}; |
| - bool has_shift_count_check() const; |
| - virtual bool CanDeoptimize() const { |
| - return FLAG_throw_on_javascript_int_overflow |
| - || has_shift_count_check() |
| - || (can_overflow() && (op_kind() == Token::kSHL)); |
| +class UnaryUint32OpInstr : public UnaryIntegerOpInstr { |
| + public: |
| + UnaryUint32OpInstr(Token::Kind op_kind, |
| + Value* value, |
| + intptr_t deopt_id) |
| + : UnaryIntegerOpInstr(op_kind, value, deopt_id) { |
| + ASSERT(op_kind == Token::kBIT_NOT); |
| } |
| + virtual bool CanDeoptimize() const { return false; } |
| + |
| virtual CompileType ComputeType() const; |
| virtual Representation representation() const { |
| - return kUnboxedMint; |
| + return kUnboxedUint32; |
| } |
| virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| - ASSERT((idx == 0) || (idx == 1)); |
| - return (idx == 0) ? kUnboxedMint : kTagged; |
| - } |
| - |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| - |
| - virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| - |
| - DECLARE_INSTRUCTION(ShiftMintOp) |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - return op_kind() == other->AsShiftMintOp()->op_kind(); |
| + ASSERT(idx == 0); |
| + return kUnboxedUint32; |
| } |
| - virtual bool MayThrow() const { return false; } |
| + DECLARE_INSTRUCTION(UnaryUint32Op) |
| private: |
| - const Token::Kind op_kind_; |
| - bool can_overflow_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); |
| + DISALLOW_COPY_AND_ASSIGN(UnaryUint32OpInstr); |
| }; |
| -class UnaryMintOpInstr : public TemplateDefinition<1> { |
| +class UnaryMintOpInstr : public UnaryIntegerOpInstr { |
| public: |
| UnaryMintOpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id) |
| - : op_kind_(op_kind) { |
| + : UnaryIntegerOpInstr(op_kind, value, deopt_id) { |
| ASSERT(op_kind == Token::kBIT_NOT); |
| - SetInputAt(0, value); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| } |
| - Value* value() const { return inputs_[0]; } |
| - |
| - Token::Kind op_kind() const { return op_kind_; } |
| - |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| - |
| virtual bool CanDeoptimize() const { |
| return FLAG_throw_on_javascript_int_overflow; |
| } |
| + virtual CompileType ComputeType() const; |
| + |
| virtual Representation representation() const { |
| return kUnboxedMint; |
| } |
| @@ -6837,112 +6806,115 @@ class UnaryMintOpInstr : public TemplateDefinition<1> { |
| return kUnboxedMint; |
| } |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| - |
| DECLARE_INSTRUCTION(UnaryMintOp) |
| - virtual CompileType ComputeType() const; |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - return op_kind() == other->AsUnaryMintOp()->op_kind(); |
| - } |
| - |
| - virtual bool MayThrow() const { return false; } |
| private: |
| - const Token::Kind op_kind_; |
| - |
| DISALLOW_COPY_AND_ASSIGN(UnaryMintOpInstr); |
| }; |
| -class BinarySmiOpInstr : public TemplateDefinition<2> { |
| +class BinaryIntegerOpInstr : public TemplateDefinition<2> { |
| public: |
| - BinarySmiOpInstr(Token::Kind op_kind, |
| - Value* left, |
| - Value* right, |
| - intptr_t deopt_id, |
| - intptr_t token_pos) |
| + BinaryIntegerOpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| : op_kind_(op_kind), |
| - overflow_(true), |
| - is_truncating_(false), |
| - token_pos_(token_pos) { |
| + can_overflow_(true), |
| + is_truncating_(false) { |
| SetInputAt(0, left); |
| SetInputAt(1, right); |
| // Override generated deopt-id. |
| deopt_id_ = deopt_id; |
| } |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| + static BinaryIntegerOpInstr* Make(Representation representation, |
| + Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id, |
| + bool can_overflow, |
| + bool is_truncating, |
| + Range* range); |
| - virtual intptr_t token_pos() const { return token_pos_; } |
| Token::Kind op_kind() const { return op_kind_; } |
| + Value* left() const { return inputs_[0]; } |
| + Value* right() const { return inputs_[1]; } |
| - void set_overflow(bool overflow) { overflow_ = overflow; } |
| + bool can_overflow() const { return can_overflow_; } |
| + void set_can_overflow(bool overflow) { |
| + ASSERT(!is_truncating_ || !overflow); |
| + can_overflow_ = overflow; |
| + } |
| - void set_is_truncating(bool value) { is_truncating_ = value; } |
| - bool IsTruncating() const { return is_truncating_ || !overflow_; } |
| + bool is_truncating() const { return is_truncating_; } |
| + void mark_truncating() { |
| + is_truncating_ = true; |
| + set_can_overflow(false); |
| + } |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + // Returns true if right is a non-zero Smi constant which absolute value is |
| + // a power of two. |
| + bool RightIsPowerOfTwoConstant() const; |
| - DECLARE_INSTRUCTION(BinarySmiOp) |
| - virtual CompileType ComputeType() const; |
| + RawInteger* Evaluate(const Integer& left, const Integer& right) const; |
| - virtual bool CanDeoptimize() const; |
| + virtual Definition* Canonicalize(FlowGraph* flow_graph); |
| virtual bool AllowsCSE() const { return true; } |
| virtual EffectSet Effects() const { return EffectSet::None(); } |
| virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| virtual bool AttributesEqual(Instruction* other) const; |
| - void PrintTo(BufferFormatter* f) const; |
| - |
| - virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| - |
| - virtual Definition* Canonicalize(FlowGraph* flow_graph); |
| - |
| - // Returns true if right is a non-zero Smi constant which absolute value is |
| - // a power of two. |
| - bool RightIsPowerOfTwoConstant() const; |
| + virtual intptr_t DeoptimizationTarget() const { return deopt_id_; } |
| virtual bool MayThrow() const { return false; } |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| + virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + |
| + protected: |
| + void InferRangeHelper(const Range* left_range, |
| + const Range* right_range, |
| + Range* range); |
| private: |
| const Token::Kind op_kind_; |
| - bool overflow_; |
| + |
| + bool can_overflow_; |
| bool is_truncating_; |
| - const intptr_t token_pos_; |
| +}; |
| + |
| + |
| +class BinarySmiOpInstr : public BinaryIntegerOpInstr { |
| + public: |
| + BinarySmiOpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| + } |
| + |
| + virtual bool CanDeoptimize() const; |
| + |
| + virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| + virtual CompileType ComputeType() const; |
| + |
| + DECLARE_INSTRUCTION(BinarySmiOp) |
| + private: |
| DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); |
| }; |
| -class BinaryInt32OpInstr : public TemplateDefinition<2> { |
| +class BinaryInt32OpInstr : public BinaryIntegerOpInstr { |
| public: |
| BinaryInt32OpInstr(Token::Kind op_kind, |
| Value* left, |
| Value* right, |
| intptr_t deopt_id) |
| - : op_kind_(op_kind), |
| - overflow_(true), |
| - is_truncating_(false) { |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| SetInputAt(0, left); |
| SetInputAt(1, right); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| } |
| static bool IsSupported(Token::Kind op, Value* left, Value* right) { |
| @@ -6968,95 +6940,158 @@ class BinaryInt32OpInstr : public TemplateDefinition<2> { |
| #endif |
| } |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| - |
| - Token::Kind op_kind() const { return op_kind_; } |
| + virtual bool CanDeoptimize() const; |
| - void set_overflow(bool overflow) { overflow_ = overflow; } |
| + virtual Representation representation() const { |
| + return kUnboxedInt32; |
| + } |
| - void set_is_truncating(bool value) { is_truncating_ = value; } |
| - bool IsTruncating() const { return is_truncating_ || !overflow_; } |
| + virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| + ASSERT((idx == 0) || (idx == 1)); |
| + return kUnboxedInt32; |
| + } |
| - void PrintTo(BufferFormatter* f) const; |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| + virtual CompileType ComputeType() const; |
| DECLARE_INSTRUCTION(BinaryInt32Op) |
| - virtual CompileType ComputeType() const; |
| - virtual bool CanDeoptimize() const; |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(BinaryInt32OpInstr); |
| +}; |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const; |
| - virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| +class BinaryUint32OpInstr : public BinaryIntegerOpInstr { |
| + public: |
| + BinaryUint32OpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| + mark_truncating(); |
| + } |
| - virtual Definition* Canonicalize(FlowGraph* flow_graph); |
| + virtual bool CanDeoptimize() const { |
| + return false; |
| + } |
| virtual Representation representation() const { |
| - return kUnboxedInt32; |
| + return kUnboxedUint32; |
| } |
| virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| ASSERT((idx == 0) || (idx == 1)); |
| - return kUnboxedInt32; |
| + return kUnboxedUint32; |
| } |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| + virtual CompileType ComputeType() const; |
| - virtual bool MayThrow() const { return false; } |
| + DECLARE_INSTRUCTION(BinaryUint32Op) |
| private: |
| - const Token::Kind op_kind_; |
| - bool overflow_; |
| - bool is_truncating_; |
| + DISALLOW_COPY_AND_ASSIGN(BinaryUint32OpInstr); |
| +}; |
| - DISALLOW_COPY_AND_ASSIGN(BinaryInt32OpInstr); |
| + |
| +class ShiftUint32OpInstr : public BinaryIntegerOpInstr { |
| + public: |
| + ShiftUint32OpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| + ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL)); |
| + } |
| + |
| + virtual bool CanDeoptimize() const { return true; } |
| + |
| + virtual Representation representation() const { |
| + return kUnboxedUint32; |
| + } |
| + |
| + virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| + ASSERT((idx == 0) || (idx == 1)); |
| + return (idx == 0) ? kUnboxedUint32 : kTagged; |
| + } |
| + |
| + virtual CompileType ComputeType() const; |
| + |
| + DECLARE_INSTRUCTION(ShiftUint32Op) |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ShiftUint32OpInstr); |
| }; |
| -// Handles both Smi operations: BIT_OR and NEGATE. |
| -class UnarySmiOpInstr : public TemplateDefinition<1> { |
| +class BinaryMintOpInstr : public BinaryIntegerOpInstr { |
| public: |
| - UnarySmiOpInstr(Token::Kind op_kind, |
| - Value* value, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind) { |
| - ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT)); |
| - SetInputAt(0, value); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| + BinaryMintOpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| } |
| - Value* value() const { return inputs_[0]; } |
| - Token::Kind op_kind() const { return op_kind_; } |
| + virtual bool CanDeoptimize() const { |
| + return FLAG_throw_on_javascript_int_overflow |
| + || (can_overflow() && ((op_kind() == Token::kADD) || |
| + (op_kind() == Token::kSUB))) |
| + || (op_kind() == Token::kMUL); // Deopt if inputs are not int32. |
| + } |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| + virtual Representation representation() const { |
| + return kUnboxedMint; |
| + } |
| - DECLARE_INSTRUCTION(UnarySmiOp) |
| + virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| + ASSERT((idx == 0) || (idx == 1)); |
| + return kUnboxedMint; |
| + } |
| + |
| + virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| virtual CompileType ComputeType() const; |
| - virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; } |
| + DECLARE_INSTRUCTION(BinaryMintOp) |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - return other->AsUnarySmiOp()->op_kind() == op_kind(); |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr); |
| +}; |
| + |
| + |
| +class ShiftMintOpInstr : public BinaryIntegerOpInstr { |
| + public: |
| + ShiftMintOpInstr(Token::Kind op_kind, |
| + Value* left, |
| + Value* right, |
| + intptr_t deopt_id) |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| + ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL)); |
| } |
| - virtual bool MayThrow() const { return false; } |
| + virtual bool CanDeoptimize() const { |
| + return FLAG_throw_on_javascript_int_overflow |
| + || has_shift_count_check() |
| + || (can_overflow() && (op_kind() == Token::kSHL)); |
| + } |
| + |
| + virtual Representation representation() const { |
| + return kUnboxedMint; |
| + } |
| + |
| + virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| + ASSERT((idx == 0) || (idx == 1)); |
| + return (idx == 0) ? kUnboxedMint : kTagged; |
| + } |
| + |
| + virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| + virtual CompileType ComputeType() const; |
| + |
| + DECLARE_INSTRUCTION(ShiftMintOp) |
| private: |
| - const Token::Kind op_kind_; |
| + bool has_shift_count_check() const; |
| - DISALLOW_COPY_AND_ASSIGN(UnarySmiOpInstr); |
| + DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); |
| }; |
| @@ -7792,183 +7827,6 @@ class CheckArrayBoundInstr : public TemplateInstruction<2> { |
| }; |
| -class BinaryUint32OpInstr : public TemplateDefinition<2> { |
| - public: |
| - BinaryUint32OpInstr(Token::Kind op_kind, |
| - Value* left, |
| - Value* right, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind) { |
| - SetInputAt(0, left); |
| - SetInputAt(1, right); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| - } |
| - |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| - |
| - Token::Kind op_kind() const { return op_kind_; } |
| - |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| - |
| - virtual bool CanDeoptimize() const { |
| - return false; |
| - } |
| - |
| - virtual Representation representation() const { |
| - return kUnboxedUint32; |
| - } |
| - |
| - virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| - ASSERT((idx == 0) || (idx == 1)); |
| - return kUnboxedUint32; |
| - } |
| - |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| - |
| - virtual Definition* Canonicalize(FlowGraph* flow_graph); |
| - |
| - DECLARE_INSTRUCTION(BinaryUint32Op) |
| - virtual CompileType ComputeType() const; |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - ASSERT(other->IsBinaryUint32Op()); |
| - return op_kind() == other->AsBinaryUint32Op()->op_kind(); |
| - } |
| - |
| - virtual bool MayThrow() const { return false; } |
| - |
| - private: |
| - const Token::Kind op_kind_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(BinaryUint32OpInstr); |
| -}; |
| - |
| - |
| -class ShiftUint32OpInstr : public TemplateDefinition<2> { |
| - public: |
| - ShiftUint32OpInstr(Token::Kind op_kind, |
| - Value* left, |
| - Value* right, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind) { |
| - ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL); |
| - SetInputAt(0, left); |
| - SetInputAt(1, right); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| - } |
| - |
| - Value* left() const { return inputs_[0]; } |
| - Value* right() const { return inputs_[1]; } |
| - |
| - Token::Kind op_kind() const { return op_kind_; } |
| - |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| - |
| - virtual bool CanDeoptimize() const { |
| - return true; |
| - } |
| - |
| - virtual CompileType ComputeType() const; |
| - |
| - virtual Representation representation() const { |
| - return kUnboxedUint32; |
| - } |
| - |
| - virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| - ASSERT((idx == 0) || (idx == 1)); |
| - return (idx == 0) ? kUnboxedUint32 : kTagged; |
| - } |
| - |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| - |
| - DECLARE_INSTRUCTION(ShiftUint32Op) |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - return op_kind() == other->AsShiftUint32Op()->op_kind(); |
| - } |
| - |
| - virtual bool MayThrow() const { return false; } |
| - |
| - private: |
| - const Token::Kind op_kind_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(ShiftUint32OpInstr); |
| -}; |
| - |
| - |
| -class UnaryUint32OpInstr : public TemplateDefinition<1> { |
| - public: |
| - UnaryUint32OpInstr(Token::Kind op_kind, |
| - Value* value, |
| - intptr_t deopt_id) |
| - : op_kind_(op_kind) { |
| - ASSERT(op_kind == Token::kBIT_NOT); |
| - SetInputAt(0, value); |
| - // Override generated deopt-id. |
| - deopt_id_ = deopt_id; |
| - } |
| - |
| - Value* value() const { return inputs_[0]; } |
| - |
| - Token::Kind op_kind() const { return op_kind_; } |
| - |
| - virtual void PrintOperandsTo(BufferFormatter* f) const; |
| - |
| - virtual bool CanDeoptimize() const { |
| - return false; |
| - } |
| - |
| - virtual Representation representation() const { |
| - return kUnboxedUint32; |
| - } |
| - |
| - virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| - ASSERT(idx == 0); |
| - return kUnboxedUint32; |
| - } |
| - |
| - virtual intptr_t DeoptimizationTarget() const { |
| - // Direct access since this instruction cannot deoptimize, and the deopt-id |
| - // was inherited from another instruction that could deoptimize. |
| - return deopt_id_; |
| - } |
| - |
| - DECLARE_INSTRUCTION(UnaryUint32Op) |
| - virtual CompileType ComputeType() const; |
| - |
| - virtual bool AllowsCSE() const { return true; } |
| - virtual EffectSet Effects() const { return EffectSet::None(); } |
| - virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - return op_kind() == other->AsUnaryUint32Op()->op_kind(); |
| - } |
| - |
| - virtual bool MayThrow() const { return false; } |
| - |
| - private: |
| - const Token::Kind op_kind_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(UnaryUint32OpInstr); |
| -}; |
| - |
| - |
| class BoxIntNInstr : public TemplateDefinition<1> { |
| public: |
| BoxIntNInstr(Representation representation, Value* value) |