v8  9.4.146 (node 16.13.0)
V8 is Google's open source JavaScript engine
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
allocation.h
Go to the documentation of this file.
1 // Copyright 2020 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 INCLUDE_CPPGC_ALLOCATION_H_
6 #define INCLUDE_CPPGC_ALLOCATION_H_
7 
8 #include <atomic>
9 #include <cstddef>
10 #include <cstdint>
11 #include <new>
12 #include <type_traits>
13 #include <utility>
14 
15 #include "cppgc/custom-space.h"
16 #include "cppgc/internal/api-constants.h"
17 #include "cppgc/internal/gc-info.h"
18 #include "cppgc/type-traits.h"
19 #include "v8config.h" // NOLINT(build/include_directory)
20 
21 namespace cppgc {
22 
23 /**
24  * AllocationHandle is used to allocate garbage-collected objects.
25  */
26 class AllocationHandle;
27 
28 namespace internal {
29 
31  protected:
32  static inline void MarkObjectAsFullyConstructed(const void* payload) {
33  // See api_constants for an explanation of the constants.
34  std::atomic<uint16_t>* atomic_mutable_bitfield =
35  reinterpret_cast<std::atomic<uint16_t>*>(
36  const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
37  reinterpret_cast<const uint8_t*>(payload) -
38  api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
39  atomic_mutable_bitfield->fetch_or(api_constants::kFullyConstructedBitMask,
40  std::memory_order_release);
41  }
42 
43  template <typename U, typename CustomSpace>
44  struct SpacePolicy {
45  static void* Allocate(AllocationHandle& handle, size_t size) {
46  // Custom space.
47  static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
48  "Custom space must inherit from CustomSpaceBase.");
49  return MakeGarbageCollectedTraitInternal::Allocate(
50  handle, size, internal::GCInfoTrait<U>::Index(),
51  CustomSpace::kSpaceIndex);
52  }
53  };
54 
55  template <typename U>
56  struct SpacePolicy<U, void> {
57  static void* Allocate(AllocationHandle& handle, size_t size) {
58  // Default space.
59  return MakeGarbageCollectedTraitInternal::Allocate(
60  handle, size, internal::GCInfoTrait<U>::Index());
61  }
62  };
63 
64  private:
65  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
66  GCInfoIndex index);
67  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
68  GCInfoIndex index, CustomSpaceIndex space_index);
69 
70  friend class HeapObjectHeader;
71 };
72 
73 } // namespace internal
74 
75 /**
76  * Base trait that provides utilities for advancers users that have custom
77  * allocation needs (e.g., overriding size). It's expected that users override
78  * MakeGarbageCollectedTrait (see below) and inherit from
79  * MakeGarbageCollectedTraitBase and make use of the low-level primitives
80  * offered to allocate and construct an object.
81  */
82 template <typename T>
85  private:
86  static_assert(internal::IsGarbageCollectedType<T>::value,
87  "T needs to be a garbage collected object");
88  static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
89  sizeof(T) <=
90  internal::api_constants::kLargeObjectSizeThreshold,
91  "GarbageCollectedMixin may not be a large object");
92 
93  protected:
94  /**
95  * Allocates memory for an object of type T.
96  *
97  * \param handle AllocationHandle identifying the heap to allocate the object
98  * on.
99  * \param size The size that should be reserved for the object.
100  * \returns the memory to construct an object of type T on.
101  */
102  V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
103  static_assert(
104  std::is_base_of<typename T::ParentMostGarbageCollectedType, T>::value,
105  "U of GarbageCollected<U> must be a base of T. Check "
106  "GarbageCollected<T> base class inheritance.");
107  return SpacePolicy<
108  typename internal::GCInfoFolding<
109  T, typename T::ParentMostGarbageCollectedType>::ResultType,
110  typename SpaceTrait<T>::Space>::Allocate(handle, size);
111  }
112 
113  /**
114  * Marks an object as fully constructed, resulting in precise handling by the
115  * garbage collector.
116  *
117  * \param payload The base pointer the object is allocated at.
118  */
119  V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
121  payload);
122  }
123 };
124 
125 /**
126  * Passed to MakeGarbageCollected to specify how many bytes should be appended
127  * to the allocated object.
128  *
129  * Example:
130  * \code
131  * class InlinedArray final : public GarbageCollected<InlinedArray> {
132  * public:
133  * explicit InlinedArray(size_t bytes) : size(bytes), byte_array(this + 1) {}
134  * void Trace(Visitor*) const {}
135 
136  * size_t size;
137  * char* byte_array;
138  * };
139  *
140  * auto* inlined_array = MakeGarbageCollected<InlinedArray(
141  * GetAllocationHandle(), AdditionalBytes(4), 4);
142  * for (size_t i = 0; i < 4; i++) {
143  * Process(inlined_array->byte_array[i]);
144  * }
145  * \endcode
146  */
148  constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
149  const size_t value;
150 };
151 
152 /**
153  * Default trait class that specifies how to construct an object of type T.
154  * Advanced users may override how an object is constructed using the utilities
155  * that are provided through MakeGarbageCollectedTraitBase.
156  *
157  * Any trait overriding construction must
158  * - allocate through `MakeGarbageCollectedTraitBase<T>::Allocate`;
159  * - mark the object as fully constructed using
160  * `MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed`;
161  */
162 template <typename T>
164  public:
165  template <typename... Args>
166  static T* Call(AllocationHandle& handle, Args&&... args) {
167  void* memory =
168  MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
169  T* object = ::new (memory) T(std::forward<Args>(args)...);
170  MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
171  return object;
172  }
173 
174  template <typename... Args>
175  static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
176  Args&&... args) {
177  void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(
178  handle, sizeof(T) + additional_bytes.value);
179  T* object = ::new (memory) T(std::forward<Args>(args)...);
180  MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
181  return object;
182  }
183 };
184 
185 /**
186  * Allows users to specify a post-construction callback for specific types. The
187  * callback is invoked on the instance of type T right after it has been
188  * constructed. This can be useful when the callback requires a
189  * fully-constructed object to be able to dispatch to virtual methods.
190  */
191 template <typename T, typename = void>
193  static void Call(T*) {}
194 };
195 
196 /**
197  * Constructs a managed object of type T where T transitively inherits from
198  * GarbageCollected.
199  *
200  * \param args List of arguments with which an instance of T will be
201  * constructed.
202  * \returns an instance of type T.
203  */
204 template <typename T, typename... Args>
205 T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
206  T* object =
207  MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
208  PostConstructionCallbackTrait<T>::Call(object);
209  return object;
210 }
211 
212 /**
213  * Constructs a managed object of type T where T transitively inherits from
214  * GarbageCollected. Created objects will have additional bytes appended to
215  * it. Allocated memory would suffice for `sizeof(T) + additional_bytes`.
216  *
217  * \param additional_bytes Denotes how many bytes to append to T.
218  * \param args List of arguments with which an instance of T will be
219  * constructed.
220  * \returns an instance of type T.
221  */
222 template <typename T, typename... Args>
223 T* MakeGarbageCollected(AllocationHandle& handle,
224  AdditionalBytes additional_bytes, Args&&... args) {
225  T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
226  std::forward<Args>(args)...);
227  PostConstructionCallbackTrait<T>::Call(object);
228  return object;
229 }
230 
231 } // namespace cppgc
232 
233 #endif // INCLUDE_CPPGC_ALLOCATION_H_