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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |