1 // Copyright 2018 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_ALLOCATION_SITE_H_ 6 #define V8_OBJECTS_ALLOCATION_SITE_H_ 7 8 #include "src/objects/objects.h" 9 #include "src/objects/struct.h" 10 11 // Has to be the last include (doesn't have include guards): 12 #include "src/objects/object-macros.h" 13 14 namespace v8 { 15 namespace internal { 16 17 enum InstanceType : uint16_t; 18 19 #include "torque-generated/src/objects/allocation-site-tq.inc" 20 21 class AllocationSite : public Struct { 22 public: 23 NEVER_READ_ONLY_SPACE 24 static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024; 25 static const double kPretenureRatio; 26 static const int kPretenureMinimumCreated = 100; 27 28 // Values for pretenure decision field. 29 enum PretenureDecision { 30 kUndecided = 0, 31 kDontTenure = 1, 32 kMaybeTenure = 2, 33 kTenure = 3, 34 kZombie = 4, // See comment to IsZombie() for documentation. 35 kLastPretenureDecisionValue = kZombie 36 }; 37 38 const char* PretenureDecisionName(PretenureDecision decision); 39 40 // Contains either a Smi-encoded bitfield or a boilerplate. If it's a Smi the 41 // AllocationSite is for a constructed Array. 42 DECL_ACCESSORS(transition_info_or_boilerplate, Object) 43 DECL_RELEASE_ACQUIRE_ACCESSORS(transition_info_or_boilerplate, Object) 44 DECL_GETTER(boilerplate, JSObject) 45 DECL_RELEASE_ACQUIRE_ACCESSORS(boilerplate, JSObject) 46 DECL_INT_ACCESSORS(transition_info) 47 48 // nested_site threads a list of sites that represent nested literals 49 // walked in a particular order. So [[1, 2], 1, 2] will have one 50 // nested_site, but [[1, 2], 3, [4]] will have a list of two. 51 DECL_ACCESSORS(nested_site, Object) 52 53 // Bitfield containing pretenuring information. 54 DECL_RELAXED_INT32_ACCESSORS(pretenure_data) 55 56 DECL_INT32_ACCESSORS(pretenure_create_count) 57 DECL_ACCESSORS(dependent_code, DependentCode) 58 59 // heap->allocation_site_list() points to the last AllocationSite which form 60 // a linked list through the weak_next property. The GC might remove elements 61 // from the list by updateing weak_next. 62 DECL_ACCESSORS(weak_next, Object) 63 64 inline void Initialize(); 65 66 // Checks if the allocation site contain weak_next field; 67 inline bool HasWeakNext() const; 68 69 // This method is expensive, it should only be called for reporting. 70 bool IsNested(); 71 72 // transition_info bitfields, for constructed array transition info. 73 using ElementsKindBits = base::BitField<ElementsKind, 0, 6>; 74 using DoNotInlineBit = base::BitField<bool, 6, 1>; 75 // Unused bits 7-30. 76 77 // Bitfields for pretenure_data 78 using MementoFoundCountBits = base::BitField<int, 0, 26>; 79 using PretenureDecisionBits = base::BitField<PretenureDecision, 26, 3>; 80 using DeoptDependentCodeBit = base::BitField<bool, 29, 1>; 81 STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue); 82 83 // Increments the mementos found counter and returns true when the first 84 // memento was found for a given allocation site. 85 inline bool IncrementMementoFoundCount(int increment = 1); 86 87 inline void IncrementMementoCreateCount(); 88 89 AllocationType GetAllocationType() const; 90 91 void ResetPretenureDecision(); 92 93 inline PretenureDecision pretenure_decision() const; 94 inline void set_pretenure_decision(PretenureDecision decision); 95 96 inline bool deopt_dependent_code() const; 97 inline void set_deopt_dependent_code(bool deopt); 98 99 inline int memento_found_count() const; 100 inline void set_memento_found_count(int count); 101 102 inline int memento_create_count() const; 103 inline void set_memento_create_count(int count); 104 105 // A "zombie" AllocationSite is one which has no more strong roots to 106 // it, and yet must be maintained until the next GC. The reason is that 107 // it may be that in new space there are AllocationMementos hanging around 108 // which point to the AllocationSite. If we scavenge these AllocationSites 109 // too soon, those AllocationMementos will end up pointing to garbage 110 // addresses. The garbage collector marks such AllocationSites as zombies 111 // when it discovers there are no roots, allowing the subsequent collection 112 // pass to recognize zombies and discard them later. 113 inline bool IsZombie() const; 114 115 inline bool IsMaybeTenure() const; 116 117 inline void MarkZombie(); 118 119 inline bool MakePretenureDecision(PretenureDecision current_decision, 120 double ratio, bool maximum_size_scavenge); 121 122 inline bool DigestPretenuringFeedback(bool maximum_size_scavenge); 123 124 inline ElementsKind GetElementsKind() const; 125 inline void SetElementsKind(ElementsKind kind); 126 127 inline bool CanInlineCall() const; 128 inline void SetDoNotInlineCall(); 129 130 inline bool PointsToLiteral() const; 131 132 template <AllocationSiteUpdateMode update_or_check = 133 AllocationSiteUpdateMode::kUpdate> 134 static bool DigestTransitionFeedback(Handle<AllocationSite> site, 135 ElementsKind to_kind); 136 137 DECL_PRINTER(AllocationSite) 138 DECL_VERIFIER(AllocationSite) 139 140 DECL_CAST(AllocationSite) 141 static inline bool ShouldTrack(ElementsKind boilerplate_elements_kind); 142 static bool ShouldTrack(ElementsKind from, ElementsKind to); 143 static inline bool CanTrack(InstanceType type); 144 145 // Layout description. 146 // AllocationSite has to start with TransitionInfoOrboilerPlateOffset 147 // and end with WeakNext field. 148 #define ALLOCATION_SITE_FIELDS(V) \ 149 V(kStartOffset, 0) \ 150 V(kTransitionInfoOrBoilerplateOffset, kTaggedSize) \ 151 V(kNestedSiteOffset, kTaggedSize) \ 152 V(kDependentCodeOffset, kTaggedSize) \ 153 V(kCommonPointerFieldEndOffset, 0) \ 154 V(kPretenureDataOffset, kInt32Size) \ 155 V(kPretenureCreateCountOffset, kInt32Size) \ 156 /* Size of AllocationSite without WeakNext field */ \ 157 V(kSizeWithoutWeakNext, 0) \ 158 V(kWeakNextOffset, kTaggedSize) \ 159 /* Size of AllocationSite with WeakNext field */ \ 160 V(kSizeWithWeakNext, 0) 161 162 DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, ALLOCATION_SITE_FIELDS) 163 #undef ALLOCATION_SITE_FIELDS 164 165 class BodyDescriptor; 166 167 private: 168 inline bool PretenuringDecisionMade() const; 169 170 OBJECT_CONSTRUCTORS(AllocationSite, Struct); 171 }; 172 173 class AllocationMemento 174 : public TorqueGeneratedAllocationMemento<AllocationMemento, Struct> { 175 public: 176 DECL_ACCESSORS(allocation_site, Object) 177 178 inline bool IsValid() const; 179 inline AllocationSite GetAllocationSite() const; 180 inline Address GetAllocationSiteUnchecked() const; 181 182 DECL_PRINTER(AllocationMemento) 183 184 using BodyDescriptor = StructBodyDescriptor; 185 186 TQ_OBJECT_CONSTRUCTORS(AllocationMemento) 187 }; 188 189 } // namespace internal 190 } // namespace v8 191 192 #include "src/objects/object-macros-undef.h" 193 194 #endif // V8_OBJECTS_ALLOCATION_SITE_H_ 195