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: return false; | |
Jakob Kummerow
2013/03/14 12:50:09
As an additional safeguard, I'd prefer:
case NONE:
Massi
2013/03/14 15:07:18
Done.
| |
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 RangeEvaluationContext BASE_EMBEDDED { | |
710 public: | |
711 RangeEvaluationContext(HValue* value, HValue* upper); | |
712 | |
713 HValue* lower_bound() { return lower_bound_; } | |
714 HValue* lower_check_guarantee() { return lower_check_guarantee_; } | |
715 HValue* candidate() { return candidate_; } | |
716 HValue* upper_bound() { return upper_bound_; } | |
717 HValue* upper_check_guarantee() { return upper_check_guarantee_; } | |
718 int offset() { return offset_; } | |
719 int scale() { return scale_; } | |
720 | |
721 bool is_lower_bound_satisfied() { return lower_check_guarantee_ != NULL; } | |
Jakob Kummerow
2013/03/14 12:50:09
I'm still not quite happy with these names.
(1) Wh
Massi
2013/03/14 15:07:18
Done.
| |
722 bool is_upper_bound_satisfied() { return upper_check_guarantee_ != NULL; } | |
723 bool is_range_satisfied() { | |
724 return is_lower_bound_satisfied() && is_upper_bound_satisfied(); | |
725 } | |
726 | |
727 void set_lower_check_guarantee(HValue* guarantee) { | |
728 lower_check_guarantee_ = ConvertGuarantee(guarantee); | |
729 } | |
730 void set_upper_check_guarantee(HValue* guarantee) { | |
731 upper_check_guarantee_ = ConvertGuarantee(guarantee); | |
732 } | |
733 | |
734 void swap_candidate(HValue** other_candidate, | |
735 int* other_offset, | |
736 int* other_scale) { | |
737 swap(&candidate_, other_candidate); | |
738 swap(&offset_, other_offset); | |
739 swap(&scale_, other_scale); | |
740 } | |
741 | |
742 private: | |
743 HValue* ConvertGuarantee(HValue* guarantee); | |
744 | |
745 template <class T> void swap(T* a, T* b) { | |
746 T c(*a); | |
747 *a = *b; | |
748 *b = c; | |
749 } | |
750 | |
751 HValue* lower_bound_; | |
752 HValue* lower_check_guarantee_; | |
753 HValue* candidate_; | |
754 HValue* upper_bound_; | |
755 HValue* upper_check_guarantee_; | |
756 int offset_; | |
757 int scale_; | |
758 }; | |
759 | |
760 | |
676 typedef EnumSet<GVNFlag> GVNFlagSet; | 761 typedef EnumSet<GVNFlag> GVNFlagSet; |
677 | 762 |
678 | 763 |
679 class HValue: public ZoneObject { | 764 class HValue: public ZoneObject { |
680 public: | 765 public: |
681 static const int kNoNumber = -1; | 766 static const int kNoNumber = -1; |
682 | 767 |
683 enum Flag { | 768 enum Flag { |
684 kFlexibleRepresentation, | 769 kFlexibleRepresentation, |
685 // Participate in Global Value Numbering, i.e. elimination of | 770 // Participate in Global Value Numbering, i.e. elimination of |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
966 } | 1051 } |
967 | 1052 |
968 bool IsDead() const { | 1053 bool IsDead() const { |
969 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); | 1054 return HasNoUses() && !HasObservableSideEffects() && IsDeletable(); |
970 } | 1055 } |
971 | 1056 |
972 #ifdef DEBUG | 1057 #ifdef DEBUG |
973 virtual void Verify() = 0; | 1058 virtual void Verify() = 0; |
974 #endif | 1059 #endif |
975 | 1060 |
976 // This method is recursive but it is guaranteed to terminate because | 1061 bool IsRelationTrue(NumericRelation relation, |
977 // RedefinedOperand() always dominates "this". | 1062 HValue* other, |
978 bool IsRelationTrue(NumericRelation relation, HValue* other) { | 1063 int offset = 0, |
979 if (this == other) { | 1064 int scale = 0); |
980 return NumericRelation::Eq().Implies(relation); | 1065 |
1066 bool TryGuaranteeRange(HValue* upper_bound); | |
1067 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { | |
1068 if (RedefinedOperand() != NULL) { | |
1069 return RedefinedOperand()->TryDecompose(base, offset, scale); | |
1070 } else { | |
1071 return false; | |
981 } | 1072 } |
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 } | 1073 } |
993 | 1074 |
994 protected: | 1075 protected: |
1076 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | |
1077 | |
1078 enum RangeGuaranteeDirection { | |
1079 DIRECTION_NONE = 0, | |
1080 DIRECTION_UPPER = 1, | |
1081 DIRECTION_LOWER = 2, | |
1082 DIRECTION_BOTH = 4 | |
Jakob Kummerow
2013/03/14 12:50:09
Looks like you're not using DIRECTION_BOTH anywher
Massi
2013/03/14 15:07:18
Done.
| |
1083 }; | |
1084 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} | |
1085 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {} | |
1086 | |
995 // This function must be overridden for instructions with flag kUseGVN, to | 1087 // This function must be overridden for instructions with flag kUseGVN, to |
996 // compare the non-Operand parts of the instruction. | 1088 // compare the non-Operand parts of the instruction. |
997 virtual bool DataEquals(HValue* other) { | 1089 virtual bool DataEquals(HValue* other) { |
998 UNREACHABLE(); | 1090 UNREACHABLE(); |
999 return false; | 1091 return false; |
1000 } | 1092 } |
1001 | 1093 |
1002 virtual Representation RepresentationFromInputs() { | 1094 virtual Representation RepresentationFromInputs() { |
1003 return representation(); | 1095 return representation(); |
1004 } | 1096 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1048 HValue* use = uses.value(); | 1140 HValue* use = uses.value(); |
1049 if (TestDominance(this, use)) { | 1141 if (TestDominance(this, use)) { |
1050 use->SetOperandAt(uses.index(), this); | 1142 use->SetOperandAt(uses.index(), this); |
1051 } | 1143 } |
1052 } | 1144 } |
1053 } | 1145 } |
1054 } | 1146 } |
1055 | 1147 |
1056 // Informative definitions can override this method to state any numeric | 1148 // Informative definitions can override this method to state any numeric |
1057 // relation they provide on the redefined value. | 1149 // relation they provide on the redefined value. |
1058 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 1150 // Returns true if it is guaranteed that: |
1151 // ((this + offset) >> scale) relation other | |
1152 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
1153 HValue* other, | |
1154 int offset = 0, | |
1155 int scale = 0) { | |
1059 return false; | 1156 return false; |
1060 } | 1157 } |
1061 | 1158 |
1062 static GVNFlagSet AllDependsOnFlagSet() { | 1159 static GVNFlagSet AllDependsOnFlagSet() { |
1063 GVNFlagSet result; | 1160 GVNFlagSet result; |
1064 // Create changes mask. | 1161 // Create changes mask. |
1065 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 1162 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
1066 GVN_TRACKED_FLAG_LIST(ADD_FLAG) | 1163 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
1067 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | 1164 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
1068 #undef ADD_FLAG | 1165 #undef ADD_FLAG |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1297 virtual int RedefinedOperandIndex() { return 0; } | 1394 virtual int RedefinedOperandIndex() { return 0; } |
1298 virtual bool IsPurelyInformativeDefinition() { return true; } | 1395 virtual bool IsPurelyInformativeDefinition() { return true; } |
1299 | 1396 |
1300 virtual Representation RequiredInputRepresentation(int index) { | 1397 virtual Representation RequiredInputRepresentation(int index) { |
1301 return representation(); | 1398 return representation(); |
1302 } | 1399 } |
1303 | 1400 |
1304 virtual void PrintDataTo(StringStream* stream); | 1401 virtual void PrintDataTo(StringStream* stream); |
1305 | 1402 |
1306 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 1403 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
1307 HValue* other_related_value) { | 1404 HValue* other_related_value, |
1405 int offset = 0, | |
1406 int scale = 0) { | |
1308 if (related_value() == other_related_value) { | 1407 if (related_value() == other_related_value) { |
1309 return relation().Implies(other_relation); | 1408 return relation().CompoundImplies(other_relation, offset, scale); |
1310 } else { | 1409 } else { |
1311 return false; | 1410 return false; |
1312 } | 1411 } |
1313 } | 1412 } |
1314 | 1413 |
1315 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) | 1414 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) |
1316 | 1415 |
1317 private: | 1416 private: |
1318 HNumericConstraint(HValue* constrained_value, | 1417 HNumericConstraint(HValue* constrained_value, |
1319 NumericRelation relation, | 1418 NumericRelation relation, |
1320 HValue* related_value) | 1419 HValue* related_value) |
1321 : relation_(relation) { | 1420 : relation_(relation) { |
1322 SetOperandAt(0, constrained_value); | 1421 SetOperandAt(0, constrained_value); |
1323 SetOperandAt(1, related_value); | 1422 SetOperandAt(1, related_value); |
1324 set_representation(constrained_value->representation()); | |
1325 } | 1423 } |
1326 | 1424 |
1327 NumericRelation relation_; | 1425 NumericRelation relation_; |
1328 }; | 1426 }; |
1329 | 1427 |
1330 | 1428 |
1331 // We insert soft-deoptimize when we hit code with unknown typefeedback, | 1429 // We insert soft-deoptimize when we hit code with unknown typefeedback, |
1332 // so that we get a chance of re-optimizing with useful typefeedback. | 1430 // so that we get a chance of re-optimizing with useful typefeedback. |
1333 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. | 1431 // HSoftDeoptimize does not end a basic block as opposed to HDeoptimize. |
1334 class HSoftDeoptimize: public HTemplateInstruction<0> { | 1432 class HSoftDeoptimize: public HTemplateInstruction<0> { |
(...skipping 1617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2952 } | 3050 } |
2953 return true; | 3051 return true; |
2954 } | 3052 } |
2955 | 3053 |
2956 protected: | 3054 protected: |
2957 virtual void DeleteFromGraph(); | 3055 virtual void DeleteFromGraph(); |
2958 virtual void InternalSetOperandAt(int index, HValue* value) { | 3056 virtual void InternalSetOperandAt(int index, HValue* value) { |
2959 inputs_[index] = value; | 3057 inputs_[index] = value; |
2960 } | 3058 } |
2961 | 3059 |
2962 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other); | 3060 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3061 HValue* other, | |
3062 int offset = 0, | |
3063 int scale = 0); | |
2963 | 3064 |
2964 private: | 3065 private: |
2965 ZoneList<HValue*> inputs_; | 3066 ZoneList<HValue*> inputs_; |
2966 int merged_index_; | 3067 int merged_index_; |
2967 | 3068 |
2968 int non_phi_uses_[Representation::kNumRepresentations]; | 3069 int non_phi_uses_[Representation::kNumRepresentations]; |
2969 int indirect_uses_[Representation::kNumRepresentations]; | 3070 int indirect_uses_[Representation::kNumRepresentations]; |
2970 int phi_id_; | 3071 int phi_id_; |
2971 bool is_live_; | 3072 bool is_live_; |
2972 bool is_convertible_to_integer_; | 3073 bool is_convertible_to_integer_; |
(...skipping 11 matching lines...) Expand all Loading... | |
2984 | 3085 |
2985 virtual int RedefinedOperandIndex() { return 0; } | 3086 virtual int RedefinedOperandIndex() { return 0; } |
2986 virtual bool IsPurelyInformativeDefinition() { return true; } | 3087 virtual bool IsPurelyInformativeDefinition() { return true; } |
2987 virtual Representation RequiredInputRepresentation(int index) { | 3088 virtual Representation RequiredInputRepresentation(int index) { |
2988 return representation(); | 3089 return representation(); |
2989 } | 3090 } |
2990 | 3091 |
2991 virtual void PrintDataTo(StringStream* stream); | 3092 virtual void PrintDataTo(StringStream* stream); |
2992 | 3093 |
2993 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | 3094 virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
2994 HValue* other_related_value) { | 3095 HValue* other_related_value, |
3096 int offset = 0, | |
3097 int scale = 0) { | |
2995 if (induction_base() == other_related_value) { | 3098 if (induction_base() == other_related_value) { |
2996 return relation().Implies(other_relation); | 3099 return relation().CompoundImplies(other_relation, offset, scale); |
2997 } else { | 3100 } else { |
2998 return false; | 3101 return false; |
2999 } | 3102 } |
3000 } | 3103 } |
3001 | 3104 |
3002 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) | 3105 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) |
3003 | 3106 |
3004 private: | 3107 private: |
3005 HInductionVariableAnnotation(HPhi* phi, | 3108 HInductionVariableAnnotation(HPhi* phi, |
3006 NumericRelation relation, | 3109 NumericRelation relation, |
3007 int operand_index) | 3110 int operand_index) |
3008 : HUnaryOperation(phi), | 3111 : HUnaryOperation(phi), |
3009 phi_(phi), relation_(relation), operand_index_(operand_index) { | 3112 phi_(phi), relation_(relation), operand_index_(operand_index) { |
3010 set_representation(phi->representation()); | |
3011 } | 3113 } |
3012 | 3114 |
3013 // We need to store the phi both here and in the instruction operand because | 3115 // 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 | 3116 // 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). | 3117 // and this instruction (inserting an idef updates every use). |
3016 HPhi* phi_; | 3118 HPhi* phi_; |
3017 NumericRelation relation_; | 3119 NumericRelation relation_; |
3018 int operand_index_; | 3120 int operand_index_; |
3019 }; | 3121 }; |
3020 | 3122 |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3375 virtual bool DataEquals(HValue* other) { return true; } | 3477 virtual bool DataEquals(HValue* other) { return true; } |
3376 }; | 3478 }; |
3377 | 3479 |
3378 | 3480 |
3379 enum BoundsCheckKeyMode { | 3481 enum BoundsCheckKeyMode { |
3380 DONT_ALLOW_SMI_KEY, | 3482 DONT_ALLOW_SMI_KEY, |
3381 ALLOW_SMI_KEY | 3483 ALLOW_SMI_KEY |
3382 }; | 3484 }; |
3383 | 3485 |
3384 | 3486 |
3487 class HBoundsCheckBaseIndexInformation; | |
3488 | |
3489 | |
3385 class HBoundsCheck: public HTemplateInstruction<2> { | 3490 class HBoundsCheck: public HTemplateInstruction<2> { |
3386 public: | 3491 public: |
3492 friend class HBoundsCheckBaseIndexInformation; | |
Jakob Kummerow
2013/03/14 12:50:09
Friend declarations should always be in the "priva
Massi
2013/03/14 15:07:18
Done (in the "protected:" section).
| |
3493 | |
3387 // Normally HBoundsCheck should be created using the | 3494 // Normally HBoundsCheck should be created using the |
3388 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with | 3495 // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with |
3389 // a HCheckSmiOrInt32 check. | 3496 // a HCheckSmiOrInt32 check. |
3390 // However when building stubs, where we know that the arguments are Int32, | 3497 // However when building stubs, where we know that the arguments are Int32, |
3391 // it makes sense to invoke this constructor directly. | 3498 // it makes sense to invoke this constructor directly. |
3392 HBoundsCheck(HValue* index, | 3499 HBoundsCheck(HValue* index, |
3393 HValue* length, | 3500 HValue* length, |
3394 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, | 3501 BoundsCheckKeyMode key_mode = DONT_ALLOW_SMI_KEY, |
3395 Representation r = Representation::None()) | 3502 Representation r = Representation::None()) |
3396 : key_mode_(key_mode), skip_check_(false) { | 3503 : key_mode_(key_mode), skip_check_(false), |
3504 base_(NULL), offset_(0), scale_(0), | |
3505 responsibility_direction_(DIRECTION_NONE) { | |
3397 SetOperandAt(0, index); | 3506 SetOperandAt(0, index); |
3398 SetOperandAt(1, length); | 3507 SetOperandAt(1, length); |
3399 if (r.IsNone()) { | 3508 if (r.IsNone()) { |
3400 // In the normal compilation pipeline the representation is flexible | 3509 // In the normal compilation pipeline the representation is flexible |
3401 // (see InferRepresentation). | 3510 // (see InferRepresentation). |
3402 SetFlag(kFlexibleRepresentation); | 3511 SetFlag(kFlexibleRepresentation); |
3403 } else { | 3512 } else { |
3404 // When compiling stubs we want to set the representation explicitly | 3513 // When compiling stubs we want to set the representation explicitly |
3405 // so the compilation pipeline can skip the HInferRepresentation phase. | 3514 // so the compilation pipeline can skip the HInferRepresentation phase. |
3406 set_representation(r); | 3515 set_representation(r); |
3407 } | 3516 } |
3408 SetFlag(kUseGVN); | 3517 SetFlag(kUseGVN); |
3409 } | 3518 } |
3410 | 3519 |
3411 bool skip_check() { return skip_check_; } | 3520 bool skip_check() { return skip_check_; } |
3412 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } | 3521 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } |
3522 HValue* base() { return base_; } | |
3523 int offset() { return offset_; } | |
3524 int scale() { return scale_; } | |
3525 bool index_can_increase() { | |
3526 return (responsibility_direction_ & DIRECTION_LOWER) == 0; | |
3527 } | |
3528 bool index_can_decrease() { | |
3529 return (responsibility_direction_ & DIRECTION_UPPER) == 0; | |
3530 } | |
3531 | |
3532 void ApplyIndexChange(); | |
3533 bool DetectCompoundIndex() { | |
3534 ASSERT(base() == NULL); | |
3535 | |
3536 HValue* index_base = NULL; | |
3537 int index_offset = 0; | |
3538 int index_scale = 0; | |
3539 if (index()->TryDecompose(&index_base, &index_offset, &index_scale)) { | |
3540 base_ = index_base; | |
3541 offset_ = index_offset; | |
3542 scale_ = index_scale; | |
3543 return true; | |
3544 } else { | |
3545 base_ = index(); | |
3546 offset_ = 0; | |
3547 scale_ = 0; | |
3548 return false; | |
3549 } | |
3550 } | |
3413 | 3551 |
3414 virtual Representation RequiredInputRepresentation(int arg_index) { | 3552 virtual Representation RequiredInputRepresentation(int arg_index) { |
3415 return representation(); | 3553 return representation(); |
3416 } | 3554 } |
3417 virtual Representation observed_input_representation(int index) { | 3555 virtual Representation observed_input_representation(int index) { |
3418 return Representation::Integer32(); | 3556 return Representation::Integer32(); |
3419 } | 3557 } |
3420 | 3558 |
3421 virtual bool IsRelationTrueInternal(NumericRelation relation, | 3559 virtual bool IsRelationTrueInternal(NumericRelation relation, |
3422 HValue* related_value); | 3560 HValue* related_value, |
3561 int offset = 0, | |
3562 int scale = 0); | |
3423 | 3563 |
3424 virtual void PrintDataTo(StringStream* stream); | 3564 virtual void PrintDataTo(StringStream* stream); |
3425 virtual void InferRepresentation(HInferRepresentation* h_infer); | 3565 virtual void InferRepresentation(HInferRepresentation* h_infer); |
3426 | 3566 |
3427 HValue* index() { return OperandAt(0); } | 3567 HValue* index() { return OperandAt(0); } |
3428 HValue* length() { return OperandAt(1); } | 3568 HValue* length() { return OperandAt(1); } |
3429 | 3569 |
3430 virtual int RedefinedOperandIndex() { return 0; } | 3570 virtual int RedefinedOperandIndex() { return 0; } |
3431 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3571 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
3432 virtual void AddInformativeDefinitions(); | 3572 virtual void AddInformativeDefinitions(); |
3433 | 3573 |
3434 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3574 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3435 | 3575 |
3436 protected: | 3576 protected: |
3577 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
3578 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( | |
3579 responsibility_direction_ | direction); | |
3580 } | |
3581 | |
3437 virtual bool DataEquals(HValue* other) { return true; } | 3582 virtual bool DataEquals(HValue* other) { return true; } |
3583 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | |
3438 BoundsCheckKeyMode key_mode_; | 3584 BoundsCheckKeyMode key_mode_; |
3439 bool skip_check_; | 3585 bool skip_check_; |
3586 HValue* base_; | |
3587 int offset_; | |
3588 int scale_; | |
3589 RangeGuaranteeDirection responsibility_direction_; | |
3440 }; | 3590 }; |
3441 | 3591 |
3442 | 3592 |
3593 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { | |
3594 public: | |
3595 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | |
3596 HValue* base = NULL; | |
3597 int offset = 0; | |
3598 int scale = 0; | |
3599 if (check->index()->TryDecompose(&base, &offset, &scale)) { | |
3600 SetOperandAt(0, base); | |
3601 SetOperandAt(1, check); | |
3602 } else { | |
3603 UNREACHABLE(); | |
3604 } | |
3605 } | |
3606 | |
3607 HValue* base_index() { return OperandAt(0); } | |
3608 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | |
3609 | |
3610 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | |
3611 | |
3612 virtual Representation RequiredInputRepresentation(int arg_index) { | |
3613 return representation(); | |
3614 } | |
3615 | |
3616 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
3617 HValue* related_value, | |
3618 int offset = 0, | |
3619 int scale = 0); | |
3620 virtual void PrintDataTo(StringStream* stream); | |
3621 | |
3622 virtual int RedefinedOperandIndex() { return 0; } | |
3623 virtual bool IsPurelyInformativeDefinition() { return true; } | |
3624 | |
3625 protected: | |
3626 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
3627 bounds_check()->SetResponsibilityForRange(direction); | |
3628 } | |
3629 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
3630 bounds_check()->TryGuaranteeRangeChanging(context); | |
3631 } | |
3632 }; | |
3633 | |
3634 | |
3443 class HBitwiseBinaryOperation: public HBinaryOperation { | 3635 class HBitwiseBinaryOperation: public HBinaryOperation { |
3444 public: | 3636 public: |
3445 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) | 3637 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right) |
3446 : HBinaryOperation(context, left, right) { | 3638 : HBinaryOperation(context, left, right) { |
3447 SetFlag(kFlexibleRepresentation); | 3639 SetFlag(kFlexibleRepresentation); |
3448 SetFlag(kTruncatingToInt32); | 3640 SetFlag(kTruncatingToInt32); |
3449 SetAllSideEffects(); | 3641 SetAllSideEffects(); |
3450 } | 3642 } |
3451 | 3643 |
3452 virtual Representation RequiredInputRepresentation(int index) { | 3644 virtual Representation RequiredInputRepresentation(int index) { |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4005 | 4197 |
4006 static HInstruction* NewHAdd(Zone* zone, | 4198 static HInstruction* NewHAdd(Zone* zone, |
4007 HValue* context, | 4199 HValue* context, |
4008 HValue* left, | 4200 HValue* left, |
4009 HValue* right); | 4201 HValue* right); |
4010 | 4202 |
4011 virtual HType CalculateInferredType(); | 4203 virtual HType CalculateInferredType(); |
4012 | 4204 |
4013 virtual HValue* Canonicalize(); | 4205 virtual HValue* Canonicalize(); |
4014 | 4206 |
4015 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4207 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { |
4016 HValue* base = NULL; | |
4017 int32_t offset = 0; | |
4018 if (left()->IsInteger32Constant()) { | 4208 if (left()->IsInteger32Constant()) { |
4019 base = right(); | 4209 *base = right(); |
4020 offset = left()->GetInteger32Constant(); | 4210 *offset += left()->GetInteger32Constant(); |
4211 return true; | |
4021 } else if (right()->IsInteger32Constant()) { | 4212 } else if (right()->IsInteger32Constant()) { |
4022 base = left(); | 4213 *base = left(); |
4023 offset = right()->GetInteger32Constant(); | 4214 *offset += right()->GetInteger32Constant(); |
4215 return true; | |
4024 } else { | 4216 } else { |
4025 return false; | 4217 return false; |
4026 } | 4218 } |
4027 | |
4028 return relation.IsExtendable(offset) | |
4029 ? base->IsRelationTrue(relation, other) : false; | |
4030 } | 4219 } |
4031 | 4220 |
4032 DECLARE_CONCRETE_INSTRUCTION(Add) | 4221 DECLARE_CONCRETE_INSTRUCTION(Add) |
4033 | 4222 |
4034 protected: | 4223 protected: |
4035 virtual bool DataEquals(HValue* other) { return true; } | 4224 virtual bool DataEquals(HValue* other) { return true; } |
4036 | 4225 |
4037 virtual Range* InferRange(Zone* zone); | 4226 virtual Range* InferRange(Zone* zone); |
4038 }; | 4227 }; |
4039 | 4228 |
4040 | 4229 |
4041 class HSub: public HArithmeticBinaryOperation { | 4230 class HSub: public HArithmeticBinaryOperation { |
4042 public: | 4231 public: |
4043 HSub(HValue* context, HValue* left, HValue* right) | 4232 HSub(HValue* context, HValue* left, HValue* right) |
4044 : HArithmeticBinaryOperation(context, left, right) { | 4233 : HArithmeticBinaryOperation(context, left, right) { |
4045 SetFlag(kCanOverflow); | 4234 SetFlag(kCanOverflow); |
4046 } | 4235 } |
4047 | 4236 |
4048 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); | 4237 virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); |
4049 | 4238 |
4050 virtual HValue* Canonicalize(); | 4239 virtual HValue* Canonicalize(); |
4051 | 4240 |
4052 static HInstruction* NewHSub(Zone* zone, | 4241 static HInstruction* NewHSub(Zone* zone, |
4053 HValue* context, | 4242 HValue* context, |
4054 HValue* left, | 4243 HValue* left, |
4055 HValue* right); | 4244 HValue* right); |
4056 | 4245 |
4057 virtual bool IsRelationTrueInternal(NumericRelation relation, HValue* other) { | 4246 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { |
4058 if (right()->IsInteger32Constant()) { | 4247 if (right()->IsInteger32Constant()) { |
4059 HValue* base = left(); | 4248 *base = left(); |
4060 int32_t offset = right()->GetInteger32Constant(); | 4249 *offset -= right()->GetInteger32Constant(); |
4061 return relation.IsExtendable(-offset) | 4250 return true; |
4062 ? base->IsRelationTrue(relation, other) : false; | |
4063 } else { | 4251 } else { |
4064 return false; | 4252 return false; |
4065 } | 4253 } |
4066 } | 4254 } |
4067 | 4255 |
4068 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4256 DECLARE_CONCRETE_INSTRUCTION(Sub) |
4069 | 4257 |
4070 protected: | 4258 protected: |
4071 virtual bool DataEquals(HValue* other) { return true; } | 4259 virtual bool DataEquals(HValue* other) { return true; } |
4072 | 4260 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4292 }; | 4480 }; |
4293 | 4481 |
4294 | 4482 |
4295 class HSar: public HBitwiseBinaryOperation { | 4483 class HSar: public HBitwiseBinaryOperation { |
4296 public: | 4484 public: |
4297 HSar(HValue* context, HValue* left, HValue* right) | 4485 HSar(HValue* context, HValue* left, HValue* right) |
4298 : HBitwiseBinaryOperation(context, left, right) { } | 4486 : HBitwiseBinaryOperation(context, left, right) { } |
4299 | 4487 |
4300 virtual Range* InferRange(Zone* zone); | 4488 virtual Range* InferRange(Zone* zone); |
4301 | 4489 |
4490 virtual bool TryDecompose(HValue** base, int* offset, int* scale) { | |
4491 if (!scale != 0) return false; | |
Jakob Kummerow
2013/03/14 12:50:09
I think you mean s/!scale/*scale/.
Please add a t
Massi
2013/03/14 15:07:18
Done, but with a small refactoring.
| |
4492 | |
4493 if (right()->IsInteger32Constant()) { | |
4494 *base = left(); | |
4495 *scale = right()->GetInteger32Constant(); | |
4496 // Note that this call can change *base again, this is intended to | |
4497 // also take HAdd and HSub effects on offset into account. | |
4498 (*base)->TryDecompose(base, offset, scale); | |
4499 return true; | |
4500 } else { | |
4501 return false; | |
4502 } | |
4503 } | |
4504 | |
4302 static HInstruction* NewHSar(Zone* zone, | 4505 static HInstruction* NewHSar(Zone* zone, |
4303 HValue* context, | 4506 HValue* context, |
4304 HValue* left, | 4507 HValue* left, |
4305 HValue* right); | 4508 HValue* right); |
4306 | 4509 |
4307 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4510 DECLARE_CONCRETE_INSTRUCTION(Sar) |
4308 | 4511 |
4309 protected: | 4512 protected: |
4310 virtual bool DataEquals(HValue* other) { return true; } | 4513 virtual bool DataEquals(HValue* other) { return true; } |
4311 }; | 4514 }; |
(...skipping 1772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6084 virtual bool IsDeletable() const { return true; } | 6287 virtual bool IsDeletable() const { return true; } |
6085 }; | 6288 }; |
6086 | 6289 |
6087 | 6290 |
6088 #undef DECLARE_INSTRUCTION | 6291 #undef DECLARE_INSTRUCTION |
6089 #undef DECLARE_CONCRETE_INSTRUCTION | 6292 #undef DECLARE_CONCRETE_INSTRUCTION |
6090 | 6293 |
6091 } } // namespace v8::internal | 6294 } } // namespace v8::internal |
6092 | 6295 |
6093 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6296 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |