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 |