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
47using AlignVal = std::align_val_t;
48
50 protected:
51 static inline void MarkObjectAsFullyConstructed(const void* payload) {
52 // See api_constants for an explanation of the constants.
53 std::atomic_ref<uint16_t> atomic_mutable_bitfield(
54 *const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
55 reinterpret_cast<const uint8_t*>(payload) -
56 api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
57 // It's safe to split use load+store here (instead of a read-modify-write
58 // operation), since it's guaranteed that this 16-bit bitfield is only
59 // modified by a single thread. This is cheaper in terms of code bloat (on
60 // ARM) and performance.
61 uint16_t value = atomic_mutable_bitfield.load(std::memory_order_relaxed);
62 value |= api_constants::kFullyConstructedBitMask;
63 atomic_mutable_bitfield.store(value, std::memory_order_release);
64 }
65
66 // Dispatch based on compile-time information.
67 //
68 // Default implementation is for a custom space with >`kDefaultAlignment` byte
69 // alignment.
70 template <typename GCInfoType, typename CustomSpace, size_t alignment>
71 struct AllocationDispatcher final {
72 static void* Invoke(AllocationHandle& handle, size_t size) {
73 static_assert(std::is_base_of_v<CustomSpaceBase, CustomSpace>,
74 "Custom space must inherit from CustomSpaceBase.");
75 static_assert(
77 "Custom spaces that support compaction do not support allocating "
78 "objects with non-default (i.e. word-sized) alignment.");
79 return MakeGarbageCollectedTraitInternal::Allocate(
80 handle, size, static_cast<AlignVal>(alignment),
81 internal::GCInfoTrait<GCInfoType>::Index(), CustomSpace::kSpaceIndex);
82 }
83 };
84
85 // Fast path for regular allocations for the default space with
86 // `kDefaultAlignment` byte alignment.
87 template <typename GCInfoType>
88 struct AllocationDispatcher<GCInfoType, void,
89 api_constants::kDefaultAlignment>
90 final {
91 static void* Invoke(AllocationHandle& handle, size_t size) {
92 return MakeGarbageCollectedTraitInternal::Allocate(
94 }
95 };
96
97 // Default space with >`kDefaultAlignment` byte alignment.
98 template <typename GCInfoType, size_t alignment>
99 struct AllocationDispatcher<GCInfoType, void, alignment> final {
100 static void* Invoke(AllocationHandle& handle, size_t size) {
101 return MakeGarbageCollectedTraitInternal::Allocate(
102 handle, size, static_cast<AlignVal>(alignment),
104 }
105 };
106
107 // Custom space with `kDefaultAlignment` byte alignment.
108 template <typename GCInfoType, typename CustomSpace>
110 api_constants::kDefaultAlignment>
111 final {
112 static void* Invoke(AllocationHandle& handle, size_t size) {
113 static_assert(std::is_base_of_v<CustomSpaceBase, CustomSpace>,
114 "Custom space must inherit from CustomSpaceBase.");
115 return MakeGarbageCollectedTraitInternal::Allocate(
117 CustomSpace::kSpaceIndex);
118 }
119 };
120
121 private:
123 Allocate(cppgc::AllocationHandle&, size_t, GCInfoIndex);
125 Allocate(cppgc::AllocationHandle&, size_t, AlignVal, GCInfoIndex);
127 Allocate(cppgc::AllocationHandle&, size_t, GCInfoIndex, CustomSpaceIndex);
129 Allocate(cppgc::AllocationHandle&, size_t, AlignVal, GCInfoIndex,
131
132 friend class HeapObjectHeader;
133};
134
135} // namespace internal
136
144template <typename T>
147 private:
149 "T needs to be a garbage collected object");
150 static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
151 sizeof(T) <=
152 internal::api_constants::kLargeObjectSizeThreshold,
153 "GarbageCollectedMixin may not be a large object");
154
155 protected:
164 V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
165 static_assert(
166 std::is_base_of_v<typename T::ParentMostGarbageCollectedType, T>,
167 "U of GarbageCollected<U> must be a base of T. Check "
168 "GarbageCollected<T> base class inheritance.");
169 static constexpr size_t kWantedAlignment =
170 alignof(T) < internal::api_constants::kDefaultAlignment
171 ? internal::api_constants::kDefaultAlignment
172 : alignof(T);
173 static_assert(
174 kWantedAlignment <= internal::api_constants::kMaxSupportedAlignment,
175 "Requested alignment larger than alignof(std::max_align_t) bytes. "
176 "Please file a bug to possibly get this restriction lifted.");
179 T, typename T::ParentMostGarbageCollectedType>::ResultType,
180 typename SpaceTrait<T>::Space, kWantedAlignment>::Invoke(handle, size);
181 }
182
189 V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
191 payload);
192 }
193};
194
218 constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
219 const size_t value;
220};
221
232template <typename T>
234 public:
235 template <typename... Args>
236 static T* Call(AllocationHandle& handle, Args&&... args) {
237 void* memory =
239 T* object = ::new (memory) T(std::forward<Args>(args)...);
241 return object;
242 }
243
244 template <typename... Args>
245 static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
246 Args&&... args) {
248 handle, sizeof(T) + additional_bytes.value);
249 T* object = ::new (memory) T(std::forward<Args>(args)...);
251 return object;
252 }
253};
254
261template <typename T, typename = void>
263 static void Call(T*) {}
264};
265
274template <typename T, typename... Args>
275V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
276 T* object =
277 MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
279 return object;
280}
281
292template <typename T, typename... Args>
293V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
294 AdditionalBytes additional_bytes,
295 Args&&... args) {
296 T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
297 std::forward<Args>(args)...);
299 return object;
300}
301
302} // namespace cppgc
303
304#undef CPPGC_DEFAULT_ALIGNED
305#undef CPPGC_DOUBLE_WORD_ALIGNED
306
307#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:146
static void * Allocate(AllocationHandle &handle, size_t size)
Definition: allocation.h:164
static void MarkObjectAsFullyConstructed(const void *payload)
Definition: allocation.h:189
Definition: allocation.h:233
static T * Call(AllocationHandle &handle, Args &&... args)
Definition: allocation.h:236
static T * Call(AllocationHandle &handle, AdditionalBytes additional_bytes, Args &&... args)
Definition: allocation.h:245
friend class HeapObjectHeader
Definition: allocation.h:132
static void MarkObjectAsFullyConstructed(const void *payload)
Definition: allocation.h:51
uint16_t GCInfoIndex
Definition: gc-info.h:21
std::align_val_t AlignVal
Definition: allocation.h:47
Definition: allocation.h:38
T * MakeGarbageCollected(AllocationHandle &handle, Args &&... args)
Definition: allocation.h:275
Definition: allocation.h:217
constexpr AdditionalBytes(size_t bytes)
Definition: allocation.h:218
const size_t value
Definition: allocation.h:219
Definition: custom-space.h:15
Definition: allocation.h:262
static void Call(T *)
Definition: allocation.h:263
void Space
Definition: custom-space.h:70
Definition: gc-info.h:109
Definition: gc-info.h:83
Definition: type-traits.h:99
static void * Invoke(AllocationHandle &handle, size_t size)
Definition: allocation.h:100
static void * Invoke(AllocationHandle &handle, size_t size)
Definition: allocation.h:72
#define V8_EXPORT
Definition: v8config.h:855
#define V8_INLINE
Definition: v8config.h:508