Chromium Code Reviews| 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(CallRuntime) \ | 87 V(CallRuntime) \ |
| 87 V(CallStub) \ | 88 V(CallStub) \ |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 case GT: return (direction >= 0); | 660 case GT: return (direction >= 0); |
| 660 case GE: return (direction >= 0); | 661 case GE: return (direction >= 0); |
| 661 case LT: return (direction <= 0); | 662 case LT: return (direction <= 0); |
| 662 case LE: return (direction <= 0); | 663 case LE: return (direction <= 0); |
| 663 case NE: return false; | 664 case NE: return false; |
| 664 } | 665 } |
| 665 UNREACHABLE(); | 666 UNREACHABLE(); |
| 666 return false; | 667 return false; |
| 667 } | 668 } |
| 668 | 669 |
| 670 // CompoundImplies returns true when | |
| 671 // "((x + my_offset) >> my_scale) rel y" implies | |
| 672 // "((x + other_offset) >> other_scale) other_relation y". | |
| 673 bool CompoundImplies(NumericRelation other_relation, | |
| 674 int my_offset, | |
| 675 int my_scale, | |
| 676 int other_offset = 0, | |
| 677 int other_scale = 0) { | |
| 678 return Implies(other_relation) && ComponentsImply( | |
| 679 my_offset, my_scale, other_offset, other_scale); | |
| 680 } | |
| 681 | |
| 669 private: | 682 private: |
| 683 // ComponentsImply returns true when | |
| 684 // "((x + my_offset) >> my_scale) rel y" implies | |
| 685 // "((x + other_offset) >> other_scale) rel y". | |
| 686 bool ComponentsImply(int my_offset, | |
| 687 int my_scale, | |
| 688 int other_offset, | |
| 689 int other_scale) { | |
| 690 switch (kind_) { | |
| 691 case NONE: break; // Fall through to UNREACHABLE(). | |
| 692 case EQ: | |
| 693 case NE: return my_offset == other_offset && my_scale == other_scale; | |
| 694 case GT: | |
| 695 case GE: return my_offset <= other_offset && my_scale >= other_scale; | |
| 696 case LT: | |
| 697 case LE: return my_offset >= other_offset && my_scale <= other_scale; | |
| 698 } | |
| 699 UNREACHABLE(); | |
| 700 return false; | |
| 701 } | |
| 702 | |
| 670 explicit NumericRelation(Kind kind) : kind_(kind) {} | 703 explicit NumericRelation(Kind kind) : kind_(kind) {} |
| 671 | 704 |
| 672 Kind kind_; | 705 Kind kind_; |
| 673 }; | 706 }; |
| 674 | 707 |
| 675 | 708 |
| 709 class DecompositionResult BASE_EMBEDDED { | |
| 710 public: | |
| 711 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {} | |
| 712 | |
| 713 HValue* base() { return base_; } | |
| 714 int offset() { return offset_; } | |
| 715 int scale() { return scale_; } | |
| 716 | |
| 717 bool Apply(HValue* b, int o, int s = 0) { | |
|
Jakob Kummerow
2013/03/14 16:16:32
nit: please spell out the names ("base", "offset",
| |
| 718 if (base() == NULL) { | |
|
Jakob Kummerow
2013/03/14 16:16:32
nit: s/base()/base_/ [for consistency with "base_
| |
| 719 base_ = b; | |
| 720 offset_ = o; | |
| 721 scale_ = s; | |
| 722 return true; | |
| 723 } else { | |
| 724 if (scale_ == 0) { | |
| 725 base_ = b; | |
| 726 offset_ += o; | |
| 727 scale_ = s; | |
| 728 return true; | |
| 729 } else { | |
| 730 return false; | |
| 731 } | |
| 732 } | |
| 733 } | |
| 734 | |
| 735 void SwapValues(HValue** b, int* o, int* s) { | |
|
Jakob Kummerow
2013/03/14 16:16:32
again
| |
| 736 swap(&base_, b); | |
| 737 swap(&offset_, o); | |
| 738 swap(&scale_, s); | |
| 739 } | |
| 740 | |
| 741 private: | |
| 742 template <class T> void swap(T* a, T* b) { | |
| 743 T c(*a); | |
| 744 *a = *b; | |
| 745 *b = c; | |
| 746 } | |
| 747 | |
| 748 HValue* base_; | |
| 749 int offset_; | |
| 750 int scale_; | |
| 751 }; | |
| 752 | |
| 753 | |
| 754 class RangeEvaluationContext BASE_EMBEDDED { | |
| 755 public: | |
| 756 RangeEvaluationContext(HValue* value, HValue* upper); | |
| 757 | |
| 758 HValue* lower_bound() { return lower_bound_; } | |
| 759 HValue* lower_bound_guarantee() { return lower_bound_guarantee_; } | |
| 760 HValue* candidate() { return candidate_; } | |
| 761 HValue* upper_bound() { return upper_bound_; } | |
| 762 HValue* upper_bound_guarantee() { return upper_bound_guarantee_; } | |
| 763 int offset() { return offset_; } | |
| 764 int scale() { return scale_; } | |
| 765 | |
| 766 bool is_range_satisfied() { | |
| 767 return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL; | |
| 768 } | |
| 769 | |
| 770 void set_lower_bound_guarantee(HValue* guarantee) { | |
| 771 lower_bound_guarantee_ = ConvertGuarantee(guarantee); | |
| 772 } | |
| 773 void set_upper_bound_guarantee(HValue* guarantee) { | |
| 774 upper_bound_guarantee_ = ConvertGuarantee(guarantee); | |
| 775 } | |
| 776 | |
| 777 void swap_candidate(DecompositionResult* other_candicate) { | |
| 778 other_candicate->SwapValues(&candidate_, &offset_, &scale_); | |
| 779 } | |
| 780 | |
| 781 private: | |
| 782 HValue* ConvertGuarantee(HValue* guarantee); | |
| 783 | |
| 784 HValue* lower_bound_; | |
| 785 HValue* lower_bound_guarantee_; | |
| 786 HValue* candidate_; | |
| 787 HValue* upper_bound_; | |
| 788 HValue* upper_bound_guarantee_; | |
| 789 int offset_; | |
| 790 int scale_; | |
| 791 }; | |
| 792 | |
| 793 | |
| 676 typedef EnumSet<GVNFlag> GVNFlagSet; | 794 typedef EnumSet<GVNFlag> GVNFlagSet; |
| 677 | 795 |
| 678 | 796 |
| 679 class HValue: public ZoneObject { | 797 class HValue: public ZoneObject { |
| 680 public: | 798 public: |
| 681 static const int kNoNumber = -1; | 799 static const int kNoNumber = -1; |
| 682 | 800 |
| 683 enum Flag { | 801 enum Flag { |
| 684 kFlexibleRepresentation, | 802 kFlexibleRepresentation, |
| 685 // Participate in Global Value Numbering, i.e. elimination of | 803 // Participate in Global Value Numbering, i.e. elimination of |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 966 } | 1084 } |
| 967 | 1085 |
| 968 bool IsDead() const { | 1086 bool IsDead() const { |
| 969 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); | 1087 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); |
| 970 } | 1088 } |
| 971 | 1089 |
| 972 #ifdef DEBUG | 1090 #ifdef DEBUG |
| 973 virtual void Verify() = 0; | 1091 virtual void Verify() = 0; |
| 974 #endif | 1092 #endif |
| 975 | 1093 |
| 976 // This method is recursive but it is guaranteed to terminate because | 1094 bool IsRelationTrue(NumericRelation relation, |
| 977 // RedefinedOperand() always dominates "this". | 1095 HValue* other, |
| 978 bool IsRelationTrue(NumericRelation relation, HValue* other) { | 1096 int offset = 0, |
| 979 if (this == other) { | 1097 int scale = 0); |
| 980 return NumericRelation::Eq().Implies(relation); | 1098 |
| 1099 bool TryGuaranteeRange(HValue* upper_bound); | |
| 1100 virtual bool TryDecompose(DecompositionResult* decomposition) { | |
| 1101 if (RedefinedOperand() != NULL) { | |
| 1102 return RedefinedOperand()->TryDecompose(decomposition); | |
| 1103 } else { | |
| 1104 return false; | |
| 981 } | 1105 } |
| 982 | |
| 983 bool result = IsRelationTrueInternal(relation, other) || | |
| 984 other->IsRelationTrueInternal(relation.Reversed(), this); | |
| 985 if (!result) { | |
| 986 HValue* redefined = RedefinedOperand(); | |
| 987 if (redefined != NULL) { | |
| 988 result = redefined->IsRelationTrue(relation, other); | |
| 989 } | |
| 990 } | |
| 991 return result; | |
| 992 } | 1106 } |
| 993 | 1107 |
| 994 protected: | 1108 protected: |
| 1109 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | |
| 1110 | |
| 1111 enum RangeGuaranteeDirection { | |
| 1112 DIRECTION_NONE = 0, | |
| 1113 DIRECTION_UPPER = 1, | |
| 1114 DIRECTION_LOWER = 2, | |
| 1115 DIRECTION_BOTH = DIRECTION_UPPER|DIRECTION_LOWER | |
|
Jakob Kummerow
2013/03/14 16:16:32
nit: spaces around '|'
| |
| 1116 }; | |
| 1117 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} | |
| 1118 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {} | |
| 1119 | |
| 995 // This function must be overridden for instructions with flag kUseGVN, to | 1120 // This function must be overridden for instructions with flag kUseGVN, to |
| 996 // compare the non-Operand parts of the instruction. | 1121 // compare the non-Operand parts of the instruction. |
| 997 virtual bool DataEquals(HValue* other) { | 1122 virtual bool DataEquals(HValue* other) { |
| 998 UNREACHABLE(); | 1123 UNREACHABLE(); |
| 999 return false; | 1124 return false; |
| 1000 } | 1125 } |
| 1001 | 1126 |
| 1002 virtual Representation RepresentationFromInputs() { | 1127 virtual Representation RepresentationFromInputs() { |
| 1003 return representation(); | 1128 return representation(); |
| 1004 } | 1129 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1048 HValue* use = uses.value(); | 1173 HValue* use = uses.value(); |
| 1049 if (TestDominance(this, use)) { | 1174 if (TestDominance(this, use)) { |
| 1050 use->SetOperandAt(uses.index(), this); | 1175 use->SetOperandAt(uses.index(), this); |
| 1051 } | 1176 } |
| 1052 } | 1177 } |
| 1053 } | 1178 } |
| 1054 } | 1179 } |
| 1055 | 1180 |
| 1056 // Informative definitions can override this method to state any numeric | 1181 // Informative definitions can override this method to state any numeric |
| 1057 // relation they provide on the redefined value. | 1182 // relation they provide on the redefined value. |
| 1058 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 1183 // Returns true if it is guaranteed that: |
| 1184 // ((this + offset) >> scale) relation other | |
| 1185 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 1186 HValue* other, | |
| 1187 int offset = 0, | |
| 1188 int scale = 0) { | |
| 1059 return false; | 1189 return false; |
| 1060 } | 1190 } |
| 1061 | 1191 |
| 1062 static GVNFlagSet AllDependsOnFlagSet() { | 1192 static GVNFlagSet AllDependsOnFlagSet() { |
| 1063 GVNFlagSet result; | 1193 GVNFlagSet result; |
| 1064 // Create changes mask. | 1194 // Create changes mask. |
| 1065 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 1195 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
| 1066 GVN_TRACKED_FLAG_LIST(ADD_FLAG) | 1196 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
| 1067 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | 1197 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
| 1068 #undef ADD_FLAG | 1198 #undef ADD_FLAG |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1297 virtual int RedefinedOperandIndex() { return 0; } | 1427 virtual int RedefinedOperandIndex() { return 0; } |
| 1298 virtual bool IsPurelyInformativeDefinition() { return true; } | 1428 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 1299 | 1429 |
| 1300 virtual Representation RequiredInputRepresentation(int index) { | 1430 virtual Representation RequiredInputRepresentation(int index) { |
| 1301 return representation(); | 1431 return representation(); |
| 1302 } | 1432 } |
| 1303 | 1433 |
| 1304 virtual void PrintDataTo(StringStream* stream); | 1434 virtual void PrintDataTo(StringStream* stream); |
| 1305 | 1435 |
| 1306 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 1436 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
| 1307 HValue* other_related_value) { | 1437 HValue* other_related_value, |
| 1438 int offset = 0, | |
| 1439 int scale = 0) { | |
| 1308 if (related_value() == other_related_value) { | 1440 if (related_value() == other_related_value) { |
| 1309 return relation().Implies(other_relation); | 1441 return relation().CompoundImplies(other_relation, offset, scale); |
| 1310 } else { | 1442 } else { |
| 1311 return false; | 1443 return false; |
| 1312 } | 1444 } |
| 1313 } | 1445 } |
| 1314 | 1446 |
| 1315 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) | 1447 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) |
| 1316 | 1448 |
| 1317 private: | 1449 private: |
| 1318 HNumericConstraint(HValue* constrained_value, | 1450 HNumericConstraint(HValue* constrained_value, |
| 1319 NumericRelation relation, | 1451 NumericRelation relation, |
| 1320 HValue* related_value) | 1452 HValue* related_value) |
| 1321 : relation_(relation) { | 1453 : relation_(relation) { |
| 1322 SetOperandAt(0, constrained_value); | 1454 SetOperandAt(0, constrained_value); |
| 1323 SetOperandAt(1, related_value); | 1455 SetOperandAt(1, related_value); |
| 1324 set_representation(constrained_value->representation()); | |
| 1325 } | 1456 } |
| 1326 | 1457 |
| 1327 NumericRelation relation_; | 1458 NumericRelation relation_; |
| 1328 }; | 1459 }; |
| 1329 | 1460 |
| 1330 | 1461 |
| 1331 // We insert soft-deoptimize when we hit code with unknown typefeedback, | 1462 // We insert soft-deoptimize when we hit code with unknown typefeedback, |
| 1332 // so that we get a chance of re-optimizing with useful typefeedback. | 1463 // so that we get a chance of re-optimizing with useful typefeedback. |
| 1333 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. | 1464 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. |
| 1334 class HSoftDeoptimize: public HTemplateInstruction<0> { | 1465 class HSoftDeoptimize: public HTemplateInstruction<0> { |
| (...skipping 1617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2952 } | 3083 } |
| 2953 return true; | 3084 return true; |
| 2954 } | 3085 } |
| 2955 | 3086 |
| 2956 protected: | 3087 protected: |
| 2957 virtual void DeleteFromGraph(); | 3088 virtual void DeleteFromGraph(); |
| 2958 virtual void InternalSetOperandAt(int index, HValue* value) { | 3089 virtual void InternalSetOperandAt(int index, HValue* value) { |
| 2959 inputs_[index] = value; | 3090 inputs_[index] = value; |
| 2960 } | 3091 } |
| 2961 | 3092 |
| 2962 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other); | 3093 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 3094 HValue* other, | |
| 3095 int offset = 0, | |
| 3096 int scale = 0); | |
| 2963 | 3097 |
| 2964 private: | 3098 private: |
| 2965 ZoneList<HValue*> inputs_; | 3099 ZoneList<HValue*> inputs_; |
| 2966 int merged_index_; | 3100 int merged_index_; |
| 2967 | 3101 |
| 2968 int non_phi_uses_[Representation::kNumRepresentations]; | 3102 int non_phi_uses_[Representation::kNumRepresentations]; |
| 2969 int indirect_uses_[Representation::kNumRepresentations]; | 3103 int indirect_uses_[Representation::kNumRepresentations]; |
| 2970 int phi_id_; | 3104 int phi_id_; |
| 2971 bool is_live_; | 3105 bool is_live_; |
| 2972 bool is_convertible_to_integer_; | 3106 bool is_convertible_to_integer_; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2984 | 3118 |
| 2985 virtual int RedefinedOperandIndex() { return 0; } | 3119 virtual int RedefinedOperandIndex() { return 0; } |
| 2986 virtual bool IsPurelyInformativeDefinition() { return true; } | 3120 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 2987 virtual Representation RequiredInputRepresentation(int index) { | 3121 virtual Representation RequiredInputRepresentation(int index) { |
| 2988 return representation(); | 3122 return representation(); |
| 2989 } | 3123 } |
| 2990 | 3124 |
| 2991 virtual void PrintDataTo(StringStream* stream); | 3125 virtual void PrintDataTo(StringStream* stream); |
| 2992 | 3126 |
| 2993 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 3127 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
| 2994 HValue* other_related_value) { | 3128 HValue* other_related_value, |
| 3129 int offset = 0, | |
| 3130 int scale = 0) { | |
| 2995 if (induction_base() == other_related_value) { | 3131 if (induction_base() == other_related_value) { |
| 2996 return relation().Implies(other_relation); | 3132 return relation().CompoundImplies(other_relation, offset, scale); |
| 2997 } else { | 3133 } else { |
| 2998 return false; | 3134 return false; |
| 2999 } | 3135 } |
| 3000 } | 3136 } |
| 3001 | 3137 |
| 3002 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) | 3138 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) |
| 3003 | 3139 |
| 3004 private: | 3140 private: |
| 3005 HInductionVariableAnnotation(HPhi* phi, | 3141 HInductionVariableAnnotation(HPhi* phi, |
| 3006 NumericRelation relation, | 3142 NumericRelation relation, |
| 3007 int operand_index) | 3143 int operand_index) |
| 3008 : HUnaryOperation(phi), | 3144 : HUnaryOperation(phi), |
| 3009 phi_(phi), relation_(relation), operand_index_(operand_index) { | 3145 phi_(phi), relation_(relation), operand_index_(operand_index) { |
| 3010 set_representation(phi->representation()); | |
| 3011 } | 3146 } |
| 3012 | 3147 |
| 3013 // We need to store the phi both here and in the instruction operand because | 3148 // We need to store the phi both here and in the instruction operand because |
| 3014 // the operand can change if a new idef of the phi is added between the phi | 3149 // the operand can change if a new idef of the phi is added between the phi |
| 3015 // and this instruction (inserting an idef updates every use). | 3150 // and this instruction (inserting an idef updates every use). |
| 3016 HPhi* phi_; | 3151 HPhi* phi_; |
| 3017 NumericRelation relation_; | 3152 NumericRelation relation_; |
| 3018 int operand_index_; | 3153 int operand_index_; |
| 3019 }; | 3154 }; |
| 3020 | 3155 |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3375 virtual bool DataEquals(HValue* other) { return true; } | 3510 virtual bool DataEquals(HValue* other) { return true; } |
| 3376 }; | 3511 }; |
| 3377 | 3512 |
| 3378 | 3513 |
| 3379 enum BoundsCheckKeyMode { | 3514 enum BoundsCheckKeyMode { |
| 3380 DONT_ALLOW_SMI_KEY, | 3515 DONT_ALLOW_SMI_KEY, |
| 3381 ALLOW_SMI_KEY | 3516 ALLOW_SMI_KEY |
| 3382 }; | 3517 }; |
| 3383 | 3518 |
| 3384 | 3519 |
| 3520 class HBoundsCheckBaseIndexInformation; | |
| 3521 | |
| 3522 | |
| 3385 class HBoundsCheck: public HTemplateInstruction<2> { | 3523 class HBoundsCheck: public HTemplateInstruction<2> { |
| 3386 public: | 3524 public: |
| 3387 // Normally HBoundsCheck should be created using the | 3525 // Normally HBoundsCheck should be created using the |
| 3388 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with | 3526 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with |
| 3389 // a HCheckSmiOrInt32 check. | 3527 // a HCheckSmiOrInt32 check. |
| 3390 // However when building stubs, where we know that the arguments are Int32, | 3528 // However when building stubs, where we know that the arguments are Int32, |
| 3391 // it makes sense to invoke this constructor directly. | 3529 // it makes sense to invoke this constructor directly. |
| 3392 HBoundsCheck(HValue* index, | 3530 HBoundsCheck(HValue* index, |
| 3393 HValue* length, | 3531 HValue* length, |
| 3394 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, | 3532 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
| 3395 Representation r = Representation::None()) | 3533 Representation r = Representation::None()) |
| 3396 : key_mode_(key_mode), skip_check_(false) { | 3534 : key_mode_(key_mode), skip_check_(false), |
| 3535 base_(NULL), offset_(0), scale_(0), | |
| 3536 responsibility_direction_(DIRECTION_NONE) { | |
| 3397 SetOperandAt(0, index); | 3537 SetOperandAt(0, index); |
| 3398 SetOperandAt(1, length); | 3538 SetOperandAt(1, length); |
| 3399 if (r.IsNone()) { | 3539 if (r.IsNone()) { |
| 3400 // In the normal compilation pipeline the representation is flexible | 3540 // In the normal compilation pipeline the representation is flexible |
| 3401 // (see InferRepresentation). | 3541 // (see InferRepresentation). |
| 3402 SetFlag(kFlexibleRepresentation); | 3542 SetFlag(kFlexibleRepresentation); |
| 3403 } else { | 3543 } else { |
| 3404 // When compiling stubs we want to set the representation explicitly | 3544 // When compiling stubs we want to set the representation explicitly |
| 3405 // so the compilation pipeline can skip the HInferRepresentation phase. | 3545 // so the compilation pipeline can skip the HInferRepresentation phase. |
| 3406 set_representation(r); | 3546 set_representation(r); |
| 3407 } | 3547 } |
| 3408 SetFlag(kUseGVN); | 3548 SetFlag(kUseGVN); |
| 3409 } | 3549 } |
| 3410 | 3550 |
| 3411 bool skip_check() { return skip_check_; } | 3551 bool skip_check() { return skip_check_; } |
| 3412 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } | 3552 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } |
| 3553 HValue* base() { return base_; } | |
| 3554 int offset() { return offset_; } | |
| 3555 int scale() { return scale_; } | |
| 3556 bool index_can_increase() { | |
| 3557 return (responsibility_direction_ & DIRECTION_LOWER) == 0; | |
| 3558 } | |
| 3559 bool index_can_decrease() { | |
| 3560 return (responsibility_direction_ & DIRECTION_UPPER) == 0; | |
| 3561 } | |
| 3562 | |
| 3563 void ApplyIndexChange(); | |
| 3564 bool DetectCompoundIndex() { | |
| 3565 ASSERT(base() == NULL); | |
| 3566 | |
| 3567 DecompositionResult decomposition; | |
| 3568 if (index()->TryDecompose(&decomposition)) { | |
| 3569 base_ = decomposition.base(); | |
| 3570 offset_ = decomposition.offset(); | |
| 3571 scale_ = decomposition.scale(); | |
| 3572 return true; | |
| 3573 } else { | |
| 3574 base_ = index(); | |
| 3575 offset_ = 0; | |
| 3576 scale_ = 0; | |
| 3577 return false; | |
| 3578 } | |
| 3579 } | |
| 3413 | 3580 |
| 3414 virtual Representation RequiredInputRepresentation(int arg_index) { | 3581 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 3415 return representation(); | 3582 return representation(); |
| 3416 } | 3583 } |
| 3417 virtual Representation observed_input_representation(int index) { | 3584 virtual Representation observed_input_representation(int index) { |
| 3418 return Representation::Integer32(); | 3585 return Representation::Integer32(); |
| 3419 } | 3586 } |
| 3420 | 3587 |
| 3421 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3588 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 3422 HValue* related_value); | 3589 HValue* related_value, |
| 3590 int offset = 0, | |
| 3591 int scale = 0); | |
| 3423 | 3592 |
| 3424 virtual void PrintDataTo(StringStream* stream); | 3593 virtual void PrintDataTo(StringStream* stream); |
| 3425 virtual void InferRepresentation(HInferRepresentation* h_infer); | 3594 virtual void InferRepresentation(HInferRepresentation* h_infer); |
| 3426 | 3595 |
| 3427 HValue* index() { return OperandAt(0); } | 3596 HValue* index() { return OperandAt(0); } |
| 3428 HValue* length() { return OperandAt(1); } | 3597 HValue* length() { return OperandAt(1); } |
| 3429 | 3598 |
| 3430 virtual int RedefinedOperandIndex() { return 0; } | 3599 virtual int RedefinedOperandIndex() { return 0; } |
| 3431 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3600 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
| 3432 virtual void AddInformativeDefinitions(); | 3601 virtual void AddInformativeDefinitions(); |
| 3433 | 3602 |
| 3434 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3603 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
| 3435 | 3604 |
| 3436 protected: | 3605 protected: |
| 3606 friend class HBoundsCheckBaseIndexInformation; | |
| 3607 | |
| 3608 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
| 3609 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( | |
| 3610 responsibility_direction_ | direction); | |
| 3611 } | |
| 3612 | |
| 3437 virtual bool DataEquals(HValue* other) { return true; } | 3613 virtual bool DataEquals(HValue* other) { return true; } |
| 3614 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | |
| 3438 BoundsCheckKeyMode key_mode_; | 3615 BoundsCheckKeyMode key_mode_; |
| 3439 bool skip_check_; | 3616 bool skip_check_; |
| 3617 HValue* base_; | |
| 3618 int offset_; | |
| 3619 int scale_; | |
| 3620 RangeGuaranteeDirection responsibility_direction_; | |
| 3440 }; | 3621 }; |
| 3441 | 3622 |
| 3442 | 3623 |
| 3624 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | |
| 3625 public: | |
| 3626 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | |
| 3627 DecompositionResult decomposition; | |
| 3628 if (check->index()->TryDecompose(&decomposition)) { | |
| 3629 SetOperandAt(0, decomposition.base()); | |
| 3630 SetOperandAt(1, check); | |
| 3631 } else { | |
| 3632 UNREACHABLE(); | |
| 3633 } | |
| 3634 } | |
| 3635 | |
| 3636 HValue* base_index() { return OperandAt(0); } | |
| 3637 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | |
| 3638 | |
| 3639 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | |
| 3640 | |
| 3641 virtual Representation RequiredInputRepresentation(int arg_index) { | |
| 3642 return representation(); | |
| 3643 } | |
| 3644 | |
| 3645 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 3646 HValue* related_value, | |
| 3647 int offset = 0, | |
| 3648 int scale = 0); | |
| 3649 virtual void PrintDataTo(StringStream* stream); | |
| 3650 | |
| 3651 virtual int RedefinedOperandIndex() { return 0; } | |
| 3652 virtual bool IsPurelyInformativeDefinition() { return true; } | |
| 3653 | |
| 3654 protected: | |
| 3655 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
| 3656 bounds_check()->SetResponsibilityForRange(direction); | |
| 3657 } | |
| 3658 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
| 3659 bounds_check()->TryGuaranteeRangeChanging(context); | |
| 3660 } | |
| 3661 }; | |
| 3662 | |
| 3663 | |
| 3443 class HBitwiseBinaryOperation: public HBinaryOperation { | 3664 class HBitwiseBinaryOperation: public HBinaryOperation { |
| 3444 public: | 3665 public: |
| 3445 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 3666 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
| 3446 : HBinaryOperation(context, left, right) { | 3667 : HBinaryOperation(context, left, right) { |
| 3447 SetFlag(kFlexibleRepresentation); | 3668 SetFlag(kFlexibleRepresentation); |
| 3448 SetFlag(kTruncatingToInt32); | 3669 SetFlag(kTruncatingToInt32); |
| 3449 SetAllSideEffects(); | 3670 SetAllSideEffects(); |
| 3450 } | 3671 } |
| 3451 | 3672 |
| 3452 virtual Representation RequiredInputRepresentation(int index) { | 3673 virtual Representation RequiredInputRepresentation(int index) { |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4005 | 4226 |
| 4006 static HInstruction* NewHAdd(Zone* zone, | 4227 static HInstruction* NewHAdd(Zone* zone, |
| 4007 HValue* context, | 4228 HValue* context, |
| 4008 HValue* left, | 4229 HValue* left, |
| 4009 HValue* right); | 4230 HValue* right); |
| 4010 | 4231 |
| 4011 virtual HType CalculateInferredType(); | 4232 virtual HType CalculateInferredType(); |
| 4012 | 4233 |
| 4013 virtual HValue* Canonicalize(); | 4234 virtual HValue* Canonicalize(); |
| 4014 | 4235 |
| 4015 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4236 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 4016 HValue* base = NULL; | |
| 4017 int32_t offset = 0; | |
| 4018 if (left()->IsInteger32Constant()) { | 4237 if (left()->IsInteger32Constant()) { |
| 4019 base = right(); | 4238 decomposition->Apply(right(), left()->GetInteger32Constant()); |
| 4020 offset = left()->GetInteger32Constant(); | 4239 return true; |
| 4021 } else if (right()->IsInteger32Constant()) { | 4240 } else if (right()->IsInteger32Constant()) { |
| 4022 base = left(); | 4241 decomposition->Apply(left(), right()->GetInteger32Constant()); |
| 4023 offset = right()->GetInteger32Constant(); | 4242 return true; |
| 4024 } else { | 4243 } else { |
| 4025 return false; | 4244 return false; |
| 4026 } | 4245 } |
| 4027 | |
| 4028 return relation.IsExtendable(offset) | |
| 4029 ? base->IsRelationTrue(relation, other) : false; | |
| 4030 } | 4246 } |
| 4031 | 4247 |
| 4032 DECLARE_CONCRETE_INSTRUCTION(Add) | 4248 DECLARE_CONCRETE_INSTRUCTION(Add) |
| 4033 | 4249 |
| 4034 protected: | 4250 protected: |
| 4035 virtual bool DataEquals(HValue* other) { return true; } | 4251 virtual bool DataEquals(HValue* other) { return true; } |
| 4036 | 4252 |
| 4037 virtual Range* InferRange(Zone* zone); | 4253 virtual Range* InferRange(Zone* zone); |
| 4038 }; | 4254 }; |
| 4039 | 4255 |
| 4040 | 4256 |
| 4041 class HSub: public HArithmeticBinaryOperation { | 4257 class HSub: public HArithmeticBinaryOperation { |
| 4042 public: | 4258 public: |
| 4043 HSub(HValue* context, HValue* left, HValue* right) | 4259 HSub(HValue* context, HValue* left, HValue* right) |
| 4044 : HArithmeticBinaryOperation(context, left, right) { | 4260 : HArithmeticBinaryOperation(context, left, right) { |
| 4045 SetFlag(kCanOverflow); | 4261 SetFlag(kCanOverflow); |
| 4046 } | 4262 } |
| 4047 | 4263 |
| 4048 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4264 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
| 4049 | 4265 |
| 4050 virtual HValue* Canonicalize(); | 4266 virtual HValue* Canonicalize(); |
| 4051 | 4267 |
| 4052 static HInstruction* NewHSub(Zone* zone, | 4268 static HInstruction* NewHSub(Zone* zone, |
| 4053 HValue* context, | 4269 HValue* context, |
| 4054 HValue* left, | 4270 HValue* left, |
| 4055 HValue* right); | 4271 HValue* right); |
| 4056 | 4272 |
| 4057 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4273 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 4058 if (right()->IsInteger32Constant()) { | 4274 if (right()->IsInteger32Constant()) { |
| 4059 HValue* base = left(); | 4275 decomposition->Apply(left(), -right()->GetInteger32Constant()); |
| 4060 int32_t offset = right()->GetInteger32Constant(); | 4276 return true; |
| 4061 return relation.IsExtendable(-offset) | |
| 4062 ? base->IsRelationTrue(relation, other) : false; | |
| 4063 } else { | 4277 } else { |
| 4064 return false; | 4278 return false; |
| 4065 } | 4279 } |
| 4066 } | 4280 } |
| 4067 | 4281 |
| 4068 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4282 DECLARE_CONCRETE_INSTRUCTION(Sub) |
| 4069 | 4283 |
| 4070 protected: | 4284 protected: |
| 4071 virtual bool DataEquals(HValue* other) { return true; } | 4285 virtual bool DataEquals(HValue* other) { return true; } |
| 4072 | 4286 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4292 }; | 4506 }; |
| 4293 | 4507 |
| 4294 | 4508 |
| 4295 class HSar: public HBitwiseBinaryOperation { | 4509 class HSar: public HBitwiseBinaryOperation { |
| 4296 public: | 4510 public: |
| 4297 HSar(HValue* context, HValue* left, HValue* right) | 4511 HSar(HValue* context, HValue* left, HValue* right) |
| 4298 : HBitwiseBinaryOperation(context, left, right) { } | 4512 : HBitwiseBinaryOperation(context, left, right) { } |
| 4299 | 4513 |
| 4300 virtual Range* InferRange(Zone* zone); | 4514 virtual Range* InferRange(Zone* zone); |
| 4301 | 4515 |
| 4516 virtual bool TryDecompose(DecompositionResult* decomposition) { | |
|
Jakob Kummerow
2013/03/14 16:16:32
Shouldn't we make the same change to HShr too?
| |
| 4517 if (right()->IsInteger32Constant()) { | |
| 4518 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { | |
| 4519 // This is intended to look for HAdd and HSub, to handle compounds | |
| 4520 // like ((base = offset) >> scale) with one single decomposition. | |
|
Jakob Kummerow
2013/03/14 16:16:32
nit: s/=/+/
| |
| 4521 left()->TryDecompose(decomposition); | |
| 4522 return true; | |
| 4523 } | |
| 4524 } | |
| 4525 return false; | |
| 4526 } | |
| 4527 | |
| 4302 static HInstruction* NewHSar(Zone* zone, | 4528 static HInstruction* NewHSar(Zone* zone, |
| 4303 HValue* context, | 4529 HValue* context, |
| 4304 HValue* left, | 4530 HValue* left, |
| 4305 HValue* right); | 4531 HValue* right); |
| 4306 | 4532 |
| 4307 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4533 DECLARE_CONCRETE_INSTRUCTION(Sar) |
| 4308 | 4534 |
| 4309 protected: | 4535 protected: |
| 4310 virtual bool DataEquals(HValue* other) { return true; } | 4536 virtual bool DataEquals(HValue* other) { return true; } |
| 4311 }; | 4537 }; |
| (...skipping 1772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6084 virtual bool IsDeletable() const { return true; } | 6310 virtual bool IsDeletable() const { return true; } |
| 6085 }; | 6311 }; |
| 6086 | 6312 |
| 6087 | 6313 |
| 6088 #undef DECLARE_INSTRUCTION | 6314 #undef DECLARE_INSTRUCTION |
| 6089 #undef DECLARE_CONCRETE_INSTRUCTION | 6315 #undef DECLARE_CONCRETE_INSTRUCTION |
| 6090 | 6316 |
| 6091 } } // namespace v8::internal | 6317 } } // namespace v8::internal |
| 6092 | 6318 |
| 6093 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6319 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |