• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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