allocation-site.h 6.7 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_ALLOCATION_SITE_H_
#define V8_OBJECTS_ALLOCATION_SITE_H_

8
#include "src/objects/objects.h"
9
#include "src/objects/struct.h"
10 11 12 13 14 15 16

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

17 18
enum InstanceType : uint16_t;

19 20
#include "torque-generated/src/objects/allocation-site-tq.inc"

21
class AllocationSite : public Struct {
22
 public:
23
  NEVER_READ_ONLY_SPACE
24 25 26 27 28 29 30 31 32 33
  static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024;
  static const double kPretenureRatio;
  static const int kPretenureMinimumCreated = 100;

  // Values for pretenure decision field.
  enum PretenureDecision {
    kUndecided = 0,
    kDontTenure = 1,
    kMaybeTenure = 2,
    kTenure = 3,
34
    kZombie = 4,  // See comment to IsZombie() for documentation.
35 36 37 38 39 40 41 42
    kLastPretenureDecisionValue = kZombie
  };

  const char* PretenureDecisionName(PretenureDecision decision);

  // Contains either a Smi-encoded bitfield or a boilerplate. If it's a Smi the
  // AllocationSite is for a constructed Array.
  DECL_ACCESSORS(transition_info_or_boilerplate, Object)
43 44 45
  DECL_RELEASE_ACQUIRE_ACCESSORS(transition_info_or_boilerplate, Object)
  DECL_GETTER(boilerplate, JSObject)
  DECL_RELEASE_ACQUIRE_ACCESSORS(boilerplate, JSObject)
46 47 48 49 50 51 52 53 54 55 56
  DECL_INT_ACCESSORS(transition_info)

  // nested_site threads a list of sites that represent nested literals
  // walked in a particular order. So [[1, 2], 1, 2] will have one
  // nested_site, but [[1, 2], 3, [4]] will have a list of two.
  DECL_ACCESSORS(nested_site, Object)

  // Bitfield containing pretenuring information.
  DECL_INT32_ACCESSORS(pretenure_data)

  DECL_INT32_ACCESSORS(pretenure_create_count)
57
  DECL_ACCESSORS(dependent_code, DependentCode)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

  // heap->allocation_site_list() points to the last AllocationSite which form
  // a linked list through the weak_next property. The GC might remove elements
  // from the list by updateing weak_next.
  DECL_ACCESSORS(weak_next, Object)

  inline void Initialize();

  // Checks if the allocation site contain weak_next field;
  inline bool HasWeakNext() const;

  // This method is expensive, it should only be called for reporting.
  bool IsNested();

  // transition_info bitfields, for constructed array transition info.
73 74 75
  using ElementsKindBits = base::BitField<ElementsKind, 0, 6>;
  using DoNotInlineBit = base::BitField<bool, 6, 1>;
  // Unused bits 7-30.
76 77

  // Bitfields for pretenure_data
78 79 80
  using MementoFoundCountBits = base::BitField<int, 0, 26>;
  using PretenureDecisionBits = base::BitField<PretenureDecision, 26, 3>;
  using DeoptDependentCodeBit = base::BitField<bool, 29, 1>;
81 82 83 84 85 86 87 88
  STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue);

  // Increments the mementos found counter and returns true when the first
  // memento was found for a given allocation site.
  inline bool IncrementMementoFoundCount(int increment = 1);

  inline void IncrementMementoCreateCount();

89
  AllocationType GetAllocationType() const;
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

  void ResetPretenureDecision();

  inline PretenureDecision pretenure_decision() const;
  inline void set_pretenure_decision(PretenureDecision decision);

  inline bool deopt_dependent_code() const;
  inline void set_deopt_dependent_code(bool deopt);

  inline int memento_found_count() const;
  inline void set_memento_found_count(int count);

  inline int memento_create_count() const;
  inline void set_memento_create_count(int count);

105 106 107 108 109 110 111 112
  // A "zombie" AllocationSite is one which has no more strong roots to
  // it, and yet must be maintained until the next GC. The reason is that
  // it may be that in new space there are AllocationMementos hanging around
  // which point to the AllocationSite. If we scavenge these AllocationSites
  // too soon, those AllocationMementos will end up pointing to garbage
  // addresses. The garbage collector marks such AllocationSites as zombies
  // when it discovers there are no roots, allowing the subsequent collection
  // pass to recognize zombies and discard them later.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
  inline bool IsZombie() const;

  inline bool IsMaybeTenure() const;

  inline void MarkZombie();

  inline bool MakePretenureDecision(PretenureDecision current_decision,
                                    double ratio, bool maximum_size_scavenge);

  inline bool DigestPretenuringFeedback(bool maximum_size_scavenge);

  inline ElementsKind GetElementsKind() const;
  inline void SetElementsKind(ElementsKind kind);

  inline bool CanInlineCall() const;
  inline void SetDoNotInlineCall();

  inline bool PointsToLiteral() const;

  template <AllocationSiteUpdateMode update_or_check =
                AllocationSiteUpdateMode::kUpdate>
  static bool DigestTransitionFeedback(Handle<AllocationSite> site,
                                       ElementsKind to_kind);

  DECL_PRINTER(AllocationSite)
  DECL_VERIFIER(AllocationSite)

140
  DECL_CAST(AllocationSite)
141 142 143 144
  static inline bool ShouldTrack(ElementsKind boilerplate_elements_kind);
  static bool ShouldTrack(ElementsKind from, ElementsKind to);
  static inline bool CanTrack(InstanceType type);

Irina Yatsenko's avatar
Irina Yatsenko committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
  // Layout description.
  // AllocationSite has to start with TransitionInfoOrboilerPlateOffset
  // and end with WeakNext field.
  #define ALLOCATION_SITE_FIELDS(V)                     \
    V(kStartOffset, 0)                                  \
    V(kTransitionInfoOrBoilerplateOffset, kTaggedSize)  \
    V(kNestedSiteOffset, kTaggedSize)                   \
    V(kDependentCodeOffset, kTaggedSize)                \
    V(kCommonPointerFieldEndOffset, 0)                  \
    V(kPretenureDataOffset, kInt32Size)                 \
    V(kPretenureCreateCountOffset, kInt32Size)          \
    /* Size of AllocationSite without WeakNext field */ \
    V(kSizeWithoutWeakNext, 0)                          \
    V(kWeakNextOffset, kTaggedSize)                     \
    /* Size of AllocationSite with WeakNext field */    \
    V(kSizeWithWeakNext, 0)
161 162

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, ALLOCATION_SITE_FIELDS)
Irina Yatsenko's avatar
Irina Yatsenko committed
163
  #undef ALLOCATION_SITE_FIELDS
164

165
  class BodyDescriptor;
166 167 168 169

 private:
  inline bool PretenuringDecisionMade() const;

170
  OBJECT_CONSTRUCTORS(AllocationSite, Struct);
171 172
};

173 174
class AllocationMemento
    : public TorqueGeneratedAllocationMemento<AllocationMemento, Struct> {
175 176 177 178
 public:
  DECL_ACCESSORS(allocation_site, Object)

  inline bool IsValid() const;
179
  inline AllocationSite GetAllocationSite() const;
180 181 182 183
  inline Address GetAllocationSiteUnchecked() const;

  DECL_PRINTER(AllocationMemento)

184
  TQ_OBJECT_CONSTRUCTORS(AllocationMemento)
185 186 187 188 189 190 191 192
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_ALLOCATION_SITE_H_