• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/name-trait.h"
14 #include "cppgc/trace-trait.h"
15 #include "v8config.h"  // NOLINT(build/include_directory)
16 
17 namespace cppgc {
18 namespace internal {
19 
20 using GCInfoIndex = uint16_t;
21 
22 struct V8_EXPORT EnsureGCInfoIndexTrait final {
23   // Acquires a new GC info object and returns the index. In addition, also
24   // updates `registered_index` atomically.
25   template <typename T>
EnsureIndexfinal26   V8_INLINE static GCInfoIndex EnsureIndex(
27       std::atomic<GCInfoIndex>& registered_index) {
28     return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
29   }
30 
31  private:
32   template <typename T, bool = std::is_polymorphic<T>::value,
33             bool = FinalizerTrait<T>::HasFinalizer(),
34             bool = NameTrait<T>::HasNonHiddenName()>
35   struct EnsureGCInfoIndexTraitDispatch;
36 
37   static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
38                                                   TraceCallback,
39                                                   FinalizationCallback,
40                                                   NameCallback);
41   static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
42                                                   TraceCallback,
43                                                   FinalizationCallback);
44   static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
45                                                   TraceCallback, NameCallback);
46   static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
47                                                   TraceCallback);
48   static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
49                                                      TraceCallback,
50                                                      FinalizationCallback,
51 
52                                                      NameCallback);
53   static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
54                                                      TraceCallback,
55                                                      FinalizationCallback);
56   static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
57                                                      TraceCallback,
58                                                      NameCallback);
59   static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
60                                                      TraceCallback);
61 };
62 
63 #define DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function) \
64   template <typename T>                                                        \
65   struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch<               \
66       T, is_polymorphic, has_finalizer, has_non_hidden_name> {                 \
67     V8_INLINE GCInfoIndex                                                      \
68     operator()(std::atomic<GCInfoIndex>& registered_index) {                   \
69       return function;                                                         \
70     }                                                                          \
71   };
72 
73 // --------------------------------------------------------------------- //
74 // DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function)
75 // --------------------------------------------------------------------- //
76 DISPATCH(true, true, true,                                               //
77          EnsureGCInfoIndexPolymorphic(registered_index,                  //
78                                       TraceTrait<T>::Trace,              //
79                                       FinalizerTrait<T>::kCallback,      //
80                                       NameTrait<T>::GetName))            //
81 DISPATCH(true, true, false,                                              //
82          EnsureGCInfoIndexPolymorphic(registered_index,                  //
83                                       TraceTrait<T>::Trace,              //
84                                       FinalizerTrait<T>::kCallback))     //
85 DISPATCH(true, false, true,                                              //
86          EnsureGCInfoIndexPolymorphic(registered_index,                  //
87                                       TraceTrait<T>::Trace,              //
88                                       NameTrait<T>::GetName))            //
89 DISPATCH(true, false, false,                                             //
90          EnsureGCInfoIndexPolymorphic(registered_index,                  //
91                                       TraceTrait<T>::Trace))             //
92 DISPATCH(false, true, true,                                              //
93          EnsureGCInfoIndexNonPolymorphic(registered_index,               //
94                                          TraceTrait<T>::Trace,           //
95                                          FinalizerTrait<T>::kCallback,   //
96                                          NameTrait<T>::GetName))         //
97 DISPATCH(false, true, false,                                             //
98          EnsureGCInfoIndexNonPolymorphic(registered_index,               //
99                                          TraceTrait<T>::Trace,           //
100                                          FinalizerTrait<T>::kCallback))  //
101 DISPATCH(false, false, true,                                             //
102          EnsureGCInfoIndexNonPolymorphic(registered_index,               //
103                                          TraceTrait<T>::Trace,           //
104                                          NameTrait<T>::GetName))         //
105 DISPATCH(false, false, false,                                            //
106          EnsureGCInfoIndexNonPolymorphic(registered_index,               //
107                                          TraceTrait<T>::Trace))          //
108 
109 #undef DISPATCH
110 
111 // Fold types based on finalizer behavior. Note that finalizer characteristics
112 // align with trace behavior, i.e., destructors are virtual when trace methods
113 // are and vice versa.
114 template <typename T, typename ParentMostGarbageCollectedType>
115 struct GCInfoFolding {
116   static constexpr bool kHasVirtualDestructorAtBase =
117       std::has_virtual_destructor<ParentMostGarbageCollectedType>::value;
118   static constexpr bool kBothTypesAreTriviallyDestructible =
119       std::is_trivially_destructible<ParentMostGarbageCollectedType>::value &&
120       std::is_trivially_destructible<T>::value;
121   static constexpr bool kHasCustomFinalizerDispatchAtBase =
122       internal::HasFinalizeGarbageCollectedObject<
123           ParentMostGarbageCollectedType>::value;
124 #ifdef CPPGC_SUPPORTS_OBJECT_NAMES
125   static constexpr bool kWantsDetailedObjectNames = true;
126 #else   // !CPPGC_SUPPORTS_OBJECT_NAMES
127   static constexpr bool kWantsDetailedObjectNames = false;
128 #endif  // !CPPGC_SUPPORTS_OBJECT_NAMES
129 
130   // Folding would regresses name resolution when deriving names from C++
131   // class names as it would just folds a name to the base class name.
132   using ResultType = std::conditional_t<(kHasVirtualDestructorAtBase ||
133                                          kBothTypesAreTriviallyDestructible ||
134                                          kHasCustomFinalizerDispatchAtBase) &&
135                                             !kWantsDetailedObjectNames,
136                                         ParentMostGarbageCollectedType, T>;
137 };
138 
139 // Trait determines how the garbage collector treats objects wrt. to traversing,
140 // finalization, and naming.
141 template <typename T>
142 struct GCInfoTrait final {
Indexfinal143   V8_INLINE static GCInfoIndex Index() {
144     static_assert(sizeof(T), "T must be fully defined");
145     static std::atomic<GCInfoIndex>
146         registered_index;  // Uses zero initialization.
147     const GCInfoIndex index = registered_index.load(std::memory_order_acquire);
148     return index ? index
149                  : EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
150   }
151 };
152 
153 }  // namespace internal
154 }  // namespace cppgc
155 
156 #endif  // INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
157