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 // CompoundOperandsAreCompatible returns true when | |
| 671 // "((x + my_offset) >> my_scale) rel y" implies | |
| 672 // "((x + other_offset) >> other_scale) rel y". | |
| 673 bool CompoundOperandsAreCompatible(int my_offset, | |
|
Jakob Kummerow
2013/03/11 11:55:02
I don't like this name. "compatible" in what sense
| |
| 674 int my_scale, | |
| 675 int other_offset, | |
| 676 int other_scale) { | |
| 677 switch (kind_) { | |
| 678 case NONE: return false; | |
| 679 case EQ: return my_offset == other_offset && my_scale == other_scale; | |
|
Jakob Kummerow
2013/03/11 11:55:02
let's combine identical cases, i.e.:
switch (
| |
| 680 case GT: return my_offset <= other_offset && my_scale >= other_scale; | |
| 681 case GE: return my_offset <= other_offset && my_scale >= other_scale; | |
| 682 case LT: return my_offset >= other_offset && my_scale <= other_scale; | |
| 683 case LE: return my_offset >= other_offset && my_scale <= other_scale; | |
| 684 case NE: return my_offset == other_offset && my_scale == other_scale; | |
| 685 } | |
| 686 UNREACHABLE(); | |
| 687 return false; | |
| 688 } | |
| 689 | |
| 690 // CompoundOperandsAreCompatible returns true when | |
|
Jakob Kummerow
2013/03/11 11:55:02
comment is about the wrong method.
| |
| 691 // "((x + my_offset) >> my_scale) rel y" implies | |
| 692 // "((x + other_offset) >> other_scale) other_relation y". | |
| 693 bool CompoundImplies(NumericRelation other_relation, | |
| 694 int my_offset, | |
| 695 int my_scale, | |
| 696 int other_offset = 0, | |
| 697 int other_scale = 0) { | |
| 698 return Implies(other_relation) && CompoundOperandsAreCompatible( | |
| 699 my_offset, my_scale, other_offset, other_scale); | |
| 700 } | |
| 701 | |
| 669 private: | 702 private: |
| 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 |
| 676 typedef EnumSet<GVNFlag> GVNFlagSet; | 709 typedef EnumSet<GVNFlag> GVNFlagSet; |
| 677 | 710 |
| 678 | 711 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 virtual void AssumeRepresentation(Representation r); | 816 virtual void AssumeRepresentation(Representation r); |
| 784 | 817 |
| 785 virtual bool IsConvertibleToInteger() const { return true; } | 818 virtual bool IsConvertibleToInteger() const { return true; } |
| 786 | 819 |
| 787 HType type() const { return type_; } | 820 HType type() const { return type_; } |
| 788 void set_type(HType new_type) { | 821 void set_type(HType new_type) { |
| 789 ASSERT(new_type.IsSubtypeOf(type_)); | 822 ASSERT(new_type.IsSubtypeOf(type_)); |
| 790 type_ = new_type; | 823 type_ = new_type; |
| 791 } | 824 } |
| 792 | 825 |
| 826 // +++++++++++++ | |
| 827 void SimplyPrint() { | |
| 828 HValue* base = NULL; | |
| 829 int offset = 0; | |
| 830 int scale = 0; | |
| 831 PrintF("%s%d(", representation().Mnemonic(), id()); | |
| 832 if (TryDecompose(&base, &offset, &scale)) { | |
| 833 PrintF("(%s%d + %d) >> %d", | |
| 834 base->representation().Mnemonic(), base->id(), offset, scale); | |
| 835 } else if (IsInteger32Constant()) { | |
| 836 PrintF("CONSTANT %d", GetInteger32Constant()); | |
| 837 } else { | |
| 838 PrintF("%s", Mnemonic()); | |
| 839 } | |
| 840 PrintF(")"); | |
| 841 } | |
| 842 | |
| 843 | |
| 793 // An operation needs to override this function iff: | 844 // An operation needs to override this function iff: |
| 794 // 1) it can produce an int32 output. | 845 // 1) it can produce an int32 output. |
| 795 // 2) the true value of its output can potentially be minus zero. | 846 // 2) the true value of its output can potentially be minus zero. |
| 796 // The implementation must set a flag so that it bails out in the case where | 847 // The implementation must set a flag so that it bails out in the case where |
| 797 // it would otherwise output what should be a minus zero as an int32 zero. | 848 // it would otherwise output what should be a minus zero as an int32 zero. |
| 798 // If the operation also exists in a form that takes int32 and outputs int32 | 849 // If the operation also exists in a form that takes int32 and outputs int32 |
| 799 // then the operation should return its input value so that we can propagate | 850 // then the operation should return its input value so that we can propagate |
| 800 // back. There are three operations that need to propagate back to more than | 851 // back. There are three operations that need to propagate back to more than |
| 801 // one input. They are phi and binary div and mul. They always return NULL | 852 // one input. They are phi and binary div and mul. They always return NULL |
| 802 // and expect the caller to take care of things. | 853 // and expect the caller to take care of things. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 968 bool IsDead() const { | 1019 bool IsDead() const { |
| 969 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); | 1020 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); |
| 970 } | 1021 } |
| 971 | 1022 |
| 972 #ifdef DEBUG | 1023 #ifdef DEBUG |
| 973 virtual void Verify() = 0; | 1024 virtual void Verify() = 0; |
| 974 #endif | 1025 #endif |
| 975 | 1026 |
| 976 // This method is recursive but it is guaranteed to terminate because | 1027 // This method is recursive but it is guaranteed to terminate because |
| 977 // RedefinedOperand() always dominates "this". | 1028 // RedefinedOperand() always dominates "this". |
| 978 bool IsRelationTrue(NumericRelation relation, HValue* other) { | 1029 bool IsRelationTrue( |
|
Jakob Kummerow
2013/03/11 11:55:02
This method is big enough to move its implementati
| |
| 1030 NumericRelation relation, HValue* other, int offset = 0, int scale = 0) { | |
|
Jakob Kummerow
2013/03/11 11:55:02
for method/function declarations (as opposed to ca
| |
| 979 if (this == other) { | 1031 if (this == other) { |
| 980 return NumericRelation::Eq().Implies(relation); | 1032 return NumericRelation::Eq().Implies(relation); |
|
Jakob Kummerow
2013/03/11 11:55:02
Doesn't this need updating to account for offset/s
Massi
2013/03/13 15:58:14
No, this is a real identity check, if "this" and "
| |
| 981 } | 1033 } |
| 982 | 1034 |
| 983 bool result = IsRelationTrueInternal(relation, other) || | 1035 // Test the direct relation. |
| 984 other->IsRelationTrueInternal(relation.Reversed(), this); | 1036 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; |
| 985 if (!result) { | 1037 |
| 986 HValue* redefined = RedefinedOperand(); | 1038 // TODO: do we need the recursive pass? We are not doing it now... |
| 987 if (redefined != NULL) { | 1039 // If scale is 0 try the reversed relation (with the full recursive pass). |
| 988 result = redefined->IsRelationTrue(relation, other); | 1040 if (scale == 0 && other->IsRelationTrueInternal(relation.Reversed(), this, |
| 989 } | 1041 -offset)) return true; |
|
Jakob Kummerow
2013/03/11 11:55:02
if-statements that span multiple lines need {}. I'
| |
| 1042 | |
| 1043 // Try decomposition. | |
| 1044 HValue* my_base = NULL; | |
| 1045 int my_offset = 0; | |
| 1046 int my_scale = 0; | |
| 1047 if (TryDecompose(&my_base, &my_offset, &my_scale) && my_scale == 0 && | |
| 1048 my_base->IsRelationTrue(relation, other, offset + my_offset, scale)) { | |
| 1049 return true; | |
| 990 } | 1050 } |
| 991 return result; | 1051 |
| 1052 // Pass the request to the redefined value. | |
| 1053 HValue* redefined = RedefinedOperand(); | |
| 1054 return redefined != NULL && redefined->IsRelationTrue(relation, other, | |
| 1055 offset, scale); | |
| 1056 } | |
| 1057 | |
| 1058 bool TryGuaranteeRange(HValue* upper_bound); | |
| 1059 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { | |
| 1060 if (RedefinedOperand() != NULL) { | |
| 1061 return RedefinedOperand()->TryDecompose(base, offset, scale); | |
| 1062 } else { | |
| 1063 return false; | |
| 1064 } | |
| 992 } | 1065 } |
| 993 | 1066 |
| 994 protected: | 1067 protected: |
| 1068 class RangeEvaluationContext BASE_EMBEDDED { | |
|
Jakob Kummerow
2013/03/11 11:55:02
I'd prefer this to be a top-level class.
| |
| 1069 public: | |
| 1070 HValue* lower_bound() { return lower_bound_; } | |
| 1071 HValue* lower_check_guarantee() { return lower_check_guarantee_; } | |
| 1072 HValue* origin() { return origin_; } | |
| 1073 HValue* upper_bound() { return upper_bound_; } | |
| 1074 HValue* upper_check_guarantee() { return upper_check_guarantee_; } | |
| 1075 int offset() { return offset_; } | |
| 1076 int scale() { return scale_; } | |
| 1077 | |
| 1078 bool lower_check_satisfied() { return lower_check_guarantee_ != NULL; } | |
|
Jakob Kummerow
2013/03/11 11:55:02
I'd prefer not to have this method, because it add
Massi
2013/03/13 15:58:14
I ended up renaming the methods, and at this point
| |
| 1079 bool upper_check_satisfied() { return upper_check_guarantee_ != NULL; } | |
| 1080 bool RangeSatisfied() { | |
|
Jakob Kummerow
2013/03/11 11:55:02
is_range_satisfied()
| |
| 1081 return lower_check_satisfied() && upper_check_satisfied(); | |
| 1082 } | |
| 1083 | |
| 1084 void set_lower_check_guarantee(HValue* guarantee) { | |
| 1085 lower_check_guarantee_ = ConvertGuarantee(guarantee); | |
| 1086 } | |
| 1087 void set_upper_check_guarantee(HValue* guarantee) { | |
| 1088 upper_check_guarantee_ = ConvertGuarantee(guarantee); | |
| 1089 } | |
| 1090 | |
| 1091 template <class T> void swap(T& a, T& b) { | |
|
Jakob Kummerow
2013/03/11 11:55:02
Private helper function should be private (or glob
| |
| 1092 T c(a); a=b; b=c; | |
|
Jakob Kummerow
2013/03/11 11:55:02
nit: formatting: one statement per line, spaces ar
| |
| 1093 } | |
| 1094 | |
| 1095 void swap_origin(HValue*& other_origin, | |
|
Jakob Kummerow
2013/03/11 11:55:02
Again, all references must be const. Use pointers.
| |
| 1096 int& other_offset, | |
| 1097 int& other_scale) { | |
| 1098 swap(origin_, other_origin); | |
| 1099 swap(offset_, other_offset); | |
| 1100 swap(scale_, other_scale); | |
| 1101 } | |
| 1102 | |
| 1103 RangeEvaluationContext(HValue* value, HValue* upper); | |
|
Jakob Kummerow
2013/03/11 11:55:02
nit: constructor should be before methods (http://
| |
| 1104 private: | |
|
Jakob Kummerow
2013/03/11 11:55:02
nit: empty line before "private:"
| |
| 1105 HValue* ConvertGuarantee(HValue* guarantee); | |
| 1106 | |
| 1107 HValue* lower_bound_; | |
| 1108 HValue* lower_check_guarantee_; | |
| 1109 HValue* origin_; | |
|
Jakob Kummerow
2013/03/11 11:55:02
I'm not too happy with the name "origin_", it's bi
| |
| 1110 HValue* upper_bound_; | |
| 1111 HValue* upper_check_guarantee_; | |
| 1112 int offset_; | |
| 1113 int scale_; | |
| 1114 }; | |
| 1115 | |
| 1116 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | |
| 1117 virtual void TryGuaranteeRangeInner(RangeEvaluationContext* context) { | |
| 1118 | |
| 1119 if (FLAG_log_abcd) { | |
| 1120 PrintF(" !!! TryGuaranteeRangeInner(%s%d:%s): DEFAULT\n", | |
| 1121 representation().Mnemonic(), id(), Mnemonic()); | |
| 1122 } | |
| 1123 | |
| 1124 } | |
| 1125 | |
| 995 // This function must be overridden for instructions with flag kUseGVN, to | 1126 // This function must be overridden for instructions with flag kUseGVN, to |
| 996 // compare the non-Operand parts of the instruction. | 1127 // compare the non-Operand parts of the instruction. |
| 997 virtual bool DataEquals(HValue* other) { | 1128 virtual bool DataEquals(HValue* other) { |
| 998 UNREACHABLE(); | 1129 UNREACHABLE(); |
| 999 return false; | 1130 return false; |
| 1000 } | 1131 } |
| 1001 | 1132 |
| 1002 virtual Representation RepresentationFromInputs() { | 1133 virtual Representation RepresentationFromInputs() { |
| 1003 return representation(); | 1134 return representation(); |
| 1004 } | 1135 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1047 for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) { | 1178 for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) { |
| 1048 HValue* use = uses.value(); | 1179 HValue* use = uses.value(); |
| 1049 if (TestDominance(this, use)) { | 1180 if (TestDominance(this, use)) { |
| 1050 use->SetOperandAt(uses.index(), this); | 1181 use->SetOperandAt(uses.index(), this); |
| 1051 } | 1182 } |
| 1052 } | 1183 } |
| 1053 } | 1184 } |
| 1054 } | 1185 } |
| 1055 | 1186 |
| 1056 // Informative definitions can override this method to state any numeric | 1187 // Informative definitions can override this method to state any numeric |
| 1057 // relation they provide on the redefined value. | 1188 // relation they provide on the redefined value. |
|
Jakob Kummerow
2013/03/11 11:55:02
Please extend this comment:
// Returns true if it
| |
| 1058 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 1189 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other, |
|
Jakob Kummerow
2013/03/11 11:55:02
for method/function declarations (as opposed to ca
| |
| 1190 int offset = 0, int scale = 0) { | |
| 1059 return false; | 1191 return false; |
| 1060 } | 1192 } |
| 1061 | 1193 |
| 1062 static GVNFlagSet AllDependsOnFlagSet() { | 1194 static GVNFlagSet AllDependsOnFlagSet() { |
| 1063 GVNFlagSet result; | 1195 GVNFlagSet result; |
| 1064 // Create changes mask. | 1196 // Create changes mask. |
| 1065 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 1197 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
| 1066 GVN_TRACKED_FLAG_LIST(ADD_FLAG) | 1198 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
| 1067 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | 1199 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
| 1068 #undef ADD_FLAG | 1200 #undef ADD_FLAG |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1297 virtual int RedefinedOperandIndex() { return 0; } | 1429 virtual int RedefinedOperandIndex() { return 0; } |
| 1298 virtual bool IsPurelyInformativeDefinition() { return true; } | 1430 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 1299 | 1431 |
| 1300 virtual Representation RequiredInputRepresentation(int index) { | 1432 virtual Representation RequiredInputRepresentation(int index) { |
| 1301 return representation(); | 1433 return representation(); |
| 1302 } | 1434 } |
| 1303 | 1435 |
| 1304 virtual void PrintDataTo(StringStream* stream); | 1436 virtual void PrintDataTo(StringStream* stream); |
| 1305 | 1437 |
| 1306 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 1438 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
| 1307 HValue* other_related_value) { | 1439 HValue* other_related_value, |
| 1440 int offset = 0, | |
| 1441 int scale = 0) { | |
| 1308 if (related_value() == other_related_value) { | 1442 if (related_value() == other_related_value) { |
| 1309 return relation().Implies(other_relation); | 1443 return relation().CompoundImplies(other_relation, offset, scale); |
| 1310 } else { | 1444 } else { |
| 1311 return false; | 1445 return false; |
| 1312 } | 1446 } |
| 1313 } | 1447 } |
| 1314 | 1448 |
| 1315 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) | 1449 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) |
| 1316 | 1450 |
| 1317 private: | 1451 private: |
| 1318 HNumericConstraint(HValue* constrained_value, | 1452 HNumericConstraint(HValue* constrained_value, |
| 1319 NumericRelation relation, | 1453 NumericRelation relation, |
| (...skipping 1632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2952 } | 3086 } |
| 2953 return true; | 3087 return true; |
| 2954 } | 3088 } |
| 2955 | 3089 |
| 2956 protected: | 3090 protected: |
| 2957 virtual void DeleteFromGraph(); | 3091 virtual void DeleteFromGraph(); |
| 2958 virtual void InternalSetOperandAt(int index, HValue* value) { | 3092 virtual void InternalSetOperandAt(int index, HValue* value) { |
| 2959 inputs_[index] = value; | 3093 inputs_[index] = value; |
| 2960 } | 3094 } |
| 2961 | 3095 |
| 2962 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other); | 3096 virtual bool IsRelationTrueInternal( |
|
Jakob Kummerow
2013/03/11 11:55:02
for method/function declarations (as opposed to ca
| |
| 3097 NumericRelation relation, HValue* other, int offset = 0, int scale = 0); | |
| 2963 | 3098 |
| 2964 private: | 3099 private: |
| 2965 ZoneList<HValue*> inputs_; | 3100 ZoneList<HValue*> inputs_; |
| 2966 int merged_index_; | 3101 int merged_index_; |
| 2967 | 3102 |
| 2968 int non_phi_uses_[Representation::kNumRepresentations]; | 3103 int non_phi_uses_[Representation::kNumRepresentations]; |
| 2969 int indirect_uses_[Representation::kNumRepresentations]; | 3104 int indirect_uses_[Representation::kNumRepresentations]; |
| 2970 int phi_id_; | 3105 int phi_id_; |
| 2971 bool is_live_; | 3106 bool is_live_; |
| 2972 bool is_convertible_to_integer_; | 3107 bool is_convertible_to_integer_; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2984 | 3119 |
| 2985 virtual int RedefinedOperandIndex() { return 0; } | 3120 virtual int RedefinedOperandIndex() { return 0; } |
| 2986 virtual bool IsPurelyInformativeDefinition() { return true; } | 3121 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 2987 virtual Representation RequiredInputRepresentation(int index) { | 3122 virtual Representation RequiredInputRepresentation(int index) { |
| 2988 return representation(); | 3123 return representation(); |
| 2989 } | 3124 } |
| 2990 | 3125 |
| 2991 virtual void PrintDataTo(StringStream* stream); | 3126 virtual void PrintDataTo(StringStream* stream); |
| 2992 | 3127 |
| 2993 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 3128 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
| 2994 HValue* other_related_value) { | 3129 HValue* other_related_value, |
| 3130 int offset = 0, | |
| 3131 int scale = 0) { | |
| 2995 if (induction_base() == other_related_value) { | 3132 if (induction_base() == other_related_value) { |
| 2996 return relation().Implies(other_relation); | 3133 return relation().CompoundImplies(other_relation, offset, scale); |
| 2997 } else { | 3134 } else { |
| 2998 return false; | 3135 return false; |
| 2999 } | 3136 } |
| 3000 } | 3137 } |
| 3001 | 3138 |
| 3002 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) | 3139 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) |
| 3003 | 3140 |
| 3004 private: | 3141 private: |
| 3005 HInductionVariableAnnotation(HPhi* phi, | 3142 HInductionVariableAnnotation(HPhi* phi, |
| 3006 NumericRelation relation, | 3143 NumericRelation relation, |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3375 virtual bool DataEquals(HValue* other) { return true; } | 3512 virtual bool DataEquals(HValue* other) { return true; } |
| 3376 }; | 3513 }; |
| 3377 | 3514 |
| 3378 | 3515 |
| 3379 enum BoundsCheckKeyMode { | 3516 enum BoundsCheckKeyMode { |
| 3380 DONT_ALLOW_SMI_KEY, | 3517 DONT_ALLOW_SMI_KEY, |
| 3381 ALLOW_SMI_KEY | 3518 ALLOW_SMI_KEY |
| 3382 }; | 3519 }; |
| 3383 | 3520 |
| 3384 | 3521 |
| 3522 class HBoundsCheckBaseIndexInformation; | |
| 3523 | |
| 3524 | |
| 3385 class HBoundsCheck: public HTemplateInstruction<2> { | 3525 class HBoundsCheck: public HTemplateInstruction<2> { |
| 3386 public: | 3526 public: |
| 3527 friend class HBoundsCheckBaseIndexInformation; | |
|
Jakob Kummerow
2013/03/11 11:55:02
Friend declarations should always be in the "priva
| |
| 3528 | |
| 3387 // Normally HBoundsCheck should be created using the | 3529 // Normally HBoundsCheck should be created using the |
| 3388 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with | 3530 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with |
| 3389 // a HCheckSmiOrInt32 check. | 3531 // a HCheckSmiOrInt32 check. |
| 3390 // However when building stubs, where we know that the arguments are Int32, | 3532 // However when building stubs, where we know that the arguments are Int32, |
| 3391 // it makes sense to invoke this constructor directly. | 3533 // it makes sense to invoke this constructor directly. |
| 3392 HBoundsCheck(HValue* index, | 3534 HBoundsCheck(HValue* index, |
| 3393 HValue* length, | 3535 HValue* length, |
| 3394 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, | 3536 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
| 3395 Representation r = Representation::None()) | 3537 Representation r = Representation::None()) |
| 3396 : key_mode_(key_mode), skip_check_(false) { | 3538 : key_mode_(key_mode), skip_check_(false), |
|
Jakob Kummerow
2013/03/11 11:55:02
let's put each initializer onto its own line.
| |
| 3539 base_(NULL), offset_(0), scale_(0), change_direction_(0) { | |
| 3397 SetOperandAt(0, index); | 3540 SetOperandAt(0, index); |
| 3398 SetOperandAt(1, length); | 3541 SetOperandAt(1, length); |
| 3399 if (r.IsNone()) { | 3542 if (r.IsNone()) { |
| 3400 // In the normal compilation pipeline the representation is flexible | 3543 // In the normal compilation pipeline the representation is flexible |
| 3401 // (see InferRepresentation). | 3544 // (see InferRepresentation). |
| 3402 SetFlag(kFlexibleRepresentation); | 3545 SetFlag(kFlexibleRepresentation); |
| 3403 } else { | 3546 } else { |
| 3404 // When compiling stubs we want to set the representation explicitly | 3547 // When compiling stubs we want to set the representation explicitly |
| 3405 // so the compilation pipeline can skip the HInferRepresentation phase. | 3548 // so the compilation pipeline can skip the HInferRepresentation phase. |
| 3406 set_representation(r); | 3549 set_representation(r); |
| 3407 } | 3550 } |
| 3408 SetFlag(kUseGVN); | 3551 SetFlag(kUseGVN); |
| 3409 } | 3552 } |
| 3410 | 3553 |
| 3411 bool skip_check() { return skip_check_; } | 3554 bool skip_check() { return skip_check_; } |
| 3412 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } | 3555 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } |
| 3556 HValue* base() { return base_; } | |
| 3557 int offset() { return offset_; } | |
| 3558 int scale() { return scale_; } | |
| 3559 bool index_can_increase() { return change_direction_ >= 0; } | |
| 3560 bool index_can_decrease() { return change_direction_ <= 0; } | |
| 3561 bool index_has_not_been_changed() { return change_direction_ == 0; } | |
| 3562 | |
| 3563 void ApplyIndexChange(); | |
| 3564 bool DetectCompoundIndex() { | |
| 3565 ASSERT(base() == NULL); | |
|
Jakob Kummerow
2013/03/11 11:55:02
nit: You're using accessors ("base()") and direct
| |
| 3566 | |
| 3567 HValue* index_base = NULL; | |
| 3568 int index_offset = 0; | |
| 3569 int index_scale = 0; | |
| 3570 if (index()->TryDecompose(&index_base, &index_offset, &index_scale)) { | |
| 3571 base_ = index_base; | |
| 3572 offset_ = index_offset; | |
| 3573 scale_ = index_scale; | |
| 3574 return true; | |
| 3575 } else { | |
| 3576 base_ = index(); | |
| 3577 offset_ = 0; | |
| 3578 scale_ = 0; | |
| 3579 return false; | |
| 3580 } | |
| 3581 } | |
| 3582 bool HasOriginalIndex() { | |
| 3583 if (base() == NULL) return true; | |
| 3584 | |
| 3585 HValue* index_base = NULL; | |
| 3586 int index_offset = 0; | |
| 3587 int index_scale = 0; | |
| 3588 if (index()->TryDecompose(&index_base, &index_offset, &index_scale)) { | |
| 3589 ASSERT(index_base == base()); | |
| 3590 return index_offset == offset() && index_scale == scale(); | |
| 3591 } else { | |
| 3592 ASSERT(index() == base()); | |
| 3593 return offset() == 0 && scale() == 0; | |
| 3594 } | |
| 3595 } | |
| 3413 | 3596 |
| 3414 virtual Representation RequiredInputRepresentation(int arg_index) { | 3597 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 3415 return representation(); | 3598 return representation(); |
| 3416 } | 3599 } |
| 3417 virtual Representation observed_input_representation(int index) { | 3600 virtual Representation observed_input_representation(int index) { |
| 3418 return Representation::Integer32(); | 3601 return Representation::Integer32(); |
| 3419 } | 3602 } |
| 3420 | 3603 |
| 3421 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3604 virtual bool IsRelationTrueInternal(NumericRelation relation, |
| 3422 HValue* related_value); | 3605 HValue* related_value, |
| 3606 int offset = 0, | |
| 3607 int scale = 0); | |
| 3423 | 3608 |
| 3424 virtual void PrintDataTo(StringStream* stream); | 3609 virtual void PrintDataTo(StringStream* stream); |
| 3425 virtual void InferRepresentation(HInferRepresentation* h_infer); | 3610 virtual void InferRepresentation(HInferRepresentation* h_infer); |
| 3426 | 3611 |
| 3427 HValue* index() { return OperandAt(0); } | 3612 HValue* index() { return OperandAt(0); } |
| 3428 HValue* length() { return OperandAt(1); } | 3613 HValue* length() { return OperandAt(1); } |
| 3429 | 3614 |
| 3430 virtual int RedefinedOperandIndex() { return 0; } | 3615 virtual int RedefinedOperandIndex() { return 0; } |
| 3431 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3616 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
| 3432 virtual void AddInformativeDefinitions(); | 3617 virtual void AddInformativeDefinitions(); |
| 3433 | 3618 |
| 3434 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3619 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
| 3435 | 3620 |
| 3436 protected: | 3621 protected: |
| 3437 virtual bool DataEquals(HValue* other) { return true; } | 3622 virtual bool DataEquals(HValue* other) { return true; } |
| 3623 virtual void TryGuaranteeRangeInner(RangeEvaluationContext* context); | |
| 3438 BoundsCheckKeyMode key_mode_; | 3624 BoundsCheckKeyMode key_mode_; |
| 3439 bool skip_check_; | 3625 bool skip_check_; |
| 3626 HValue* base_; | |
| 3627 int offset_; | |
| 3628 int scale_; | |
| 3629 int change_direction_; | |
| 3440 }; | 3630 }; |
| 3441 | 3631 |
| 3442 | 3632 |
| 3633 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | |
| 3634 public: | |
| 3635 HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | |
|
Jakob Kummerow
2013/03/11 11:55:02
explicit
| |
| 3636 HValue* base = NULL; | |
| 3637 int offset = 0; | |
| 3638 int scale = 0; | |
| 3639 if (check->index()->TryDecompose(&base, &offset, &scale)) { | |
| 3640 SetOperandAt(0, base); | |
| 3641 SetOperandAt(1, check); | |
| 3642 } else { | |
| 3643 UNREACHABLE(); | |
| 3644 } | |
| 3645 } | |
| 3646 | |
| 3647 HValue* base_index() { return OperandAt(0); } | |
| 3648 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | |
| 3649 | |
| 3650 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | |
| 3651 | |
| 3652 virtual Representation RequiredInputRepresentation(int arg_index) { | |
| 3653 return representation(); | |
| 3654 } | |
| 3655 | |
| 3656 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 3657 HValue* related_value, | |
| 3658 int offset = 0, | |
| 3659 int scale = 0); | |
| 3660 virtual void PrintDataTo(StringStream* stream); | |
| 3661 | |
| 3662 virtual int RedefinedOperandIndex() { return 0; } | |
| 3663 virtual bool IsPurelyInformativeDefinition() { return true; } | |
| 3664 | |
| 3665 protected: | |
| 3666 virtual void TryGuaranteeRangeInner(RangeEvaluationContext* context) { | |
| 3667 | |
| 3668 if (FLAG_log_abcd) { | |
| 3669 PrintF(" !!! TryGuaranteeRangeInner(%s%d): BOUNDS INFO START\n", | |
| 3670 representation().Mnemonic(), id()); | |
| 3671 } | |
| 3672 | |
| 3673 bounds_check()->TryGuaranteeRangeInner(context); | |
| 3674 | |
| 3675 if (FLAG_log_abcd) { | |
| 3676 PrintF(" !!! TryGuaranteeRangeInner(%s%d): BOUNDS INFO END\n", | |
| 3677 representation().Mnemonic(), id()); | |
| 3678 } | |
| 3679 | |
| 3680 } | |
| 3681 }; | |
| 3682 | |
| 3683 | |
| 3443 class HBitwiseBinaryOperation: public HBinaryOperation { | 3684 class HBitwiseBinaryOperation: public HBinaryOperation { |
| 3444 public: | 3685 public: |
| 3445 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 3686 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
| 3446 : HBinaryOperation(context, left, right) { | 3687 : HBinaryOperation(context, left, right) { |
| 3447 SetFlag(kFlexibleRepresentation); | 3688 SetFlag(kFlexibleRepresentation); |
| 3448 SetFlag(kTruncatingToInt32); | 3689 SetFlag(kTruncatingToInt32); |
| 3449 SetAllSideEffects(); | 3690 SetAllSideEffects(); |
| 3450 } | 3691 } |
| 3451 | 3692 |
| 3452 virtual Representation RequiredInputRepresentation(int index) { | 3693 virtual Representation RequiredInputRepresentation(int index) { |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4005 | 4246 |
| 4006 static HInstruction* NewHAdd(Zone* zone, | 4247 static HInstruction* NewHAdd(Zone* zone, |
| 4007 HValue* context, | 4248 HValue* context, |
| 4008 HValue* left, | 4249 HValue* left, |
| 4009 HValue* right); | 4250 HValue* right); |
| 4010 | 4251 |
| 4011 virtual HType CalculateInferredType(); | 4252 virtual HType CalculateInferredType(); |
| 4012 | 4253 |
| 4013 virtual HValue* Canonicalize(); | 4254 virtual HValue* Canonicalize(); |
| 4014 | 4255 |
| 4015 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4256 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { |
| 4016 HValue* base = NULL; | |
| 4017 int32_t offset = 0; | |
| 4018 if (left()->IsInteger32Constant()) { | 4257 if (left()->IsInteger32Constant()) { |
| 4019 base = right(); | 4258 *base = right(); |
| 4020 offset = left()->GetInteger32Constant(); | 4259 *offset += left()->GetInteger32Constant(); |
| 4260 return true; | |
| 4021 } else if (right()->IsInteger32Constant()) { | 4261 } else if (right()->IsInteger32Constant()) { |
| 4022 base = left(); | 4262 *base = left(); |
| 4023 offset = right()->GetInteger32Constant(); | 4263 *offset += right()->GetInteger32Constant(); |
| 4264 return true; | |
| 4024 } else { | 4265 } else { |
| 4025 return false; | 4266 return false; |
| 4026 } | 4267 } |
| 4027 | |
| 4028 return relation.IsExtendable(offset) | |
| 4029 ? base->IsRelationTrue(relation, other) : false; | |
| 4030 } | 4268 } |
| 4031 | 4269 |
| 4032 DECLARE_CONCRETE_INSTRUCTION(Add) | 4270 DECLARE_CONCRETE_INSTRUCTION(Add) |
| 4033 | 4271 |
| 4034 protected: | 4272 protected: |
| 4035 virtual bool DataEquals(HValue* other) { return true; } | 4273 virtual bool DataEquals(HValue* other) { return true; } |
| 4036 | 4274 |
| 4037 virtual Range* InferRange(Zone* zone); | 4275 virtual Range* InferRange(Zone* zone); |
| 4038 }; | 4276 }; |
| 4039 | 4277 |
| 4040 | 4278 |
| 4041 class HSub: public HArithmeticBinaryOperation { | 4279 class HSub: public HArithmeticBinaryOperation { |
| 4042 public: | 4280 public: |
| 4043 HSub(HValue* context, HValue* left, HValue* right) | 4281 HSub(HValue* context, HValue* left, HValue* right) |
| 4044 : HArithmeticBinaryOperation(context, left, right) { | 4282 : HArithmeticBinaryOperation(context, left, right) { |
| 4045 SetFlag(kCanOverflow); | 4283 SetFlag(kCanOverflow); |
| 4046 } | 4284 } |
| 4047 | 4285 |
| 4048 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4286 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
| 4049 | 4287 |
| 4050 virtual HValue* Canonicalize(); | 4288 virtual HValue* Canonicalize(); |
| 4051 | 4289 |
| 4052 static HInstruction* NewHSub(Zone* zone, | 4290 static HInstruction* NewHSub(Zone* zone, |
| 4053 HValue* context, | 4291 HValue* context, |
| 4054 HValue* left, | 4292 HValue* left, |
| 4055 HValue* right); | 4293 HValue* right); |
| 4056 | 4294 |
| 4057 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4295 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { |
| 4058 if (right()->IsInteger32Constant()) { | 4296 if (right()->IsInteger32Constant()) { |
| 4059 HValue* base = left(); | 4297 *base = left(); |
| 4060 int32_t offset = right()->GetInteger32Constant(); | 4298 *offset -= right()->GetInteger32Constant(); |
| 4061 return relation.IsExtendable(-offset) | 4299 return true; |
| 4062 ? base->IsRelationTrue(relation, other) : false; | |
| 4063 } else { | 4300 } else { |
| 4064 return false; | 4301 return false; |
| 4065 } | 4302 } |
| 4066 } | 4303 } |
| 4067 | 4304 |
| 4068 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4305 DECLARE_CONCRETE_INSTRUCTION(Sub) |
| 4069 | 4306 |
| 4070 protected: | 4307 protected: |
| 4071 virtual bool DataEquals(HValue* other) { return true; } | 4308 virtual bool DataEquals(HValue* other) { return true; } |
| 4072 | 4309 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4292 }; | 4529 }; |
| 4293 | 4530 |
| 4294 | 4531 |
| 4295 class HSar: public HBitwiseBinaryOperation { | 4532 class HSar: public HBitwiseBinaryOperation { |
| 4296 public: | 4533 public: |
| 4297 HSar(HValue* context, HValue* left, HValue* right) | 4534 HSar(HValue* context, HValue* left, HValue* right) |
| 4298 : HBitwiseBinaryOperation(context, left, right) { } | 4535 : HBitwiseBinaryOperation(context, left, right) { } |
| 4299 | 4536 |
| 4300 virtual Range* InferRange(Zone* zone); | 4537 virtual Range* InferRange(Zone* zone); |
| 4301 | 4538 |
| 4539 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { | |
| 4540 if (!scale != 0) return false; | |
| 4541 | |
| 4542 if (right()->IsInteger32Constant()) { | |
| 4543 *base = left(); | |
| 4544 *scale = right()->GetInteger32Constant(); | |
| 4545 // Note that this call can change *base again, this is intended to | |
| 4546 // also take HAdd and HSub effects on offset into account. | |
| 4547 (*base)->TryDecompose(base, offset, scale); | |
| 4548 return true; | |
| 4549 } else { | |
| 4550 return false; | |
| 4551 } | |
| 4552 } | |
| 4553 | |
| 4302 static HInstruction* NewHSar(Zone* zone, | 4554 static HInstruction* NewHSar(Zone* zone, |
| 4303 HValue* context, | 4555 HValue* context, |
| 4304 HValue* left, | 4556 HValue* left, |
| 4305 HValue* right); | 4557 HValue* right); |
| 4306 | 4558 |
| 4307 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4559 DECLARE_CONCRETE_INSTRUCTION(Sar) |
| 4308 | 4560 |
| 4309 protected: | 4561 protected: |
| 4310 virtual bool DataEquals(HValue* other) { return true; } | 4562 virtual bool DataEquals(HValue* other) { return true; } |
| 4311 }; | 4563 }; |
| (...skipping 1772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6084 virtual bool IsDeletable() const { return true; } | 6336 virtual bool IsDeletable() const { return true; } |
| 6085 }; | 6337 }; |
| 6086 | 6338 |
| 6087 | 6339 |
| 6088 #undef DECLARE_INSTRUCTION | 6340 #undef DECLARE_INSTRUCTION |
| 6089 #undef DECLARE_CONCRETE_INSTRUCTION | 6341 #undef DECLARE_CONCRETE_INSTRUCTION |
| 6090 | 6342 |
| 6091 } } // namespace v8::internal | 6343 } } // namespace v8::internal |
| 6092 | 6344 |
| 6093 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6345 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |