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(NewSpace) | |
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 | |
Erik Corry
2012/04/10 12:06:52
I think it would be nice to provide functions:
GV
Michael Starzinger
2012/04/11 09:53:08
Done.
| |
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 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 void PrintChangesTo(StringStream* stream); | 730 void PrintChangesTo(StringStream* stream); |
720 | 731 |
721 const char* Mnemonic() const; | 732 const char* Mnemonic() const; |
722 | 733 |
723 // Updated the inferred type of this instruction and returns true if | 734 // Updated the inferred type of this instruction and returns true if |
724 // it has changed. | 735 // it has changed. |
725 bool UpdateInferredType(); | 736 bool UpdateInferredType(); |
726 | 737 |
727 virtual HType CalculateInferredType(); | 738 virtual HType CalculateInferredType(); |
728 | 739 |
740 // This function must be overridden for instructions which have the | |
741 // kTrackSideEffectDominators flag set, to track instructions that are | |
742 // dominating side effects. | |
743 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { | |
744 UNREACHABLE(); | |
745 } | |
746 | |
729 #ifdef DEBUG | 747 #ifdef DEBUG |
730 virtual void Verify() = 0; | 748 virtual void Verify() = 0; |
731 #endif | 749 #endif |
732 | 750 |
733 protected: | 751 protected: |
734 // This function must be overridden for instructions with flag kUseGVN, to | 752 // This function must be overridden for instructions with flag kUseGVN, to |
735 // compare the non-Operand parts of the instruction. | 753 // compare the non-Operand parts of the instruction. |
736 virtual bool DataEquals(HValue* other) { | 754 virtual bool DataEquals(HValue* other) { |
737 UNREACHABLE(); | 755 UNREACHABLE(); |
738 return false; | 756 return false; |
(...skipping 10 matching lines...) Expand all Loading... | |
749 void set_representation(Representation r) { | 767 void set_representation(Representation r) { |
750 // Representation is set-once. | 768 // Representation is set-once. |
751 ASSERT(representation_.IsNone() && !r.IsNone()); | 769 ASSERT(representation_.IsNone() && !r.IsNone()); |
752 representation_ = r; | 770 representation_ = r; |
753 } | 771 } |
754 | 772 |
755 static GVNFlagSet AllDependsOnFlagSet() { | 773 static GVNFlagSet AllDependsOnFlagSet() { |
756 GVNFlagSet result; | 774 GVNFlagSet result; |
757 // Create changes mask. | 775 // Create changes mask. |
758 #define ADD_FLAG(type) result.Add(kDependsOn##type); | 776 #define ADD_FLAG(type) result.Add(kDependsOn##type); |
759 GVN_FLAG_LIST(ADD_FLAG) | 777 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
778 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | |
760 #undef ADD_FLAG | 779 #undef ADD_FLAG |
761 return result; | 780 return result; |
762 } | 781 } |
763 | 782 |
764 static GVNFlagSet AllChangesFlagSet() { | 783 static GVNFlagSet AllChangesFlagSet() { |
765 GVNFlagSet result; | 784 GVNFlagSet result; |
766 // Create changes mask. | 785 // Create changes mask. |
767 #define ADD_FLAG(type) result.Add(kChanges##type); | 786 #define ADD_FLAG(type) result.Add(kChanges##type); |
768 GVN_FLAG_LIST(ADD_FLAG) | 787 GVN_TRACKED_FLAG_LIST(ADD_FLAG) |
788 GVN_UNTRACKED_FLAG_LIST(ADD_FLAG) | |
769 #undef ADD_FLAG | 789 #undef ADD_FLAG |
770 return result; | 790 return result; |
771 } | 791 } |
772 | 792 |
773 // A flag mask to mark an instruction as having arbitrary side effects. | 793 // A flag mask to mark an instruction as having arbitrary side effects. |
774 static GVNFlagSet AllSideEffectsFlagSet() { | 794 static GVNFlagSet AllSideEffectsFlagSet() { |
775 GVNFlagSet result = AllChangesFlagSet(); | 795 GVNFlagSet result = AllChangesFlagSet(); |
776 result.Remove(kChangesOsrEntries); | 796 result.Remove(kChangesOsrEntries); |
777 return result; | 797 return result; |
778 } | 798 } |
779 | 799 |
780 // A flag mask of all side effects that can make observable changes in | 800 // 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); | 801 // an executing program (i.e. are not safe to repeat, move or remove); |
782 static GVNFlagSet AllObservableSideEffectsFlagSet() { | 802 static GVNFlagSet AllObservableSideEffectsFlagSet() { |
783 GVNFlagSet result = AllChangesFlagSet(); | 803 GVNFlagSet result = AllChangesFlagSet(); |
804 result.Remove(kChangesNewSpace); | |
Erik Corry
2012/04/10 12:06:52
The name makes it sound like any write to new spac
Michael Starzinger
2012/04/11 09:53:08
Done.
| |
784 result.Remove(kChangesElementsKind); | 805 result.Remove(kChangesElementsKind); |
785 result.Remove(kChangesElementsPointer); | 806 result.Remove(kChangesElementsPointer); |
786 result.Remove(kChangesMaps); | 807 result.Remove(kChangesMaps); |
787 return result; | 808 return result; |
788 } | 809 } |
789 | 810 |
790 // Remove the matching use from the use list if present. Returns the | 811 // Remove the matching use from the use list if present. Returns the |
791 // removed list node or NULL. | 812 // removed list node or NULL. |
792 HUseListNode* RemoveUse(HValue* value, int index); | 813 HUseListNode* RemoveUse(HValue* value, int index); |
793 | 814 |
(...skipping 2756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3550 }; | 3571 }; |
3551 | 3572 |
3552 | 3573 |
3553 inline bool StoringValueNeedsWriteBarrier(HValue* value) { | 3574 inline bool StoringValueNeedsWriteBarrier(HValue* value) { |
3554 return !value->type().IsBoolean() | 3575 return !value->type().IsBoolean() |
3555 && !value->type().IsSmi() | 3576 && !value->type().IsSmi() |
3556 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 3577 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
3557 } | 3578 } |
3558 | 3579 |
3559 | 3580 |
3581 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, | |
3582 HValue* new_space_dominator) { | |
3583 return !object->IsAllocateObject() || (object != new_space_dominator); | |
3584 } | |
3585 | |
3586 | |
3560 class HStoreGlobalCell: public HUnaryOperation { | 3587 class HStoreGlobalCell: public HUnaryOperation { |
3561 public: | 3588 public: |
3562 HStoreGlobalCell(HValue* value, | 3589 HStoreGlobalCell(HValue* value, |
3563 Handle<JSGlobalPropertyCell> cell, | 3590 Handle<JSGlobalPropertyCell> cell, |
3564 PropertyDetails details) | 3591 PropertyDetails details) |
3565 : HUnaryOperation(value), | 3592 : HUnaryOperation(value), |
3566 cell_(cell), | 3593 cell_(cell), |
3567 details_(details) { | 3594 details_(details) { |
3568 SetGVNFlag(kChangesGlobalVars); | 3595 SetGVNFlag(kChangesGlobalVars); |
3569 } | 3596 } |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4016 | 4043 |
4017 class HStoreNamedField: public HTemplateInstruction<2> { | 4044 class HStoreNamedField: public HTemplateInstruction<2> { |
4018 public: | 4045 public: |
4019 HStoreNamedField(HValue* obj, | 4046 HStoreNamedField(HValue* obj, |
4020 Handle<String> name, | 4047 Handle<String> name, |
4021 HValue* val, | 4048 HValue* val, |
4022 bool in_object, | 4049 bool in_object, |
4023 int offset) | 4050 int offset) |
4024 : name_(name), | 4051 : name_(name), |
4025 is_in_object_(in_object), | 4052 is_in_object_(in_object), |
4026 offset_(offset) { | 4053 offset_(offset) { |
Erik Corry
2012/04/10 12:06:52
Should you not initialize new_space_dominator_ her
Michael Starzinger
2012/04/11 09:53:08
Done.
| |
4027 SetOperandAt(0, obj); | 4054 SetOperandAt(0, obj); |
4028 SetOperandAt(1, val); | 4055 SetOperandAt(1, val); |
4056 SetFlag(kTrackSideEffectDominators); | |
4057 SetGVNFlag(kDependsOnNewSpace); | |
4029 if (is_in_object_) { | 4058 if (is_in_object_) { |
4030 SetGVNFlag(kChangesInobjectFields); | 4059 SetGVNFlag(kChangesInobjectFields); |
4031 } else { | 4060 } else { |
4032 SetGVNFlag(kChangesBackingStoreFields); | 4061 SetGVNFlag(kChangesBackingStoreFields); |
4033 } | 4062 } |
4034 } | 4063 } |
4035 | 4064 |
4036 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) | 4065 DECLARE_CONCRETE_INSTRUCTION(StoreNamedField) |
4037 | 4066 |
4038 virtual Representation RequiredInputRepresentation(int index) { | 4067 virtual Representation RequiredInputRepresentation(int index) { |
4039 return Representation::Tagged(); | 4068 return Representation::Tagged(); |
4040 } | 4069 } |
4070 virtual void SetSideEffectDominator(GVNFlag side_effect, HValue* dominator) { | |
4071 ASSERT(side_effect == kChangesNewSpace); | |
4072 new_space_dominator_ = dominator; | |
4073 } | |
4041 virtual void PrintDataTo(StringStream* stream); | 4074 virtual void PrintDataTo(StringStream* stream); |
4042 | 4075 |
4043 HValue* object() { return OperandAt(0); } | 4076 HValue* object() { return OperandAt(0); } |
4044 HValue* value() { return OperandAt(1); } | 4077 HValue* value() { return OperandAt(1); } |
4045 | 4078 |
4046 Handle<String> name() const { return name_; } | 4079 Handle<String> name() const { return name_; } |
4047 bool is_in_object() const { return is_in_object_; } | 4080 bool is_in_object() const { return is_in_object_; } |
4048 int offset() const { return offset_; } | 4081 int offset() const { return offset_; } |
4049 Handle<Map> transition() const { return transition_; } | 4082 Handle<Map> transition() const { return transition_; } |
4050 void set_transition(Handle<Map> map) { transition_ = map; } | 4083 void set_transition(Handle<Map> map) { transition_ = map; } |
4084 HValue* new_space_dominator() const { return new_space_dominator_; } | |
4051 | 4085 |
4052 bool NeedsWriteBarrier() { | 4086 bool NeedsWriteBarrier() { |
4053 return StoringValueNeedsWriteBarrier(value()); | 4087 return StoringValueNeedsWriteBarrier(value()) && |
4088 ReceiverObjectNeedsWriteBarrier(object(), new_space_dominator()); | |
4054 } | 4089 } |
4055 | 4090 |
4056 private: | 4091 private: |
4057 Handle<String> name_; | 4092 Handle<String> name_; |
4058 bool is_in_object_; | 4093 bool is_in_object_; |
4059 int offset_; | 4094 int offset_; |
4060 Handle<Map> transition_; | 4095 Handle<Map> transition_; |
4096 HValue* new_space_dominator_; | |
4061 }; | 4097 }; |
4062 | 4098 |
4063 | 4099 |
4064 class HStoreNamedGeneric: public HTemplateInstruction<3> { | 4100 class HStoreNamedGeneric: public HTemplateInstruction<3> { |
4065 public: | 4101 public: |
4066 HStoreNamedGeneric(HValue* context, | 4102 HStoreNamedGeneric(HValue* context, |
4067 HValue* object, | 4103 HValue* object, |
4068 Handle<String> name, | 4104 Handle<String> name, |
4069 HValue* value, | 4105 HValue* value, |
4070 StrictModeFlag strict_mode_flag) | 4106 StrictModeFlag strict_mode_flag) |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4397 } | 4433 } |
4398 }; | 4434 }; |
4399 | 4435 |
4400 | 4436 |
4401 class HAllocateObject: public HTemplateInstruction<1> { | 4437 class HAllocateObject: public HTemplateInstruction<1> { |
4402 public: | 4438 public: |
4403 HAllocateObject(HValue* context, Handle<JSFunction> constructor) | 4439 HAllocateObject(HValue* context, Handle<JSFunction> constructor) |
4404 : constructor_(constructor) { | 4440 : constructor_(constructor) { |
4405 SetOperandAt(0, context); | 4441 SetOperandAt(0, context); |
4406 set_representation(Representation::Tagged()); | 4442 set_representation(Representation::Tagged()); |
4443 SetGVNFlag(kChangesNewSpace); | |
4407 } | 4444 } |
4408 | 4445 |
4409 // Maximum instance size for which allocations will be inlined. | 4446 // Maximum instance size for which allocations will be inlined. |
4410 static const int kMaxSize = 64 * kPointerSize; | 4447 static const int kMaxSize = 64 * kPointerSize; |
4411 | 4448 |
4412 HValue* context() { return OperandAt(0); } | 4449 HValue* context() { return OperandAt(0); } |
4413 Handle<JSFunction> constructor() { return constructor_; } | 4450 Handle<JSFunction> constructor() { return constructor_; } |
4414 | 4451 |
4415 virtual Representation RequiredInputRepresentation(int index) { | 4452 virtual Representation RequiredInputRepresentation(int index) { |
4416 return Representation::Tagged(); | 4453 return Representation::Tagged(); |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4857 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); | 4894 DECLARE_CONCRETE_INSTRUCTION(LoadFieldByIndex); |
4858 }; | 4895 }; |
4859 | 4896 |
4860 | 4897 |
4861 #undef DECLARE_INSTRUCTION | 4898 #undef DECLARE_INSTRUCTION |
4862 #undef DECLARE_CONCRETE_INSTRUCTION | 4899 #undef DECLARE_CONCRETE_INSTRUCTION |
4863 | 4900 |
4864 } } // namespace v8::internal | 4901 } } // namespace v8::internal |
4865 | 4902 |
4866 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 4903 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |