File indexing completed on 2026-03-28 08:23:49
0001
0002
0003
0004
0005 #ifndef INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
0006 #define INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
0007
0008 #include <atomic>
0009 #include <cstdint>
0010 #include <type_traits>
0011
0012 #include "cppgc/internal/finalizer-trait.h"
0013 #include "cppgc/internal/logging.h"
0014 #include "cppgc/internal/name-trait.h"
0015 #include "cppgc/trace-trait.h"
0016 #include "v8config.h" // NOLINT(build/include_directory)
0017
0018 namespace cppgc {
0019 namespace internal {
0020
0021 using GCInfoIndex = uint16_t;
0022
0023 struct V8_EXPORT EnsureGCInfoIndexTrait final {
0024
0025
0026 template <typename T>
0027 V8_INLINE static GCInfoIndex EnsureIndex(
0028 std::atomic<GCInfoIndex>& registered_index) {
0029 return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
0030 }
0031
0032 private:
0033 template <typename T, bool = FinalizerTrait<T>::HasFinalizer(),
0034 bool = NameTrait<T>::HasNonHiddenName()>
0035 struct EnsureGCInfoIndexTraitDispatch;
0036
0037 static GCInfoIndex V8_PRESERVE_MOST
0038 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback,
0039 FinalizationCallback, NameCallback);
0040 static GCInfoIndex V8_PRESERVE_MOST EnsureGCInfoIndex(
0041 std::atomic<GCInfoIndex>&, TraceCallback, FinalizationCallback);
0042 static GCInfoIndex V8_PRESERVE_MOST
0043 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback, NameCallback);
0044 static GCInfoIndex V8_PRESERVE_MOST
0045 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback);
0046 };
0047
0048 #define DISPATCH(has_finalizer, has_non_hidden_name, function) \
0049 template <typename T> \
0050 struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch< \
0051 T, has_finalizer, has_non_hidden_name> { \
0052 V8_INLINE GCInfoIndex \
0053 operator()(std::atomic<GCInfoIndex>& registered_index) { \
0054 return function; \
0055 } \
0056 };
0057
0058
0059
0060
0061 DISPATCH(true, true,
0062 EnsureGCInfoIndex(registered_index,
0063 TraceTrait<T>::Trace,
0064 FinalizerTrait<T>::kCallback,
0065 NameTrait<T>::GetName))
0066 DISPATCH(true, false,
0067 EnsureGCInfoIndex(registered_index,
0068 TraceTrait<T>::Trace,
0069 FinalizerTrait<T>::kCallback))
0070 DISPATCH(false, true,
0071 EnsureGCInfoIndex(registered_index,
0072 TraceTrait<T>::Trace,
0073 NameTrait<T>::GetName))
0074 DISPATCH(false, false,
0075 EnsureGCInfoIndex(registered_index,
0076 TraceTrait<T>::Trace))
0077
0078 #undef DISPATCH
0079
0080
0081
0082 template <typename T>
0083 struct GCInfoTrait final {
0084 V8_INLINE static GCInfoIndex Index() {
0085 static_assert(sizeof(T), "T must be fully defined");
0086 static std::atomic<GCInfoIndex>
0087 registered_index;
0088 GCInfoIndex index = registered_index.load(std::memory_order_acquire);
0089 if (V8_UNLIKELY(!index)) {
0090 index = EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
0091 CPPGC_DCHECK(index != 0);
0092 CPPGC_DCHECK(index == registered_index.load(std::memory_order_acquire));
0093 }
0094 return index;
0095 }
0096
0097 static constexpr void CheckCallbacksAreDefined() {
0098
0099 (void)static_cast<TraceCallback>(TraceTrait<T>::Trace);
0100 (void)static_cast<FinalizationCallback>(FinalizerTrait<T>::kCallback);
0101 (void)static_cast<NameCallback>(NameTrait<T>::GetName);
0102 }
0103 };
0104
0105
0106
0107
0108 template <typename T, typename ParentMostGarbageCollectedType>
0109 struct GCInfoFolding final {
0110 static constexpr bool kHasVirtualDestructorAtBase =
0111 std::has_virtual_destructor<ParentMostGarbageCollectedType>::value;
0112 static constexpr bool kBothTypesAreTriviallyDestructible =
0113 std::is_trivially_destructible<ParentMostGarbageCollectedType>::value &&
0114 std::is_trivially_destructible<T>::value;
0115 static constexpr bool kHasCustomFinalizerDispatchAtBase =
0116 internal::HasFinalizeGarbageCollectedObject<
0117 ParentMostGarbageCollectedType>::value;
0118 #ifdef CPPGC_SUPPORTS_OBJECT_NAMES
0119 static constexpr bool kWantsDetailedObjectNames = true;
0120 #else
0121 static constexpr bool kWantsDetailedObjectNames = false;
0122 #endif
0123
0124
0125
0126
0127
0128
0129 static constexpr bool WantToFold() {
0130 if constexpr ((kHasVirtualDestructorAtBase ||
0131 kBothTypesAreTriviallyDestructible ||
0132 kHasCustomFinalizerDispatchAtBase) &&
0133 !kWantsDetailedObjectNames) {
0134 GCInfoTrait<T>::CheckCallbacksAreDefined();
0135 GCInfoTrait<ParentMostGarbageCollectedType>::CheckCallbacksAreDefined();
0136 return true;
0137 }
0138 return false;
0139 }
0140
0141
0142
0143 using ResultType =
0144 std::conditional_t<WantToFold(), ParentMostGarbageCollectedType, T>;
0145 };
0146
0147 }
0148 }
0149
0150 #endif