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() { | |
Michael Lippautz
2016/05/10 08:32:57
nit: It would probably make more sense to pass the
Hannes Payer (out of office)
2016/05/10 09:04:44
Done.
| |
5016 flags_ = static_cast<HAllocate::Flags>(flags_ | ALLOCATION_FOLDED); | |
5017 ClearFlag(kTrackSideEffectDominators); | |
5018 ClearChangesFlag(kNewSpacePromotion); | |
5019 } | |
5020 | |
5021 bool IsAllocationFolded() { return (flags_ & ALLOCATION_FOLDED) != 0; } | |
5022 | |
5016 bool HandleSideEffectDominator(GVNFlag side_effect, | 5023 bool HandleSideEffectDominator(GVNFlag side_effect, |
5017 HValue* dominator) override; | 5024 HValue* dominator) override; |
5018 | 5025 |
5019 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | 5026 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT |
5020 | 5027 |
5021 DECLARE_CONCRETE_INSTRUCTION(Allocate) | 5028 DECLARE_CONCRETE_INSTRUCTION(Allocate) |
5022 | 5029 |
5023 private: | 5030 private: |
5024 enum Flags { | 5031 enum Flags { |
5025 ALLOCATE_IN_NEW_SPACE = 1 << 0, | 5032 ALLOCATE_IN_NEW_SPACE = 1 << 0, |
5026 ALLOCATE_IN_OLD_SPACE = 1 << 2, | 5033 ALLOCATE_IN_OLD_SPACE = 1 << 2, |
5027 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, | 5034 ALLOCATE_DOUBLE_ALIGNED = 1 << 3, |
5028 PREFILL_WITH_FILLER = 1 << 4, | 5035 PREFILL_WITH_FILLER = 1 << 4, |
5029 CLEAR_NEXT_MAP_WORD = 1 << 5 | 5036 ALLOCATION_FOLDING_DOMINATOR = 1 << 5, |
5037 ALLOCATION_FOLDED = 1 << 6 | |
5030 }; | 5038 }; |
5031 | 5039 |
5032 HAllocate(HValue* context, | 5040 HAllocate( |
5033 HValue* size, | 5041 HValue* context, HValue* size, HType type, PretenureFlag pretenure_flag, |
5034 HType type, | 5042 InstanceType instance_type, HValue* dominator, |
5035 PretenureFlag pretenure_flag, | 5043 Handle<AllocationSite> allocation_site = Handle<AllocationSite>::null()) |
5036 InstanceType instance_type, | 5044 : HTemplateInstruction<3>(type), |
5037 Handle<AllocationSite> allocation_site = | 5045 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); | 5046 SetOperandAt(0, context); |
5045 UpdateSize(size); | 5047 UpdateSize(size); |
5048 SetOperandAt(2, dominator); | |
5046 set_representation(Representation::Tagged()); | 5049 set_representation(Representation::Tagged()); |
5047 SetFlag(kTrackSideEffectDominators); | 5050 SetFlag(kTrackSideEffectDominators); |
5048 SetChangesFlag(kNewSpacePromotion); | 5051 SetChangesFlag(kNewSpacePromotion); |
5049 SetDependsOnFlag(kNewSpacePromotion); | 5052 SetDependsOnFlag(kNewSpacePromotion); |
5050 | 5053 |
5051 if (FLAG_trace_pretenuring) { | 5054 if (FLAG_trace_pretenuring) { |
5052 PrintF("HAllocate with AllocationSite %p %s\n", | 5055 PrintF("HAllocate with AllocationSite %p %s\n", |
5053 allocation_site.is_null() | 5056 allocation_site.is_null() |
5054 ? static_cast<void*>(NULL) | 5057 ? static_cast<void*>(NULL) |
5055 : static_cast<void*>(*allocation_site), | 5058 : static_cast<void*>(*allocation_site), |
5056 pretenure_flag == TENURED ? "tenured" : "not tenured"); | 5059 pretenure_flag == TENURED ? "tenured" : "not tenured"); |
5057 } | 5060 } |
5058 } | 5061 } |
5059 | 5062 |
5060 static Flags ComputeFlags(PretenureFlag pretenure_flag, | 5063 static Flags ComputeFlags(PretenureFlag pretenure_flag, |
5061 InstanceType instance_type) { | 5064 InstanceType instance_type) { |
5062 Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE | 5065 Flags flags = pretenure_flag == TENURED ? ALLOCATE_IN_OLD_SPACE |
5063 : ALLOCATE_IN_NEW_SPACE; | 5066 : ALLOCATE_IN_NEW_SPACE; |
5064 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { | 5067 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { |
5065 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED); | 5068 flags = static_cast<Flags>(flags | ALLOCATE_DOUBLE_ALIGNED); |
5066 } | 5069 } |
5067 // We have to fill the allocated object with one word fillers if we do | 5070 // 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 | 5071 // 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 | 5072 // 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 | 5073 // allocations may leave such objects behind in a not completely initialized |
5071 // state. | 5074 // state. |
5072 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { | 5075 if (!FLAG_use_gvn || !FLAG_use_allocation_folding) { |
5073 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER); | 5076 flags = static_cast<Flags>(flags | PREFILL_WITH_FILLER); |
5074 } | 5077 } |
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; | 5078 return flags; |
5080 } | 5079 } |
5081 | 5080 |
5082 void UpdateClearNextMapWord(bool clear_next_map_word) { | 5081 void UpdateSize(HValue* size) { |
5083 flags_ = static_cast<Flags>(clear_next_map_word | 5082 SetOperandAt(1, size); |
5084 ? flags_ | CLEAR_NEXT_MAP_WORD | |
5085 : flags_ & ~CLEAR_NEXT_MAP_WORD); | |
5086 } | 5083 } |
5087 | 5084 |
5088 void UpdateSize(HValue* size) { | 5085 void UpdateAllocationFoldingDominator(HAllocate* dominator) { |
5089 SetOperandAt(1, size); | 5086 SetOperandAt(2, dominator); |
5090 if (size->IsInteger32Constant()) { | |
5091 size_upper_bound_ = HConstant::cast(size); | |
5092 } else { | |
5093 size_upper_bound_ = NULL; | |
5094 } | |
5095 } | 5087 } |
5096 | 5088 |
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) { | 5089 bool IsFoldable(HAllocate* allocate) { |
5104 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) || | 5090 return (IsNewSpaceAllocation() && allocate->IsNewSpaceAllocation()) || |
5105 (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation()); | 5091 (IsOldSpaceAllocation() && allocate->IsOldSpaceAllocation()); |
5106 } | 5092 } |
5107 | 5093 |
5108 void ClearNextMapWord(int offset); | |
5109 | |
5110 Flags flags_; | 5094 Flags flags_; |
5111 Handle<Map> known_initial_map_; | 5095 Handle<Map> known_initial_map_; |
5112 HAllocate* dominating_allocate_; | |
5113 HStoreNamedField* filler_free_space_size_; | |
5114 HConstant* size_upper_bound_; | |
5115 }; | 5096 }; |
5116 | 5097 |
5117 | 5098 |
5118 class HStoreCodeEntry final : public HTemplateInstruction<2> { | 5099 class HStoreCodeEntry final : public HTemplateInstruction<2> { |
5119 public: | 5100 public: |
5120 static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context, | 5101 static HStoreCodeEntry* New(Isolate* isolate, Zone* zone, HValue* context, |
5121 HValue* function, HValue* code) { | 5102 HValue* function, HValue* code) { |
5122 return new(zone) HStoreCodeEntry(function, code); | 5103 return new(zone) HStoreCodeEntry(function, code); |
5123 } | 5104 } |
5124 | 5105 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5176 && !value->type().IsNull() | 5157 && !value->type().IsNull() |
5177 && !value->type().IsBoolean() | 5158 && !value->type().IsBoolean() |
5178 && !value->type().IsUndefined() | 5159 && !value->type().IsUndefined() |
5179 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); | 5160 && !(value->IsConstant() && HConstant::cast(value)->ImmortalImmovable()); |
5180 } | 5161 } |
5181 | 5162 |
5182 | 5163 |
5183 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, | 5164 inline bool ReceiverObjectNeedsWriteBarrier(HValue* object, |
5184 HValue* value, | 5165 HValue* value, |
5185 HValue* dominator) { | 5166 HValue* dominator) { |
5167 // There may be multiple inner allocates dominated by one allocate. | |
5186 while (object->IsInnerAllocatedObject()) { | 5168 while (object->IsInnerAllocatedObject()) { |
5187 object = HInnerAllocatedObject::cast(object)->base_object(); | 5169 object = HInnerAllocatedObject::cast(object)->base_object(); |
5188 } | 5170 } |
5171 | |
5172 if (object->IsAllocate()) { | |
5173 HAllocate* allocate = HAllocate::cast(object); | |
5174 if (allocate->IsAllocationFolded()) { | |
5175 HValue* dominator = allocate->allocation_folding_dominator(); | |
Michael Lippautz
2016/05/10 08:32:57
nit: If you make this a nullptr check and not use
Hannes Payer (out of office)
2016/05/10 09:04:44
This is not possible. The input has to be a valid
| |
5176 DCHECK(HAllocate::cast(dominator)->IsAllocationFoldingDominator()); | |
5177 object = dominator; | |
5178 } | |
5179 } | |
5180 | |
5189 if (object->IsConstant() && | 5181 if (object->IsConstant() && |
5190 HConstant::cast(object)->HasExternalReferenceValue()) { | 5182 HConstant::cast(object)->HasExternalReferenceValue()) { |
5191 // Stores to external references require no write barriers | 5183 // Stores to external references require no write barriers |
5192 return false; | 5184 return false; |
5193 } | 5185 } |
5194 // We definitely need a write barrier unless the object is the allocation | 5186 // We definitely need a write barrier unless the object is the allocation |
5195 // dominator. | 5187 // dominator. |
5196 if (object == dominator && object->IsAllocate()) { | 5188 if (object == dominator && object->IsAllocate()) { |
5197 // Stores to new space allocations require no write barriers. | 5189 // Stores to new space allocations require no write barriers. |
5198 if (HAllocate::cast(object)->IsNewSpaceAllocation()) { | 5190 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; } | 7229 bool IsDeletable() const override { return true; } |
7238 }; | 7230 }; |
7239 | 7231 |
7240 #undef DECLARE_INSTRUCTION | 7232 #undef DECLARE_INSTRUCTION |
7241 #undef DECLARE_CONCRETE_INSTRUCTION | 7233 #undef DECLARE_CONCRETE_INSTRUCTION |
7242 | 7234 |
7243 } // namespace internal | 7235 } // namespace internal |
7244 } // namespace v8 | 7236 } // namespace v8 |
7245 | 7237 |
7246 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 7238 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |