File indexing completed on 2025-02-23 10:08:50
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 bool 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 return true;
0103 }
0104 };
0105
0106
0107
0108
0109 template <typename T, typename ParentMostGarbageCollectedType>
0110 struct GCInfoFolding final {
0111 static constexpr bool kHasVirtualDestructorAtBase =
0112 std::has_virtual_destructor<ParentMostGarbageCollectedType>::value;
0113 static constexpr bool kBothTypesAreTriviallyDestructible =
0114 std::is_trivially_destructible<ParentMostGarbageCollectedType>::value &&
0115 std::is_trivially_destructible<T>::value;
0116 static constexpr bool kHasCustomFinalizerDispatchAtBase =
0117 internal::HasFinalizeGarbageCollectedObject<
0118 ParentMostGarbageCollectedType>::value;
0119 #ifdef CPPGC_SUPPORTS_OBJECT_NAMES
0120 static constexpr bool kWantsDetailedObjectNames = true;
0121 #else
0122 static constexpr bool kWantsDetailedObjectNames = false;
0123 #endif
0124
0125
0126
0127
0128
0129
0130 static constexpr bool kCheckTypeGuardAlwaysTrue =
0131 GCInfoTrait<T>::CheckCallbacksAreDefined() &&
0132 GCInfoTrait<ParentMostGarbageCollectedType>::CheckCallbacksAreDefined();
0133
0134
0135
0136 using ResultType =
0137 std::conditional_t<kCheckTypeGuardAlwaysTrue &&
0138 (kHasVirtualDestructorAtBase ||
0139 kBothTypesAreTriviallyDestructible ||
0140 kHasCustomFinalizerDispatchAtBase) &&
0141 !kWantsDetailedObjectNames,
0142 ParentMostGarbageCollectedType, T>;
0143 };
0144
0145 }
0146 }
0147
0148 #endif