Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: src/crankshaft/hydrogen-instructions.h

Issue 1899813003: [crankshaft] Fragmentation-free allocation folding. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698