| 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 |