Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(736)

Side by Side Diff: src/hydrogen-instructions.h

Issue 22715004: Version 3.20.15 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Add TypedArray API and correctness patches r16033 and r16084 Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-dehoist.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \ 65 #define HYDROGEN_CONCRETE_INSTRUCTION_LIST(V) \
66 V(AbnormalExit) \ 66 V(AbnormalExit) \
67 V(AccessArgumentsAt) \ 67 V(AccessArgumentsAt) \
68 V(Add) \ 68 V(Add) \
69 V(Allocate) \ 69 V(Allocate) \
70 V(ApplyArguments) \ 70 V(ApplyArguments) \
71 V(ArgumentsElements) \ 71 V(ArgumentsElements) \
72 V(ArgumentsLength) \ 72 V(ArgumentsLength) \
73 V(ArgumentsObject) \ 73 V(ArgumentsObject) \
74 V(Bitwise) \ 74 V(Bitwise) \
75 V(BitNot) \
75 V(BlockEntry) \ 76 V(BlockEntry) \
76 V(BoundsCheck) \ 77 V(BoundsCheck) \
77 V(BoundsCheckBaseIndexInformation) \ 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(CallNewArray) \ 87 V(CallNewArray) \
87 V(CallRuntime) \ 88 V(CallRuntime) \
88 V(CallStub) \ 89 V(CallStub) \
89 V(Change) \ 90 V(Change) \
90 V(CheckFunction) \ 91 V(CheckFunction) \
91 V(CheckHeapObject) \ 92 V(CheckHeapObject) \
92 V(CheckInstanceType) \ 93 V(CheckInstanceType) \
93 V(CheckMaps) \ 94 V(CheckMaps) \
94 V(CheckMapValue) \ 95 V(CheckMapValue) \
96 V(CheckPrototypeMaps) \
95 V(CheckSmi) \ 97 V(CheckSmi) \
96 V(ClampToUint8) \ 98 V(ClampToUint8) \
97 V(ClassOfTestAndBranch) \ 99 V(ClassOfTestAndBranch) \
98 V(CompareNumericAndBranch) \ 100 V(CompareNumericAndBranch) \
99 V(CompareGeneric) \ 101 V(CompareGeneric) \
100 V(CompareObjectEqAndBranch) \ 102 V(CompareObjectEqAndBranch) \
101 V(CompareMap) \ 103 V(CompareMap) \
102 V(Constant) \ 104 V(Constant) \
103 V(Context) \ 105 V(Context) \
104 V(DateField) \ 106 V(DateField) \
105 V(DebugBreak) \ 107 V(DebugBreak) \
106 V(DeclareGlobals) \ 108 V(DeclareGlobals) \
107 V(Deoptimize) \ 109 V(Deoptimize) \
108 V(Div) \ 110 V(Div) \
109 V(DummyUse) \ 111 V(DummyUse) \
110 V(ElementsKind) \ 112 V(ElementsKind) \
111 V(EnterInlined) \ 113 V(EnterInlined) \
112 V(EnvironmentMarker) \ 114 V(EnvironmentMarker) \
113 V(ForceRepresentation) \ 115 V(ForceRepresentation) \
114 V(ForInCacheArray) \ 116 V(ForInCacheArray) \
115 V(ForInPrepareMap) \ 117 V(ForInPrepareMap) \
116 V(FunctionLiteral) \ 118 V(FunctionLiteral) \
117 V(GetCachedArrayIndex) \ 119 V(GetCachedArrayIndex) \
118 V(GlobalObject) \ 120 V(GlobalObject) \
119 V(GlobalReceiver) \ 121 V(GlobalReceiver) \
120 V(Goto) \ 122 V(Goto) \
121 V(HasCachedArrayIndexAndBranch) \ 123 V(HasCachedArrayIndexAndBranch) \
122 V(HasInstanceTypeAndBranch) \ 124 V(HasInstanceTypeAndBranch) \
125 V(InductionVariableAnnotation) \
123 V(InnerAllocatedObject) \ 126 V(InnerAllocatedObject) \
124 V(InstanceOf) \ 127 V(InstanceOf) \
125 V(InstanceOfKnownGlobal) \ 128 V(InstanceOfKnownGlobal) \
126 V(InstanceSize) \ 129 V(InstanceSize) \
127 V(InvokeFunction) \ 130 V(InvokeFunction) \
128 V(IsConstructCallAndBranch) \ 131 V(IsConstructCallAndBranch) \
129 V(IsObjectAndBranch) \ 132 V(IsObjectAndBranch) \
130 V(IsNumberAndBranch) \ 133 V(IsNumberAndBranch) \
131 V(IsStringAndBranch) \ 134 V(IsStringAndBranch) \
132 V(IsSmiAndBranch) \ 135 V(IsSmiAndBranch) \
133 V(IsUndetectableAndBranch) \ 136 V(IsUndetectableAndBranch) \
134 V(LeaveInlined) \ 137 V(LeaveInlined) \
135 V(LoadContextSlot) \ 138 V(LoadContextSlot) \
136 V(LoadExternalArrayPointer) \ 139 V(LoadExternalArrayPointer) \
137 V(LoadFieldByIndex) \ 140 V(LoadFieldByIndex) \
138 V(LoadFunctionPrototype) \ 141 V(LoadFunctionPrototype) \
139 V(LoadGlobalCell) \ 142 V(LoadGlobalCell) \
140 V(LoadGlobalGeneric) \ 143 V(LoadGlobalGeneric) \
141 V(LoadKeyed) \ 144 V(LoadKeyed) \
142 V(LoadKeyedGeneric) \ 145 V(LoadKeyedGeneric) \
143 V(LoadNamedField) \ 146 V(LoadNamedField) \
144 V(LoadNamedFieldPolymorphic) \ 147 V(LoadNamedFieldPolymorphic) \
145 V(LoadNamedGeneric) \ 148 V(LoadNamedGeneric) \
146 V(MapEnumLength) \ 149 V(MapEnumLength) \
147 V(MathFloorOfDiv) \ 150 V(MathFloorOfDiv) \
148 V(MathMinMax) \ 151 V(MathMinMax) \
149 V(Mod) \ 152 V(Mod) \
150 V(Mul) \ 153 V(Mul) \
154 V(NumericConstraint) \
151 V(OsrEntry) \ 155 V(OsrEntry) \
152 V(OuterContext) \ 156 V(OuterContext) \
153 V(Parameter) \ 157 V(Parameter) \
154 V(Power) \ 158 V(Power) \
155 V(PushArgument) \ 159 V(PushArgument) \
156 V(Random) \ 160 V(Random) \
157 V(RegExpLiteral) \ 161 V(RegExpLiteral) \
158 V(Return) \ 162 V(Return) \
159 V(Ror) \ 163 V(Ror) \
160 V(Sar) \ 164 V(Sar) \
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) 535 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
532 #undef DECLARE_FLAG 536 #undef DECLARE_FLAG
533 kAfterLastFlag, 537 kAfterLastFlag,
534 kLastFlag = kAfterLastFlag - 1, 538 kLastFlag = kAfterLastFlag - 1,
535 #define COUNT_FLAG(type) + 1 539 #define COUNT_FLAG(type) + 1
536 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG) 540 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG)
537 #undef COUNT_FLAG 541 #undef COUNT_FLAG
538 }; 542 };
539 543
540 544
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
541 class DecompositionResult BASE_EMBEDDED { 697 class DecompositionResult BASE_EMBEDDED {
542 public: 698 public:
543 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {} 699 DecompositionResult() : base_(NULL), offset_(0), scale_(0) {}
544 700
545 HValue* base() { return base_; } 701 HValue* base() { return base_; }
546 int offset() { return offset_; } 702 int offset() { return offset_; }
547 int scale() { return scale_; } 703 int scale() { return scale_; }
548 704
549 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) { 705 bool Apply(HValue* other_base, int other_offset, int other_scale = 0) {
550 if (base_ == NULL) { 706 if (base_ == NULL) {
(...skipping 25 matching lines...) Expand all
576 *a = *b; 732 *a = *b;
577 *b = c; 733 *b = c;
578 } 734 }
579 735
580 HValue* base_; 736 HValue* base_;
581 int offset_; 737 int offset_;
582 int scale_; 738 int scale_;
583 }; 739 };
584 740
585 741
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
586 typedef EnumSet<GVNFlag> GVNFlagSet; 782 typedef EnumSet<GVNFlag> GVNFlagSet;
587 783
588 784
589 class HValue: public ZoneObject { 785 class HValue: public ZoneObject {
590 public: 786 public:
591 static const int kNoNumber = -1; 787 static const int kNoNumber = -1;
592 788
593 enum Flag { 789 enum Flag {
594 kFlexibleRepresentation, 790 kFlexibleRepresentation,
595 kCannotBeTagged, 791 kCannotBeTagged,
(...skipping 17 matching lines...) Expand all
613 kAllUsesTruncatingToSmi, 809 kAllUsesTruncatingToSmi,
614 // Set after an instruction is killed. 810 // Set after an instruction is killed.
615 kIsDead, 811 kIsDead,
616 // Instructions that are allowed to produce full range unsigned integer 812 // Instructions that are allowed to produce full range unsigned integer
617 // values are marked with kUint32 flag. If arithmetic shift or a load from 813 // values are marked with kUint32 flag. If arithmetic shift or a load from
618 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag 814 // EXTERNAL_UNSIGNED_INT_ELEMENTS array is not marked with this flag
619 // it will deoptimize if result does not fit into signed integer range. 815 // it will deoptimize if result does not fit into signed integer range.
620 // HGraph::ComputeSafeUint32Operations is responsible for setting this 816 // HGraph::ComputeSafeUint32Operations is responsible for setting this
621 // flag. 817 // flag.
622 kUint32, 818 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,
623 kHasNoObservableSideEffects, 825 kHasNoObservableSideEffects,
624 // Indicates the instruction is live during dead code elimination. 826 // Indicates the instruction is live during dead code elimination.
625 kIsLive, 827 kIsLive,
626 828
627 // HEnvironmentMarkers are deleted before dead code 829 // HEnvironmentMarkers are deleted before dead code
628 // elimination takes place, so they can repurpose the kIsLive flag: 830 // elimination takes place, so they can repurpose the kIsLive flag:
629 kEndsLiveRange = kIsLive, 831 kEndsLiveRange = kIsLive,
630 832
631 // TODO(everyone): Don't forget to update this! 833 // TODO(everyone): Don't forget to update this!
632 kLastFlag = kIsLive 834 kLastFlag = kIsLive
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 // One of the iDef operands is special because it is the value that is 952 // One of the iDef operands is special because it is the value that is
751 // "transferred" to the output, we call it the "redefined operand". 953 // "transferred" to the output, we call it the "redefined operand".
752 // If an HValue is an iDef it must override RedefinedOperandIndex() so that 954 // If an HValue is an iDef it must override RedefinedOperandIndex() so that
753 // it does not return kNoRedefinedOperand; 955 // it does not return kNoRedefinedOperand;
754 static const int kNoRedefinedOperand = -1; 956 static const int kNoRedefinedOperand = -1;
755 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; } 957 virtual int RedefinedOperandIndex() { return kNoRedefinedOperand; }
756 bool IsInformativeDefinition() { 958 bool IsInformativeDefinition() {
757 return RedefinedOperandIndex() != kNoRedefinedOperand; 959 return RedefinedOperandIndex() != kNoRedefinedOperand;
758 } 960 }
759 HValue* RedefinedOperand() { 961 HValue* RedefinedOperand() {
760 int index = RedefinedOperandIndex(); 962 return IsInformativeDefinition() ? OperandAt(RedefinedOperandIndex())
761 return index == kNoRedefinedOperand ? NULL : OperandAt(index); 963 : NULL;
762 } 964 }
763 965
764 // A purely informative definition is an idef that will not emit code and 966 // A purely informative definition is an idef that will not emit code and
765 // should therefore be removed from the graph in the RestoreActualValues 967 // should therefore be removed from the graph in the RestoreActualValues
766 // phase (so that live ranges will be shorter). 968 // phase (so that live ranges will be shorter).
767 virtual bool IsPurelyInformativeDefinition() { return false; } 969 virtual bool IsPurelyInformativeDefinition() { return false; }
768 970
769 // This method must always return the original HValue SSA definition 971 // This method must always return the original HValue SSA definition
770 // (regardless of any iDef of this value). 972 // (regardless of any iDef of this value).
771 HValue* ActualValue() { 973 HValue* ActualValue() {
772 int index = RedefinedOperandIndex(); 974 return IsInformativeDefinition() ? RedefinedOperand()->ActualValue()
773 return index == kNoRedefinedOperand ? this : OperandAt(index); 975 : this;
976 }
977
978 virtual void AddInformativeDefinitions() {}
979
980 void UpdateRedefinedUsesWhileSettingUpInformativeDefinitions() {
981 UpdateRedefinedUsesInner<TestDominanceUsingProcessedFlag>();
982 }
983 void UpdateRedefinedUses() {
984 UpdateRedefinedUsesInner<Dominates>();
774 } 985 }
775 986
776 bool IsInteger32Constant(); 987 bool IsInteger32Constant();
777 int32_t GetInteger32Constant(); 988 int32_t GetInteger32Constant();
778 bool EqualsInteger32Constant(int32_t value); 989 bool EqualsInteger32Constant(int32_t value);
779 990
780 bool IsDefinedAfter(HBasicBlock* other) const; 991 bool IsDefinedAfter(HBasicBlock* other) const;
781 992
782 // Operands. 993 // Operands.
783 virtual int OperandCount() = 0; 994 virtual int OperandCount() = 0;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 1125
915 // Check if this instruction has some reason that prevents elimination. 1126 // Check if this instruction has some reason that prevents elimination.
916 bool CannotBeEliminated() const { 1127 bool CannotBeEliminated() const {
917 return HasObservableSideEffects() || !IsDeletable(); 1128 return HasObservableSideEffects() || !IsDeletable();
918 } 1129 }
919 1130
920 #ifdef DEBUG 1131 #ifdef DEBUG
921 virtual void Verify() = 0; 1132 virtual void Verify() = 0;
922 #endif 1133 #endif
923 1134
1135 bool IsRelationTrue(NumericRelation relation,
1136 HValue* other,
1137 int offset = 0,
1138 int scale = 0);
1139
1140 bool TryGuaranteeRange(HValue* upper_bound);
924 virtual bool TryDecompose(DecompositionResult* decomposition) { 1141 virtual bool TryDecompose(DecompositionResult* decomposition) {
925 if (RedefinedOperand() != NULL) { 1142 if (RedefinedOperand() != NULL) {
926 return RedefinedOperand()->TryDecompose(decomposition); 1143 return RedefinedOperand()->TryDecompose(decomposition);
927 } else { 1144 } else {
928 return false; 1145 return false;
929 } 1146 }
930 } 1147 }
931 1148
932 // Returns true conservatively if the program might be able to observe a 1149 // Returns true conservatively if the program might be able to observe a
933 // ToString() operation on this value. 1150 // ToString() operation on this value.
934 bool ToStringCanBeObserved() const { 1151 bool ToStringCanBeObserved() const {
935 return type().ToStringOrToNumberCanBeObserved(representation()); 1152 return type().ToStringOrToNumberCanBeObserved(representation());
936 } 1153 }
937 1154
938 // Returns true conservatively if the program might be able to observe a 1155 // Returns true conservatively if the program might be able to observe a
939 // ToNumber() operation on this value. 1156 // ToNumber() operation on this value.
940 bool ToNumberCanBeObserved() const { 1157 bool ToNumberCanBeObserved() const {
941 return type().ToStringOrToNumberCanBeObserved(representation()); 1158 return type().ToStringOrToNumberCanBeObserved(representation());
942 } 1159 }
943 1160
944 protected: 1161 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
945 // This function must be overridden for instructions with flag kUseGVN, to 1173 // This function must be overridden for instructions with flag kUseGVN, to
946 // compare the non-Operand parts of the instruction. 1174 // compare the non-Operand parts of the instruction.
947 virtual bool DataEquals(HValue* other) { 1175 virtual bool DataEquals(HValue* other) {
948 UNREACHABLE(); 1176 UNREACHABLE();
949 return false; 1177 return false;
950 } 1178 }
951 1179
952 virtual Representation RepresentationFromInputs() { 1180 virtual Representation RepresentationFromInputs() {
953 return representation(); 1181 return representation();
954 } 1182 }
(...skipping 13 matching lines...) Expand all
968 void clear_block() { 1196 void clear_block() {
969 ASSERT(block_ != NULL); 1197 ASSERT(block_ != NULL);
970 block_ = NULL; 1198 block_ = NULL;
971 } 1199 }
972 1200
973 void set_representation(Representation r) { 1201 void set_representation(Representation r) {
974 ASSERT(representation_.IsNone() && !r.IsNone()); 1202 ASSERT(representation_.IsNone() && !r.IsNone());
975 representation_ = r; 1203 representation_ = r;
976 } 1204 }
977 1205
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
978 static GVNFlagSet AllDependsOnFlagSet() { 1247 static GVNFlagSet AllDependsOnFlagSet() {
979 GVNFlagSet result; 1248 GVNFlagSet result;
980 // Create changes mask. 1249 // Create changes mask.
981 #define ADD_FLAG(type) result.Add(kDependsOn##type); 1250 #define ADD_FLAG(type) result.Add(kDependsOn##type);
982 GVN_TRACKED_FLAG_LIST(ADD_FLAG) 1251 GVN_TRACKED_FLAG_LIST(ADD_FLAG)
983 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) 1252 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG)
984 #undef ADD_FLAG 1253 #undef ADD_FLAG
985 return result; 1254 return result;
986 } 1255 }
987 1256
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 virtual Representation RequiredInputRepresentation(int index) { 1507 virtual Representation RequiredInputRepresentation(int index) {
1239 return Representation::None(); 1508 return Representation::None();
1240 } 1509 }
1241 1510
1242 virtual void PrintDataTo(StringStream* stream); 1511 virtual void PrintDataTo(StringStream* stream);
1243 1512
1244 DECLARE_CONCRETE_INSTRUCTION(DummyUse); 1513 DECLARE_CONCRETE_INSTRUCTION(DummyUse);
1245 }; 1514 };
1246 1515
1247 1516
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
1248 class HDeoptimize: public HTemplateInstruction<0> { 1563 class HDeoptimize: public HTemplateInstruction<0> {
1249 public: 1564 public:
1250 DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType); 1565 DECLARE_INSTRUCTION_FACTORY_P1(HDeoptimize, Deoptimizer::BailoutType);
1251 1566
1252 virtual Representation RequiredInputRepresentation(int index) { 1567 virtual Representation RequiredInputRepresentation(int index) {
1253 return Representation::None(); 1568 return Representation::None();
1254 } 1569 }
1255 1570
1256 Deoptimizer::BailoutType type() { return type_; } 1571 Deoptimizer::BailoutType type() { return type_; }
1257 1572
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 DECLARE_CONCRETE_INSTRUCTION(ElementsKind) 2699 DECLARE_CONCRETE_INSTRUCTION(ElementsKind)
2385 2700
2386 protected: 2701 protected:
2387 virtual bool DataEquals(HValue* other) { return true; } 2702 virtual bool DataEquals(HValue* other) { return true; }
2388 2703
2389 private: 2704 private:
2390 virtual bool IsDeletable() const { return true; } 2705 virtual bool IsDeletable() const { return true; }
2391 }; 2706 };
2392 2707
2393 2708
2709 class HBitNot: public HUnaryOperation {
2710 public:
2711 DECLARE_INSTRUCTION_FACTORY_P1(HBitNot, HValue*);
2712
2713 virtual Representation RequiredInputRepresentation(int index) {
2714 return Representation::Integer32();
2715 }
2716 virtual Representation observed_input_representation(int index) {
2717 return Representation::Integer32();
2718 }
2719
2720 virtual HValue* Canonicalize();
2721
2722 DECLARE_CONCRETE_INSTRUCTION(BitNot)
2723
2724 protected:
2725 virtual bool DataEquals(HValue* other) { return true; }
2726
2727 private:
2728 explicit HBitNot(HValue* value)
2729 : HUnaryOperation(value, HType::TaggedNumber()) {
2730 set_representation(Representation::Integer32());
2731 SetFlag(kUseGVN);
2732 SetFlag(kTruncatingToInt32);
2733 SetFlag(kAllowUndefinedAsNaN);
2734 }
2735
2736 virtual bool IsDeletable() const { return true; }
2737 };
2738
2739
2394 class HUnaryMathOperation: public HTemplateInstruction<2> { 2740 class HUnaryMathOperation: public HTemplateInstruction<2> {
2395 public: 2741 public:
2396 static HInstruction* New(Zone* zone, 2742 static HInstruction* New(Zone* zone,
2397 HValue* context, 2743 HValue* context,
2398 HValue* value, 2744 HValue* value,
2399 BuiltinFunctionId op); 2745 BuiltinFunctionId op);
2400 2746
2401 HValue* context() { return OperandAt(0); } 2747 HValue* context() { return OperandAt(0); }
2402 HValue* value() { return OperandAt(1); } 2748 HValue* value() { return OperandAt(1); }
2403 2749
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2525 public: 2871 public:
2526 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value, 2872 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
2527 Handle<Map> map, CompilationInfo* info, 2873 Handle<Map> map, CompilationInfo* info,
2528 HValue *typecheck = NULL); 2874 HValue *typecheck = NULL);
2529 static HCheckMaps* New(Zone* zone, HValue* context, 2875 static HCheckMaps* New(Zone* zone, HValue* context,
2530 HValue* value, SmallMapList* maps, 2876 HValue* value, SmallMapList* maps,
2531 HValue *typecheck = NULL) { 2877 HValue *typecheck = NULL) {
2532 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); 2878 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck);
2533 for (int i = 0; i < maps->length(); i++) { 2879 for (int i = 0; i < maps->length(); i++) {
2534 check_map->map_set_.Add(maps->at(i), zone); 2880 check_map->map_set_.Add(maps->at(i), zone);
2535 check_map->has_migration_target_ |= maps->at(i)->is_migration_target();
2536 } 2881 }
2537 check_map->map_set_.Sort(); 2882 check_map->map_set_.Sort();
2538 return check_map; 2883 return check_map;
2539 } 2884 }
2540 2885
2541 bool CanOmitMapChecks() { return omit_; } 2886 bool CanOmitMapChecks() { return omit_; }
2542 2887
2543 virtual bool HasEscapingOperandAt(int index) { return false; } 2888 virtual bool HasEscapingOperandAt(int index) { return false; }
2544 virtual Representation RequiredInputRepresentation(int index) { 2889 virtual Representation RequiredInputRepresentation(int index) {
2545 return Representation::Tagged(); 2890 return Representation::Tagged();
2546 } 2891 }
2547 virtual void HandleSideEffectDominator(GVNFlag side_effect, 2892 virtual void HandleSideEffectDominator(GVNFlag side_effect,
2548 HValue* dominator); 2893 HValue* dominator);
2549 virtual void PrintDataTo(StringStream* stream); 2894 virtual void PrintDataTo(StringStream* stream);
2550 2895
2551 HValue* value() { return OperandAt(0); } 2896 HValue* value() { return OperandAt(0); }
2552 SmallMapList* map_set() { return &map_set_; } 2897 SmallMapList* map_set() { return &map_set_; }
2553 2898
2554 bool has_migration_target() {
2555 return has_migration_target_;
2556 }
2557
2558 virtual void FinalizeUniqueValueId(); 2899 virtual void FinalizeUniqueValueId();
2559 2900
2560 DECLARE_CONCRETE_INSTRUCTION(CheckMaps) 2901 DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
2561 2902
2562 protected: 2903 protected:
2563 virtual bool DataEquals(HValue* other) { 2904 virtual bool DataEquals(HValue* other) {
2564 ASSERT_EQ(map_set_.length(), map_unique_ids_.length()); 2905 ASSERT_EQ(map_set_.length(), map_unique_ids_.length());
2565 HCheckMaps* b = HCheckMaps::cast(other); 2906 HCheckMaps* b = HCheckMaps::cast(other);
2566 // Relies on the fact that map_set has been sorted before. 2907 // Relies on the fact that map_set has been sorted before.
2567 if (map_unique_ids_.length() != b->map_unique_ids_.length()) { 2908 if (map_unique_ids_.length() != b->map_unique_ids_.length()) {
2568 return false; 2909 return false;
2569 } 2910 }
2570 for (int i = 0; i < map_unique_ids_.length(); i++) { 2911 for (int i = 0; i < map_unique_ids_.length(); i++) {
2571 if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) { 2912 if (map_unique_ids_.at(i) != b->map_unique_ids_.at(i)) {
2572 return false; 2913 return false;
2573 } 2914 }
2574 } 2915 }
2575 return true; 2916 return true;
2576 } 2917 }
2577 2918
2578 private: 2919 private:
2579 // Clients should use one of the static New* methods above. 2920 // Clients should use one of the static New* methods above.
2580 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck) 2921 HCheckMaps(HValue* value, Zone *zone, HValue* typecheck)
2581 : HTemplateInstruction<2>(value->type()), 2922 : HTemplateInstruction<2>(value->type()),
2582 omit_(false), has_migration_target_(false), map_unique_ids_(0, zone) { 2923 omit_(false), map_unique_ids_(0, zone) {
2583 SetOperandAt(0, value); 2924 SetOperandAt(0, value);
2584 // Use the object value for the dependency if NULL is passed. 2925 // Use the object value for the dependency if NULL is passed.
2585 // TODO(titzer): do GVN flags already express this dependency? 2926 // TODO(titzer): do GVN flags already express this dependency?
2586 SetOperandAt(1, typecheck != NULL ? typecheck : value); 2927 SetOperandAt(1, typecheck != NULL ? typecheck : value);
2587 set_representation(Representation::Tagged()); 2928 set_representation(Representation::Tagged());
2588 SetFlag(kUseGVN); 2929 SetFlag(kUseGVN);
2589 SetFlag(kTrackSideEffectDominators); 2930 SetFlag(kTrackSideEffectDominators);
2590 SetGVNFlag(kDependsOnMaps); 2931 SetGVNFlag(kDependsOnMaps);
2591 SetGVNFlag(kDependsOnElementsKind); 2932 SetGVNFlag(kDependsOnElementsKind);
2592 } 2933 }
2593 2934
2594 void omit(CompilationInfo* info) { 2935 void omit(CompilationInfo* info) {
2595 omit_ = true; 2936 omit_ = true;
2596 for (int i = 0; i < map_set_.length(); i++) { 2937 for (int i = 0; i < map_set_.length(); i++) {
2597 Handle<Map> map = map_set_.at(i); 2938 Handle<Map> map = map_set_.at(i);
2598 map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup, 2939 map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
2599 info); 2940 info);
2600 } 2941 }
2601 } 2942 }
2602 2943
2603 bool omit_; 2944 bool omit_;
2604 bool has_migration_target_;
2605 SmallMapList map_set_; 2945 SmallMapList map_set_;
2606 ZoneList<UniqueValueId> map_unique_ids_; 2946 ZoneList<UniqueValueId> map_unique_ids_;
2607 }; 2947 };
2608 2948
2609 2949
2610 class HCheckFunction: public HUnaryOperation { 2950 class HCheckFunction: public HUnaryOperation {
2611 public: 2951 public:
2612 DECLARE_INSTRUCTION_FACTORY_P2(HCheckFunction, HValue*, Handle<JSFunction>); 2952 DECLARE_INSTRUCTION_FACTORY_P2(HCheckFunction, HValue*, Handle<JSFunction>);
2613 2953
2614 virtual Representation RequiredInputRepresentation(int index) { 2954 virtual Representation RequiredInputRepresentation(int index) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2779 3119
2780 private: 3120 private:
2781 explicit HCheckHeapObject(HValue* value) 3121 explicit HCheckHeapObject(HValue* value)
2782 : HUnaryOperation(value, HType::NonPrimitive()) { 3122 : HUnaryOperation(value, HType::NonPrimitive()) {
2783 set_representation(Representation::Tagged()); 3123 set_representation(Representation::Tagged());
2784 SetFlag(kUseGVN); 3124 SetFlag(kUseGVN);
2785 } 3125 }
2786 }; 3126 };
2787 3127
2788 3128
3129 class HCheckPrototypeMaps: public HTemplateInstruction<0> {
3130 public:
3131 static HCheckPrototypeMaps* New(Zone* zone,
3132 HValue* context,
3133 Handle<JSObject> prototype,
3134 Handle<JSObject> holder,
3135 CompilationInfo* info) {
3136 return new(zone) HCheckPrototypeMaps(prototype, holder, zone, info);
3137 }
3138
3139 ZoneList<Handle<JSObject> >* prototypes() { return &prototypes_; }
3140
3141 ZoneList<Handle<Map> >* maps() { return &maps_; }
3142
3143 DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps)
3144
3145 virtual Representation RequiredInputRepresentation(int index) {
3146 return Representation::None();
3147 }
3148
3149 virtual void PrintDataTo(StringStream* stream);
3150
3151 virtual intptr_t Hashcode() {
3152 return first_prototype_unique_id_.Hashcode() * 17 +
3153 last_prototype_unique_id_.Hashcode();
3154 }
3155
3156 virtual void FinalizeUniqueValueId() {
3157 first_prototype_unique_id_ = UniqueValueId(prototypes_.first());
3158 last_prototype_unique_id_ = UniqueValueId(prototypes_.last());
3159 }
3160
3161 bool CanOmitPrototypeChecks() { return can_omit_prototype_maps_; }
3162
3163 protected:
3164 virtual bool DataEquals(HValue* other) {
3165 HCheckPrototypeMaps* b = HCheckPrototypeMaps::cast(other);
3166 return first_prototype_unique_id_ == b->first_prototype_unique_id_ &&
3167 last_prototype_unique_id_ == b->last_prototype_unique_id_;
3168 }
3169
3170 private:
3171 HCheckPrototypeMaps(Handle<JSObject> prototype,
3172 Handle<JSObject> holder,
3173 Zone* zone,
3174 CompilationInfo* info)
3175 : prototypes_(2, zone),
3176 maps_(2, zone),
3177 first_prototype_unique_id_(),
3178 last_prototype_unique_id_(),
3179 can_omit_prototype_maps_(true) {
3180 SetFlag(kUseGVN);
3181 SetGVNFlag(kDependsOnMaps);
3182 // Keep a list of all objects on the prototype chain up to the holder
3183 // and the expected maps.
3184 while (true) {
3185 prototypes_.Add(prototype, zone);
3186 Handle<Map> map(prototype->map());
3187 maps_.Add(map, zone);
3188 can_omit_prototype_maps_ &= map->CanOmitPrototypeChecks();
3189 if (prototype.is_identical_to(holder)) break;
3190 prototype = Handle<JSObject>(JSObject::cast(prototype->GetPrototype()));
3191 }
3192 if (can_omit_prototype_maps_) {
3193 // Mark in-flight compilation as dependent on those maps.
3194 for (int i = 0; i < maps()->length(); i++) {
3195 Handle<Map> map = maps()->at(i);
3196 map->AddDependentCompilationInfo(DependentCode::kPrototypeCheckGroup,
3197 info);
3198 }
3199 }
3200 }
3201
3202 ZoneList<Handle<JSObject> > prototypes_;
3203 ZoneList<Handle<Map> > maps_;
3204 UniqueValueId first_prototype_unique_id_;
3205 UniqueValueId last_prototype_unique_id_;
3206 bool can_omit_prototype_maps_;
3207 };
3208
3209
2789 class InductionVariableData; 3210 class InductionVariableData;
2790 3211
2791 3212
2792 struct InductionVariableLimitUpdate { 3213 struct InductionVariableLimitUpdate {
2793 InductionVariableData* updated_variable; 3214 InductionVariableData* updated_variable;
2794 HValue* limit; 3215 HValue* limit;
2795 bool limit_is_upper; 3216 bool limit_is_upper;
2796 bool limit_is_included; 3217 bool limit_is_included;
2797 3218
2798 InductionVariableLimitUpdate() 3219 InductionVariableLimitUpdate()
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
3052 } 3473 }
3053 bool IsLimitedInductionVariable() { 3474 bool IsLimitedInductionVariable() {
3054 return IsInductionVariable() && 3475 return IsInductionVariable() &&
3055 induction_variable_data_->limit() != NULL; 3476 induction_variable_data_->limit() != NULL;
3056 } 3477 }
3057 void DetectInductionVariable() { 3478 void DetectInductionVariable() {
3058 ASSERT(induction_variable_data_ == NULL); 3479 ASSERT(induction_variable_data_ == NULL);
3059 induction_variable_data_ = InductionVariableData::ExaminePhi(this); 3480 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3060 } 3481 }
3061 3482
3483 virtual void AddInformativeDefinitions();
3484
3062 virtual void PrintTo(StringStream* stream); 3485 virtual void PrintTo(StringStream* stream);
3063 3486
3064 #ifdef DEBUG 3487 #ifdef DEBUG
3065 virtual void Verify(); 3488 virtual void Verify();
3066 #endif 3489 #endif
3067 3490
3068 void InitRealUses(int id); 3491 void InitRealUses(int id);
3069 void AddNonPhiUsesFrom(HPhi* other); 3492 void AddNonPhiUsesFrom(HPhi* other);
3070 void AddIndirectUsesTo(int* use_count); 3493 void AddIndirectUsesTo(int* use_count);
3071 3494
(...skipping 30 matching lines...) Expand all
3102 virtual Opcode opcode() const { return HValue::kPhi; } 3525 virtual Opcode opcode() const { return HValue::kPhi; }
3103 3526
3104 void SimplifyConstantInputs(); 3527 void SimplifyConstantInputs();
3105 3528
3106 protected: 3529 protected:
3107 virtual void DeleteFromGraph(); 3530 virtual void DeleteFromGraph();
3108 virtual void InternalSetOperandAt(int index, HValue* value) { 3531 virtual void InternalSetOperandAt(int index, HValue* value) {
3109 inputs_[index] = value; 3532 inputs_[index] = value;
3110 } 3533 }
3111 3534
3535 virtual bool IsRelationTrueInternal(NumericRelation relation,
3536 HValue* other,
3537 int offset = 0,
3538 int scale = 0);
3539
3112 private: 3540 private:
3113 ZoneList<HValue*> inputs_; 3541 ZoneList<HValue*> inputs_;
3114 int merged_index_; 3542 int merged_index_;
3115 3543
3116 int non_phi_uses_[Representation::kNumRepresentations]; 3544 int non_phi_uses_[Representation::kNumRepresentations];
3117 int indirect_uses_[Representation::kNumRepresentations]; 3545 int indirect_uses_[Representation::kNumRepresentations];
3118 int phi_id_; 3546 int phi_id_;
3119 InductionVariableData* induction_variable_data_; 3547 InductionVariableData* induction_variable_data_;
3120 3548
3121 // TODO(titzer): we can't eliminate the receiver for generating backtraces 3549 // TODO(titzer): we can't eliminate the receiver for generating backtraces
3122 virtual bool IsDeletable() const { return !IsReceiver(); } 3550 virtual bool IsDeletable() const { return !IsReceiver(); }
3123 }; 3551 };
3124 3552
3125 3553
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
3126 class HArgumentsObject: public HTemplateInstruction<0> { 3601 class HArgumentsObject: public HTemplateInstruction<0> {
3127 public: 3602 public:
3128 static HArgumentsObject* New(Zone* zone, 3603 static HArgumentsObject* New(Zone* zone,
3129 HValue* context, 3604 HValue* context,
3130 int count) { 3605 int count) {
3131 return new(zone) HArgumentsObject(count, zone); 3606 return new(zone) HArgumentsObject(count, zone);
3132 } 3607 }
3133 3608
3134 const ZoneList<HValue*>* arguments_values() const { return &values_; } 3609 const ZoneList<HValue*>* arguments_values() const { return &values_; }
3135 int arguments_count() const { return values_.length(); } 3610 int arguments_count() const { return values_.length(); }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3205 bool ImmortalImmovable() const { 3680 bool ImmortalImmovable() const {
3206 if (has_int32_value_) { 3681 if (has_int32_value_) {
3207 return false; 3682 return false;
3208 } 3683 }
3209 if (has_double_value_) { 3684 if (has_double_value_) {
3210 if (IsSpecialDouble()) { 3685 if (IsSpecialDouble()) {
3211 return true; 3686 return true;
3212 } 3687 }
3213 return false; 3688 return false;
3214 } 3689 }
3215 if (has_external_reference_value_) {
3216 return false;
3217 }
3218 3690
3219 ASSERT(!handle_.is_null()); 3691 ASSERT(!handle_.is_null());
3220 Heap* heap = isolate()->heap(); 3692 Heap* heap = isolate()->heap();
3221 ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value())); 3693 ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
3222 ASSERT(unique_id_ != UniqueValueId(heap->nan_value())); 3694 ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
3223 return unique_id_ == UniqueValueId(heap->undefined_value()) || 3695 return unique_id_ == UniqueValueId(heap->undefined_value()) ||
3224 unique_id_ == UniqueValueId(heap->null_value()) || 3696 unique_id_ == UniqueValueId(heap->null_value()) ||
3225 unique_id_ == UniqueValueId(heap->true_value()) || 3697 unique_id_ == UniqueValueId(heap->true_value()) ||
3226 unique_id_ == UniqueValueId(heap->false_value()) || 3698 unique_id_ == UniqueValueId(heap->false_value()) ||
3227 unique_id_ == UniqueValueId(heap->the_hole_value()) || 3699 unique_id_ == UniqueValueId(heap->the_hole_value()) ||
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 class HBoundsCheck: public HTemplateInstruction<2> { 4108 class HBoundsCheck: public HTemplateInstruction<2> {
3637 public: 4109 public:
3638 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); 4110 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*);
3639 4111
3640 bool skip_check() const { return skip_check_; } 4112 bool skip_check() const { return skip_check_; }
3641 void set_skip_check() { skip_check_ = true; } 4113 void set_skip_check() { skip_check_ = true; }
3642 4114
3643 HValue* base() { return base_; } 4115 HValue* base() { return base_; }
3644 int offset() { return offset_; } 4116 int offset() { return offset_; }
3645 int scale() { return scale_; } 4117 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 }
3646 4124
3647 void ApplyIndexChange(); 4125 void ApplyIndexChange();
3648 bool DetectCompoundIndex() { 4126 bool DetectCompoundIndex() {
3649 ASSERT(base() == NULL); 4127 ASSERT(base() == NULL);
3650 4128
3651 DecompositionResult decomposition; 4129 DecompositionResult decomposition;
3652 if (index()->TryDecompose(&decomposition)) { 4130 if (index()->TryDecompose(&decomposition)) {
3653 base_ = decomposition.base(); 4131 base_ = decomposition.base();
3654 offset_ = decomposition.offset(); 4132 offset_ = decomposition.offset();
3655 scale_ = decomposition.scale(); 4133 scale_ = decomposition.scale();
3656 return true; 4134 return true;
3657 } else { 4135 } else {
3658 base_ = index(); 4136 base_ = index();
3659 offset_ = 0; 4137 offset_ = 0;
3660 scale_ = 0; 4138 scale_ = 0;
3661 return false; 4139 return false;
3662 } 4140 }
3663 } 4141 }
3664 4142
3665 virtual Representation RequiredInputRepresentation(int arg_index) { 4143 virtual Representation RequiredInputRepresentation(int arg_index) {
3666 return representation(); 4144 return representation();
3667 } 4145 }
3668 4146
4147 virtual bool IsRelationTrueInternal(NumericRelation relation,
4148 HValue* related_value,
4149 int offset = 0,
4150 int scale = 0);
4151
3669 virtual void PrintDataTo(StringStream* stream); 4152 virtual void PrintDataTo(StringStream* stream);
3670 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); 4153 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
3671 4154
3672 HValue* index() { return OperandAt(0); } 4155 HValue* index() { return OperandAt(0); }
3673 HValue* length() { return OperandAt(1); } 4156 HValue* length() { return OperandAt(1); }
3674 bool allow_equality() { return allow_equality_; } 4157 bool allow_equality() { return allow_equality_; }
3675 void set_allow_equality(bool v) { allow_equality_ = v; } 4158 void set_allow_equality(bool v) { allow_equality_ = v; }
3676 4159
3677 virtual int RedefinedOperandIndex() { return 0; } 4160 virtual int RedefinedOperandIndex() { return 0; }
3678 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } 4161 virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
4162 virtual void AddInformativeDefinitions();
3679 4163
3680 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) 4164 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3681 4165
3682 protected: 4166 protected:
3683 friend class HBoundsCheckBaseIndexInformation; 4167 friend class HBoundsCheckBaseIndexInformation;
3684 4168
4169 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
4170 responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
4171 responsibility_direction_ | direction);
4172 }
4173
3685 virtual bool DataEquals(HValue* other) { return true; } 4174 virtual bool DataEquals(HValue* other) { return true; }
4175 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
3686 bool skip_check_; 4176 bool skip_check_;
3687 HValue* base_; 4177 HValue* base_;
3688 int offset_; 4178 int offset_;
3689 int scale_; 4179 int scale_;
4180 RangeGuaranteeDirection responsibility_direction_;
3690 bool allow_equality_; 4181 bool allow_equality_;
3691 4182
3692 private: 4183 private:
3693 // Normally HBoundsCheck should be created using the 4184 // Normally HBoundsCheck should be created using the
3694 // HGraphBuilder::AddBoundsCheck() helper. 4185 // HGraphBuilder::AddBoundsCheck() helper.
3695 // However when building stubs, where we know that the arguments are Int32, 4186 // However when building stubs, where we know that the arguments are Int32,
3696 // it makes sense to invoke this constructor directly. 4187 // it makes sense to invoke this constructor directly.
3697 HBoundsCheck(HValue* index, HValue* length) 4188 HBoundsCheck(HValue* index, HValue* length)
3698 : skip_check_(false), 4189 : skip_check_(false),
3699 base_(NULL), offset_(0), scale_(0), 4190 base_(NULL), offset_(0), scale_(0),
4191 responsibility_direction_(DIRECTION_NONE),
3700 allow_equality_(false) { 4192 allow_equality_(false) {
3701 SetOperandAt(0, index); 4193 SetOperandAt(0, index);
3702 SetOperandAt(1, length); 4194 SetOperandAt(1, length);
3703 SetFlag(kFlexibleRepresentation); 4195 SetFlag(kFlexibleRepresentation);
3704 SetFlag(kUseGVN); 4196 SetFlag(kUseGVN);
3705 } 4197 }
3706 4198
3707 virtual bool IsDeletable() const { 4199 virtual bool IsDeletable() const {
3708 return skip_check() && !FLAG_debug_code; 4200 return skip_check() && !FLAG_debug_code;
3709 } 4201 }
(...skipping 14 matching lines...) Expand all
3724 4216
3725 HValue* base_index() { return OperandAt(0); } 4217 HValue* base_index() { return OperandAt(0); }
3726 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } 4218 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); }
3727 4219
3728 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) 4220 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation)
3729 4221
3730 virtual Representation RequiredInputRepresentation(int arg_index) { 4222 virtual Representation RequiredInputRepresentation(int arg_index) {
3731 return representation(); 4223 return representation();
3732 } 4224 }
3733 4225
4226 virtual bool IsRelationTrueInternal(NumericRelation relation,
4227 HValue* related_value,
4228 int offset = 0,
4229 int scale = 0);
3734 virtual void PrintDataTo(StringStream* stream); 4230 virtual void PrintDataTo(StringStream* stream);
3735 4231
3736 virtual int RedefinedOperandIndex() { return 0; } 4232 virtual int RedefinedOperandIndex() { return 0; }
3737 virtual bool IsPurelyInformativeDefinition() { return true; } 4233 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 }
3738 }; 4242 };
3739 4243
3740 4244
3741 class HBitwiseBinaryOperation: public HBinaryOperation { 4245 class HBitwiseBinaryOperation: public HBinaryOperation {
3742 public: 4246 public:
3743 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, 4247 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right,
3744 HType type = HType::Tagged()) 4248 HType type = HType::Tagged())
3745 : HBinaryOperation(context, left, right, type) { 4249 : HBinaryOperation(context, left, right, type) {
3746 SetFlag(kFlexibleRepresentation); 4250 SetFlag(kFlexibleRepresentation);
3747 SetFlag(kTruncatingToInt32); 4251 SetFlag(kTruncatingToInt32);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
3900 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); 4404 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
3901 4405
3902 virtual Representation RequiredInputRepresentation(int index) { 4406 virtual Representation RequiredInputRepresentation(int index) {
3903 return representation(); 4407 return representation();
3904 } 4408 }
3905 virtual Representation observed_input_representation(int index) { 4409 virtual Representation observed_input_representation(int index) {
3906 return observed_input_representation_[index]; 4410 return observed_input_representation_[index];
3907 } 4411 }
3908 virtual void PrintDataTo(StringStream* stream); 4412 virtual void PrintDataTo(StringStream* stream);
3909 4413
4414 virtual void AddInformativeDefinitions();
4415
3910 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch) 4416 DECLARE_CONCRETE_INSTRUCTION(CompareNumericAndBranch)
3911 4417
3912 private: 4418 private:
3913 Representation observed_input_representation_[2]; 4419 Representation observed_input_representation_[2];
3914 Token::Value token_; 4420 Token::Value token_;
3915 }; 4421 };
3916 4422
3917 4423
3918 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> { 4424 class HCompareObjectEqAndBranch: public HTemplateControlInstruction<2, 2> {
3919 public: 4425 public:
(...skipping 1939 matching lines...) Expand 10 before | Expand all | Expand 10 after
5859 // tagged[tagged] 6365 // tagged[tagged]
5860 return Representation::Tagged(); 6366 return Representation::Tagged();
5861 } 6367 }
5862 6368
5863 virtual HValue* Canonicalize(); 6369 virtual HValue* Canonicalize();
5864 6370
5865 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric) 6371 DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric)
5866 }; 6372 };
5867 6373
5868 6374
5869 class HStoreNamedField: public HTemplateInstruction<3> { 6375 class HStoreNamedField: public HTemplateInstruction<2> {
5870 public: 6376 public:
5871 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*, 6377 DECLARE_INSTRUCTION_FACTORY_P3(HStoreNamedField, HValue*,
5872 HObjectAccess, HValue*); 6378 HObjectAccess, HValue*);
5873 6379
5874 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) 6380 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
5875 6381
5876 virtual bool HasEscapingOperandAt(int index) { return index == 1; } 6382 virtual bool HasEscapingOperandAt(int index) { return index == 1; }
5877 virtual Representation RequiredInputRepresentation(int index) { 6383 virtual Representation RequiredInputRepresentation(int index) {
5878 if (index == 0 && access().IsExternalMemory()) { 6384 if (index == 0 && access().IsExternalMemory()) {
5879 // object must be external in case of external memory access 6385 // object must be external in case of external memory access
(...skipping 11 matching lines...) Expand all
5891 ASSERT(side_effect == kChangesNewSpacePromotion); 6397 ASSERT(side_effect == kChangesNewSpacePromotion);
5892 new_space_dominator_ = dominator; 6398 new_space_dominator_ = dominator;
5893 } 6399 }
5894 virtual void PrintDataTo(StringStream* stream); 6400 virtual void PrintDataTo(StringStream* stream);
5895 6401
5896 void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; } 6402 void SkipWriteBarrier() { write_barrier_mode_ = SKIP_WRITE_BARRIER; }
5897 bool IsSkipWriteBarrier() const { 6403 bool IsSkipWriteBarrier() const {
5898 return write_barrier_mode_ == SKIP_WRITE_BARRIER; 6404 return write_barrier_mode_ == SKIP_WRITE_BARRIER;
5899 } 6405 }
5900 6406
5901 HValue* object() const { return OperandAt(0); } 6407 HValue* object() { return OperandAt(0); }
5902 HValue* value() const { return OperandAt(1); } 6408 HValue* value() { return OperandAt(1); }
5903 HValue* transition() const { return OperandAt(2); }
5904 6409
5905 HObjectAccess access() const { return access_; } 6410 HObjectAccess access() const { return access_; }
5906 HValue* new_space_dominator() const { return new_space_dominator_; } 6411 Handle<Map> transition() const { return transition_; }
5907 bool has_transition() const { return has_transition_; } 6412 UniqueValueId transition_unique_id() const { return transition_unique_id_; }
5908 6413 void SetTransition(Handle<Map> map, CompilationInfo* info) {
5909 Handle<Map> transition_map() const { 6414 ASSERT(transition_.is_null()); // Only set once.
5910 if (has_transition()) {
5911 return Handle<Map>::cast(HConstant::cast(transition())->handle());
5912 } else {
5913 return Handle<Map>();
5914 }
5915 }
5916
5917 void SetTransition(HConstant* map_constant, CompilationInfo* info) {
5918 ASSERT(!has_transition()); // Only set once.
5919 Handle<Map> map = Handle<Map>::cast(map_constant->handle());
5920 if (map->CanBeDeprecated()) { 6415 if (map->CanBeDeprecated()) {
5921 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info); 6416 map->AddDependentCompilationInfo(DependentCode::kTransitionGroup, info);
5922 } 6417 }
5923 SetOperandAt(2, map_constant); 6418 transition_ = map;
5924 has_transition_ = true;
5925 } 6419 }
6420 HValue* new_space_dominator() const { return new_space_dominator_; }
5926 6421
5927 bool NeedsWriteBarrier() { 6422 bool NeedsWriteBarrier() {
5928 ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) || 6423 ASSERT(!(FLAG_track_double_fields && field_representation().IsDouble()) ||
5929 !has_transition()); 6424 transition_.is_null());
5930 if (IsSkipWriteBarrier()) return false; 6425 if (IsSkipWriteBarrier()) return false;
5931 if (field_representation().IsDouble()) return false; 6426 if (field_representation().IsDouble()) return false;
5932 if (field_representation().IsSmi()) return false; 6427 if (field_representation().IsSmi()) return false;
5933 if (field_representation().IsInteger32()) return false; 6428 if (field_representation().IsInteger32()) return false;
5934 if (field_representation().IsExternal()) return false; 6429 if (field_representation().IsExternal()) return false;
5935 return StoringValueNeedsWriteBarrier(value()) && 6430 return StoringValueNeedsWriteBarrier(value()) &&
5936 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); 6431 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
5937 } 6432 }
5938 6433
5939 bool NeedsWriteBarrierForMap() { 6434 bool NeedsWriteBarrierForMap() {
5940 if (IsSkipWriteBarrier()) return false; 6435 if (IsSkipWriteBarrier()) return false;
5941 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); 6436 return ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator());
5942 } 6437 }
5943 6438
6439 virtual void FinalizeUniqueValueId() {
6440 transition_unique_id_ = UniqueValueId(transition_);
6441 }
6442
5944 Representation field_representation() const { 6443 Representation field_representation() const {
5945 return access_.representation(); 6444 return access_.representation();
5946 } 6445 }
5947 6446
5948 private: 6447 private:
5949 HStoreNamedField(HValue* obj, 6448 HStoreNamedField(HValue* obj,
5950 HObjectAccess access, 6449 HObjectAccess access,
5951 HValue* val) 6450 HValue* val)
5952 : access_(access), 6451 : access_(access),
6452 transition_(),
6453 transition_unique_id_(),
5953 new_space_dominator_(NULL), 6454 new_space_dominator_(NULL),
5954 write_barrier_mode_(UPDATE_WRITE_BARRIER), 6455 write_barrier_mode_(UPDATE_WRITE_BARRIER) {
5955 has_transition_(false) {
5956 SetOperandAt(0, obj); 6456 SetOperandAt(0, obj);
5957 SetOperandAt(1, val); 6457 SetOperandAt(1, val);
5958 SetOperandAt(2, obj);
5959 access.SetGVNFlags(this, true); 6458 access.SetGVNFlags(this, true);
5960 } 6459 }
5961 6460
5962 HObjectAccess access_; 6461 HObjectAccess access_;
6462 Handle<Map> transition_;
6463 UniqueValueId transition_unique_id_;
5963 HValue* new_space_dominator_; 6464 HValue* new_space_dominator_;
5964 WriteBarrierMode write_barrier_mode_ : 1; 6465 WriteBarrierMode write_barrier_mode_;
5965 bool has_transition_ : 1;
5966 }; 6466 };
5967 6467
5968 6468
5969 class HStoreNamedGeneric: public HTemplateInstruction<3> { 6469 class HStoreNamedGeneric: public HTemplateInstruction<3> {
5970 public: 6470 public:
5971 HStoreNamedGeneric(HValue* context, 6471 HStoreNamedGeneric(HValue* context,
5972 HValue* object, 6472 HValue* object,
5973 Handle<String> name, 6473 Handle<String> name,
5974 HValue* value, 6474 HValue* value,
5975 StrictModeFlag strict_mode_flag) 6475 StrictModeFlag strict_mode_flag)
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after
6749 virtual bool IsDeletable() const { return true; } 7249 virtual bool IsDeletable() const { return true; }
6750 }; 7250 };
6751 7251
6752 7252
6753 #undef DECLARE_INSTRUCTION 7253 #undef DECLARE_INSTRUCTION
6754 #undef DECLARE_CONCRETE_INSTRUCTION 7254 #undef DECLARE_CONCRETE_INSTRUCTION
6755 7255
6756 } } // namespace v8::internal 7256 } } // namespace v8::internal
6757 7257
6758 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ 7258 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
OLDNEW
« no previous file with comments | « src/hydrogen-dehoist.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698