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