Chromium Code Reviews| 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 |