File indexing completed on 2025-04-02 08:54:42
0001
0002
0003
0004
0005 #ifndef INCLUDE_CPPGC_ALLOCATION_H_
0006 #define INCLUDE_CPPGC_ALLOCATION_H_
0007
0008 #include <atomic>
0009 #include <cstddef>
0010 #include <cstdint>
0011 #include <new>
0012 #include <type_traits>
0013 #include <utility>
0014
0015 #include "cppgc/custom-space.h"
0016 #include "cppgc/internal/api-constants.h"
0017 #include "cppgc/internal/gc-info.h"
0018 #include "cppgc/type-traits.h"
0019 #include "v8config.h" // NOLINT(build/include_directory)
0020
0021 #if defined(__has_attribute)
0022 #if __has_attribute(assume_aligned)
0023 #define CPPGC_DEFAULT_ALIGNED \
0024 __attribute__((assume_aligned(api_constants::kDefaultAlignment)))
0025 #define CPPGC_DOUBLE_WORD_ALIGNED \
0026 __attribute__((assume_aligned(2 * api_constants::kDefaultAlignment)))
0027 #endif
0028 #endif
0029
0030 #if !defined(CPPGC_DEFAULT_ALIGNED)
0031 #define CPPGC_DEFAULT_ALIGNED
0032 #endif
0033
0034 #if !defined(CPPGC_DOUBLE_WORD_ALIGNED)
0035 #define CPPGC_DOUBLE_WORD_ALIGNED
0036 #endif
0037
0038 namespace cppgc {
0039
0040
0041
0042
0043 class AllocationHandle;
0044
0045 namespace internal {
0046
0047
0048 enum class AlignVal : size_t {};
0049
0050 class V8_EXPORT MakeGarbageCollectedTraitInternal {
0051 protected:
0052 static inline void MarkObjectAsFullyConstructed(const void* payload) {
0053
0054 std::atomic<uint16_t>* atomic_mutable_bitfield =
0055 reinterpret_cast<std::atomic<uint16_t>*>(
0056 const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
0057 reinterpret_cast<const uint8_t*>(payload) -
0058 api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
0059
0060
0061
0062
0063 uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
0064 value |= api_constants::kFullyConstructedBitMask;
0065 atomic_mutable_bitfield->store(value, std::memory_order_release);
0066 }
0067
0068
0069
0070
0071
0072 template <typename GCInfoType, typename CustomSpace, size_t alignment>
0073 struct AllocationDispatcher final {
0074 static void* Invoke(AllocationHandle& handle, size_t size) {
0075 static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
0076 "Custom space must inherit from CustomSpaceBase.");
0077 static_assert(
0078 !CustomSpace::kSupportsCompaction,
0079 "Custom spaces that support compaction do not support allocating "
0080 "objects with non-default (i.e. word-sized) alignment.");
0081 return MakeGarbageCollectedTraitInternal::Allocate(
0082 handle, size, static_cast<AlignVal>(alignment),
0083 internal::GCInfoTrait<GCInfoType>::Index(), CustomSpace::kSpaceIndex);
0084 }
0085 };
0086
0087
0088
0089 template <typename GCInfoType>
0090 struct AllocationDispatcher<GCInfoType, void,
0091 api_constants::kDefaultAlignment>
0092 final {
0093 static void* Invoke(AllocationHandle& handle, size_t size) {
0094 return MakeGarbageCollectedTraitInternal::Allocate(
0095 handle, size, internal::GCInfoTrait<GCInfoType>::Index());
0096 }
0097 };
0098
0099
0100 template <typename GCInfoType, size_t alignment>
0101 struct AllocationDispatcher<GCInfoType, void, alignment> final {
0102 static void* Invoke(AllocationHandle& handle, size_t size) {
0103 return MakeGarbageCollectedTraitInternal::Allocate(
0104 handle, size, static_cast<AlignVal>(alignment),
0105 internal::GCInfoTrait<GCInfoType>::Index());
0106 }
0107 };
0108
0109
0110 template <typename GCInfoType, typename CustomSpace>
0111 struct AllocationDispatcher<GCInfoType, CustomSpace,
0112 api_constants::kDefaultAlignment>
0113 final {
0114 static void* Invoke(AllocationHandle& handle, size_t size) {
0115 static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
0116 "Custom space must inherit from CustomSpaceBase.");
0117 return MakeGarbageCollectedTraitInternal::Allocate(
0118 handle, size, internal::GCInfoTrait<GCInfoType>::Index(),
0119 CustomSpace::kSpaceIndex);
0120 }
0121 };
0122
0123 private:
0124 static void* CPPGC_DEFAULT_ALIGNED Allocate(cppgc::AllocationHandle&, size_t,
0125 GCInfoIndex);
0126 static void* CPPGC_DOUBLE_WORD_ALIGNED Allocate(cppgc::AllocationHandle&,
0127 size_t, AlignVal,
0128 GCInfoIndex);
0129 static void* CPPGC_DEFAULT_ALIGNED Allocate(cppgc::AllocationHandle&, size_t,
0130 GCInfoIndex, CustomSpaceIndex);
0131 static void* CPPGC_DOUBLE_WORD_ALIGNED Allocate(cppgc::AllocationHandle&,
0132 size_t, AlignVal, GCInfoIndex,
0133 CustomSpaceIndex);
0134
0135 friend class HeapObjectHeader;
0136 };
0137
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147 template <typename T>
0148 class MakeGarbageCollectedTraitBase
0149 : private internal::MakeGarbageCollectedTraitInternal {
0150 private:
0151 static_assert(internal::IsGarbageCollectedType<T>::value,
0152 "T needs to be a garbage collected object");
0153 static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
0154 sizeof(T) <=
0155 internal::api_constants::kLargeObjectSizeThreshold,
0156 "GarbageCollectedMixin may not be a large object");
0157
0158 protected:
0159
0160
0161
0162
0163
0164
0165
0166
0167 V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
0168 static_assert(
0169 std::is_base_of<typename T::ParentMostGarbageCollectedType, T>::value,
0170 "U of GarbageCollected<U> must be a base of T. Check "
0171 "GarbageCollected<T> base class inheritance.");
0172 static constexpr size_t kWantedAlignment =
0173 alignof(T) < internal::api_constants::kDefaultAlignment
0174 ? internal::api_constants::kDefaultAlignment
0175 : alignof(T);
0176 static_assert(
0177 kWantedAlignment <= internal::api_constants::kMaxSupportedAlignment,
0178 "Requested alignment larger than alignof(std::max_align_t) bytes. "
0179 "Please file a bug to possibly get this restriction lifted.");
0180 return AllocationDispatcher<
0181 typename internal::GCInfoFolding<
0182 T, typename T::ParentMostGarbageCollectedType>::ResultType,
0183 typename SpaceTrait<T>::Space, kWantedAlignment>::Invoke(handle, size);
0184 }
0185
0186
0187
0188
0189
0190
0191
0192 V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
0193 internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
0194 payload);
0195 }
0196 };
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 struct AdditionalBytes {
0221 constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
0222 const size_t value;
0223 };
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 template <typename T>
0236 class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
0237 public:
0238 template <typename... Args>
0239 static T* Call(AllocationHandle& handle, Args&&... args) {
0240 void* memory =
0241 MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
0242 T* object = ::new (memory) T(std::forward<Args>(args)...);
0243 MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
0244 return object;
0245 }
0246
0247 template <typename... Args>
0248 static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
0249 Args&&... args) {
0250 void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(
0251 handle, sizeof(T) + additional_bytes.value);
0252 T* object = ::new (memory) T(std::forward<Args>(args)...);
0253 MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
0254 return object;
0255 }
0256 };
0257
0258
0259
0260
0261
0262
0263
0264 template <typename T, typename = void>
0265 struct PostConstructionCallbackTrait {
0266 static void Call(T*) {}
0267 };
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 template <typename T, typename... Args>
0278 V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
0279 T* object =
0280 MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
0281 PostConstructionCallbackTrait<T>::Call(object);
0282 return object;
0283 }
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 template <typename T, typename... Args>
0296 V8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
0297 AdditionalBytes additional_bytes,
0298 Args&&... args) {
0299 T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
0300 std::forward<Args>(args)...);
0301 PostConstructionCallbackTrait<T>::Call(object);
0302 return object;
0303 }
0304
0305 }
0306
0307 #undef CPPGC_DEFAULT_ALIGNED
0308 #undef CPPGC_DOUBLE_WORD_ALIGNED
0309
0310 #endif