| 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 V(UnknownOSRValue) \ | 181 V(UnknownOSRValue) \ |
| 182 V(UseConst) \ | 182 V(UseConst) \ |
| 183 V(ValueOf) \ | 183 V(ValueOf) \ |
| 184 V(ForInPrepareMap) \ | 184 V(ForInPrepareMap) \ |
| 185 V(ForInCacheArray) \ | 185 V(ForInCacheArray) \ |
| 186 V(CheckMapValue) \ | 186 V(CheckMapValue) \ |
| 187 V(LoadFieldByIndex) \ | 187 V(LoadFieldByIndex) \ |
| 188 V(DateField) \ | 188 V(DateField) \ |
| 189 V(WrapReceiver) | 189 V(WrapReceiver) |
| 190 | 190 |
| 191 #define GVN_FLAG_LIST(V) \ | 191 #define GVN_TRACKED_FLAG_LIST(V) \ |
| 192 V(NewSpacePromotion) |
| 193 |
| 194 #define GVN_UNTRACKED_FLAG_LIST(V) \ |
| 192 V(Calls) \ | 195 V(Calls) \ |
| 193 V(InobjectFields) \ | 196 V(InobjectFields) \ |
| 194 V(BackingStoreFields) \ | 197 V(BackingStoreFields) \ |
| 195 V(ElementsKind) \ | 198 V(ElementsKind) \ |
| 196 V(ElementsPointer) \ | 199 V(ElementsPointer) \ |
| 197 V(ArrayElements) \ | 200 V(ArrayElements) \ |
| 198 V(DoubleArrayElements) \ | 201 V(DoubleArrayElements) \ |
| 199 V(SpecializedArrayElements) \ | 202 V(SpecializedArrayElements) \ |
| 200 V(GlobalVars) \ | 203 V(GlobalVars) \ |
| 201 V(Maps) \ | 204 V(Maps) \ |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 HUseListNode* next_; | 502 HUseListNode* next_; |
| 500 HValue* value_; | 503 HValue* value_; |
| 501 int index_; | 504 int index_; |
| 502 | 505 |
| 503 friend class HValue; | 506 friend class HValue; |
| 504 }; | 507 }; |
| 505 | 508 |
| 506 | 509 |
| 507 // There must be one corresponding kDepends flag for every kChanges flag and | 510 // There must be one corresponding kDepends flag for every kChanges flag and |
| 508 // the order of the kChanges flags must be exactly the same as of the kDepends | 511 // the order of the kChanges flags must be exactly the same as of the kDepends |
| 509 // flags. | 512 // flags. All tracked flags should appear before untracked ones. |
| 510 enum GVNFlag { | 513 enum GVNFlag { |
| 511 // Declare global value numbering flags. | 514 // Declare global value numbering flags. |
| 512 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type, | 515 #define DECLARE_FLAG(type) kChanges##type, kDependsOn##type, |
| 513 GVN_FLAG_LIST(DECLARE_FLAG) | 516 GVN_TRACKED_FLAG_LIST(DECLARE_FLAG) |
| 517 GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG) |
| 514 #undef DECLARE_FLAG | 518 #undef DECLARE_FLAG |
| 515 kAfterLastFlag, | 519 kAfterLastFlag, |
| 516 kLastFlag = kAfterLastFlag - 1 | 520 kLastFlag = kAfterLastFlag - 1, |
| 521 #define COUNT_FLAG(type) + 1 |
| 522 kNumberOfTrackedSideEffects = 0 GVN_TRACKED_FLAG_LIST(COUNT_FLAG) |
| 523 #undef COUNT_FLAG |
| 517 }; | 524 }; |
| 518 | 525 |
| 519 typedef EnumSet<GVNFlag> GVNFlagSet; | 526 typedef EnumSet<GVNFlag> GVNFlagSet; |
| 520 | 527 |
| 521 | 528 |
| 522 class HValue: public ZoneObject { | 529 class HValue: public ZoneObject { |
| 523 public: | 530 public: |
| 524 static const int kNoNumber = -1; | 531 static const int kNoNumber = -1; |
| 525 | 532 |
| 526 enum Flag { | 533 enum Flag { |
| 527 kFlexibleRepresentation, | 534 kFlexibleRepresentation, |
| 528 // Participate in Global Value Numbering, i.e. elimination of | 535 // Participate in Global Value Numbering, i.e. elimination of |
| 529 // unnecessary recomputations. If an instruction sets this flag, it must | 536 // unnecessary recomputations. If an instruction sets this flag, it must |
| 530 // implement DataEquals(), which will be used to determine if other | 537 // implement DataEquals(), which will be used to determine if other |
| 531 // occurrences of the instruction are indeed the same. | 538 // occurrences of the instruction are indeed the same. |
| 532 kUseGVN, | 539 kUseGVN, |
| 540 // Track instructions that are dominating side effects. If an instruction |
| 541 // sets this flag, it must implement SetSideEffectDominator() and should |
| 542 // indicate which side effects to track by setting GVN flags. |
| 543 kTrackSideEffectDominators, |
| 533 kCanOverflow, | 544 kCanOverflow, |
| 534 kBailoutOnMinusZero, | 545 kBailoutOnMinusZero, |
| 535 kCanBeDivByZero, | 546 kCanBeDivByZero, |
| 536 kDeoptimizeOnUndefined, | 547 kDeoptimizeOnUndefined, |
| 537 kIsArguments, | 548 kIsArguments, |
| 538 kTruncatingToInt32, | 549 kTruncatingToInt32, |
| 539 kIsDead, | 550 kIsDead, |
| 540 kLastFlag = kIsDead | 551 kLastFlag = kIsDead |
| 541 }; | 552 }; |
| 542 | 553 |
| 543 STATIC_ASSERT(kLastFlag < kBitsPerInt); | 554 STATIC_ASSERT(kLastFlag < kBitsPerInt); |
| 544 | 555 |
| 545 static const int kChangesToDependsFlagsLeftShift = 1; | 556 static const int kChangesToDependsFlagsLeftShift = 1; |
| 546 | 557 |
| 558 static GVNFlag ChangesFlagFromInt(int x) { |
| 559 return static_cast<GVNFlag>(x * 2); |
| 560 } |
| 561 static GVNFlag DependsOnFlagFromInt(int x) { |
| 562 return static_cast<GVNFlag>(x * 2 + 1); |
| 563 } |
| 547 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) { | 564 static GVNFlagSet ConvertChangesToDependsFlags(GVNFlagSet flags) { |
| 548 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift); | 565 return GVNFlagSet(flags.ToIntegral() << kChangesToDependsFlagsLeftShift); |
| 549 } | 566 } |
| 550 | 567 |
| 551 static HValue* cast(HValue* value) { return value; } | 568 static HValue* cast(HValue* value) { return value; } |
| 552 | 569 |
| 553 enum Opcode { | 570 enum Opcode { |
| 554 // Declare a unique enum value for each hydrogen instruction. | 571 // Declare a unique enum value for each hydrogen instruction. |
| 555 #define DECLARE_OPCODE(type) k##type, | 572 #define DECLARE_OPCODE(type) k##type, |
| 556 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) | 573 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DECLARE_OPCODE) |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 void PrintChangesTo(StringStream* stream); | 736 void PrintChangesTo(StringStream* stream); |
| 720 | 737 |
| 721 const char* Mnemonic() const; | 738 const char* Mnemonic() const; |
| 722 | 739 |
| 723 // Updated the inferred type of this instruction and returns true if | 740 // Updated the inferred type of this instruction and returns true if |
| 724 // it has changed. | 741 // it has changed. |
| 725 bool UpdateInferredType(); | 742 bool UpdateInferredType(); |
| 726 | 743 |
| 727 virtual HType CalculateInferredType(); | 744 virtual HType CalculateInferredType(); |
| 728 | 745 |
| 746 // This function must be overridden for instructions which have the |
| 747 // kTrackSideEffectDominators flag set, to track instructions that are |
| 748 // dominating side effects. |
| 749 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { |
| 750 UNREACHABLE(); |
| 751 } |
| 752 |
| 729 #ifdef DEBUG | 753 #ifdef DEBUG |
| 730 virtual void Verify() = 0; | 754 virtual void Verify() = 0; |
| 731 #endif | 755 #endif |
| 732 | 756 |
| 733 protected: | 757 protected: |
| 734 // This function must be overridden for instructions with flag kUseGVN, to | 758 // This function must be overridden for instructions with flag kUseGVN, to |
| 735 // compare the non-Operand parts of the instruction. | 759 // compare the non-Operand parts of the instruction. |
| 736 virtual bool DataEquals(HValue* other) { | 760 virtual bool DataEquals(HValue* other) { |
| 737 UNREACHABLE(); | 761 UNREACHABLE(); |
| 738 return false; | 762 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 749 void set_representation(Representation r) { | 773 void set_representation(Representation r) { |
| 750 // Representation is set-once. | 774 // Representation is set-once. |
| 751 ASSERT(representation_.IsNone() && !r.IsNone()); | 775 ASSERT(representation_.IsNone() && !r.IsNone()); |
| 752 representation_ = r; | 776 representation_ = r; |
| 753 } | 777 } |
| 754 | 778 |
| 755 static GVNFlagSet AllDependsOnFlagSet() { | 779 static GVNFlagSet AllDependsOnFlagSet() { |
| 756 GVNFlagSet result; | 780 GVNFlagSet result; |
| 757 // Create changes mask. | 781 // Create changes mask. |
| 758 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 782 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
| 759 GVN_FLAG_LIST(ADD_FLAG) | 783 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
| 784 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
| 760 #undef ADD_FLAG | 785 #undef ADD_FLAG |
| 761 return result; | 786 return result; |
| 762 } | 787 } |
| 763 | 788 |
| 764 static GVNFlagSet AllChangesFlagSet() { | 789 static GVNFlagSet AllChangesFlagSet() { |
| 765 GVNFlagSet result; | 790 GVNFlagSet result; |
| 766 // Create changes mask. | 791 // Create changes mask. |
| 767 #define ADD_FLAG(type) result.Add(kChanges##type); | 792 #define ADD_FLAG(type) result.Add(kChanges##type); |
| 768 GVN_FLAG_LIST(ADD_FLAG) | 793 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
| 794 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) |
| 769 #undef ADD_FLAG | 795 #undef ADD_FLAG |
| 770 return result; | 796 return result; |
| 771 } | 797 } |
| 772 | 798 |
| 773 // A flag mask to mark an instruction as having arbitrary side effects. | 799 // A flag mask to mark an instruction as having arbitrary side effects. |
| 774 static GVNFlagSet AllSideEffectsFlagSet() { | 800 static GVNFlagSet AllSideEffectsFlagSet() { |
| 775 GVNFlagSet result = AllChangesFlagSet(); | 801 GVNFlagSet result = AllChangesFlagSet(); |
| 776 result.Remove(kChangesOsrEntries); | 802 result.Remove(kChangesOsrEntries); |
| 777 return result; | 803 return result; |
| 778 } | 804 } |
| 779 | 805 |
| 780 // A flag mask of all side effects that can make observable changes in | 806 // A flag mask of all side effects that can make observable changes in |
| 781 // an executing program (i.e. are not safe to repeat, move or remove); | 807 // an executing program (i.e. are not safe to repeat, move or remove); |
| 782 static GVNFlagSet AllObservableSideEffectsFlagSet() { | 808 static GVNFlagSet AllObservableSideEffectsFlagSet() { |
| 783 GVNFlagSet result = AllChangesFlagSet(); | 809 GVNFlagSet result = AllChangesFlagSet(); |
| 810 result.Remove(kChangesNewSpacePromotion); |
| 784 result.Remove(kChangesElementsKind); | 811 result.Remove(kChangesElementsKind); |
| 785 result.Remove(kChangesElementsPointer); | 812 result.Remove(kChangesElementsPointer); |
| 786 result.Remove(kChangesMaps); | 813 result.Remove(kChangesMaps); |
| 787 return result; | 814 return result; |
| 788 } | 815 } |
| 789 | 816 |
| 790 // Remove the matching use from the use list if present. Returns the | 817 // Remove the matching use from the use list if present. Returns the |
| 791 // removed list node or NULL. | 818 // removed list node or NULL. |
| 792 HUseListNode* RemoveUse(HValue* value, int index); | 819 HUseListNode* RemoveUse(HValue* value, int index); |
| 793 | 820 |
| (...skipping 2756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3550 }; | 3577 }; |
| 3551 | 3578 |
| 3552 | 3579 |
| 3553 inline bool StoringValueNeedsWriteBarrier(HValue* value) { | 3580 inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
| 3554 return !value->type().IsBoolean() | 3581 return !value->type().IsBoolean() |
| 3555 && !value->type().IsSmi() | 3582 && !value->type().IsSmi() |
| 3556 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 3583 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
| 3557 } | 3584 } |
| 3558 | 3585 |
| 3559 | 3586 |
| 3587 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
| 3588 HValue* new_space_dominator) { |
| 3589 return !object->IsAllocateObject() || (object != new_space_dominator); |
| 3590 } |
| 3591 |
| 3592 |
| 3560 class HStoreGlobalCell: public HUnaryOperation { | 3593 class HStoreGlobalCell: public HUnaryOperation { |
| 3561 public: | 3594 public: |
| 3562 HStoreGlobalCell(HValue* value, | 3595 HStoreGlobalCell(HValue* value, |
| 3563 Handle<JSGlobalPropertyCell> cell, | 3596 Handle<JSGlobalPropertyCell> cell, |
| 3564 PropertyDetails details) | 3597 PropertyDetails details) |
| 3565 : HUnaryOperation(value), | 3598 : HUnaryOperation(value), |
| 3566 cell_(cell), | 3599 cell_(cell), |
| 3567 details_(details) { | 3600 details_(details) { |
| 3568 SetGVNFlag(kChangesGlobalVars); | 3601 SetGVNFlag(kChangesGlobalVars); |
| 3569 } | 3602 } |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4016 | 4049 |
| 4017 class HStoreNamedField: public HTemplateInstruction<2> { | 4050 class HStoreNamedField: public HTemplateInstruction<2> { |
| 4018 public: | 4051 public: |
| 4019 HStoreNamedField(HValue* obj, | 4052 HStoreNamedField(HValue* obj, |
| 4020 Handle<String> name, | 4053 Handle<String> name, |
| 4021 HValue* val, | 4054 HValue* val, |
| 4022 bool in_object, | 4055 bool in_object, |
| 4023 int offset) | 4056 int offset) |
| 4024 : name_(name), | 4057 : name_(name), |
| 4025 is_in_object_(in_object), | 4058 is_in_object_(in_object), |
| 4026 offset_(offset) { | 4059 offset_(offset), |
| 4060 new_space_dominator_(NULL) { |
| 4027 SetOperandAt(0, obj); | 4061 SetOperandAt(0, obj); |
| 4028 SetOperandAt(1, val); | 4062 SetOperandAt(1, val); |
| 4063 SetFlag(kTrackSideEffectDominators); |
| 4064 SetGVNFlag(kDependsOnNewSpacePromotion); |
| 4029 if (is_in_object_) { | 4065 if (is_in_object_) { |
| 4030 SetGVNFlag(kChangesInobjectFields); | 4066 SetGVNFlag(kChangesInobjectFields); |
| 4031 } else { | 4067 } else { |
| 4032 SetGVNFlag(kChangesBackingStoreFields); | 4068 SetGVNFlag(kChangesBackingStoreFields); |
| 4033 } | 4069 } |
| 4034 } | 4070 } |
| 4035 | 4071 |
| 4036 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 4072 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
| 4037 | 4073 |
| 4038 virtual Representation RequiredInputRepresentation(int index) { | 4074 virtual Representation RequiredInputRepresentation(int index) { |
| 4039 return Representation::Tagged(); | 4075 return Representation::Tagged(); |
| 4040 } | 4076 } |
| 4077 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { |
| 4078 ASSERT(side_effect == kChangesNewSpacePromotion); |
| 4079 new_space_dominator_ = dominator; |
| 4080 } |
| 4041 virtual void PrintDataTo(StringStream* stream); | 4081 virtual void PrintDataTo(StringStream* stream); |
| 4042 | 4082 |
| 4043 HValue* object() { return OperandAt(0); } | 4083 HValue* object() { return OperandAt(0); } |
| 4044 HValue* value() { return OperandAt(1); } | 4084 HValue* value() { return OperandAt(1); } |
| 4045 | 4085 |
| 4046 Handle<String> name() const { return name_; } | 4086 Handle<String> name() const { return name_; } |
| 4047 bool is_in_object() const { return is_in_object_; } | 4087 bool is_in_object() const { return is_in_object_; } |
| 4048 int offset() const { return offset_; } | 4088 int offset() const { return offset_; } |
| 4049 Handle<Map> transition() const { return transition_; } | 4089 Handle<Map> transition() const { return transition_; } |
| 4050 void set_transition(Handle<Map> map) { transition_ = map; } | 4090 void set_transition(Handle<Map> map) { transition_ = map; } |
| 4091 HValue* new_space_dominator() const { return new_space_dominator_; } |
| 4051 | 4092 |
| 4052 bool NeedsWriteBarrier() { | 4093 bool NeedsWriteBarrier() { |
| 4053 return StoringValueNeedsWriteBarrier(value()); | 4094 return StoringValueNeedsWriteBarrier(value()) && |
| 4095 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); |
| 4054 } | 4096 } |
| 4055 | 4097 |
| 4056 private: | 4098 private: |
| 4057 Handle<String> name_; | 4099 Handle<String> name_; |
| 4058 bool is_in_object_; | 4100 bool is_in_object_; |
| 4059 int offset_; | 4101 int offset_; |
| 4060 Handle<Map> transition_; | 4102 Handle<Map> transition_; |
| 4103 HValue* new_space_dominator_; |
| 4061 }; | 4104 }; |
| 4062 | 4105 |
| 4063 | 4106 |
| 4064 class HStoreNamedGeneric: public HTemplateInstruction<3> { | 4107 class HStoreNamedGeneric: public HTemplateInstruction<3> { |
| 4065 public: | 4108 public: |
| 4066 HStoreNamedGeneric(HValue* context, | 4109 HStoreNamedGeneric(HValue* context, |
| 4067 HValue* object, | 4110 HValue* object, |
| 4068 Handle<String> name, | 4111 Handle<String> name, |
| 4069 HValue* value, | 4112 HValue* value, |
| 4070 StrictModeFlag strict_mode_flag) | 4113 StrictModeFlag strict_mode_flag) |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4397 } | 4440 } |
| 4398 }; | 4441 }; |
| 4399 | 4442 |
| 4400 | 4443 |
| 4401 class HAllocateObject: public HTemplateInstruction<1> { | 4444 class HAllocateObject: public HTemplateInstruction<1> { |
| 4402 public: | 4445 public: |
| 4403 HAllocateObject(HValue* context, Handle<JSFunction> constructor) | 4446 HAllocateObject(HValue* context, Handle<JSFunction> constructor) |
| 4404 : constructor_(constructor) { | 4447 : constructor_(constructor) { |
| 4405 SetOperandAt(0, context); | 4448 SetOperandAt(0, context); |
| 4406 set_representation(Representation::Tagged()); | 4449 set_representation(Representation::Tagged()); |
| 4450 SetGVNFlag(kChangesNewSpacePromotion); |
| 4407 } | 4451 } |
| 4408 | 4452 |
| 4409 // Maximum instance size for which allocations will be inlined. | 4453 // Maximum instance size for which allocations will be inlined. |
| 4410 static const int kMaxSize = 64 * kPointerSize; | 4454 static const int kMaxSize = 64 * kPointerSize; |
| 4411 | 4455 |
| 4412 HValue* context() { return OperandAt(0); } | 4456 HValue* context() { return OperandAt(0); } |
| 4413 Handle<JSFunction> constructor() { return constructor_; } | 4457 Handle<JSFunction> constructor() { return constructor_; } |
| 4414 | 4458 |
| 4415 virtual Representation RequiredInputRepresentation(int index) { | 4459 virtual Representation RequiredInputRepresentation(int index) { |
| 4416 return Representation::Tagged(); | 4460 return Representation::Tagged(); |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4857 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); | 4901 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); |
| 4858 }; | 4902 }; |
| 4859 | 4903 |
| 4860 | 4904 |
| 4861 #undef DECLARE_INSTRUCTION | 4905 #undef DECLARE_INSTRUCTION |
| 4862 #undef DECLARE_CONCRETE_INSTRUCTION | 4906 #undef DECLARE_CONCRETE_INSTRUCTION |
| 4863 | 4907 |
| 4864 } } // namespace v8::internal | 4908 } } // namespace v8::internal |
| 4865 | 4909 |
| 4866 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 4910 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
| OLD | NEW |