| 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 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 V(ForceRepresentation) \ | 115 V(ForceRepresentation) \ |
| 116 V(ForInCacheArray) \ | 116 V(ForInCacheArray) \ |
| 117 V(ForInPrepareMap) \ | 117 V(ForInPrepareMap) \ |
| 118 V(FunctionLiteral) \ | 118 V(FunctionLiteral) \ |
| 119 V(GetCachedArrayIndex) \ | 119 V(GetCachedArrayIndex) \ |
| 120 V(GlobalObject) \ | 120 V(GlobalObject) \ |
| 121 V(GlobalReceiver) \ | 121 V(GlobalReceiver) \ |
| 122 V(Goto) \ | 122 V(Goto) \ |
| 123 V(HasCachedArrayIndexAndBranch) \ | 123 V(HasCachedArrayIndexAndBranch) \ |
| 124 V(HasInstanceTypeAndBranch) \ | 124 V(HasInstanceTypeAndBranch) \ |
| 125 V(InductionVariableAnnotation) \ | |
| 126 V(InnerAllocatedObject) \ | 125 V(InnerAllocatedObject) \ |
| 127 V(InstanceOf) \ | 126 V(InstanceOf) \ |
| 128 V(InstanceOfKnownGlobal) \ | 127 V(InstanceOfKnownGlobal) \ |
| 129 V(InstanceSize) \ | 128 V(InstanceSize) \ |
| 130 V(InvokeFunction) \ | 129 V(InvokeFunction) \ |
| 131 V(IsConstructCallAndBranch) \ | 130 V(IsConstructCallAndBranch) \ |
| 132 V(IsObjectAndBranch) \ | 131 V(IsObjectAndBranch) \ |
| 133 V(IsNumberAndBranch) \ | 132 V(IsNumberAndBranch) \ |
| 134 V(IsStringAndBranch) \ | 133 V(IsStringAndBranch) \ |
| 135 V(IsSmiAndBranch) \ | 134 V(IsSmiAndBranch) \ |
| 136 V(IsUndetectableAndBranch) \ | 135 V(IsUndetectableAndBranch) \ |
| 137 V(LeaveInlined) \ | 136 V(LeaveInlined) \ |
| 138 V(LoadContextSlot) \ | 137 V(LoadContextSlot) \ |
| 139 V(LoadExternalArrayPointer) \ | 138 V(LoadExternalArrayPointer) \ |
| 140 V(LoadFieldByIndex) \ | 139 V(LoadFieldByIndex) \ |
| 141 V(LoadFunctionPrototype) \ | 140 V(LoadFunctionPrototype) \ |
| 142 V(LoadGlobalCell) \ | 141 V(LoadGlobalCell) \ |
| 143 V(LoadGlobalGeneric) \ | 142 V(LoadGlobalGeneric) \ |
| 144 V(LoadKeyed) \ | 143 V(LoadKeyed) \ |
| 145 V(LoadKeyedGeneric) \ | 144 V(LoadKeyedGeneric) \ |
| 146 V(LoadNamedField) \ | 145 V(LoadNamedField) \ |
| 147 V(LoadNamedFieldPolymorphic) \ | 146 V(LoadNamedFieldPolymorphic) \ |
| 148 V(LoadNamedGeneric) \ | 147 V(LoadNamedGeneric) \ |
| 149 V(MapEnumLength) \ | 148 V(MapEnumLength) \ |
| 150 V(MathFloorOfDiv) \ | 149 V(MathFloorOfDiv) \ |
| 151 V(MathMinMax) \ | 150 V(MathMinMax) \ |
| 152 V(Mod) \ | 151 V(Mod) \ |
| 153 V(Mul) \ | 152 V(Mul) \ |
| 154 V(NumericConstraint) \ | |
| 155 V(OsrEntry) \ | 153 V(OsrEntry) \ |
| 156 V(OuterContext) \ | 154 V(OuterContext) \ |
| 157 V(Parameter) \ | 155 V(Parameter) \ |
| 158 V(Power) \ | 156 V(Power) \ |
| 159 V(PushArgument) \ | 157 V(PushArgument) \ |
| 160 V(Random) \ | 158 V(Random) \ |
| 161 V(RegExpLiteral) \ | 159 V(RegExpLiteral) \ |
| 162 V(Return) \ | 160 V(Return) \ |
| 163 V(Ror) \ | 161 V(Ror) \ |
| 164 V(Sar) \ | 162 V(Sar) \ |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) | 533 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) |
| 536 #undef DECLARE_FLAG | 534 #undef DECLARE_FLAG |
| 537 kAfterLastFlag, | 535 kAfterLastFlag, |
| 538 kLastFlag = kAfterLastFlag - 1, | 536 kLastFlag = kAfterLastFlag - 1, |
| 539 #define COUNT_FLAG(type) + 1 | 537 #define COUNT_FLAG(type) + 1 |
| 540 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG) | 538 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG) |
| 541 #undef COUNT_FLAG | 539 #undef COUNT_FLAG |
| 542 }; | 540 }; |
| 543 | 541 |
| 544 | 542 |
| 545 class NumericRelation { | |
| 546 public: | |
| 547 enum Kind { NONE, EQ, GT, GE, LT, LE, NE }; | |
| 548 static const char* MnemonicFromKind(Kind kind) { | |
| 549 switch (kind) { | |
| 550 case NONE: return "NONE"; | |
| 551 case EQ: return "EQ"; | |
| 552 case GT: return "GT"; | |
| 553 case GE: return "GE"; | |
| 554 case LT: return "LT"; | |
| 555 case LE: return "LE"; | |
| 556 case NE: return "NE"; | |
| 557 } | |
| 558 UNREACHABLE(); | |
| 559 return NULL; | |
| 560 } | |
| 561 const char* Mnemonic() const { return MnemonicFromKind(kind_); } | |
| 562 | |
| 563 static NumericRelation None() { return NumericRelation(NONE); } | |
| 564 static NumericRelation Eq() { return NumericRelation(EQ); } | |
| 565 static NumericRelation Gt() { return NumericRelation(GT); } | |
| 566 static NumericRelation Ge() { return NumericRelation(GE); } | |
| 567 static NumericRelation Lt() { return NumericRelation(LT); } | |
| 568 static NumericRelation Le() { return NumericRelation(LE); } | |
| 569 static NumericRelation Ne() { return NumericRelation(NE); } | |
| 570 | |
| 571 bool IsNone() { return kind_ == NONE; } | |
| 572 | |
| 573 static NumericRelation FromToken(Token::Value token) { | |
| 574 switch (token) { | |
| 575 case Token::EQ: return Eq(); | |
| 576 case Token::EQ_STRICT: return Eq(); | |
| 577 case Token::LT: return Lt(); | |
| 578 case Token::GT: return Gt(); | |
| 579 case Token::LTE: return Le(); | |
| 580 case Token::GTE: return Ge(); | |
| 581 case Token::NE: return Ne(); | |
| 582 case Token::NE_STRICT: return Ne(); | |
| 583 default: return None(); | |
| 584 } | |
| 585 } | |
| 586 | |
| 587 // The semantics of "Reversed" is that if "x rel y" is true then also | |
| 588 // "y rel.Reversed() x" is true, and that rel.Reversed().Reversed() == rel. | |
| 589 NumericRelation Reversed() { | |
| 590 switch (kind_) { | |
| 591 case NONE: return None(); | |
| 592 case EQ: return Eq(); | |
| 593 case GT: return Lt(); | |
| 594 case GE: return Le(); | |
| 595 case LT: return Gt(); | |
| 596 case LE: return Ge(); | |
| 597 case NE: return Ne(); | |
| 598 } | |
| 599 UNREACHABLE(); | |
| 600 return None(); | |
| 601 } | |
| 602 | |
| 603 // The semantics of "Negated" is that if "x rel y" is true then also | |
| 604 // "!(x rel.Negated() y)" is true. | |
| 605 NumericRelation Negated() { | |
| 606 switch (kind_) { | |
| 607 case NONE: return None(); | |
| 608 case EQ: return Ne(); | |
| 609 case GT: return Le(); | |
| 610 case GE: return Lt(); | |
| 611 case LT: return Ge(); | |
| 612 case LE: return Gt(); | |
| 613 case NE: return Eq(); | |
| 614 } | |
| 615 UNREACHABLE(); | |
| 616 return None(); | |
| 617 } | |
| 618 | |
| 619 // The semantics of "Implies" is that if "x rel y" is true | |
| 620 // then also "x other_relation y" is true. | |
| 621 bool Implies(NumericRelation other_relation) { | |
| 622 switch (kind_) { | |
| 623 case NONE: return false; | |
| 624 case EQ: return (other_relation.kind_ == EQ) | |
| 625 || (other_relation.kind_ == GE) | |
| 626 || (other_relation.kind_ == LE); | |
| 627 case GT: return (other_relation.kind_ == GT) | |
| 628 || (other_relation.kind_ == GE) | |
| 629 || (other_relation.kind_ == NE); | |
| 630 case LT: return (other_relation.kind_ == LT) | |
| 631 || (other_relation.kind_ == LE) | |
| 632 || (other_relation.kind_ == NE); | |
| 633 case GE: return (other_relation.kind_ == GE); | |
| 634 case LE: return (other_relation.kind_ == LE); | |
| 635 case NE: return (other_relation.kind_ == NE); | |
| 636 } | |
| 637 UNREACHABLE(); | |
| 638 return false; | |
| 639 } | |
| 640 | |
| 641 // The semantics of "IsExtendable" is that if | |
| 642 // "rel.IsExtendable(direction)" is true then | |
| 643 // "x rel y" implies "(x + direction) rel y" . | |
| 644 bool IsExtendable(int direction) { | |
| 645 switch (kind_) { | |
| 646 case NONE: return false; | |
| 647 case EQ: return false; | |
| 648 case GT: return (direction >= 0); | |
| 649 case GE: return (direction >= 0); | |
| 650 case LT: return (direction <= 0); | |
| 651 case LE: return (direction <= 0); | |
| 652 case NE: return false; | |
| 653 } | |
| 654 UNREACHABLE(); | |
| 655 return false; | |
| 656 } | |
| 657 | |
| 658 // CompoundImplies returns true when | |
| 659 // "((x + my_offset) >> my_scale) rel y" implies | |
| 660 // "((x + other_offset) >> other_scale) other_relation y". | |
| 661 bool CompoundImplies(NumericRelation other_relation, | |
| 662 int my_offset, | |
| 663 int my_scale, | |
| 664 int other_offset = 0, | |
| 665 int other_scale = 0) { | |
| 666 return Implies(other_relation) && ComponentsImply( | |
| 667 my_offset, my_scale, other_offset, other_scale); | |
| 668 } | |
| 669 | |
| 670 private: | |
| 671 // ComponentsImply returns true when | |
| 672 // "((x + my_offset) >> my_scale) rel y" implies | |
| 673 // "((x + other_offset) >> other_scale) rel y". | |
| 674 bool ComponentsImply(int my_offset, | |
| 675 int my_scale, | |
| 676 int other_offset, | |
| 677 int other_scale) { | |
| 678 switch (kind_) { | |
| 679 case NONE: break; // Fall through to UNREACHABLE(). | |
| 680 case EQ: | |
| 681 case NE: return my_offset == other_offset && my_scale == other_scale; | |
| 682 case GT: | |
| 683 case GE: return my_offset <= other_offset && my_scale >= other_scale; | |
| 684 case LT: | |
| 685 case LE: return my_offset >= other_offset && my_scale <= other_scale; | |
| 686 } | |
| 687 UNREACHABLE(); | |
| 688 return false; | |
| 689 } | |
| 690 | |
| 691 explicit NumericRelation(Kind kind) : kind_(kind) {} | |
| 692 | |
| 693 Kind kind_; | |
| 694 }; | |
| 695 | |
| 696 | |
| 697 class DecompositionResult BASE_EMBEDDED { | 543 class DecompositionResult BASE_EMBEDDED { |
| 698 public: | 544 public: |
| 699 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {} | 545 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {} |
| 700 | 546 |
| 701 HValue* base() { return base_; } | 547 HValue* base() { return base_; } |
| 702 int offset() { return offset_; } | 548 int offset() { return offset_; } |
| 703 int scale() { return scale_; } | 549 int scale() { return scale_; } |
| 704 | 550 |
| 705 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) { | 551 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) { |
| 706 if (base_ == NULL) { | 552 if (base_ == NULL) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 732 *a = *b; | 578 *a = *b; |
| 733 *b = c; | 579 *b = c; |
| 734 } | 580 } |
| 735 | 581 |
| 736 HValue* base_; | 582 HValue* base_; |
| 737 int offset_; | 583 int offset_; |
| 738 int scale_; | 584 int scale_; |
| 739 }; | 585 }; |
| 740 | 586 |
| 741 | 587 |
| 742 class RangeEvaluationContext BASE_EMBEDDED { | |
| 743 public: | |
| 744 RangeEvaluationContext(HValue* value, HValue* upper); | |
| 745 | |
| 746 HValue* lower_bound() { return lower_bound_; } | |
| 747 HValue* lower_bound_guarantee() { return lower_bound_guarantee_; } | |
| 748 HValue* candidate() { return candidate_; } | |
| 749 HValue* upper_bound() { return upper_bound_; } | |
| 750 HValue* upper_bound_guarantee() { return upper_bound_guarantee_; } | |
| 751 int offset() { return offset_; } | |
| 752 int scale() { return scale_; } | |
| 753 | |
| 754 bool is_range_satisfied() { | |
| 755 return lower_bound_guarantee() != NULL && upper_bound_guarantee() != NULL; | |
| 756 } | |
| 757 | |
| 758 void set_lower_bound_guarantee(HValue* guarantee) { | |
| 759 lower_bound_guarantee_ = ConvertGuarantee(guarantee); | |
| 760 } | |
| 761 void set_upper_bound_guarantee(HValue* guarantee) { | |
| 762 upper_bound_guarantee_ = ConvertGuarantee(guarantee); | |
| 763 } | |
| 764 | |
| 765 void swap_candidate(DecompositionResult* other_candicate) { | |
| 766 other_candicate->SwapValues(&candidate_, &offset_, &scale_); | |
| 767 } | |
| 768 | |
| 769 private: | |
| 770 HValue* ConvertGuarantee(HValue* guarantee); | |
| 771 | |
| 772 HValue* lower_bound_; | |
| 773 HValue* lower_bound_guarantee_; | |
| 774 HValue* candidate_; | |
| 775 HValue* upper_bound_; | |
| 776 HValue* upper_bound_guarantee_; | |
| 777 int offset_; | |
| 778 int scale_; | |
| 779 }; | |
| 780 | |
| 781 | |
| 782 typedef EnumSet<GVNFlag> GVNFlagSet; | 588 typedef EnumSet<GVNFlag> GVNFlagSet; |
| 783 | 589 |
| 784 | 590 |
| 785 class HValue: public ZoneObject { | 591 class HValue: public ZoneObject { |
| 786 public: | 592 public: |
| 787 static const int kNoNumber = -1; | 593 static const int kNoNumber = -1; |
| 788 | 594 |
| 789 enum Flag { | 595 enum Flag { |
| 790 kFlexibleRepresentation, | 596 kFlexibleRepresentation, |
| 791 kCannotBeTagged, | 597 kCannotBeTagged, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 809 kAllUsesTruncatingToSmi, | 615 kAllUsesTruncatingToSmi, |
| 810 // Set after an instruction is killed. | 616 // Set after an instruction is killed. |
| 811 kIsDead, | 617 kIsDead, |
| 812 // Instructions that are allowed to produce full range unsigned integer | 618 // Instructions that are allowed to produce full range unsigned integer |
| 813 // values are marked with kUint32 flag. If arithmetic shift or a load from | 619 // values are marked with kUint32 flag. If arithmetic shift or a load from |
| 814 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag | 620 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag |
| 815 // it will deoptimize if result does not fit into signed integer range. | 621 // it will deoptimize if result does not fit into signed integer range. |
| 816 // HGraph::ComputeSafeUint32Operations is responsible for setting this | 622 // HGraph::ComputeSafeUint32Operations is responsible for setting this |
| 817 // flag. | 623 // flag. |
| 818 kUint32, | 624 kUint32, |
| 819 // If a phi is involved in the evaluation of a numeric constraint the | |
| 820 // recursion can cause an endless cycle: we use this flag to exit the loop. | |
| 821 kNumericConstraintEvaluationInProgress, | |
| 822 // This flag is set to true after the SetupInformativeDefinitions() pass | |
| 823 // has processed this instruction. | |
| 824 kIDefsProcessingDone, | |
| 825 kHasNoObservableSideEffects, | 625 kHasNoObservableSideEffects, |
| 826 // Indicates the instruction is live during dead code elimination. | 626 // Indicates the instruction is live during dead code elimination. |
| 827 kIsLive, | 627 kIsLive, |
| 828 | 628 |
| 829 // HEnvironmentMarkers are deleted before dead code | 629 // HEnvironmentMarkers are deleted before dead code |
| 830 // elimination takes place, so they can repurpose the kIsLive flag: | 630 // elimination takes place, so they can repurpose the kIsLive flag: |
| 831 kEndsLiveRange = kIsLive, | 631 kEndsLiveRange = kIsLive, |
| 832 | 632 |
| 833 // TODO(everyone): Don't forget to update this! | 633 // TODO(everyone): Don't forget to update this! |
| 834 kLastFlag = kIsLive | 634 kLastFlag = kIsLive |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 // One of the iDef operands is special because it is the value that is | 752 // One of the iDef operands is special because it is the value that is |
| 953 // "transferred" to the output, we call it the "redefined operand". | 753 // "transferred" to the output, we call it the "redefined operand". |
| 954 // If an HValue is an iDef it must override RedefinedOperandIndex() so that | 754 // If an HValue is an iDef it must override RedefinedOperandIndex() so that |
| 955 // it does not return kNoRedefinedOperand; | 755 // it does not return kNoRedefinedOperand; |
| 956 static const int kNoRedefinedOperand = -1; | 756 static const int kNoRedefinedOperand = -1; |
| 957 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } | 757 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } |
| 958 bool IsInformativeDefinition() { | 758 bool IsInformativeDefinition() { |
| 959 return RedefinedOperandIndex() != kNoRedefinedOperand; | 759 return RedefinedOperandIndex() != kNoRedefinedOperand; |
| 960 } | 760 } |
| 961 HValue* RedefinedOperand() { | 761 HValue* RedefinedOperand() { |
| 962 return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex()) | 762 int index = RedefinedOperandIndex(); |
| 963 : NULL; | 763 return index == kNoRedefinedOperand ? NULL : OperandAt(index); |
| 964 } | 764 } |
| 965 | 765 |
| 966 // A purely informative definition is an idef that will not emit code and | 766 // A purely informative definition is an idef that will not emit code and |
| 967 // should therefore be removed from the graph in the RestoreActualValues | 767 // should therefore be removed from the graph in the RestoreActualValues |
| 968 // phase (so that live ranges will be shorter). | 768 // phase (so that live ranges will be shorter). |
| 969 virtual bool IsPurelyInformativeDefinition() { return false; } | 769 virtual bool IsPurelyInformativeDefinition() { return false; } |
| 970 | 770 |
| 971 // This method must always return the original HValue SSA definition | 771 // This method must always return the original HValue SSA definition |
| 972 // (regardless of any iDef of this value). | 772 // (regardless of any iDef of this value). |
| 973 HValue* ActualValue() { | 773 HValue* ActualValue() { |
| 974 return IsInformativeDefinition() ? RedefinedOperand()->ActualValue() | 774 int index = RedefinedOperandIndex(); |
| 975 : this; | 775 return index == kNoRedefinedOperand ? this : OperandAt(index); |
| 976 } | |
| 977 | |
| 978 virtual void AddInformativeDefinitions() {} | |
| 979 | |
| 980 void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() { | |
| 981 UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>(); | |
| 982 } | |
| 983 void UpdateRedefinedUses() { | |
| 984 UpdateRedefinedUsesInner<Dominates>(); | |
| 985 } | 776 } |
| 986 | 777 |
| 987 bool IsInteger32Constant(); | 778 bool IsInteger32Constant(); |
| 988 int32_t GetInteger32Constant(); | 779 int32_t GetInteger32Constant(); |
| 989 bool EqualsInteger32Constant(int32_t value); | 780 bool EqualsInteger32Constant(int32_t value); |
| 990 | 781 |
| 991 bool IsDefinedAfter(HBasicBlock* other) const; | 782 bool IsDefinedAfter(HBasicBlock* other) const; |
| 992 | 783 |
| 993 // Operands. | 784 // Operands. |
| 994 virtual int OperandCount() = 0; | 785 virtual int OperandCount() = 0; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1125 | 916 |
| 1126 // Check if this instruction has some reason that prevents elimination. | 917 // Check if this instruction has some reason that prevents elimination. |
| 1127 bool CannotBeEliminated() const { | 918 bool CannotBeEliminated() const { |
| 1128 return HasObservableSideEffects() || !IsDeletable(); | 919 return HasObservableSideEffects() || !IsDeletable(); |
| 1129 } | 920 } |
| 1130 | 921 |
| 1131 #ifdef DEBUG | 922 #ifdef DEBUG |
| 1132 virtual void Verify() = 0; | 923 virtual void Verify() = 0; |
| 1133 #endif | 924 #endif |
| 1134 | 925 |
| 1135 bool IsRelationTrue(NumericRelation relation, | |
| 1136 HValue* other, | |
| 1137 int offset = 0, | |
| 1138 int scale = 0); | |
| 1139 | |
| 1140 bool TryGuaranteeRange(HValue* upper_bound); | |
| 1141 virtual bool TryDecompose(DecompositionResult* decomposition) { | 926 virtual bool TryDecompose(DecompositionResult* decomposition) { |
| 1142 if (RedefinedOperand() != NULL) { | 927 if (RedefinedOperand() != NULL) { |
| 1143 return RedefinedOperand()->TryDecompose(decomposition); | 928 return RedefinedOperand()->TryDecompose(decomposition); |
| 1144 } else { | 929 } else { |
| 1145 return false; | 930 return false; |
| 1146 } | 931 } |
| 1147 } | 932 } |
| 1148 | 933 |
| 1149 // Returns true conservatively if the program might be able to observe a | 934 // Returns true conservatively if the program might be able to observe a |
| 1150 // ToString() operation on this value. | 935 // ToString() operation on this value. |
| 1151 bool ToStringCanBeObserved() const { | 936 bool ToStringCanBeObserved() const { |
| 1152 return type().ToStringOrToNumberCanBeObserved(representation()); | 937 return type().ToStringOrToNumberCanBeObserved(representation()); |
| 1153 } | 938 } |
| 1154 | 939 |
| 1155 // Returns true conservatively if the program might be able to observe a | 940 // Returns true conservatively if the program might be able to observe a |
| 1156 // ToNumber() operation on this value. | 941 // ToNumber() operation on this value. |
| 1157 bool ToNumberCanBeObserved() const { | 942 bool ToNumberCanBeObserved() const { |
| 1158 return type().ToStringOrToNumberCanBeObserved(representation()); | 943 return type().ToStringOrToNumberCanBeObserved(representation()); |
| 1159 } | 944 } |
| 1160 | 945 |
| 1161 protected: | 946 protected: |
| 1162 void TryGuaranteeRangeRecursive(RangeEvaluationContext* context); | |
| 1163 | |
| 1164 enum RangeGuaranteeDirection { | |
| 1165 DIRECTION_NONE = 0, | |
| 1166 DIRECTION_UPPER = 1, | |
| 1167 DIRECTION_LOWER = 2, | |
| 1168 DIRECTION_BOTH = DIRECTION_UPPER | DIRECTION_LOWER | |
| 1169 }; | |
| 1170 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {} | |
| 1171 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) {} | |
| 1172 | |
| 1173 // This function must be overridden for instructions with flag kUseGVN, to | 947 // This function must be overridden for instructions with flag kUseGVN, to |
| 1174 // compare the non-Operand parts of the instruction. | 948 // compare the non-Operand parts of the instruction. |
| 1175 virtual bool DataEquals(HValue* other) { | 949 virtual bool DataEquals(HValue* other) { |
| 1176 UNREACHABLE(); | 950 UNREACHABLE(); |
| 1177 return false; | 951 return false; |
| 1178 } | 952 } |
| 1179 | 953 |
| 1180 virtual Representation RepresentationFromInputs() { | 954 virtual Representation RepresentationFromInputs() { |
| 1181 return representation(); | 955 return representation(); |
| 1182 } | 956 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1196 void clear_block() { | 970 void clear_block() { |
| 1197 ASSERT(block_ != NULL); | 971 ASSERT(block_ != NULL); |
| 1198 block_ = NULL; | 972 block_ = NULL; |
| 1199 } | 973 } |
| 1200 | 974 |
| 1201 void set_representation(Representation r) { | 975 void set_representation(Representation r) { |
| 1202 ASSERT(representation_.IsNone() && !r.IsNone()); | 976 ASSERT(representation_.IsNone() && !r.IsNone()); |
| 1203 representation_ = r; | 977 representation_ = r; |
| 1204 } | 978 } |
| 1205 | 979 |
| 1206 // Signature of a function testing if a HValue properly dominates another. | |
| 1207 typedef bool (*DominanceTest)(HValue*, HValue*); | |
| 1208 | |
| 1209 // Simple implementation of DominanceTest implemented walking the chain | |
| 1210 // of Hinstructions (used in UpdateRedefinedUsesInner). | |
| 1211 static bool Dominates(HValue* dominator, HValue* dominated); | |
| 1212 | |
| 1213 // A fast implementation of DominanceTest that works only for the | |
| 1214 // "current" instruction in the SetupInformativeDefinitions() phase. | |
| 1215 // During that phase we use a flag to mark processed instructions, and by | |
| 1216 // checking the flag we can quickly test if an instruction comes before or | |
| 1217 // after the "current" one. | |
| 1218 static bool TestDominanceUsingProcessedFlag(HValue* dominator, | |
| 1219 HValue* dominated); | |
| 1220 | |
| 1221 // If we are redefining an operand, update all its dominated uses (the | |
| 1222 // function that checks if a use is dominated is the template argument). | |
| 1223 template<DominanceTest TestDominance> | |
| 1224 void UpdateRedefinedUsesInner() { | |
| 1225 HValue* input = RedefinedOperand(); | |
| 1226 if (input != NULL) { | |
| 1227 for (HUseIterator uses = input->uses(); !uses.Done(); uses.Advance()) { | |
| 1228 HValue* use = uses.value(); | |
| 1229 if (TestDominance(this, use)) { | |
| 1230 use->SetOperandAt(uses.index(), this); | |
| 1231 } | |
| 1232 } | |
| 1233 } | |
| 1234 } | |
| 1235 | |
| 1236 // Informative definitions can override this method to state any numeric | |
| 1237 // relation they provide on the redefined value. | |
| 1238 // Returns true if it is guaranteed that: | |
| 1239 // ((this + offset) >> scale) relation other | |
| 1240 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 1241 HValue* other, | |
| 1242 int offset = 0, | |
| 1243 int scale = 0) { | |
| 1244 return false; | |
| 1245 } | |
| 1246 | |
| 1247 static GVNFlagSet AllDependsOnFlagSet() { | 980 static GVNFlagSet AllDependsOnFlagSet() { |
| 1248 GVNFlagSet result; | 981 GVNFlagSet result; |
| 1249 // Create changes mask. | 982 // Create changes mask. |
| 1250 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 983 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
| 1251 GVN_TRACKED_FLAG_LIST(ADD_FLAG) | 984 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
| 1252 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | 985 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
| 1253 #undef ADD_FLAG | 986 #undef ADD_FLAG |
| 1254 return result; | 987 return result; |
| 1255 } | 988 } |
| 1256 | 989 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1507 virtual Representation RequiredInputRepresentation(int index) { | 1240 virtual Representation RequiredInputRepresentation(int index) { |
| 1508 return Representation::None(); | 1241 return Representation::None(); |
| 1509 } | 1242 } |
| 1510 | 1243 |
| 1511 virtual void PrintDataTo(StringStream* stream); | 1244 virtual void PrintDataTo(StringStream* stream); |
| 1512 | 1245 |
| 1513 DECLARE_CONCRETE_INSTRUCTION(DummyUse); | 1246 DECLARE_CONCRETE_INSTRUCTION(DummyUse); |
| 1514 }; | 1247 }; |
| 1515 | 1248 |
| 1516 | 1249 |
| 1517 class HNumericConstraint : public HTemplateInstruction<2> { | |
| 1518 public: | |
| 1519 static HNumericConstraint* AddToGraph(HValue* constrained_value, | |
| 1520 NumericRelation relation, | |
| 1521 HValue* related_value, | |
| 1522 HInstruction* insertion_point = NULL); | |
| 1523 | |
| 1524 HValue* constrained_value() { return OperandAt(0); } | |
| 1525 HValue* related_value() { return OperandAt(1); } | |
| 1526 NumericRelation relation() { return relation_; } | |
| 1527 | |
| 1528 virtual int RedefinedOperandIndex() { return 0; } | |
| 1529 virtual bool IsPurelyInformativeDefinition() { return true; } | |
| 1530 | |
| 1531 virtual Representation RequiredInputRepresentation(int index) { | |
| 1532 return representation(); | |
| 1533 } | |
| 1534 | |
| 1535 virtual void PrintDataTo(StringStream* stream); | |
| 1536 | |
| 1537 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | |
| 1538 HValue* other_related_value, | |
| 1539 int offset = 0, | |
| 1540 int scale = 0) { | |
| 1541 if (related_value() == other_related_value) { | |
| 1542 return relation().CompoundImplies(other_relation, offset, scale); | |
| 1543 } else { | |
| 1544 return false; | |
| 1545 } | |
| 1546 } | |
| 1547 | |
| 1548 DECLARE_CONCRETE_INSTRUCTION(NumericConstraint) | |
| 1549 | |
| 1550 private: | |
| 1551 HNumericConstraint(HValue* constrained_value, | |
| 1552 NumericRelation relation, | |
| 1553 HValue* related_value) | |
| 1554 : relation_(relation) { | |
| 1555 SetOperandAt(0, constrained_value); | |
| 1556 SetOperandAt(1, related_value); | |
| 1557 } | |
| 1558 | |
| 1559 NumericRelation relation_; | |
| 1560 }; | |
| 1561 | |
| 1562 | |
| 1563 class HDeoptimize: public HTemplateInstruction<0> { | 1250 class HDeoptimize: public HTemplateInstruction<0> { |
| 1564 public: | 1251 public: |
| 1565 DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType); | 1252 DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType); |
| 1566 | 1253 |
| 1567 virtual Representation RequiredInputRepresentation(int index) { | 1254 virtual Representation RequiredInputRepresentation(int index) { |
| 1568 return Representation::None(); | 1255 return Representation::None(); |
| 1569 } | 1256 } |
| 1570 | 1257 |
| 1571 Deoptimizer::BailoutType type() { return type_; } | 1258 Deoptimizer::BailoutType type() { return type_; } |
| 1572 | 1259 |
| (...skipping 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3473 } | 3160 } |
| 3474 bool IsLimitedInductionVariable() { | 3161 bool IsLimitedInductionVariable() { |
| 3475 return IsInductionVariable() && | 3162 return IsInductionVariable() && |
| 3476 induction_variable_data_->limit() != NULL; | 3163 induction_variable_data_->limit() != NULL; |
| 3477 } | 3164 } |
| 3478 void DetectInductionVariable() { | 3165 void DetectInductionVariable() { |
| 3479 ASSERT(induction_variable_data_ == NULL); | 3166 ASSERT(induction_variable_data_ == NULL); |
| 3480 induction_variable_data_ = InductionVariableData::ExaminePhi(this); | 3167 induction_variable_data_ = InductionVariableData::ExaminePhi(this); |
| 3481 } | 3168 } |
| 3482 | 3169 |
| 3483 virtual void AddInformativeDefinitions(); | |
| 3484 | |
| 3485 virtual void PrintTo(StringStream* stream); | 3170 virtual void PrintTo(StringStream* stream); |
| 3486 | 3171 |
| 3487 #ifdef DEBUG | 3172 #ifdef DEBUG |
| 3488 virtual void Verify(); | 3173 virtual void Verify(); |
| 3489 #endif | 3174 #endif |
| 3490 | 3175 |
| 3491 void InitRealUses(int id); | 3176 void InitRealUses(int id); |
| 3492 void AddNonPhiUsesFrom(HPhi* other); | 3177 void AddNonPhiUsesFrom(HPhi* other); |
| 3493 void AddIndirectUsesTo(int* use_count); | 3178 void AddIndirectUsesTo(int* use_count); |
| 3494 | 3179 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3525 virtual Opcode opcode() const { return HValue::kPhi; } | 3210 virtual Opcode opcode() const { return HValue::kPhi; } |
| 3526 | 3211 |
| 3527 void SimplifyConstantInputs(); | 3212 void SimplifyConstantInputs(); |
| 3528 | 3213 |
| 3529 protected: | 3214 protected: |
| 3530 virtual void DeleteFromGraph(); | 3215 virtual void DeleteFromGraph(); |
| 3531 virtual void InternalSetOperandAt(int index, HValue* value) { | 3216 virtual void InternalSetOperandAt(int index, HValue* value) { |
| 3532 inputs_[index] = value; | 3217 inputs_[index] = value; |
| 3533 } | 3218 } |
| 3534 | 3219 |
| 3535 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 3536 HValue* other, | |
| 3537 int offset = 0, | |
| 3538 int scale = 0); | |
| 3539 | |
| 3540 private: | 3220 private: |
| 3541 ZoneList<HValue*> inputs_; | 3221 ZoneList<HValue*> inputs_; |
| 3542 int merged_index_; | 3222 int merged_index_; |
| 3543 | 3223 |
| 3544 int non_phi_uses_[Representation::kNumRepresentations]; | 3224 int non_phi_uses_[Representation::kNumRepresentations]; |
| 3545 int indirect_uses_[Representation::kNumRepresentations]; | 3225 int indirect_uses_[Representation::kNumRepresentations]; |
| 3546 int phi_id_; | 3226 int phi_id_; |
| 3547 InductionVariableData* induction_variable_data_; | 3227 InductionVariableData* induction_variable_data_; |
| 3548 | 3228 |
| 3549 // TODO(titzer): we can't eliminate the receiver for generating backtraces | 3229 // TODO(titzer): we can't eliminate the receiver for generating backtraces |
| 3550 virtual bool IsDeletable() const { return !IsReceiver(); } | 3230 virtual bool IsDeletable() const { return !IsReceiver(); } |
| 3551 }; | 3231 }; |
| 3552 | 3232 |
| 3553 | 3233 |
| 3554 class HInductionVariableAnnotation : public HUnaryOperation { | |
| 3555 public: | |
| 3556 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, | |
| 3557 NumericRelation relation, | |
| 3558 int operand_index); | |
| 3559 | |
| 3560 NumericRelation relation() { return relation_; } | |
| 3561 HValue* induction_base() { return phi_->OperandAt(operand_index_); } | |
| 3562 | |
| 3563 virtual int RedefinedOperandIndex() { return 0; } | |
| 3564 virtual bool IsPurelyInformativeDefinition() { return true; } | |
| 3565 virtual Representation RequiredInputRepresentation(int index) { | |
| 3566 return representation(); | |
| 3567 } | |
| 3568 | |
| 3569 virtual void PrintDataTo(StringStream* stream); | |
| 3570 | |
| 3571 virtual bool IsRelationTrueInternal(NumericRelation other_relation, | |
| 3572 HValue* other_related_value, | |
| 3573 int offset = 0, | |
| 3574 int scale = 0) { | |
| 3575 if (induction_base() == other_related_value) { | |
| 3576 return relation().CompoundImplies(other_relation, offset, scale); | |
| 3577 } else { | |
| 3578 return false; | |
| 3579 } | |
| 3580 } | |
| 3581 | |
| 3582 DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) | |
| 3583 | |
| 3584 private: | |
| 3585 HInductionVariableAnnotation(HPhi* phi, | |
| 3586 NumericRelation relation, | |
| 3587 int operand_index) | |
| 3588 : HUnaryOperation(phi), | |
| 3589 phi_(phi), relation_(relation), operand_index_(operand_index) { | |
| 3590 } | |
| 3591 | |
| 3592 // We need to store the phi both here and in the instruction operand because | |
| 3593 // the operand can change if a new idef of the phi is added between the phi | |
| 3594 // and this instruction (inserting an idef updates every use). | |
| 3595 HPhi* phi_; | |
| 3596 NumericRelation relation_; | |
| 3597 int operand_index_; | |
| 3598 }; | |
| 3599 | |
| 3600 | |
| 3601 class HArgumentsObject: public HTemplateInstruction<0> { | 3234 class HArgumentsObject: public HTemplateInstruction<0> { |
| 3602 public: | 3235 public: |
| 3603 static HArgumentsObject* New(Zone* zone, | 3236 static HArgumentsObject* New(Zone* zone, |
| 3604 HValue* context, | 3237 HValue* context, |
| 3605 int count) { | 3238 int count) { |
| 3606 return new(zone) HArgumentsObject(count, zone); | 3239 return new(zone) HArgumentsObject(count, zone); |
| 3607 } | 3240 } |
| 3608 | 3241 |
| 3609 const ZoneList<HValue*>* arguments_values() const { return &values_; } | 3242 const ZoneList<HValue*>* arguments_values() const { return &values_; } |
| 3610 int arguments_count() const { return values_.length(); } | 3243 int arguments_count() const { return values_.length(); } |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4108 class HBoundsCheck: public HTemplateInstruction<2> { | 3741 class HBoundsCheck: public HTemplateInstruction<2> { |
| 4109 public: | 3742 public: |
| 4110 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); | 3743 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); |
| 4111 | 3744 |
| 4112 bool skip_check() const { return skip_check_; } | 3745 bool skip_check() const { return skip_check_; } |
| 4113 void set_skip_check() { skip_check_ = true; } | 3746 void set_skip_check() { skip_check_ = true; } |
| 4114 | 3747 |
| 4115 HValue* base() { return base_; } | 3748 HValue* base() { return base_; } |
| 4116 int offset() { return offset_; } | 3749 int offset() { return offset_; } |
| 4117 int scale() { return scale_; } | 3750 int scale() { return scale_; } |
| 4118 bool index_can_increase() { | |
| 4119 return (responsibility_direction_ & DIRECTION_LOWER) == 0; | |
| 4120 } | |
| 4121 bool index_can_decrease() { | |
| 4122 return (responsibility_direction_ & DIRECTION_UPPER) == 0; | |
| 4123 } | |
| 4124 | 3751 |
| 4125 void ApplyIndexChange(); | 3752 void ApplyIndexChange(); |
| 4126 bool DetectCompoundIndex() { | 3753 bool DetectCompoundIndex() { |
| 4127 ASSERT(base() == NULL); | 3754 ASSERT(base() == NULL); |
| 4128 | 3755 |
| 4129 DecompositionResult decomposition; | 3756 DecompositionResult decomposition; |
| 4130 if (index()->TryDecompose(&decomposition)) { | 3757 if (index()->TryDecompose(&decomposition)) { |
| 4131 base_ = decomposition.base(); | 3758 base_ = decomposition.base(); |
| 4132 offset_ = decomposition.offset(); | 3759 offset_ = decomposition.offset(); |
| 4133 scale_ = decomposition.scale(); | 3760 scale_ = decomposition.scale(); |
| 4134 return true; | 3761 return true; |
| 4135 } else { | 3762 } else { |
| 4136 base_ = index(); | 3763 base_ = index(); |
| 4137 offset_ = 0; | 3764 offset_ = 0; |
| 4138 scale_ = 0; | 3765 scale_ = 0; |
| 4139 return false; | 3766 return false; |
| 4140 } | 3767 } |
| 4141 } | 3768 } |
| 4142 | 3769 |
| 4143 virtual Representation RequiredInputRepresentation(int arg_index) { | 3770 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 4144 return representation(); | 3771 return representation(); |
| 4145 } | 3772 } |
| 4146 | 3773 |
| 4147 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 4148 HValue* related_value, | |
| 4149 int offset = 0, | |
| 4150 int scale = 0); | |
| 4151 | |
| 4152 virtual void PrintDataTo(StringStream* stream); | 3774 virtual void PrintDataTo(StringStream* stream); |
| 4153 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 3775 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
| 4154 | 3776 |
| 4155 HValue* index() { return OperandAt(0); } | 3777 HValue* index() { return OperandAt(0); } |
| 4156 HValue* length() { return OperandAt(1); } | 3778 HValue* length() { return OperandAt(1); } |
| 4157 bool allow_equality() { return allow_equality_; } | 3779 bool allow_equality() { return allow_equality_; } |
| 4158 void set_allow_equality(bool v) { allow_equality_ = v; } | 3780 void set_allow_equality(bool v) { allow_equality_ = v; } |
| 4159 | 3781 |
| 4160 virtual int RedefinedOperandIndex() { return 0; } | 3782 virtual int RedefinedOperandIndex() { return 0; } |
| 4161 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } | 3783 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
| 4162 virtual void AddInformativeDefinitions(); | |
| 4163 | 3784 |
| 4164 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3785 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
| 4165 | 3786 |
| 4166 protected: | 3787 protected: |
| 4167 friend class HBoundsCheckBaseIndexInformation; | 3788 friend class HBoundsCheckBaseIndexInformation; |
| 4168 | 3789 |
| 4169 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
| 4170 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( | |
| 4171 responsibility_direction_ | direction); | |
| 4172 } | |
| 4173 | |
| 4174 virtual bool DataEquals(HValue* other) { return true; } | 3790 virtual bool DataEquals(HValue* other) { return true; } |
| 4175 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); | |
| 4176 bool skip_check_; | 3791 bool skip_check_; |
| 4177 HValue* base_; | 3792 HValue* base_; |
| 4178 int offset_; | 3793 int offset_; |
| 4179 int scale_; | 3794 int scale_; |
| 4180 RangeGuaranteeDirection responsibility_direction_; | |
| 4181 bool allow_equality_; | 3795 bool allow_equality_; |
| 4182 | 3796 |
| 4183 private: | 3797 private: |
| 4184 // Normally HBoundsCheck should be created using the | 3798 // Normally HBoundsCheck should be created using the |
| 4185 // HGraphBuilder::AddBoundsCheck() helper. | 3799 // HGraphBuilder::AddBoundsCheck() helper. |
| 4186 // However when building stubs, where we know that the arguments are Int32, | 3800 // However when building stubs, where we know that the arguments are Int32, |
| 4187 // it makes sense to invoke this constructor directly. | 3801 // it makes sense to invoke this constructor directly. |
| 4188 HBoundsCheck(HValue* index, HValue* length) | 3802 HBoundsCheck(HValue* index, HValue* length) |
| 4189 : skip_check_(false), | 3803 : skip_check_(false), |
| 4190 base_(NULL), offset_(0), scale_(0), | 3804 base_(NULL), offset_(0), scale_(0), |
| 4191 responsibility_direction_(DIRECTION_NONE), | |
| 4192 allow_equality_(false) { | 3805 allow_equality_(false) { |
| 4193 SetOperandAt(0, index); | 3806 SetOperandAt(0, index); |
| 4194 SetOperandAt(1, length); | 3807 SetOperandAt(1, length); |
| 4195 SetFlag(kFlexibleRepresentation); | 3808 SetFlag(kFlexibleRepresentation); |
| 4196 SetFlag(kUseGVN); | 3809 SetFlag(kUseGVN); |
| 4197 } | 3810 } |
| 4198 | 3811 |
| 4199 virtual bool IsDeletable() const { | 3812 virtual bool IsDeletable() const { |
| 4200 return skip_check() && !FLAG_debug_code; | 3813 return skip_check() && !FLAG_debug_code; |
| 4201 } | 3814 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4216 | 3829 |
| 4217 HValue* base_index() { return OperandAt(0); } | 3830 HValue* base_index() { return OperandAt(0); } |
| 4218 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | 3831 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } |
| 4219 | 3832 |
| 4220 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | 3833 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) |
| 4221 | 3834 |
| 4222 virtual Representation RequiredInputRepresentation(int arg_index) { | 3835 virtual Representation RequiredInputRepresentation(int arg_index) { |
| 4223 return representation(); | 3836 return representation(); |
| 4224 } | 3837 } |
| 4225 | 3838 |
| 4226 virtual bool IsRelationTrueInternal(NumericRelation relation, | |
| 4227 HValue* related_value, | |
| 4228 int offset = 0, | |
| 4229 int scale = 0); | |
| 4230 virtual void PrintDataTo(StringStream* stream); | 3839 virtual void PrintDataTo(StringStream* stream); |
| 4231 | 3840 |
| 4232 virtual int RedefinedOperandIndex() { return 0; } | 3841 virtual int RedefinedOperandIndex() { return 0; } |
| 4233 virtual bool IsPurelyInformativeDefinition() { return true; } | 3842 virtual bool IsPurelyInformativeDefinition() { return true; } |
| 4234 | |
| 4235 protected: | |
| 4236 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { | |
| 4237 bounds_check()->SetResponsibilityForRange(direction); | |
| 4238 } | |
| 4239 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
| 4240 bounds_check()->TryGuaranteeRangeChanging(context); | |
| 4241 } | |
| 4242 }; | 3843 }; |
| 4243 | 3844 |
| 4244 | 3845 |
| 4245 class HBitwiseBinaryOperation: public HBinaryOperation { | 3846 class HBitwiseBinaryOperation: public HBinaryOperation { |
| 4246 public: | 3847 public: |
| 4247 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, | 3848 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, |
| 4248 HType type = HType::Tagged()) | 3849 HType type = HType::Tagged()) |
| 4249 : HBinaryOperation(context, left, right, type) { | 3850 : HBinaryOperation(context, left, right, type) { |
| 4250 SetFlag(kFlexibleRepresentation); | 3851 SetFlag(kFlexibleRepresentation); |
| 4251 SetFlag(kTruncatingToInt32); | 3852 SetFlag(kTruncatingToInt32); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4404 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); | 4005 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); |
| 4405 | 4006 |
| 4406 virtual Representation RequiredInputRepresentation(int index) { | 4007 virtual Representation RequiredInputRepresentation(int index) { |
| 4407 return representation(); | 4008 return representation(); |
| 4408 } | 4009 } |
| 4409 virtual Representation observed_input_representation(int index) { | 4010 virtual Representation observed_input_representation(int index) { |
| 4410 return observed_input_representation_[index]; | 4011 return observed_input_representation_[index]; |
| 4411 } | 4012 } |
| 4412 virtual void PrintDataTo(StringStream* stream); | 4013 virtual void PrintDataTo(StringStream* stream); |
| 4413 | 4014 |
| 4414 virtual void AddInformativeDefinitions(); | |
| 4415 | |
| 4416 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) | 4015 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) |
| 4417 | 4016 |
| 4418 private: | 4017 private: |
| 4419 Representation observed_input_representation_[2]; | 4018 Representation observed_input_representation_[2]; |
| 4420 Token::Value token_; | 4019 Token::Value token_; |
| 4421 }; | 4020 }; |
| 4422 | 4021 |
| 4423 | 4022 |
| 4424 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> { | 4023 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> { |
| 4425 public: | 4024 public: |
| (...skipping 2823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7249 virtual bool IsDeletable() const { return true; } | 6848 virtual bool IsDeletable() const { return true; } |
| 7250 }; | 6849 }; |
| 7251 | 6850 |
| 7252 | 6851 |
| 7253 #undef DECLARE_INSTRUCTION | 6852 #undef DECLARE_INSTRUCTION |
| 7254 #undef DECLARE_CONCRETE_INSTRUCTION | 6853 #undef DECLARE_CONCRETE_INSTRUCTION |
| 7255 | 6854 |
| 7256 } } // namespace v8::internal | 6855 } } // namespace v8::internal |
| 7257 | 6856 |
| 7258 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 6857 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |