OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
7 | 7 |
8 #include <cstring> | 8 #include <cstring> |
9 #include <iosfwd> | 9 #include <iosfwd> |
10 | 10 |
(...skipping 4921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4932 set_representation(Representation::Tagged()); | 4932 set_representation(Representation::Tagged()); |
4933 SetAllSideEffects(); | 4933 SetAllSideEffects(); |
4934 } | 4934 } |
4935 | 4935 |
4936 Handle<String> name_; | 4936 Handle<String> name_; |
4937 TypeofMode typeof_mode_; | 4937 TypeofMode typeof_mode_; |
4938 Handle<TypeFeedbackVector> feedback_vector_; | 4938 Handle<TypeFeedbackVector> feedback_vector_; |
4939 FeedbackVectorSlot slot_; | 4939 FeedbackVectorSlot slot_; |
4940 }; | 4940 }; |
4941 | 4941 |
4942 | 4942 class HAllocate final : public HTemplateInstruction<3> { |
4943 class HAllocate final : public HTemplateInstruction<2> { | |
4944 public: | 4943 public: |
4945 static bool CompatibleInstanceTypes(InstanceType type1, | 4944 static bool CompatibleInstanceTypes(InstanceType type1, |
4946 InstanceType type2) { | 4945 InstanceType type2) { |
4947 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) && | 4946 return ComputeFlags(TENURED, type1) == ComputeFlags(TENURED, type2) && |
4948 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2); | 4947 ComputeFlags(NOT_TENURED, type1) == ComputeFlags(NOT_TENURED, type2); |
4949 } | 4948 } |
4950 | 4949 |
4951 static HAllocate* New( | 4950 static HAllocate* New( |
4952 Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type, | 4951 Isolate* isolate, Zone* zone, HValue* context, HValue* size, HType type, |
4953 PretenureFlag pretenure_flag, InstanceType instance_type, | 4952 PretenureFlag pretenure_flag, InstanceType instance_type, |
| 4953 HValue* dominator, |
4954 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) { | 4954 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) { |
4955 return new(zone) HAllocate(context, size, type, pretenure_flag, | 4955 return new (zone) HAllocate(context, size, type, pretenure_flag, |
4956 instance_type, allocation_site); | 4956 instance_type, dominator, allocation_site); |
4957 } | 4957 } |
4958 | 4958 |
4959 // Maximum instance size for which allocations will be inlined. | 4959 // Maximum instance size for which allocations will be inlined. |
4960 static const int kMaxInlineSize = 64 * kPointerSize; | 4960 static const int kMaxInlineSize = 64 * kPointerSize; |
4961 | 4961 |
4962 HValue* context() const { return OperandAt(0); } | 4962 HValue* context() const { return OperandAt(0); } |
4963 HValue* size() const { return OperandAt(1); } | 4963 HValue* size() const { return OperandAt(1); } |
4964 | 4964 HValue* allocation_folding_dominator() const { return OperandAt(2); } |
4965 bool has_size_upper_bound() { return size_upper_bound_ != NULL; } | |
4966 HConstant* size_upper_bound() { return size_upper_bound_; } | |
4967 void set_size_upper_bound(HConstant* value) { | |
4968 DCHECK(size_upper_bound_ == NULL); | |
4969 size_upper_bound_ = value; | |
4970 } | |
4971 | 4965 |
4972 Representation RequiredInputRepresentation(int index) override { | 4966 Representation RequiredInputRepresentation(int index) override { |
4973 if (index == 0) { | 4967 if (index == 0) { |
4974 return Representation::Tagged(); | 4968 return Representation::Tagged(); |
4975 } else { | 4969 } else { |
4976 return Representation::Integer32(); | 4970 return Representation::Integer32(); |
4977 } | 4971 } |
4978 } | 4972 } |
4979 | 4973 |
4980 Handle<Map> GetMonomorphicJSObjectMap() override { | 4974 Handle<Map> GetMonomorphicJSObjectMap() override { |
(...skipping 17 matching lines...) Expand all Loading... |
4998 } | 4992 } |
4999 | 4993 |
5000 bool MustPrefillWithFiller() const { | 4994 bool MustPrefillWithFiller() const { |
5001 return (flags_ & PREFILL_WITH_FILLER) != 0; | 4995 return (flags_ & PREFILL_WITH_FILLER) != 0; |
5002 } | 4996 } |
5003 | 4997 |
5004 void MakePrefillWithFiller() { | 4998 void MakePrefillWithFiller() { |
5005 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER); | 4999 flags_ = static_cast<HAllocate::Flags>(flags_ | PREFILL_WITH_FILLER); |
5006 } | 5000 } |
5007 | 5001 |
5008 bool MustClearNextMapWord() const { | |
5009 return (flags_ & CLEAR_NEXT_MAP_WORD) != 0; | |
5010 } | |
5011 | |
5012 void MakeDoubleAligned() { | 5002 void MakeDoubleAligned() { |
5013 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED); | 5003 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATE_DOUBLE_ALIGNED); |
5014 } | 5004 } |
5015 | 5005 |
| 5006 void MakeAllocationFoldingDominator() { |
| 5007 flags_ = |
| 5008 static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDING_DOMINATOR); |
| 5009 } |
| 5010 |
| 5011 bool IsAllocationFoldingDominator() { |
| 5012 return (flags_ & ALLOCATION_FOLDING_DOMINATOR) != 0; |
| 5013 } |
| 5014 |
| 5015 void MakeFoldedAllocation(HAllocate* dominator) { |
| 5016 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED); |
| 5017 ClearFlag(kTrackSideEffectDominators); |
| 5018 ClearChangesFlag(kNewSpacePromotion); |
| 5019 SetOperandAt(2, dominator); |
| 5020 } |
| 5021 |
| 5022 bool IsAllocationFolded() { return (flags_ & ALLOCATION_FOLDED) != 0; } |
| 5023 |
5016 bool HandleSideEffectDominator(GVNFlag side_effect, | 5024 bool HandleSideEffectDominator(GVNFlag side_effect, |
5017 HValue* dominator) override; | 5025 HValue* dominator) override; |
5018 | 5026 |
5019 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | 5027 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT |
5020 | 5028 |
5021 DECLARE_CONCRETE_INSTRUCTION(Allocate) | 5029 DECLARE_CONCRETE_INSTRUCTION(Allocate) |
5022 | 5030 |
5023 private: | 5031 private: |
5024 enum Flags { | 5032 enum Flags { |
5025 ALLOCATE_IN_NEW_SPACE = 1 << 0, | 5033 ALLOCATE_IN_NEW_SPACE = 1 << 0, |
5026 ALLOCATE_IN_OLD_SPACE = 1 << 2, | 5034 ALLOCATE_IN_OLD_SPACE = 1 << 2, |
5027 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, | 5035 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, |
5028 PREFILL_WITH_FILLER = 1 << 4, | 5036 PREFILL_WITH_FILLER = 1 << 4, |
5029 CLEAR_NEXT_MAP_WORD = 1 << 5 | 5037 ALLOCATION_FOLDING_DOMINATOR = 1 << 5, |
| 5038 ALLOCATION_FOLDED = 1 << 6 |
5030 }; | 5039 }; |
5031 | 5040 |
5032 HAllocate(HValue* context, | 5041 HAllocate( |
5033 HValue* size, | 5042 HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag, |
5034 HType type, | 5043 InstanceType instance_type, HValue* dominator, |
5035 PretenureFlag pretenure_flag, | 5044 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) |
5036 InstanceType instance_type, | 5045 : HTemplateInstruction<3>(type), |
5037 Handle<AllocationSite> allocation_site = | 5046 flags_(ComputeFlags(pretenure_flag, instance_type)) { |
5038 Handle<AllocationSite>::null()) | |
5039 : HTemplateInstruction<2>(type), | |
5040 flags_(ComputeFlags(pretenure_flag, instance_type)), | |
5041 dominating_allocate_(NULL), | |
5042 filler_free_space_size_(NULL), | |
5043 size_upper_bound_(NULL) { | |
5044 SetOperandAt(0, context); | 5047 SetOperandAt(0, context); |
5045 UpdateSize(size); | 5048 UpdateSize(size); |
| 5049 SetOperandAt(2, dominator); |
5046 set_representation(Representation::Tagged()); | 5050 set_representation(Representation::Tagged()); |
5047 SetFlag(kTrackSideEffectDominators); | 5051 SetFlag(kTrackSideEffectDominators); |
5048 SetChangesFlag(kNewSpacePromotion); | 5052 SetChangesFlag(kNewSpacePromotion); |
5049 SetDependsOnFlag(kNewSpacePromotion); | 5053 SetDependsOnFlag(kNewSpacePromotion); |
5050 | 5054 |
5051 if (FLAG_trace_pretenuring) { | 5055 if (FLAG_trace_pretenuring) { |
5052 PrintF("HAllocate with AllocationSite %p %s\n", | 5056 PrintF("HAllocate with AllocationSite %p %s\n", |
5053 allocation_site.is_null() | 5057 allocation_site.is_null() |
5054 ? static_cast<void*>(NULL) | 5058 ? static_cast<void*>(NULL) |
5055 : static_cast<void*>(*allocation_site), | 5059 : static_cast<void*>(*allocation_site), |
5056 pretenure_flag == TENURED ? "tenured" : "not tenured"); | 5060 pretenure_flag == TENURED ? "tenured" : "not tenured"); |
5057 } | 5061 } |
5058 } | 5062 } |
5059 | 5063 |
5060 static Flags ComputeFlags(PretenureFlag pretenure_flag, | 5064 static Flags ComputeFlags(PretenureFlag pretenure_flag, |
5061 InstanceType instance_type) { | 5065 InstanceType instance_type) { |
5062 Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE | 5066 Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE |
5063 : ALLOCATE_IN_NEW_SPACE; | 5067 : ALLOCATE_IN_NEW_SPACE; |
5064 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { | 5068 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { |
5065 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED); | 5069 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED); |
5066 } | 5070 } |
5067 // We have to fill the allocated object with one word fillers if we do | 5071 // We have to fill the allocated object with one word fillers if we do |
5068 // not use allocation folding since some allocations may depend on each | 5072 // not use allocation folding since some allocations may depend on each |
5069 // other, i.e., have a pointer to each other. A GC in between these | 5073 // other, i.e., have a pointer to each other. A GC in between these |
5070 // allocations may leave such objects behind in a not completely initialized | 5074 // allocations may leave such objects behind in a not completely initialized |
5071 // state. | 5075 // state. |
5072 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { | 5076 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { |
5073 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER); | 5077 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER); |
5074 } | 5078 } |
5075 if (pretenure_flag == NOT_TENURED && | |
5076 AllocationSite::CanTrack(instance_type)) { | |
5077 flags = static_cast<Flags>(flags | CLEAR_NEXT_MAP_WORD); | |
5078 } | |
5079 return flags; | 5079 return flags; |
5080 } | 5080 } |
5081 | 5081 |
5082 void UpdateClearNextMapWord(bool clear_next_map_word) { | |
5083 flags_ = static_cast<Flags>(clear_next_map_word | |
5084 ? flags_ | CLEAR_NEXT_MAP_WORD | |
5085 : flags_ & ~CLEAR_NEXT_MAP_WORD); | |
5086 } | |
5087 | |
5088 void UpdateSize(HValue* size) { | 5082 void UpdateSize(HValue* size) { |
5089 SetOperandAt(1, size); | 5083 SetOperandAt(1, size); |
5090 if (size->IsInteger32Constant()) { | |
5091 size_upper_bound_ = HConstant::cast(size); | |
5092 } else { | |
5093 size_upper_bound_ = NULL; | |
5094 } | |
5095 } | 5084 } |
5096 | 5085 |
5097 HAllocate* GetFoldableDominator(HAllocate* dominator); | |
5098 | |
5099 void UpdateFreeSpaceFiller(int32_t filler_size); | |
5100 | |
5101 void CreateFreeSpaceFiller(int32_t filler_size); | |
5102 | |
5103 bool IsFoldable(HAllocate* allocate) { | 5086 bool IsFoldable(HAllocate* allocate) { |
5104 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) || | 5087 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) || |
5105 (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation()); | 5088 (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation()); |
5106 } | 5089 } |
5107 | 5090 |
5108 void ClearNextMapWord(int offset); | |
5109 | |
5110 Flags flags_; | 5091 Flags flags_; |
5111 Handle<Map> known_initial_map_; | 5092 Handle<Map> known_initial_map_; |
5112 HAllocate* dominating_allocate_; | |
5113 HStoreNamedField* filler_free_space_size_; | |
5114 HConstant* size_upper_bound_; | |
5115 }; | 5093 }; |
5116 | 5094 |
5117 | 5095 |
5118 class HStoreCodeEntry final : public HTemplateInstruction<2> { | 5096 class HStoreCodeEntry final : public HTemplateInstruction<2> { |
5119 public: | 5097 public: |
5120 static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context, | 5098 static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context, |
5121 HValue* function, HValue* code) { | 5099 HValue* function, HValue* code) { |
5122 return new(zone) HStoreCodeEntry(function, code); | 5100 return new(zone) HStoreCodeEntry(function, code); |
5123 } | 5101 } |
5124 | 5102 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5176 && !value->type().IsNull() | 5154 && !value->type().IsNull() |
5177 && !value->type().IsBoolean() | 5155 && !value->type().IsBoolean() |
5178 && !value->type().IsUndefined() | 5156 && !value->type().IsUndefined() |
5179 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 5157 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
5180 } | 5158 } |
5181 | 5159 |
5182 | 5160 |
5183 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, | 5161 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
5184 HValue* value, | 5162 HValue* value, |
5185 HValue* dominator) { | 5163 HValue* dominator) { |
| 5164 // There may be multiple inner allocates dominated by one allocate. |
5186 while (object->IsInnerAllocatedObject()) { | 5165 while (object->IsInnerAllocatedObject()) { |
5187 object = HInnerAllocatedObject::cast(object)->base_object(); | 5166 object = HInnerAllocatedObject::cast(object)->base_object(); |
5188 } | 5167 } |
| 5168 |
| 5169 if (object->IsAllocate()) { |
| 5170 HAllocate* allocate = HAllocate::cast(object); |
| 5171 if (allocate->IsAllocationFolded()) { |
| 5172 HValue* dominator = allocate->allocation_folding_dominator(); |
| 5173 DCHECK(HAllocate::cast(dominator)->IsAllocationFoldingDominator()); |
| 5174 object = dominator; |
| 5175 } |
| 5176 } |
| 5177 |
5189 if (object->IsConstant() && | 5178 if (object->IsConstant() && |
5190 HConstant::cast(object)->HasExternalReferenceValue()) { | 5179 HConstant::cast(object)->HasExternalReferenceValue()) { |
5191 // Stores to external references require no write barriers | 5180 // Stores to external references require no write barriers |
5192 return false; | 5181 return false; |
5193 } | 5182 } |
5194 // We definitely need a write barrier unless the object is the allocation | 5183 // We definitely need a write barrier unless the object is the allocation |
5195 // dominator. | 5184 // dominator. |
5196 if (object == dominator && object->IsAllocate()) { | 5185 if (object == dominator && object->IsAllocate()) { |
5197 // Stores to new space allocations require no write barriers. | 5186 // Stores to new space allocations require no write barriers. |
5198 if (HAllocate::cast(object)->IsNewSpaceAllocation()) { | 5187 if (HAllocate::cast(object)->IsNewSpaceAllocation()) { |
(...skipping 2038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7237 bool IsDeletable() const override { return true; } | 7226 bool IsDeletable() const override { return true; } |
7238 }; | 7227 }; |
7239 | 7228 |
7240 #undef DECLARE_INSTRUCTION | 7229 #undef DECLARE_INSTRUCTION |
7241 #undef DECLARE_CONCRETE_INSTRUCTION | 7230 #undef DECLARE_CONCRETE_INSTRUCTION |
7242 | 7231 |
7243 } // namespace internal | 7232 } // namespace internal |
7244 } // namespace v8 | 7233 } // namespace v8 |
7245 | 7234 |
7246 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 7235 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |