| Index: runtime/vm/intermediate_language.h
|
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
|
| index ff3822cf9754846491807a5a7f95e99c5ca8b044..efa6455a2205157d06d9107007a744d2bf2636b8 100644
|
| --- a/runtime/vm/intermediate_language.h
|
| +++ b/runtime/vm/intermediate_language.h
|
| @@ -453,7 +453,7 @@ class EmbeddedArray<T, 0> {
|
| M(OneByteStringFromCharCode) \
|
| M(StringInterpolate) \
|
| M(InvokeMathCFunction) \
|
| - M(MergedMath) \
|
| + M(TruncDivMod) \
|
| M(GuardFieldClass) \
|
| M(GuardFieldLength) \
|
| M(IfThenElse) \
|
| @@ -6929,7 +6929,8 @@ class BinarySmiOpInstr : public BinaryIntegerOpInstr {
|
| Value* left,
|
| Value* right,
|
| intptr_t deopt_id)
|
| - : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) {}
|
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id),
|
| + right_range_(NULL) {}
|
|
|
| virtual bool ComputeCanDeoptimize() const;
|
|
|
| @@ -6938,7 +6939,11 @@ class BinarySmiOpInstr : public BinaryIntegerOpInstr {
|
|
|
| DECLARE_INSTRUCTION(BinarySmiOp)
|
|
|
| + Range* right_range() const { return right_range_; }
|
| +
|
| private:
|
| + Range* right_range_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr);
|
| };
|
|
|
| @@ -6967,7 +6972,11 @@ class BinaryInt32OpInstr : public BinaryIntegerOpInstr {
|
|
|
| case Token::kSHL:
|
| case Token::kSHR:
|
| - return right->BindsToConstant();
|
| + if (right->BindsToConstant() && right->BoundConstant().IsSmi()) {
|
| + const intptr_t value = Smi::Cast(right->BoundConstant()).Value();
|
| + return 0 <= value && value < kBitsPerWord;
|
| + }
|
| + return false;
|
|
|
| default:
|
| return false;
|
| @@ -7089,10 +7098,13 @@ class ShiftMintOpInstr : public BinaryIntegerOpInstr {
|
| Value* left,
|
| Value* right,
|
| intptr_t deopt_id)
|
| - : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) {
|
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id),
|
| + shift_range_(NULL) {
|
| ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL));
|
| }
|
|
|
| + Range* shift_range() const { return shift_range_; }
|
| +
|
| virtual bool ComputeCanDeoptimize() const {
|
| return has_shift_count_check() ||
|
| (can_overflow() && (op_kind() == Token::kSHL));
|
| @@ -7111,8 +7123,11 @@ class ShiftMintOpInstr : public BinaryIntegerOpInstr {
|
| DECLARE_INSTRUCTION(ShiftMintOp)
|
|
|
| private:
|
| + static const intptr_t kMintShiftCountLimit = 63;
|
| bool has_shift_count_check() const;
|
|
|
| + Range* shift_range_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr);
|
| };
|
|
|
| @@ -7545,90 +7560,45 @@ class ExtractNthOutputInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
| };
|
|
|
|
|
| -class MergedMathInstr : public PureDefinition {
|
| +class TruncDivModInstr : public TemplateDefinition<2, NoThrow, Pure> {
|
| public:
|
| - enum Kind {
|
| - kTruncDivMod,
|
| - };
|
| -
|
| - MergedMathInstr(ZoneGrowableArray<Value*>* inputs,
|
| - intptr_t original_deopt_id,
|
| - MergedMathInstr::Kind kind);
|
| -
|
| - static intptr_t InputCountFor(MergedMathInstr::Kind kind) {
|
| - if (kind == kTruncDivMod) {
|
| - return 2;
|
| - } else {
|
| - UNIMPLEMENTED();
|
| - return -1;
|
| - }
|
| - }
|
| -
|
| - MergedMathInstr::Kind kind() const { return kind_; }
|
| -
|
| - virtual intptr_t InputCount() const { return inputs_->length(); }
|
| -
|
| - virtual Value* InputAt(intptr_t i) const { return (*inputs_)[i]; }
|
| + TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id);
|
|
|
| - static intptr_t OutputIndexOf(MethodRecognizer::Kind kind);
|
| static intptr_t OutputIndexOf(Token::Kind token);
|
|
|
| virtual CompileType ComputeType() const;
|
|
|
| - virtual bool ComputeCanDeoptimize() const {
|
| - if (kind_ == kTruncDivMod) {
|
| - return true;
|
| - } else {
|
| - UNIMPLEMENTED();
|
| - return false;
|
| - }
|
| - }
|
| + virtual bool ComputeCanDeoptimize() const { return true; }
|
|
|
| - virtual Representation representation() const {
|
| - if (kind_ == kTruncDivMod) {
|
| - return kPairOfTagged;
|
| - } else {
|
| - UNIMPLEMENTED();
|
| - return kTagged;
|
| - }
|
| - }
|
| + virtual Representation representation() const { return kPairOfTagged; }
|
|
|
| virtual Representation RequiredInputRepresentation(intptr_t idx) const {
|
| ASSERT((0 <= idx) && (idx < InputCount()));
|
| - if (kind_ == kTruncDivMod) {
|
| - return kTagged;
|
| - } else {
|
| - UNIMPLEMENTED();
|
| - return kTagged;
|
| - }
|
| + return kTagged;
|
| }
|
|
|
| virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
|
|
|
| - DECLARE_INSTRUCTION(MergedMath)
|
| -
|
| - virtual bool AttributesEqual(Instruction* other) const {
|
| - MergedMathInstr* other_invoke = other->AsMergedMath();
|
| - return other_invoke->kind() == kind();
|
| - }
|
| -
|
| - virtual bool MayThrow() const { return false; }
|
| + DECLARE_INSTRUCTION(TruncDivMod)
|
|
|
| - static const char* KindToCString(MergedMathInstr::Kind kind) {
|
| - if (kind == kTruncDivMod) return "TruncDivMod";
|
| - UNIMPLEMENTED();
|
| - return "";
|
| - }
|
| + virtual bool AttributesEqual(Instruction* other) const { return true; }
|
|
|
| PRINT_OPERANDS_TO_SUPPORT
|
|
|
| private:
|
| - virtual void RawSetInputAt(intptr_t i, Value* value) {
|
| - (*inputs_)[i] = value;
|
| + Range* divisor_range() const {
|
| + // Note: this range is only used to remove check for zero divisor from
|
| + // the emitted pattern. It is not used for deciding whether instruction
|
| + // will deoptimize or not - that is why it is ok to access range of
|
| + // the definition directly. Otherwise range analysis or another pass
|
| + // needs to cache range of the divisor in the operation to prevent
|
| + // bugs when range information gets out of sync with the final decision
|
| + // whether some instruction can deoptimize or not made in
|
| + // EliminateEnvironments().
|
| + return InputAt(1)->definition()->range();
|
| }
|
| - ZoneGrowableArray<Value*>* inputs_;
|
| - MergedMathInstr::Kind kind_;
|
| - DISALLOW_COPY_AND_ASSIGN(MergedMathInstr);
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TruncDivModInstr);
|
| };
|
|
|
|
|
|
|