OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 V(AllocateObject) \ | 68 V(AllocateObject) \ |
69 V(ApplyArguments) \ | 69 V(ApplyArguments) \ |
70 V(ArgumentsElements) \ | 70 V(ArgumentsElements) \ |
71 V(ArgumentsLength) \ | 71 V(ArgumentsLength) \ |
72 V(ArgumentsObject) \ | 72 V(ArgumentsObject) \ |
73 V(ArrayLiteral) \ | 73 V(ArrayLiteral) \ |
74 V(Bitwise) \ | 74 V(Bitwise) \ |
75 V(BitNot) \ | 75 V(BitNot) \ |
76 V(BlockEntry) \ | 76 V(BlockEntry) \ |
77 V(BoundsCheck) \ | 77 V(BoundsCheck) \ |
| 78 V(BoundsCheckBaseIndexInformation) \ |
78 V(Branch) \ | 79 V(Branch) \ |
79 V(CallConstantFunction) \ | 80 V(CallConstantFunction) \ |
80 V(CallFunction) \ | 81 V(CallFunction) \ |
81 V(CallGlobal) \ | 82 V(CallGlobal) \ |
82 V(CallKeyed) \ | 83 V(CallKeyed) \ |
83 V(CallKnownGlobal) \ | 84 V(CallKnownGlobal) \ |
84 V(CallNamed) \ | 85 V(CallNamed) \ |
85 V(CallNew) \ | 86 V(CallNew) \ |
86 V(CallNewArray) \ | 87 V(CallNewArray) \ |
87 V(CallRuntime) \ | 88 V(CallRuntime) \ |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 case GT: return (direction >= 0); | 661 case GT: return (direction >= 0); |
661 case GE: return (direction >= 0); | 662 case GE: return (direction >= 0); |
662 case LT: return (direction <= 0); | 663 case LT: return (direction <= 0); |
663 case LE: return (direction <= 0); | 664 case LE: return (direction <= 0); |
664 case NE: return false; | 665 case NE: return false; |
665 } | 666 } |
666 UNREACHABLE(); | 667 UNREACHABLE(); |
667 return false; | 668 return false; |
668 } | 669 } |
669 | 670 |
| 671 // CompoundImplies returns true when |
| 672 // "((x + my_offset) >> my_scale) rel y" implies |
| 673 // "((x + other_offset) >> other_scale) other_relation y". |
| 674 bool CompoundImplies(NumericRelation other_relation, |
| 675 int my_offset, |
| 676 int my_scale, |
| 677 int other_offset = 0, |
| 678 int other_scale = 0) { |
| 679 return Implies(other_relation) && ComponentsImply( |
| 680 my_offset, my_scale, other_offset, other_scale); |
| 681 } |
| 682 |
670 private: | 683 private: |
| 684 // ComponentsImply returns true when |
| 685 // "((x + my_offset) >> my_scale) rel y" implies |
| 686 // "((x + other_offset) >> other_scale) rel y". |
| 687 bool ComponentsImply(int my_offset, |
| 688 int my_scale, |
| 689 int other_offset, |
| 690 int other_scale) { |
| 691 switch (kind_) { |
| 692 case NONE: break; // Fall through to UNREACHABLE(). |
| 693 case EQ: |
| 694 case NE: return my_offset == other_offset && my_scale == other_scale; |
| 695 case GT: |
| 696 case GE: return my_offset <= other_offset && my_scale >= other_scale; |
| 697 case LT: |
| 698 case LE: return my_offset >= other_offset && my_scale <= other_scale; |
| 699 } |
| 700 UNREACHABLE(); |
| 701 return false; |
| 702 } |
| 703 |
671 explicit NumericRelation(Kind kind) : kind_(kind) {} | 704 explicit NumericRelation(Kind kind) : kind_(kind) {} |
672 | 705 |
673 Kind kind_; | 706 Kind kind_; |
674 }; | 707 }; |
675 | 708 |
676 | 709 |
| 710 class DecompositionResult BASE_EMBEDDED { |
| 711 public: |
| 712 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {} |
| 713 |
| 714 HValue* base() { return base_; } |
| 715 int offset() { return offset_; } |
| 716 int scale() { return scale_; } |
| 717 |
| 718 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) { |
| 719 if (base_ == NULL) { |
| 720 base_ = other_base; |
| 721 offset_ = other_offset; |
| 722 scale_ = other_scale; |
| 723 return true; |
| 724 } else { |
| 725 if (scale_ == 0) { |
| 726 base_ = other_base; |
| 727 offset_ += other_offset; |
| 728 scale_ = other_scale; |
| 729 return true; |
| 730 } else { |
| 731 return false; |
| 732 } |
| 733 } |
| 734 } |
| 735 |
| 736 void SwapValues(HValue** other_base, int* other_offset, int* other_scale) { |
| 737 swap(&base_, other_base); |
| 738 swap(&offset_, other_offset); |
| 739 swap(&scale_, other_scale); |
| 740 } |
| 741 |
| 742 private: |
| 743 template <class T> void swap(T* a, T* b) { |
| 744 T c(*a); |
| 745 *a = *b; |
| 746 *b = c; |
| 747 } |
| 748 |
| 749 HValue* base_; |
| 750 int offset_; |
| 751 int scale_; |
| 752 }; |
| 753 |
| 754 |
| 755 class RangeEvaluationContext BASE_EMBEDDED { |
| 756 public: |
| 757 RangeEvaluationContext(HValue* value, HValue* upper); |
| 758 |
| 759 HValue* lower_bound() { return lower_bound_; } |
| 760 HValue* lower_bound_guarantee() { return lower_bound_guarantee_; } |
| 761 HValue* candidate() { return candidate_; } |
| 762 HValue* upper_bound() { return upper_bound_; } |
| 763 HValue* upper_bound_guarantee() { return upper_bound_guarantee_; } |
| 764 int offset() { return offset_; } |
| 765 int scale() { return scale_; } |
| 766 |
| 767 bool is_range_satisfied() { |
| 768 return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL; |
| 769 } |
| 770 |
| 771 void set_lower_bound_guarantee(HValue* guarantee) { |
| 772 lower_bound_guarantee_ = ConvertGuarantee(guarantee); |
| 773 } |
| 774 void set_upper_bound_guarantee(HValue* guarantee) { |
| 775 upper_bound_guarantee_ = ConvertGuarantee(guarantee); |
| 776 } |
| 777 |
| 778 void swap_candidate(DecompositionResult* other_candicate) { |
| 779 other_candicate->SwapValues(&candidate_, &offset_, &scale_); |
| 780 } |
| 781 |
| 782 private: |
| 783 HValue* ConvertGuarantee(HValue* guarantee); |
| 784 |
| 785 HValue* lower_bound_; |
| 786 HValue* lower_bound_guarantee_; |
| 787 HValue* candidate_; |
| 788 HValue* upper_bound_; |
| 789 HValue* upper_bound_guarantee_; |
| 790 int offset_; |
| 791 int scale_; |
| 792 }; |
| 793 |
| 794 |
677 typedef EnumSet<GVNFlag> GVNFlagSet; | 795 typedef EnumSet<GVNFlag> GVNFlagSet; |
678 | 796 |
679 | 797 |
680 class HValue: public ZoneObject { | 798 class HValue: public ZoneObject { |
681 public: | 799 public: |
682 static const int kNoNumber = -1; | 800 static const int kNoNumber = -1; |
683 | 801 |
684 enum Flag { | 802 enum Flag { |
685 kFlexibleRepresentation, | 803 kFlexibleRepresentation, |
686 // Participate in Global Value Numbering, i.e. elimination of | 804 // Participate in Global Value Numbering, i.e. elimination of |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 } | 1088 } |
971 | 1089 |
972 bool IsDead() const { | 1090 bool IsDead() const { |
973 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); | 1091 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); |
974 } | 1092 } |
975 | 1093 |
976 #ifdef DEBUG | 1094 #ifdef DEBUG |
977 virtual void Verify() = 0; | 1095 virtual void Verify() = 0; |
978 #endif | 1096 #endif |
979 | 1097 |
980 // This method is recursive but it is guaranteed to terminate because | 1098 bool IsRelationTrue(NumericRelation relation, |
981 // RedefinedOperand() always dominates "this". | 1099 HValue* other, |
982 bool IsRelationTrue(NumericRelation relation, HValue* other) { | 1100 int offset = 0, |
983 if (this == other) { | 1101 int scale = 0); |
984 return NumericRelation::Eq().Implies(relation); | 1102 |
| 1103 bool TryGuaranteeRange(HValue* upper_bound); |
| 1104 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 1105 if (RedefinedOperand() != NULL) { |
| 1106 return RedefinedOperand()->TryDecompose(decomposition); |
| 1107 } else { |
| 1108 return false; |
985 } | 1109 } |
986 | |
987 bool result = IsRelationTrueInternal(relation, other) || | |
988 other->IsRelationTrueInternal(relation.Reversed(), this); | |
989 if (!result) { | |
990 HValue* redefined = RedefinedOperand(); | |
991 if (redefined != NULL) { | |
992 result = redefined->IsRelationTrue(relation, other); | |
993 } | |
994 } | |
995 return result; | |
996 } | 1110 } |
997 | 1111 |
998 protected: | 1112 protected: |
| 1113 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); |
| 1114 |
| 1115 enum RangeGuaranteeDirection { |
| 1116 DIRECTION_NONE = 0, |
| 1117 DIRECTION_UPPER = 1, |
| 1118 DIRECTION_LOWER = 2, |
| 1119 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER |
| 1120 }; |
| 1121 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} |
| 1122 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {} |
| 1123 |
999 // This function must be overridden for instructions with flag kUseGVN, to | 1124 // This function must be overridden for instructions with flag kUseGVN, to |
1000 // compare the non-Operand parts of the instruction. | 1125 // compare the non-Operand parts of the instruction. |
1001 virtual bool DataEquals(HValue* other) { | 1126 virtual bool DataEquals(HValue* other) { |
1002 UNREACHABLE(); | 1127 UNREACHABLE(); |
1003 return false; | 1128 return false; |
1004 } | 1129 } |
1005 | 1130 |
1006 virtual Representation RepresentationFromInputs() { | 1131 virtual Representation RepresentationFromInputs() { |
1007 return representation(); | 1132 return representation(); |
1008 } | 1133 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 HValue* use = uses.value(); | 1177 HValue* use = uses.value(); |
1053 if (TestDominance(this, use)) { | 1178 if (TestDominance(this, use)) { |
1054 use->SetOperandAt(uses.index(), this); | 1179 use->SetOperandAt(uses.index(), this); |
1055 } | 1180 } |
1056 } | 1181 } |
1057 } | 1182 } |
1058 } | 1183 } |
1059 | 1184 |
1060 // Informative definitions can override this method to state any numeric | 1185 // Informative definitions can override this method to state any numeric |
1061 // relation they provide on the redefined value. | 1186 // relation they provide on the redefined value. |
1062 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 1187 // Returns true if it is guaranteed that: |
| 1188 // ((this + offset) >> scale) relation other |
| 1189 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 1190 HValue* other, |
| 1191 int offset = 0, |
| 1192 int scale = 0) { |
1063 return false; | 1193 return false; |
1064 } | 1194 } |
1065 | 1195 |
1066 static GVNFlagSet AllDependsOnFlagSet() { | 1196 static GVNFlagSet AllDependsOnFlagSet() { |
1067 GVNFlagSet result; | 1197 GVNFlagSet result; |
1068 // Create changes mask. | 1198 // Create changes mask. |
1069 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 1199 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
1070 GVN_TRACKED_FLAG_LIST(ADD_FLAG) | 1200 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
1071 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | 1201 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
1072 #undef ADD_FLAG | 1202 #undef ADD_FLAG |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 virtual int RedefinedOperandIndex() { return 0; } | 1431 virtual int RedefinedOperandIndex() { return 0; } |
1302 virtual bool IsPurelyInformativeDefinition() { return true; } | 1432 virtual bool IsPurelyInformativeDefinition() { return true; } |
1303 | 1433 |
1304 virtual Representation RequiredInputRepresentation(int index) { | 1434 virtual Representation RequiredInputRepresentation(int index) { |
1305 return representation(); | 1435 return representation(); |
1306 } | 1436 } |
1307 | 1437 |
1308 virtual void PrintDataTo(StringStream* stream); | 1438 virtual void PrintDataTo(StringStream* stream); |
1309 | 1439 |
1310 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 1440 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
1311 HValue* other_related_value) { | 1441 HValue* other_related_value, |
| 1442 int offset = 0, |
| 1443 int scale = 0) { |
1312 if (related_value() == other_related_value) { | 1444 if (related_value() == other_related_value) { |
1313 return relation().Implies(other_relation); | 1445 return relation().CompoundImplies(other_relation, offset, scale); |
1314 } else { | 1446 } else { |
1315 return false; | 1447 return false; |
1316 } | 1448 } |
1317 } | 1449 } |
1318 | 1450 |
1319 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) | 1451 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) |
1320 | 1452 |
1321 private: | 1453 private: |
1322 HNumericConstraint(HValue* constrained_value, | 1454 HNumericConstraint(HValue* constrained_value, |
1323 NumericRelation relation, | 1455 NumericRelation relation, |
1324 HValue* related_value) | 1456 HValue* related_value) |
1325 : relation_(relation) { | 1457 : relation_(relation) { |
1326 SetOperandAt(0, constrained_value); | 1458 SetOperandAt(0, constrained_value); |
1327 SetOperandAt(1, related_value); | 1459 SetOperandAt(1, related_value); |
1328 set_representation(constrained_value->representation()); | |
1329 } | 1460 } |
1330 | 1461 |
1331 NumericRelation relation_; | 1462 NumericRelation relation_; |
1332 }; | 1463 }; |
1333 | 1464 |
1334 | 1465 |
1335 // We insert soft-deoptimize when we hit code with unknown typefeedback, | 1466 // We insert soft-deoptimize when we hit code with unknown typefeedback, |
1336 // so that we get a chance of re-optimizing with useful typefeedback. | 1467 // so that we get a chance of re-optimizing with useful typefeedback. |
1337 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. | 1468 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. |
1338 class HSoftDeoptimize: public HTemplateInstruction<0> { | 1469 class HSoftDeoptimize: public HTemplateInstruction<0> { |
(...skipping 1646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2985 } | 3116 } |
2986 return true; | 3117 return true; |
2987 } | 3118 } |
2988 | 3119 |
2989 protected: | 3120 protected: |
2990 virtual void DeleteFromGraph(); | 3121 virtual void DeleteFromGraph(); |
2991 virtual void InternalSetOperandAt(int index, HValue* value) { | 3122 virtual void InternalSetOperandAt(int index, HValue* value) { |
2992 inputs_[index] = value; | 3123 inputs_[index] = value; |
2993 } | 3124 } |
2994 | 3125 |
2995 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other); | 3126 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 3127 HValue* other, |
| 3128 int offset = 0, |
| 3129 int scale = 0); |
2996 | 3130 |
2997 private: | 3131 private: |
2998 ZoneList<HValue*> inputs_; | 3132 ZoneList<HValue*> inputs_; |
2999 int merged_index_; | 3133 int merged_index_; |
3000 | 3134 |
3001 int non_phi_uses_[Representation::kNumRepresentations]; | 3135 int non_phi_uses_[Representation::kNumRepresentations]; |
3002 int indirect_uses_[Representation::kNumRepresentations]; | 3136 int indirect_uses_[Representation::kNumRepresentations]; |
3003 int phi_id_; | 3137 int phi_id_; |
3004 bool is_live_; | 3138 bool is_live_; |
3005 bool is_convertible_to_integer_; | 3139 bool is_convertible_to_integer_; |
(...skipping 11 matching lines...) Expand all Loading... |
3017 | 3151 |
3018 virtual int RedefinedOperandIndex() { return 0; } | 3152 virtual int RedefinedOperandIndex() { return 0; } |
3019 virtual bool IsPurelyInformativeDefinition() { return true; } | 3153 virtual bool IsPurelyInformativeDefinition() { return true; } |
3020 virtual Representation RequiredInputRepresentation(int index) { | 3154 virtual Representation RequiredInputRepresentation(int index) { |
3021 return representation(); | 3155 return representation(); |
3022 } | 3156 } |
3023 | 3157 |
3024 virtual void PrintDataTo(StringStream* stream); | 3158 virtual void PrintDataTo(StringStream* stream); |
3025 | 3159 |
3026 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 3160 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
3027 HValue* other_related_value) { | 3161 HValue* other_related_value, |
| 3162 int offset = 0, |
| 3163 int scale = 0) { |
3028 if (induction_base() == other_related_value) { | 3164 if (induction_base() == other_related_value) { |
3029 return relation().Implies(other_relation); | 3165 return relation().CompoundImplies(other_relation, offset, scale); |
3030 } else { | 3166 } else { |
3031 return false; | 3167 return false; |
3032 } | 3168 } |
3033 } | 3169 } |
3034 | 3170 |
3035 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) | 3171 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) |
3036 | 3172 |
3037 private: | 3173 private: |
3038 HInductionVariableAnnotation(HPhi* phi, | 3174 HInductionVariableAnnotation(HPhi* phi, |
3039 NumericRelation relation, | 3175 NumericRelation relation, |
3040 int operand_index) | 3176 int operand_index) |
3041 : HUnaryOperation(phi), | 3177 : HUnaryOperation(phi), |
3042 phi_(phi), relation_(relation), operand_index_(operand_index) { | 3178 phi_(phi), relation_(relation), operand_index_(operand_index) { |
3043 set_representation(phi->representation()); | |
3044 } | 3179 } |
3045 | 3180 |
3046 // We need to store the phi both here and in the instruction operand because | 3181 // We need to store the phi both here and in the instruction operand because |
3047 // the operand can change if a new idef of the phi is added between the phi | 3182 // the operand can change if a new idef of the phi is added between the phi |
3048 // and this instruction (inserting an idef updates every use). | 3183 // and this instruction (inserting an idef updates every use). |
3049 HPhi* phi_; | 3184 HPhi* phi_; |
3050 NumericRelation relation_; | 3185 NumericRelation relation_; |
3051 int operand_index_; | 3186 int operand_index_; |
3052 }; | 3187 }; |
3053 | 3188 |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3438 virtual bool DataEquals(HValue* other) { return true; } | 3573 virtual bool DataEquals(HValue* other) { return true; } |
3439 }; | 3574 }; |
3440 | 3575 |
3441 | 3576 |
3442 enum BoundsCheckKeyMode { | 3577 enum BoundsCheckKeyMode { |
3443 DONT_ALLOW_SMI_KEY, | 3578 DONT_ALLOW_SMI_KEY, |
3444 ALLOW_SMI_KEY | 3579 ALLOW_SMI_KEY |
3445 }; | 3580 }; |
3446 | 3581 |
3447 | 3582 |
| 3583 class HBoundsCheckBaseIndexInformation; |
| 3584 |
| 3585 |
3448 class HBoundsCheck: public HTemplateInstruction<2> { | 3586 class HBoundsCheck: public HTemplateInstruction<2> { |
3449 public: | 3587 public: |
3450 // Normally HBoundsCheck should be created using the | 3588 // Normally HBoundsCheck should be created using the |
3451 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with | 3589 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with |
3452 // a HCheckSmiOrInt32 check. | 3590 // a HCheckSmiOrInt32 check. |
3453 // However when building stubs, where we know that the arguments are Int32, | 3591 // However when building stubs, where we know that the arguments are Int32, |
3454 // it makes sense to invoke this constructor directly. | 3592 // it makes sense to invoke this constructor directly. |
3455 HBoundsCheck(HValue* index, | 3593 HBoundsCheck(HValue* index, |
3456 HValue* length, | 3594 HValue* length, |
3457 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, | 3595 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
3458 Representation r = Representation::None()) | 3596 Representation r = Representation::None()) |
3459 : key_mode_(key_mode), skip_check_(false) { | 3597 : key_mode_(key_mode), skip_check_(false), |
| 3598 base_(NULL), offset_(0), scale_(0), |
| 3599 responsibility_direction_(DIRECTION_NONE) { |
3460 SetOperandAt(0, index); | 3600 SetOperandAt(0, index); |
3461 SetOperandAt(1, length); | 3601 SetOperandAt(1, length); |
3462 if (r.IsNone()) { | 3602 if (r.IsNone()) { |
3463 // In the normal compilation pipeline the representation is flexible | 3603 // In the normal compilation pipeline the representation is flexible |
3464 // (see InferRepresentation). | 3604 // (see InferRepresentation). |
3465 SetFlag(kFlexibleRepresentation); | 3605 SetFlag(kFlexibleRepresentation); |
3466 } else { | 3606 } else { |
3467 // When compiling stubs we want to set the representation explicitly | 3607 // When compiling stubs we want to set the representation explicitly |
3468 // so the compilation pipeline can skip the HInferRepresentation phase. | 3608 // so the compilation pipeline can skip the HInferRepresentation phase. |
3469 set_representation(r); | 3609 set_representation(r); |
3470 } | 3610 } |
3471 SetFlag(kUseGVN); | 3611 SetFlag(kUseGVN); |
3472 } | 3612 } |
3473 | 3613 |
3474 bool skip_check() { return skip_check_; } | 3614 bool skip_check() { return skip_check_; } |
3475 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } | 3615 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } |
| 3616 HValue* base() { return base_; } |
| 3617 int offset() { return offset_; } |
| 3618 int scale() { return scale_; } |
| 3619 bool index_can_increase() { |
| 3620 return (responsibility_direction_ & DIRECTION_LOWER) == 0; |
| 3621 } |
| 3622 bool index_can_decrease() { |
| 3623 return (responsibility_direction_ & DIRECTION_UPPER) == 0; |
| 3624 } |
| 3625 |
| 3626 void ApplyIndexChange(); |
| 3627 bool DetectCompoundIndex() { |
| 3628 ASSERT(base() == NULL); |
| 3629 |
| 3630 DecompositionResult decomposition; |
| 3631 if (index()->TryDecompose(&decomposition)) { |
| 3632 base_ = decomposition.base(); |
| 3633 offset_ = decomposition.offset(); |
| 3634 scale_ = decomposition.scale(); |
| 3635 return true; |
| 3636 } else { |
| 3637 base_ = index(); |
| 3638 offset_ = 0; |
| 3639 scale_ = 0; |
| 3640 return false; |
| 3641 } |
| 3642 } |
3476 | 3643 |
3477 virtual Representation RequiredInputRepresentation(int arg_index) { | 3644 virtual Representation RequiredInputRepresentation(int arg_index) { |
3478 return representation(); | 3645 return representation(); |
3479 } | 3646 } |
3480 virtual Representation observed_input_representation(int index) { | 3647 virtual Representation observed_input_representation(int index) { |
3481 return Representation::Integer32(); | 3648 return Representation::Integer32(); |
3482 } | 3649 } |
3483 | 3650 |
3484 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3651 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3485 HValue* related_value); | 3652 HValue* related_value, |
| 3653 int offset = 0, |
| 3654 int scale = 0); |
3486 | 3655 |
3487 virtual void PrintDataTo(StringStream* stream); | 3656 virtual void PrintDataTo(StringStream* stream); |
3488 virtual void InferRepresentation(HInferRepresentation* h_infer); | 3657 virtual void InferRepresentation(HInferRepresentation* h_infer); |
3489 | 3658 |
3490 HValue* index() { return OperandAt(0); } | 3659 HValue* index() { return OperandAt(0); } |
3491 HValue* length() { return OperandAt(1); } | 3660 HValue* length() { return OperandAt(1); } |
3492 | 3661 |
3493 virtual int RedefinedOperandIndex() { return 0; } | 3662 virtual int RedefinedOperandIndex() { return 0; } |
3494 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3663 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
3495 virtual void AddInformativeDefinitions(); | 3664 virtual void AddInformativeDefinitions(); |
3496 | 3665 |
3497 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3666 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3498 | 3667 |
3499 protected: | 3668 protected: |
| 3669 friend class HBoundsCheckBaseIndexInformation; |
| 3670 |
| 3671 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { |
| 3672 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( |
| 3673 responsibility_direction_ | direction); |
| 3674 } |
| 3675 |
3500 virtual bool DataEquals(HValue* other) { return true; } | 3676 virtual bool DataEquals(HValue* other) { return true; } |
| 3677 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); |
3501 BoundsCheckKeyMode key_mode_; | 3678 BoundsCheckKeyMode key_mode_; |
3502 bool skip_check_; | 3679 bool skip_check_; |
| 3680 HValue* base_; |
| 3681 int offset_; |
| 3682 int scale_; |
| 3683 RangeGuaranteeDirection responsibility_direction_; |
3503 }; | 3684 }; |
3504 | 3685 |
3505 | 3686 |
| 3687 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { |
| 3688 public: |
| 3689 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { |
| 3690 DecompositionResult decomposition; |
| 3691 if (check->index()->TryDecompose(&decomposition)) { |
| 3692 SetOperandAt(0, decomposition.base()); |
| 3693 SetOperandAt(1, check); |
| 3694 } else { |
| 3695 UNREACHABLE(); |
| 3696 } |
| 3697 } |
| 3698 |
| 3699 HValue* base_index() { return OperandAt(0); } |
| 3700 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } |
| 3701 |
| 3702 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) |
| 3703 |
| 3704 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 3705 return representation(); |
| 3706 } |
| 3707 |
| 3708 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 3709 HValue* related_value, |
| 3710 int offset = 0, |
| 3711 int scale = 0); |
| 3712 virtual void PrintDataTo(StringStream* stream); |
| 3713 |
| 3714 virtual int RedefinedOperandIndex() { return 0; } |
| 3715 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 3716 |
| 3717 protected: |
| 3718 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { |
| 3719 bounds_check()->SetResponsibilityForRange(direction); |
| 3720 } |
| 3721 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) { |
| 3722 bounds_check()->TryGuaranteeRangeChanging(context); |
| 3723 } |
| 3724 }; |
| 3725 |
| 3726 |
3506 class HBitwiseBinaryOperation: public HBinaryOperation { | 3727 class HBitwiseBinaryOperation: public HBinaryOperation { |
3507 public: | 3728 public: |
3508 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 3729 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
3509 : HBinaryOperation(context, left, right) { | 3730 : HBinaryOperation(context, left, right) { |
3510 SetFlag(kFlexibleRepresentation); | 3731 SetFlag(kFlexibleRepresentation); |
3511 SetFlag(kTruncatingToInt32); | 3732 SetFlag(kTruncatingToInt32); |
3512 SetAllSideEffects(); | 3733 SetAllSideEffects(); |
3513 } | 3734 } |
3514 | 3735 |
3515 virtual Representation RequiredInputRepresentation(int index) { | 3736 virtual Representation RequiredInputRepresentation(int index) { |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4085 virtual bool IsCommutative() const { | 4306 virtual bool IsCommutative() const { |
4086 return !representation().IsTagged(); | 4307 return !representation().IsTagged(); |
4087 } | 4308 } |
4088 | 4309 |
4089 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4310 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4090 | 4311 |
4091 virtual HType CalculateInferredType(); | 4312 virtual HType CalculateInferredType(); |
4092 | 4313 |
4093 virtual HValue* Canonicalize(); | 4314 virtual HValue* Canonicalize(); |
4094 | 4315 |
4095 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4316 virtual bool TryDecompose(DecompositionResult* decomposition) { |
4096 HValue* base = NULL; | |
4097 int32_t offset = 0; | |
4098 if (left()->IsInteger32Constant()) { | 4317 if (left()->IsInteger32Constant()) { |
4099 base = right(); | 4318 decomposition->Apply(right(), left()->GetInteger32Constant()); |
4100 offset = left()->GetInteger32Constant(); | 4319 return true; |
4101 } else if (right()->IsInteger32Constant()) { | 4320 } else if (right()->IsInteger32Constant()) { |
4102 base = left(); | 4321 decomposition->Apply(left(), right()->GetInteger32Constant()); |
4103 offset = right()->GetInteger32Constant(); | 4322 return true; |
4104 } else { | 4323 } else { |
4105 return false; | 4324 return false; |
4106 } | 4325 } |
4107 | |
4108 return relation.IsExtendable(offset) | |
4109 ? base->IsRelationTrue(relation, other) : false; | |
4110 } | 4326 } |
4111 | 4327 |
4112 DECLARE_CONCRETE_INSTRUCTION(Add) | 4328 DECLARE_CONCRETE_INSTRUCTION(Add) |
4113 | 4329 |
4114 protected: | 4330 protected: |
4115 virtual bool DataEquals(HValue* other) { return true; } | 4331 virtual bool DataEquals(HValue* other) { return true; } |
4116 | 4332 |
4117 virtual Range* InferRange(Zone* zone); | 4333 virtual Range* InferRange(Zone* zone); |
4118 | 4334 |
4119 private: | 4335 private: |
4120 HAdd(HValue* context, HValue* left, HValue* right) | 4336 HAdd(HValue* context, HValue* left, HValue* right) |
4121 : HArithmeticBinaryOperation(context, left, right) { | 4337 : HArithmeticBinaryOperation(context, left, right) { |
4122 SetFlag(kCanOverflow); | 4338 SetFlag(kCanOverflow); |
4123 } | 4339 } |
4124 }; | 4340 }; |
4125 | 4341 |
4126 | 4342 |
4127 class HSub: public HArithmeticBinaryOperation { | 4343 class HSub: public HArithmeticBinaryOperation { |
4128 public: | 4344 public: |
4129 static HInstruction* New(Zone* zone, | 4345 static HInstruction* New(Zone* zone, |
4130 HValue* context, | 4346 HValue* context, |
4131 HValue* left, | 4347 HValue* left, |
4132 HValue* right); | 4348 HValue* right); |
4133 | 4349 |
4134 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4350 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4135 | 4351 |
4136 virtual HValue* Canonicalize(); | 4352 virtual HValue* Canonicalize(); |
4137 | 4353 |
4138 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4354 virtual bool TryDecompose(DecompositionResult* decomposition) { |
4139 if (right()->IsInteger32Constant()) { | 4355 if (right()->IsInteger32Constant()) { |
4140 HValue* base = left(); | 4356 decomposition->Apply(left(), -right()->GetInteger32Constant()); |
4141 int32_t offset = right()->GetInteger32Constant(); | 4357 return true; |
4142 return relation.IsExtendable(-offset) | |
4143 ? base->IsRelationTrue(relation, other) : false; | |
4144 } else { | 4358 } else { |
4145 return false; | 4359 return false; |
4146 } | 4360 } |
4147 } | 4361 } |
4148 | 4362 |
4149 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4363 DECLARE_CONCRETE_INSTRUCTION(Sub) |
4150 | 4364 |
4151 protected: | 4365 protected: |
4152 virtual bool DataEquals(HValue* other) { return true; } | 4366 virtual bool DataEquals(HValue* other) { return true; } |
4153 | 4367 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4368 }; | 4582 }; |
4369 | 4583 |
4370 | 4584 |
4371 class HShr: public HBitwiseBinaryOperation { | 4585 class HShr: public HBitwiseBinaryOperation { |
4372 public: | 4586 public: |
4373 static HInstruction* New(Zone* zone, | 4587 static HInstruction* New(Zone* zone, |
4374 HValue* context, | 4588 HValue* context, |
4375 HValue* left, | 4589 HValue* left, |
4376 HValue* right); | 4590 HValue* right); |
4377 | 4591 |
| 4592 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 4593 if (right()->IsInteger32Constant()) { |
| 4594 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { |
| 4595 // This is intended to look for HAdd and HSub, to handle compounds |
| 4596 // like ((base + offset) >> scale) with one single decomposition. |
| 4597 left()->TryDecompose(decomposition); |
| 4598 return true; |
| 4599 } |
| 4600 } |
| 4601 return false; |
| 4602 } |
| 4603 |
4378 virtual Range* InferRange(Zone* zone); | 4604 virtual Range* InferRange(Zone* zone); |
4379 | 4605 |
4380 DECLARE_CONCRETE_INSTRUCTION(Shr) | 4606 DECLARE_CONCRETE_INSTRUCTION(Shr) |
4381 | 4607 |
4382 protected: | 4608 protected: |
4383 virtual bool DataEquals(HValue* other) { return true; } | 4609 virtual bool DataEquals(HValue* other) { return true; } |
4384 | 4610 |
4385 private: | 4611 private: |
4386 HShr(HValue* context, HValue* left, HValue* right) | 4612 HShr(HValue* context, HValue* left, HValue* right) |
4387 : HBitwiseBinaryOperation(context, left, right) { } | 4613 : HBitwiseBinaryOperation(context, left, right) { } |
4388 }; | 4614 }; |
4389 | 4615 |
4390 | 4616 |
4391 class HSar: public HBitwiseBinaryOperation { | 4617 class HSar: public HBitwiseBinaryOperation { |
4392 public: | 4618 public: |
4393 static HInstruction* New(Zone* zone, | 4619 static HInstruction* New(Zone* zone, |
4394 HValue* context, | 4620 HValue* context, |
4395 HValue* left, | 4621 HValue* left, |
4396 HValue* right); | 4622 HValue* right); |
4397 | 4623 |
| 4624 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 4625 if (right()->IsInteger32Constant()) { |
| 4626 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { |
| 4627 // This is intended to look for HAdd and HSub, to handle compounds |
| 4628 // like ((base + offset) >> scale) with one single decomposition. |
| 4629 left()->TryDecompose(decomposition); |
| 4630 return true; |
| 4631 } |
| 4632 } |
| 4633 return false; |
| 4634 } |
| 4635 |
4398 virtual Range* InferRange(Zone* zone); | 4636 virtual Range* InferRange(Zone* zone); |
4399 | 4637 |
4400 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4638 DECLARE_CONCRETE_INSTRUCTION(Sar) |
4401 | 4639 |
4402 protected: | 4640 protected: |
4403 virtual bool DataEquals(HValue* other) { return true; } | 4641 virtual bool DataEquals(HValue* other) { return true; } |
4404 | 4642 |
4405 private: | 4643 private: |
4406 HSar(HValue* context, HValue* left, HValue* right) | 4644 HSar(HValue* context, HValue* left, HValue* right) |
4407 : HBitwiseBinaryOperation(context, left, right) { } | 4645 : HBitwiseBinaryOperation(context, left, right) { } |
(...skipping 1814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6222 virtual bool IsDeletable() const { return true; } | 6460 virtual bool IsDeletable() const { return true; } |
6223 }; | 6461 }; |
6224 | 6462 |
6225 | 6463 |
6226 #undef DECLARE_INSTRUCTION | 6464 #undef DECLARE_INSTRUCTION |
6227 #undef DECLARE_CONCRETE_INSTRUCTION | 6465 #undef DECLARE_CONCRETE_INSTRUCTION |
6228 | 6466 |
6229 } } // namespace v8::internal | 6467 } } // namespace v8::internal |
6230 | 6468 |
6231 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6469 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |