| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
| 6 #define RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
| 7 | 7 |
| 8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
| 9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
| 10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 M(BinaryMintOp) \ | 446 M(BinaryMintOp) \ |
| 447 M(ShiftMintOp) \ | 447 M(ShiftMintOp) \ |
| 448 M(UnaryMintOp) \ | 448 M(UnaryMintOp) \ |
| 449 M(CheckArrayBound) \ | 449 M(CheckArrayBound) \ |
| 450 M(GenericCheckBound) \ | 450 M(GenericCheckBound) \ |
| 451 M(Constraint) \ | 451 M(Constraint) \ |
| 452 M(StringToCharCode) \ | 452 M(StringToCharCode) \ |
| 453 M(OneByteStringFromCharCode) \ | 453 M(OneByteStringFromCharCode) \ |
| 454 M(StringInterpolate) \ | 454 M(StringInterpolate) \ |
| 455 M(InvokeMathCFunction) \ | 455 M(InvokeMathCFunction) \ |
| 456 M(MergedMath) \ | 456 M(TruncDivMod) \ |
| 457 M(GuardFieldClass) \ | 457 M(GuardFieldClass) \ |
| 458 M(GuardFieldLength) \ | 458 M(GuardFieldLength) \ |
| 459 M(IfThenElse) \ | 459 M(IfThenElse) \ |
| 460 M(BinaryFloat32x4Op) \ | 460 M(BinaryFloat32x4Op) \ |
| 461 M(Simd32x4Shuffle) \ | 461 M(Simd32x4Shuffle) \ |
| 462 M(Simd32x4ShuffleMix) \ | 462 M(Simd32x4ShuffleMix) \ |
| 463 M(Simd32x4GetSignMask) \ | 463 M(Simd32x4GetSignMask) \ |
| 464 M(Float32x4Constructor) \ | 464 M(Float32x4Constructor) \ |
| 465 M(Float32x4Zero) \ | 465 M(Float32x4Zero) \ |
| 466 M(Float32x4Splat) \ | 466 M(Float32x4Splat) \ |
| (...skipping 6455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6922 bool is_truncating_; | 6922 bool is_truncating_; |
| 6923 }; | 6923 }; |
| 6924 | 6924 |
| 6925 | 6925 |
| 6926 class BinarySmiOpInstr : public BinaryIntegerOpInstr { | 6926 class BinarySmiOpInstr : public BinaryIntegerOpInstr { |
| 6927 public: | 6927 public: |
| 6928 BinarySmiOpInstr(Token::Kind op_kind, | 6928 BinarySmiOpInstr(Token::Kind op_kind, |
| 6929 Value* left, | 6929 Value* left, |
| 6930 Value* right, | 6930 Value* right, |
| 6931 intptr_t deopt_id) | 6931 intptr_t deopt_id) |
| 6932 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) {} | 6932 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id), |
| 6933 right_range_(NULL) {} |
| 6933 | 6934 |
| 6934 virtual bool ComputeCanDeoptimize() const; | 6935 virtual bool ComputeCanDeoptimize() const; |
| 6935 | 6936 |
| 6936 virtual void InferRange(RangeAnalysis* analysis, Range* range); | 6937 virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| 6937 virtual CompileType ComputeType() const; | 6938 virtual CompileType ComputeType() const; |
| 6938 | 6939 |
| 6939 DECLARE_INSTRUCTION(BinarySmiOp) | 6940 DECLARE_INSTRUCTION(BinarySmiOp) |
| 6940 | 6941 |
| 6942 Range* right_range() const { return right_range_; } |
| 6943 |
| 6941 private: | 6944 private: |
| 6945 Range* right_range_; |
| 6946 |
| 6942 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); | 6947 DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); |
| 6943 }; | 6948 }; |
| 6944 | 6949 |
| 6945 | 6950 |
| 6946 class BinaryInt32OpInstr : public BinaryIntegerOpInstr { | 6951 class BinaryInt32OpInstr : public BinaryIntegerOpInstr { |
| 6947 public: | 6952 public: |
| 6948 BinaryInt32OpInstr(Token::Kind op_kind, | 6953 BinaryInt32OpInstr(Token::Kind op_kind, |
| 6949 Value* left, | 6954 Value* left, |
| 6950 Value* right, | 6955 Value* right, |
| 6951 intptr_t deopt_id) | 6956 intptr_t deopt_id) |
| 6952 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { | 6957 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| 6953 SetInputAt(0, left); | 6958 SetInputAt(0, left); |
| 6954 SetInputAt(1, right); | 6959 SetInputAt(1, right); |
| 6955 } | 6960 } |
| 6956 | 6961 |
| 6957 static bool IsSupported(Token::Kind op, Value* left, Value* right) { | 6962 static bool IsSupported(Token::Kind op, Value* left, Value* right) { |
| 6958 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 6963 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
| 6959 switch (op) { | 6964 switch (op) { |
| 6960 case Token::kADD: | 6965 case Token::kADD: |
| 6961 case Token::kSUB: | 6966 case Token::kSUB: |
| 6962 case Token::kMUL: | 6967 case Token::kMUL: |
| 6963 case Token::kBIT_AND: | 6968 case Token::kBIT_AND: |
| 6964 case Token::kBIT_OR: | 6969 case Token::kBIT_OR: |
| 6965 case Token::kBIT_XOR: | 6970 case Token::kBIT_XOR: |
| 6966 return true; | 6971 return true; |
| 6967 | 6972 |
| 6968 case Token::kSHL: | 6973 case Token::kSHL: |
| 6969 case Token::kSHR: | 6974 case Token::kSHR: |
| 6970 return right->BindsToConstant(); | 6975 if (right->BindsToConstant() && right->BoundConstant().IsSmi()) { |
| 6976 const intptr_t value = Smi::Cast(right->BoundConstant()).Value(); |
| 6977 return 0 <= value && value < kBitsPerWord; |
| 6978 } |
| 6979 return false; |
| 6971 | 6980 |
| 6972 default: | 6981 default: |
| 6973 return false; | 6982 return false; |
| 6974 } | 6983 } |
| 6975 #else | 6984 #else |
| 6976 return false; | 6985 return false; |
| 6977 #endif | 6986 #endif |
| 6978 } | 6987 } |
| 6979 | 6988 |
| 6980 virtual bool ComputeCanDeoptimize() const; | 6989 virtual bool ComputeCanDeoptimize() const; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7082 DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr); | 7091 DISALLOW_COPY_AND_ASSIGN(BinaryMintOpInstr); |
| 7083 }; | 7092 }; |
| 7084 | 7093 |
| 7085 | 7094 |
| 7086 class ShiftMintOpInstr : public BinaryIntegerOpInstr { | 7095 class ShiftMintOpInstr : public BinaryIntegerOpInstr { |
| 7087 public: | 7096 public: |
| 7088 ShiftMintOpInstr(Token::Kind op_kind, | 7097 ShiftMintOpInstr(Token::Kind op_kind, |
| 7089 Value* left, | 7098 Value* left, |
| 7090 Value* right, | 7099 Value* right, |
| 7091 intptr_t deopt_id) | 7100 intptr_t deopt_id) |
| 7092 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { | 7101 : BinaryIntegerOpInstr(op_kind, left, right, deopt_id), |
| 7102 shift_range_(NULL) { |
| 7093 ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL)); | 7103 ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL)); |
| 7094 } | 7104 } |
| 7095 | 7105 |
| 7106 Range* shift_range() const { return shift_range_; } |
| 7107 |
| 7096 virtual bool ComputeCanDeoptimize() const { | 7108 virtual bool ComputeCanDeoptimize() const { |
| 7097 return has_shift_count_check() || | 7109 return has_shift_count_check() || |
| 7098 (can_overflow() && (op_kind() == Token::kSHL)); | 7110 (can_overflow() && (op_kind() == Token::kSHL)); |
| 7099 } | 7111 } |
| 7100 | 7112 |
| 7101 virtual Representation representation() const { return kUnboxedMint; } | 7113 virtual Representation representation() const { return kUnboxedMint; } |
| 7102 | 7114 |
| 7103 virtual Representation RequiredInputRepresentation(intptr_t idx) const { | 7115 virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| 7104 ASSERT((idx == 0) || (idx == 1)); | 7116 ASSERT((idx == 0) || (idx == 1)); |
| 7105 return (idx == 0) ? kUnboxedMint : kTagged; | 7117 return (idx == 0) ? kUnboxedMint : kTagged; |
| 7106 } | 7118 } |
| 7107 | 7119 |
| 7108 virtual void InferRange(RangeAnalysis* analysis, Range* range); | 7120 virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| 7109 virtual CompileType ComputeType() const; | 7121 virtual CompileType ComputeType() const; |
| 7110 | 7122 |
| 7111 DECLARE_INSTRUCTION(ShiftMintOp) | 7123 DECLARE_INSTRUCTION(ShiftMintOp) |
| 7112 | 7124 |
| 7113 private: | 7125 private: |
| 7126 static const intptr_t kMintShiftCountLimit = 63; |
| 7114 bool has_shift_count_check() const; | 7127 bool has_shift_count_check() const; |
| 7115 | 7128 |
| 7129 Range* shift_range_; |
| 7130 |
| 7116 DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); | 7131 DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); |
| 7117 }; | 7132 }; |
| 7118 | 7133 |
| 7119 | 7134 |
| 7120 // Handles only NEGATE. | 7135 // Handles only NEGATE. |
| 7121 class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> { | 7136 class UnaryDoubleOpInstr : public TemplateDefinition<1, NoThrow, Pure> { |
| 7122 public: | 7137 public: |
| 7123 UnaryDoubleOpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id) | 7138 UnaryDoubleOpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id) |
| 7124 : TemplateDefinition(deopt_id), op_kind_(op_kind) { | 7139 : TemplateDefinition(deopt_id), op_kind_(op_kind) { |
| 7125 ASSERT(op_kind == Token::kNEGATE); | 7140 ASSERT(op_kind == Token::kNEGATE); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7538 PRINT_OPERANDS_TO_SUPPORT | 7553 PRINT_OPERANDS_TO_SUPPORT |
| 7539 | 7554 |
| 7540 private: | 7555 private: |
| 7541 const intptr_t index_; | 7556 const intptr_t index_; |
| 7542 const Representation definition_rep_; | 7557 const Representation definition_rep_; |
| 7543 const intptr_t definition_cid_; | 7558 const intptr_t definition_cid_; |
| 7544 DISALLOW_COPY_AND_ASSIGN(ExtractNthOutputInstr); | 7559 DISALLOW_COPY_AND_ASSIGN(ExtractNthOutputInstr); |
| 7545 }; | 7560 }; |
| 7546 | 7561 |
| 7547 | 7562 |
| 7548 class MergedMathInstr : public PureDefinition { | 7563 class TruncDivModInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| 7549 public: | 7564 public: |
| 7550 enum Kind { | 7565 TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id); |
| 7551 kTruncDivMod, | |
| 7552 }; | |
| 7553 | 7566 |
| 7554 MergedMathInstr(ZoneGrowableArray<Value*>* inputs, | |
| 7555 intptr_t original_deopt_id, | |
| 7556 MergedMathInstr::Kind kind); | |
| 7557 | |
| 7558 static intptr_t InputCountFor(MergedMathInstr::Kind kind) { | |
| 7559 if (kind == kTruncDivMod) { | |
| 7560 return 2; | |
| 7561 } else { | |
| 7562 UNIMPLEMENTED(); | |
| 7563 return -1; | |
| 7564 } | |
| 7565 } | |
| 7566 | |
| 7567 MergedMathInstr::Kind kind() const { return kind_; } | |
| 7568 | |
| 7569 virtual intptr_t InputCount() const { return inputs_->length(); } | |
| 7570 | |
| 7571 virtual Value* InputAt(intptr_t i) const { return (*inputs_)[i]; } | |
| 7572 | |
| 7573 static intptr_t OutputIndexOf(MethodRecognizer::Kind kind); | |
| 7574 static intptr_t OutputIndexOf(Token::Kind token); | 7567 static intptr_t OutputIndexOf(Token::Kind token); |
| 7575 | 7568 |
| 7576 virtual CompileType ComputeType() const; | 7569 virtual CompileType ComputeType() const; |
| 7577 | 7570 |
| 7578 virtual bool ComputeCanDeoptimize() const { | 7571 virtual bool ComputeCanDeoptimize() const { return true; } |
| 7579 if (kind_ == kTruncDivMod) { | |
| 7580 return true; | |
| 7581 } else { | |
| 7582 UNIMPLEMENTED(); | |
| 7583 return false; | |
| 7584 } | |
| 7585 } | |
| 7586 | 7572 |
| 7587 virtual Representation representation() const { | 7573 virtual Representation representation() const { return kPairOfTagged; } |
| 7588 if (kind_ == kTruncDivMod) { | |
| 7589 return kPairOfTagged; | |
| 7590 } else { | |
| 7591 UNIMPLEMENTED(); | |
| 7592 return kTagged; | |
| 7593 } | |
| 7594 } | |
| 7595 | 7574 |
| 7596 virtual Representation RequiredInputRepresentation(intptr_t idx) const { | 7575 virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| 7597 ASSERT((0 <= idx) && (idx < InputCount())); | 7576 ASSERT((0 <= idx) && (idx < InputCount())); |
| 7598 if (kind_ == kTruncDivMod) { | 7577 return kTagged; |
| 7599 return kTagged; | |
| 7600 } else { | |
| 7601 UNIMPLEMENTED(); | |
| 7602 return kTagged; | |
| 7603 } | |
| 7604 } | 7578 } |
| 7605 | 7579 |
| 7606 virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); } | 7580 virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); } |
| 7607 | 7581 |
| 7608 DECLARE_INSTRUCTION(MergedMath) | 7582 DECLARE_INSTRUCTION(TruncDivMod) |
| 7609 | 7583 |
| 7610 virtual bool AttributesEqual(Instruction* other) const { | 7584 virtual bool AttributesEqual(Instruction* other) const { return true; } |
| 7611 MergedMathInstr* other_invoke = other->AsMergedMath(); | |
| 7612 return other_invoke->kind() == kind(); | |
| 7613 } | |
| 7614 | |
| 7615 virtual bool MayThrow() const { return false; } | |
| 7616 | |
| 7617 static const char* KindToCString(MergedMathInstr::Kind kind) { | |
| 7618 if (kind == kTruncDivMod) return "TruncDivMod"; | |
| 7619 UNIMPLEMENTED(); | |
| 7620 return ""; | |
| 7621 } | |
| 7622 | 7585 |
| 7623 PRINT_OPERANDS_TO_SUPPORT | 7586 PRINT_OPERANDS_TO_SUPPORT |
| 7624 | 7587 |
| 7625 private: | 7588 private: |
| 7626 virtual void RawSetInputAt(intptr_t i, Value* value) { | 7589 Range* divisor_range() const { |
| 7627 (*inputs_)[i] = value; | 7590 // Note: this range is only used to remove check for zero divisor from |
| 7591 // the emitted pattern. It is not used for deciding whether instruction |
| 7592 // will deoptimize or not - that is why it is ok to access range of |
| 7593 // the definition directly. Otherwise range analysis or another pass |
| 7594 // needs to cache range of the divisor in the operation to prevent |
| 7595 // bugs when range information gets out of sync with the final decision |
| 7596 // whether some instruction can deoptimize or not made in |
| 7597 // EliminateEnvironments(). |
| 7598 return InputAt(1)->definition()->range(); |
| 7628 } | 7599 } |
| 7629 ZoneGrowableArray<Value*>* inputs_; | 7600 |
| 7630 MergedMathInstr::Kind kind_; | 7601 DISALLOW_COPY_AND_ASSIGN(TruncDivModInstr); |
| 7631 DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); | |
| 7632 }; | 7602 }; |
| 7633 | 7603 |
| 7634 | 7604 |
| 7635 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { | 7605 class CheckClassInstr : public TemplateInstruction<1, NoThrow> { |
| 7636 public: | 7606 public: |
| 7637 CheckClassInstr(Value* value, | 7607 CheckClassInstr(Value* value, |
| 7638 intptr_t deopt_id, | 7608 intptr_t deopt_id, |
| 7639 const Cids& cids, | 7609 const Cids& cids, |
| 7640 TokenPosition token_pos); | 7610 TokenPosition token_pos); |
| 7641 | 7611 |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8170 LocationSummary* Name::MakeLocationSummary(Zone* zone, bool opt) const { \ | 8140 LocationSummary* Name::MakeLocationSummary(Zone* zone, bool opt) const { \ |
| 8171 UNIMPLEMENTED(); \ | 8141 UNIMPLEMENTED(); \ |
| 8172 return NULL; \ | 8142 return NULL; \ |
| 8173 } \ | 8143 } \ |
| 8174 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8144 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
| 8175 | 8145 |
| 8176 | 8146 |
| 8177 } // namespace dart | 8147 } // namespace dart |
| 8178 | 8148 |
| 8179 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ | 8149 #endif // RUNTIME_VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |