Loading...
Searching...
No Matches
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"
18#include "cppgc/type-traits.h"
19#include "v8config.h" // NOLINT(build/include_directory)
20
21#if defined(__has_attribute)
22#if __has_attribute(assume_aligned)
23#define CPPGC_DEFAULT_ALIGNED \
24 __attribute__((assume_aligned(api_constants::kDefaultAlignment)))
25#define CPPGC_DOUBLE_WORD_ALIGNED \
26 __attribute__((assume_aligned(2 * api_constants::kDefaultAlignment)))
27#endif // __has_attribute(assume_aligned)
28#endif // defined(__has_attribute)
29
30#if !defined(CPPGC_DEFAULT_ALIGNED)
31#define CPPGC_DEFAULT_ALIGNED
32#endif
33
34#if !defined(CPPGC_DOUBLE_WORD_ALIGNED)
35#define CPPGC_DOUBLE_WORD_ALIGNED
36#endif
37
38namespace cppgc {
39
43class AllocationHandle;
44
45namespace internal {
46
47// Similar to C++17 std::align_val_t;
48enum class AlignVal : size_t {};
49
51 protected:
52 static inline void MarkObjectAsFullyConstructed(const void* payload) {
53 // See api_constants for an explanation of the constants.
54 std::atomic<uint16_t>* atomic_mutable_bitfield =
55 reinterpret_cast<std::atomic<uint16_t>*>(
56 const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
57 reinterpret_cast<const uint8_t*>(payload) -
58 api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
59 // It's safe to split use load+store here (instead of a read-modify-write
60 // operation), since it's guaranteed that this 16-bit bitfield is only
61 // modified by a single thread. This is cheaper in terms of code bloat (on
62 // ARM) and performance.
63 uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
64 value |= api_constants::kFullyConstructedBitMask;
65 atomic_mutable_bitfield->store(value, std::memory_order_release);
66 }
67
68 // Dispatch based on compile-time information.
69 //
70 // Default implementation is for a custom space with >`kDefaultAlignment` byte
71 // alignment.
72 template <typename GCInfoType, typename CustomSpace, size_t alignment>
73 struct AllocationDispatcher final {
74 static void* Invoke(AllocationHandle& handle, size_t size) {
75 static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
76 "Custom space must inherit from CustomSpaceBase.");
77 static_assert(
79 "Custom spaces that support compaction do not support allocating "
80 "objects with non-default (i.e. word-sized) alignment.");
81 return MakeGarbageCollectedTraitInternal::Allocate(
82 handle, size, static_cast<AlignVal>(alignment),
83 internal::GCInfoTrait<GCInfoType>::Index(), CustomSpace::kSpaceIndex);
84 }
85 };
86
87 // Fast path for regular allocations for the default space with
88 // `kDefaultAlignment` byte alignment.
89 template <typename GCInfoType>
90 struct AllocationDispatcher<GCInfoType, void,
91 api_constants::kDefaultAlignment>
92 final {
93 static void* Invoke(AllocationHandle& handle, size_t size) {
94 return MakeGarbageCollectedTraitInternal::Allocate(
96 }
97 };
98
99 // Default space with >`kDefaultAlignment` byte alignment.
100 template <typename GCInfoType, size_t alignment>
101 struct AllocationDispatcher<GCInfoType, void, alignment> final {
102 static void* Invoke(AllocationHandle& handle, size_t size) {
103 return MakeGarbageCollectedTraitInternal::Allocate(
104 handle, size, static_cast<AlignVal>(alignment),
106 }
107 };
108
109 // Custom space with `kDefaultAlignment` byte alignment.
110 template <typename GCInfoType, typename CustomSpace>
112 api_constants::kDefaultAlignment>
113 final {
114 static void* Invoke(AllocationHandle& handle, size_t size) {
115 static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
116 "Custom space must inherit from CustomSpaceBase.");
117 return MakeGarbageCollectedTraitInternal::Allocate(
119 CustomSpace::kSpaceIndex);
120 }
121 };
122
123 private:
125 Allocate(cppgc::AllocationHandle&, size_t, GCInfoIndex);
127 Allocate(cppgc::AllocationHandle&, size_t, AlignVal, GCInfoIndex);
129 Allocate(cppgc::AllocationHandle&, size_t, GCInfoIndex, CustomSpaceIndex);
131 Allocate(cppgc::AllocationHandle&, size_t, AlignVal, GCInfoIndex,
133
134 friend class HeapObjectHeader;
135};
136
137} // namespace internal
138
146template <typename T>
149 private:
151 "T needs to be a garbage collected object");
152 static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
153 sizeof(T) <=
154 internal::api_constants::kLargeObjectSizeThreshold,
155 "GarbageCollectedMixin may not be a large object");
156
157 protected:
166 V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
167 static_assert(
168 std::is_base_of<typename T::ParentMostGarbageCollectedType, T>::value,
169 "U of GarbageCollected<U> must be a base of T. Check "
170 "GarbageCollected<T> base class inheritance.");
171 static constexpr size_t kWantedAlignment =
172 alignof(T) < internal::api_constants::kDefaultAlignment
173 ? internal::api_constants::kDefaultAlignment
174 : alignof(T);
175 static_assert(
176 kWantedAlignment <= internal::api_constants::kMaxSupportedAlignment,
177 "Requested alignment larger than alignof(std::max_align_t) bytes. "
178 "Please file a bug to possibly get this restriction lifted.");
181 T, typename T::ParentMostGarbageCollectedType>::ResultType,
182 typename SpaceTrait<T>::Space, kWantedAlignment>::Invoke(handle, size);
183 }
184
191 V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
193 payload);
194 }
195};
196
220 constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
221 const size_t value;
222};
223
234template <typename T>
236 public:
237 template <typename... Args>
238 static T* Call(AllocationHandle& handle, Args&&... args) {
239 void* memory =
241 T* object = ::new (memory) T(std::forward<Args>(args)...);
243 return object;
244 }
245
246 template <typename... Args>
247 static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
248 Args&&... args) {
250 handle, sizeof(T) + additional_bytes.value);
251 T* object = ::new (memory) T(std::forward<Args>(args)...);
253 return object;
254 }
255};
256
263template <typename T, typename = void>
265 static void Call(T*) {}
266};
267
276template <typename T, typename... Args>
277V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
278 T* object =
279 MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
281 return object;
282}
283
294template <typename T, typename... Args>
295V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
296 AdditionalBytes additional_bytes,
297 Args&&... args) {
298 T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
299 std::forward<Args>(args)...);
301 return object;
302}
303
304} // namespace cppgc
305
306#undef CPPGC_DEFAULT_ALIGNED
307#undef CPPGC_DOUBLE_WORD_ALIGNED
308
309#endif // INCLUDE_CPPGC_ALLOCATION_H_
#define CPPGC_DEFAULT_ALIGNED
Definition: allocation.h:31
#define CPPGC_DOUBLE_WORD_ALIGNED
Definition: allocation.h:35
Definition: custom-space.h:49
static constexpr bool kSupportsCompaction
Definition: custom-space.h:55
Definition: allocation.h:148
static void * Allocate(AllocationHandle &handle, size_t size)
Definition: allocation.h:166
static void MarkObjectAsFullyConstructed(const void *payload)
Definition: allocation.h:191
Definition: allocation.h:235
static T * Call(AllocationHandle &handle, Args &&... args)
Definition: allocation.h:238
static T * Call(AllocationHandle &handle, AdditionalBytes additional_bytes, Args &&... args)
Definition: allocation.h:247
friend class HeapObjectHeader
Definition: allocation.h:134
static void MarkObjectAsFullyConstructed(const void *payload)
Definition: allocation.h:52
uint16_t GCInfoIndex
Definition: gc-info.h:21
AlignVal
Definition: allocation.h:48
Definition: allocation.h:38
T * MakeGarbageCollected(AllocationHandle &handle, Args &&... args)
Definition: allocation.h:277
Definition: allocation.h:219
constexpr AdditionalBytes(size_t bytes)
Definition: allocation.h:220
const size_t value
Definition: allocation.h:221
Definition: custom-space.h:15
Definition: allocation.h:264
static void Call(T *)
Definition: allocation.h:265
void Space
Definition: custom-space.h:70
Definition: gc-info.h:109
Definition: gc-info.h:83
Definition: type-traits.h:98
static void * Invoke(AllocationHandle &handle, size_t size)
Definition: allocation.h:102
static void * Invoke(AllocationHandle &handle, size_t size)
Definition: allocation.h:74
#define V8_EXPORT
Definition: v8config.h:793
#define V8_INLINE
Definition: v8config.h:499