Index: runtime/vm/intermediate_language.h |
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
index c2d80811aa8788d76593c244c87ddc599cdc1920..f263c2339aae98f6161318bb9001269bd6747326 100644 |
--- a/runtime/vm/intermediate_language.h |
+++ b/runtime/vm/intermediate_language.h |
@@ -580,6 +580,12 @@ class Value : public ZoneAllocated { |
bool IsSmiValue() { return Type()->ToCid() == kSmiCid; } |
+ // Returns true if this value binds to a 32-bit mint instruction. |
+ bool BindsTo32BitMint() const; |
+ |
+ // Returns true if this value binds to the constant: 0xFFFFFFFF. |
+ bool BindsTo32BitMaskConstant() const; |
+ |
// Return true if the value represents a constant. |
bool BindsToConstant() const; |
@@ -738,6 +744,7 @@ class EmbeddedArray<T, 0> { |
M(UnboxInt32x4) \ |
M(UnboxInteger) \ |
M(BoxInteger) \ |
+ M(MintConverter) \ |
M(BinaryMintOp) \ |
M(ShiftMintOp) \ |
M(UnaryMintOp) \ |
@@ -2795,6 +2802,17 @@ class Range : public ZoneAllocated { |
return !min_.IsInfinity() && !max_.IsInfinity(); |
} |
+ bool Is32BitMask() const { |
+ return min_.IsConstant() && (min_.ConstantValue() == 0) && |
+ max_.IsConstant() && (max_.ConstantValue() == kMaxUint32); |
+ } |
+ |
+ void Make32BitMask() { |
+ min_ = RangeBoundary::FromConstant(0); |
+ // TODO(johnmccutchan): If the range has a smaller max we should use it. |
+ max_ = RangeBoundary::FromConstant(kMaxUint32); |
+ } |
+ |
// Clamp this to be within size. |
void Clamp(RangeBoundary::RangeSize size); |
@@ -5266,11 +5284,14 @@ class UnboxInt32x4Instr : public TemplateDefinition<1> { |
class UnboxIntegerInstr : public TemplateDefinition<1> { |
public: |
- UnboxIntegerInstr(Value* value, intptr_t deopt_id) { |
+ UnboxIntegerInstr(Value* value, intptr_t deopt_id) |
+ : is_32_bit_(false) { |
SetInputAt(0, value); |
deopt_id_ = deopt_id; |
} |
+ virtual void PrintTo(BufferFormatter* f) const; |
+ |
Value* value() const { return inputs_[0]; } |
virtual bool CanDeoptimize() const { |
@@ -5279,9 +5300,11 @@ class UnboxIntegerInstr : public TemplateDefinition<1> { |
} |
virtual Representation representation() const { |
- return kUnboxedMint; |
+ return is_32_bit() ? kUnboxedMint32 : kUnboxedMint; |
} |
+ bool is_32_bit() const { return is_32_bit_; } |
+ void set_is_32_bit(bool v) { is_32_bit_ = v; } |
virtual void InferRange(); |
@@ -5296,6 +5319,7 @@ class UnboxIntegerInstr : public TemplateDefinition<1> { |
virtual bool MayThrow() const { return false; } |
private: |
+ bool is_32_bit_; |
DISALLOW_COPY_AND_ASSIGN(UnboxIntegerInstr); |
}; |
@@ -7034,13 +7058,60 @@ class BinaryFloat64x2OpInstr : public TemplateDefinition<2> { |
}; |
+class MintConverterInstr : public TemplateDefinition<1> { |
+ public: |
+ enum Conversion { |
+ kMint32ToMint, |
+ kMintToMint32, |
+ }; |
+ |
+ MintConverterInstr(Conversion conversion_kind, Value* val) |
+ : conversion_kind_(conversion_kind) { |
+ ASSERT((conversion_kind_ == kMint32ToMint) || |
+ (conversion_kind_ == kMintToMint32)); |
+ SetInputAt(0, val); |
+ } |
+ |
+ Value* value() const { return inputs_[0]; } |
+ |
+ intptr_t conversion_kind() const { return conversion_kind_; } |
+ |
+ virtual bool CanDeoptimize() const { return false; } |
+ |
+ virtual Representation representation() const { |
+ return (conversion_kind_ == kMint32ToMint) ? kUnboxedMint : kUnboxedMint32; |
+ } |
+ |
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
+ ASSERT(idx == 0); |
+ return (conversion_kind_ == kMint32ToMint) ? kUnboxedMint32 : kUnboxedMint; |
+ } |
+ |
+ virtual EffectSet Effects() const { return EffectSet::None(); } |
+ virtual EffectSet Dependencies() const { return EffectSet::None(); } |
+ virtual bool AttributesEqual(Instruction* other) const { |
+ ASSERT(other->IsMintConverter()); |
+ return conversion_kind() == other->AsMintConverter()->conversion_kind(); |
+ } |
+ |
+ virtual bool MayThrow() const { return false; } |
+ |
+ DECLARE_INSTRUCTION(MintConverter) |
+ |
+ private: |
+ intptr_t conversion_kind_; |
+ DISALLOW_COPY_AND_ASSIGN(MintConverterInstr); |
+}; |
+ |
+ |
class BinaryMintOpInstr : public TemplateDefinition<2> { |
public: |
BinaryMintOpInstr(Token::Kind op_kind, |
Value* left, |
Value* right, |
intptr_t deopt_id) |
- : op_kind_(op_kind) { |
+ : op_kind_(op_kind), |
+ is_32_bit_(false) { |
SetInputAt(0, left); |
SetInputAt(1, right); |
// Override generated deopt-id. |
@@ -7052,21 +7123,27 @@ class BinaryMintOpInstr : public TemplateDefinition<2> { |
Token::Kind op_kind() const { return op_kind_; } |
+ bool IsInput32Bit(intptr_t i) const { |
+ return RequiredInputRepresentation(i) == kUnboxedMint32; |
+ } |
+ |
+ bool is_32_bit() const { return is_32_bit_; } |
+ void set_is_32_bit(bool v) { is_32_bit_ = v; } |
+ |
virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ virtual void PrintTo(BufferFormatter* f) const; |
virtual bool CanDeoptimize() const { |
return FLAG_throw_on_javascript_int_overflow || |
- (op_kind() == Token::kADD) || (op_kind() == Token::kSUB); |
+ (!is_32_bit() && |
+ ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB))); |
} |
virtual Representation representation() const { |
- return kUnboxedMint; |
+ return is_32_bit() ? kUnboxedMint32 : kUnboxedMint; |
} |
- virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
- ASSERT((idx == 0) || (idx == 1)); |
- return kUnboxedMint; |
- } |
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const; |
virtual intptr_t DeoptimizationTarget() const { |
// Direct access since this instruction cannot deoptimize, and the deopt-id |
@@ -7093,6 +7170,7 @@ class BinaryMintOpInstr : public TemplateDefinition<2> { |
private: |
const Token::Kind op_kind_; |
+ bool is_32_bit_; |
DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr); |
}; |
@@ -7104,7 +7182,8 @@ class ShiftMintOpInstr : public TemplateDefinition<2> { |
Value* left, |
Value* right, |
intptr_t deopt_id) |
- : op_kind_(op_kind) { |
+ : op_kind_(op_kind), |
+ is_32_bit_(false) { |
ASSERT(op_kind == Token::kSHR || op_kind == Token::kSHL); |
SetInputAt(0, left); |
SetInputAt(1, right); |
@@ -7117,19 +7196,36 @@ class ShiftMintOpInstr : public TemplateDefinition<2> { |
Token::Kind op_kind() const { return op_kind_; } |
+ bool IsInput32Bit(intptr_t i) const { |
+ return RequiredInputRepresentation(i) == kUnboxedMint32; |
+ } |
+ |
+ bool is_32_bit() const { return is_32_bit_; } |
+ void set_is_32_bit(bool v) { is_32_bit_ = v; } |
+ |
virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ virtual void PrintTo(BufferFormatter* f) const; |
- virtual bool CanDeoptimize() const { return true; } |
+ virtual bool CanDeoptimize() const { |
+ return true; |
+ } |
virtual CompileType ComputeType() const; |
virtual Representation representation() const { |
- return kUnboxedMint; |
+ return is_32_bit() ? kUnboxedMint32 : kUnboxedMint; |
+ } |
+ |
+ bool CanShiftLeftOverflow() const { |
+ return !IsInput32Bit(0) && !is_32_bit(); |
} |
virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
ASSERT((idx == 0) || (idx == 1)); |
- return (idx == 0) ? kUnboxedMint : kTagged; |
+ if (idx == 1) { |
+ return kTagged; |
+ } |
+ return InputAt(idx)->BindsTo32BitMint() ? kUnboxedMint32 : kUnboxedMint; |
} |
virtual intptr_t DeoptimizationTarget() const { |
@@ -7151,6 +7247,7 @@ class ShiftMintOpInstr : public TemplateDefinition<2> { |
private: |
const Token::Kind op_kind_; |
+ bool is_32_bit_; |
DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); |
}; |
@@ -7159,7 +7256,8 @@ class ShiftMintOpInstr : public TemplateDefinition<2> { |
class UnaryMintOpInstr : public TemplateDefinition<1> { |
public: |
UnaryMintOpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id) |
- : op_kind_(op_kind) { |
+ : op_kind_(op_kind), |
+ is_32_bit_(false) { |
ASSERT(op_kind == Token::kBIT_NOT); |
SetInputAt(0, value); |
// Override generated deopt-id. |
@@ -7170,19 +7268,27 @@ class UnaryMintOpInstr : public TemplateDefinition<1> { |
Token::Kind op_kind() const { return op_kind_; } |
+ bool IsInput32Bit(intptr_t i) const { |
+ return RequiredInputRepresentation(i) == kUnboxedMint32; |
+ } |
+ |
+ bool is_32_bit() const { return is_32_bit_; } |
+ void set_is_32_bit(bool v) { is_32_bit_ = v; } |
+ |
virtual void PrintOperandsTo(BufferFormatter* f) const; |
+ virtual void PrintTo(BufferFormatter* f) const; |
virtual bool CanDeoptimize() const { |
- return FLAG_throw_on_javascript_int_overflow; |
+ return FLAG_throw_on_javascript_int_overflow && !is_32_bit(); |
} |
virtual Representation representation() const { |
- return kUnboxedMint; |
+ return is_32_bit() ? kUnboxedMint32 : kUnboxedMint; |
} |
virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
ASSERT(idx == 0); |
- return kUnboxedMint; |
+ return InputAt(idx)->BindsTo32BitMint() ? kUnboxedMint32 : kUnboxedMint; |
} |
virtual intptr_t DeoptimizationTarget() const { |
@@ -7205,6 +7311,7 @@ class UnaryMintOpInstr : public TemplateDefinition<1> { |
private: |
const Token::Kind op_kind_; |
+ bool is_32_bit_; |
DISALLOW_COPY_AND_ASSIGN(UnaryMintOpInstr); |
}; |
@@ -7250,7 +7357,7 @@ class BinarySmiOpInstr : public TemplateDefinition<2> { |
virtual EffectSet Dependencies() const { return EffectSet::None(); } |
virtual bool AttributesEqual(Instruction* other) const; |
- void PrintTo(BufferFormatter* f) const; |
+ virtual void PrintTo(BufferFormatter* f) const; |
virtual void InferRange(); |