| 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 |