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 |