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