Loading...
Searching...
No Matches
gc-info.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_INTERNAL_GC_INFO_H_
6#define INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
7
8#include <atomic>
9#include <cstdint>
10#include <type_traits>
11
15#include "cppgc/trace-trait.h"
16#include "v8config.h" // NOLINT(build/include_directory)
17
18namespace cppgc::internal {
19
20using GCInfoIndex = uint16_t;
21static constexpr GCInfoIndex kMaxGCInfoIndex = 1 << 14;
22static constexpr GCInfoIndex kMinGCInfoIndex = 1;
23
24struct GCInfo final {
28
32 size_t padding = 0;
33};
34
36 const void*, HeapObjectNameForUnnamedObject name_retrieval_mode) {
37 return {
40}
41
42#if defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
43
44#if defined(__APPLE__)
45// Use __attribute__((visibility("hidden"))) explicitly here, since otherwise
46// the compiler will generate GOT-indirected loads. Although the linker emits
47// these symbols with `protected` visibility (same as `default`, i.e. exported,
48// but without GOT/PLT indirection), the compiler is not aware of that and
49// assumes any extern "C" has the `default` visibility.
50extern "C" __attribute__((visibility("hidden"))) const GCInfo
51 __start_gc_info_section[] __asm("section$start$__DATA$gc_info_section");
52extern "C" __attribute__((visibility("hidden"))) const GCInfo
53 __stop_gc_info_section[] __asm("section$end$__DATA$gc_info_section");
54#define CPPGC_GC_INFO_SECTION \
55 __attribute__((section("__DATA,gc_info_section"), used))
56#else // defined(__APPLE__)
57extern "C" __attribute__((visibility("hidden")))
58const GCInfo __start_gc_info_section[];
59extern "C" __attribute__((visibility("hidden")))
60const GCInfo __stop_gc_info_section[];
61#define CPPGC_GC_INFO_SECTION __attribute__((section("gc_info_section"), used))
62#endif // defined(__APPLE__)
63
64class V8_EXPORT GCInfoTableSection final {
65 public:
66 GCInfoTableSection() = delete;
67
68 V8_INLINE static GCInfoIndex Index(const GCInfo& info) {
69 return &info - __start_gc_info_section + 1;
70 }
71
72 V8_INLINE static const GCInfo& GCInfoFromIndex(GCInfoIndex index) {
73 CPPGC_DCHECK(index >= 1);
75 static_cast<size_t>(index - 1) <
76 static_cast<size_t>(__stop_gc_info_section - __start_gc_info_section));
77 return __start_gc_info_section[index - 1];
78 }
79};
80
81#else // defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
82
84 // Acquires a new GC info object and updates `registered_index` with the index
85 // that identifies that new info accordingly.
86 template <typename T>
88 std::atomic<GCInfoIndex>& registered_index) {
89 return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
90 }
91
92 private:
93 template <typename T, bool = FinalizerTrait<T>::HasFinalizer(),
95 struct EnsureGCInfoIndexTraitDispatch;
96
98 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback,
100 static GCInfoIndex V8_PRESERVE_MOST EnsureGCInfoIndex(
101 std::atomic<GCInfoIndex>&, TraceCallback, FinalizationCallback);
103 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback, NameCallback);
105 EnsureGCInfoIndex(std::atomic<GCInfoIndex>&, TraceCallback);
106};
107
108#define DISPATCH(has_finalizer, has_non_hidden_name, function) \
109 template <typename T> \
110 struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch< \
111 T, has_finalizer, has_non_hidden_name> { \
112 V8_INLINE GCInfoIndex \
113 operator()(std::atomic<GCInfoIndex>& registered_index) { \
114 return function; \
115 } \
116 };
117
118// ------------------------------------------------------- //
119// DISPATCH(has_finalizer, has_non_hidden_name, function) //
120// ------------------------------------------------------- //
121DISPATCH(true, true, //
122 EnsureGCInfoIndex(registered_index, //
126DISPATCH(true, false, //
127 EnsureGCInfoIndex(registered_index, //
130DISPATCH(false, true, //
131 EnsureGCInfoIndex(registered_index, //
134DISPATCH(false, false, //
135 EnsureGCInfoIndex(registered_index, //
137
138#undef DISPATCH
139
140#endif // defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
141
142// Trait determines how the garbage collector treats objects wrt. to traversing,
143// finalization, and naming.
144template <typename T>
145struct GCInfoTrait final {
146#if defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
147 static const GCInfo gc_info;
148 V8_INLINE static GCInfoIndex Index() {
149 static_assert(sizeof(T), "T must be fully defined");
150 return GCInfoTableSection::Index(gc_info);
151 }
152#else // defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
154 static_assert(sizeof(T), "T must be fully defined");
155 static std::atomic<GCInfoIndex>
156 registered_index; // Uses zero initialization.
157 GCInfoIndex index = registered_index.load(std::memory_order_acquire);
158 if (V8_UNLIKELY(!index)) {
159 index = EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
160 CPPGC_DCHECK(index != 0);
161 CPPGC_DCHECK(index == registered_index.load(std::memory_order_acquire));
162 }
163 return index;
164 }
165#endif // defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
166
167 static constexpr void CheckCallbacksAreDefined() {
168 // No USE() macro available.
169 (void)static_cast<TraceCallback>(TraceTrait<T>::Trace);
171 (void)static_cast<NameCallback>(NameTrait<T>::GetName);
172 }
173};
174
175// Fold types based on finalizer behavior. Note that finalizer characteristics
176// align with trace behavior, i.e., destructors are virtual when trace methods
177// are and vice versa.
178template <typename T, typename ParentMostGarbageCollectedType>
179struct GCInfoFolding final {
180 static constexpr bool kHasVirtualDestructorAtBase =
181 std::has_virtual_destructor_v<ParentMostGarbageCollectedType>;
183 std::is_trivially_destructible_v<ParentMostGarbageCollectedType> &&
184 std::is_trivially_destructible_v<T>;
185 static constexpr bool kHasCustomFinalizerDispatchAtBase =
187 ParentMostGarbageCollectedType>::value;
188#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
189 static constexpr bool kWantsDetailedObjectNames = true;
190#else // !CPPGC_SUPPORTS_OBJECT_NAMES
191 static constexpr bool kWantsDetailedObjectNames = false;
192#endif // !CPPGC_SUPPORTS_OBJECT_NAMES
193
194 // Always true. Forces the compiler to resolve callbacks which ensures that
195 // both modes don't break without requiring compiling a separate
196 // configuration. Only a single GCInfo (for `ResultType` below) will actually
197 // be instantiated but existence (and well-formedness) of all callbacks is
198 // checked.
199 static constexpr bool WantToFold() {
200 if constexpr ((kHasVirtualDestructorAtBase ||
206 return true;
207 }
208 return false;
209 }
210
211 // Folding would regress name resolution when deriving names from C++
212 // class names as it would just folds a name to the base class name.
214 std::conditional_t<WantToFold(), ParentMostGarbageCollectedType, T>;
215};
216
217#if defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
218template <typename T>
219const GCInfo GCInfoTrait<T>::gc_info CPPGC_GC_INFO_SECTION = GCInfo(
222#endif // defined(CPPGC_ENABLE_OBJECT_SECTION_GCINFO)
223
224} // namespace cppgc::internal
225
226#endif // INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
static constexpr const char kHiddenName[]
Definition: name-provider.h:31
Definition: name-trait.h:75
#define DISPATCH(has_finalizer, has_non_hidden_name, function)
Definition: gc-info.h:108
#define CPPGC_DCHECK(condition)
Definition: logging.h:36
Definition: allocation.h:47
uint16_t GCInfoIndex
Definition: gc-info.h:20
HeapObjectName(*)(const void *, HeapObjectNameForUnnamedObject) NameCallback
Definition: name-trait.h:135
void(*)(void *) FinalizationCallback
Definition: finalizer-trait.h:15
HeapObjectNameForUnnamedObject
Definition: name-trait.h:62
HeapObjectName GetHiddenName(const void *, HeapObjectNameForUnnamedObject name_retrieval_mode)
Definition: gc-info.h:35
void(*)(Visitor *visitor, const void *object) TraceCallback
Definition: trace-trait.h:37
Definition: trace-trait.h:104
static GCInfoIndex EnsureIndex(std::atomic< GCInfoIndex > &registered_index)
Definition: gc-info.h:87
Definition: finalizer-trait.h:66
static constexpr FinalizationCallback kCallback
Definition: finalizer-trait.h:83
Definition: gc-info.h:179
static constexpr bool kBothTypesAreTriviallyDestructible
Definition: gc-info.h:182
static constexpr bool kHasVirtualDestructorAtBase
Definition: gc-info.h:180
static constexpr bool kHasCustomFinalizerDispatchAtBase
Definition: gc-info.h:185
static constexpr bool kWantsDetailedObjectNames
Definition: gc-info.h:191
static constexpr bool WantToFold()
Definition: gc-info.h:199
std::conditional_t< WantToFold(), ParentMostGarbageCollectedType, T > ResultType
Definition: gc-info.h:214
Definition: gc-info.h:145
static GCInfoIndex Index()
Definition: gc-info.h:153
static constexpr void CheckCallbacksAreDefined()
Definition: gc-info.h:167
Definition: gc-info.h:24
FinalizationCallback finalize
Definition: gc-info.h:29
TraceCallback trace
Definition: gc-info.h:30
constexpr GCInfo(FinalizationCallback finalize, TraceCallback trace, NameCallback name)
Definition: gc-info.h:25
NameCallback name
Definition: gc-info.h:31
size_t padding
Definition: gc-info.h:32
Definition: name-trait.h:57
static void Trace(Visitor *visitor, const void *self)
Definition: trace-trait.h:96
#define V8_EXPORT
Definition: v8config.h:867
#define V8_INLINE
Definition: v8config.h:511
#define V8_UNLIKELY(condition)
Definition: v8config.h:670
#define V8_PRESERVE_MOST
Definition: v8config.h:608