Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/deps/v8/include/cppgc/internal/gc-info.h
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_INTERNAL_GC_INFO_H_ 6 #define INCLUDE_CPPGC_INTERNAL_GC_INFO_H_ 7 8 #include <atomic> 9 #include <cstdint> 10 #include <type_traits> 11 12 #include "cppgc/internal/finalizer-trait.h" 13 #include "cppgc/internal/logging.h" 14 #include "cppgc/internal/name-trait.h" 15 #include "cppgc/trace-trait.h" 16 #include "v8config.h" // NOLINT(build/include_directory) 17 18 namespace cppgc { 19 namespace internal { 20 21 using GCInfoIndex = uint16_t; 22 23 struct V8_EXPORT EnsureGCInfoIndexTrait final { 24 // Acquires a new GC info object and updates `registered_index` with the index 25 // that identifies that new info accordingly. 26 template <typename T> 27 V8_INLINE static GCInfoIndex EnsureIndex( 28 std::atomic<GCInfoIndex>& registered_index) { 29 return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index); 30 } 31 32 private: 33 template <typename T, bool = FinalizerTrait<T>::HasFinalizer(), 34 bool = NameTrait<T>::HasNonHiddenName()> 35 struct EnsureGCInfoIndexTraitDispatch; 36 37 static GCInfoIndex V8_PRESERVE_MOST 38 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback, 39 FinalizationCallback, NameCallback); 40 static GCInfoIndex V8_PRESERVE_MOST EnsureGCInfoIndex( 41 std::atomic<GCInfoIndex>&, TraceCallback, FinalizationCallback); 42 static GCInfoIndex V8_PRESERVE_MOST 43 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback, NameCallback); 44 static GCInfoIndex V8_PRESERVE_MOST 45 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback); 46 }; 47 48 #define DISPATCH(has_finalizer, has_non_hidden_name, function) \ 49 template <typename T> \ 50 struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch< \ 51 T, has_finalizer, has_non_hidden_name> { \ 52 V8_INLINE GCInfoIndex \ 53 operator()(std::atomic<GCInfoIndex>& registered_index) { \ 54 return function; \ 55 } \ 56 }; 57 58 // ------------------------------------------------------- // 59 // DISPATCH(has_finalizer, has_non_hidden_name, function) // 60 // ------------------------------------------------------- // 61 DISPATCH(true, true, // 62 EnsureGCInfoIndex(registered_index, // 63 TraceTrait<T>::Trace, // 64 FinalizerTrait<T>::kCallback, // 65 NameTrait<T>::GetName)) // 66 DISPATCH(true, false, // 67 EnsureGCInfoIndex(registered_index, // 68 TraceTrait<T>::Trace, // 69 FinalizerTrait<T>::kCallback)) // 70 DISPATCH(false, true, // 71 EnsureGCInfoIndex(registered_index, // 72 TraceTrait<T>::Trace, // 73 NameTrait<T>::GetName)) // 74 DISPATCH(false, false, // 75 EnsureGCInfoIndex(registered_index, // 76 TraceTrait<T>::Trace)) // 77 78 #undef DISPATCH 79 80 // Trait determines how the garbage collector treats objects wrt. to traversing, 81 // finalization, and naming. 82 template <typename T> 83 struct GCInfoTrait final { 84 V8_INLINE static GCInfoIndex Index() { 85 static_assert(sizeof(T), "T must be fully defined"); 86 static std::atomic<GCInfoIndex> 87 registered_index; // Uses zero initialization. 88 GCInfoIndex index = registered_index.load(std::memory_order_acquire); 89 if (V8_UNLIKELY(!index)) { 90 index = EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index); 91 CPPGC_DCHECK(index != 0); 92 CPPGC_DCHECK(index == registered_index.load(std::memory_order_acquire)); 93 } 94 return index; 95 } 96 97 static constexpr bool CheckCallbacksAreDefined() { 98 // No USE() macro available. 99 (void)static_cast<TraceCallback>(TraceTrait<T>::Trace); 100 (void)static_cast<FinalizationCallback>(FinalizerTrait<T>::kCallback); 101 (void)static_cast<NameCallback>(NameTrait<T>::GetName); 102 return true; 103 } 104 }; 105 106 // Fold types based on finalizer behavior. Note that finalizer characteristics 107 // align with trace behavior, i.e., destructors are virtual when trace methods 108 // are and vice versa. 109 template <typename T, typename ParentMostGarbageCollectedType> 110 struct GCInfoFolding final { 111 static constexpr bool kHasVirtualDestructorAtBase = 112 std::has_virtual_destructor<ParentMostGarbageCollectedType>::value; 113 static constexpr bool kBothTypesAreTriviallyDestructible = 114 std::is_trivially_destructible<ParentMostGarbageCollectedType>::value && 115 std::is_trivially_destructible<T>::value; 116 static constexpr bool kHasCustomFinalizerDispatchAtBase = 117 internal::HasFinalizeGarbageCollectedObject< 118 ParentMostGarbageCollectedType>::value; 119 #ifdef CPPGC_SUPPORTS_OBJECT_NAMES 120 static constexpr bool kWantsDetailedObjectNames = true; 121 #else // !CPPGC_SUPPORTS_OBJECT_NAMES 122 static constexpr bool kWantsDetailedObjectNames = false; 123 #endif // !CPPGC_SUPPORTS_OBJECT_NAMES 124 125 // Always true. Forces the compiler to resolve callbacks which ensures that 126 // both modes don't break without requiring compiling a separate 127 // configuration. Only a single GCInfo (for `ResultType` below) will actually 128 // be instantiated but existence (and well-formedness) of all callbacks is 129 // checked. 130 static constexpr bool kCheckTypeGuardAlwaysTrue = 131 GCInfoTrait<T>::CheckCallbacksAreDefined() && 132 GCInfoTrait<ParentMostGarbageCollectedType>::CheckCallbacksAreDefined(); 133 134 // Folding would regress name resolution when deriving names from C++ 135 // class names as it would just folds a name to the base class name. 136 using ResultType = 137 std::conditional_t<kCheckTypeGuardAlwaysTrue && 138 (kHasVirtualDestructorAtBase || 139 kBothTypesAreTriviallyDestructible || 140 kHasCustomFinalizerDispatchAtBase) && 141 !kWantsDetailedObjectNames, 142 ParentMostGarbageCollectedType, T>; 143 }; 144 145 } // namespace internal 146 } // namespace cppgc 147 148 #endif // INCLUDE_CPPGC_INTERNAL_GC_INFO_H_