v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
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 
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>
26  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>
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 =
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 ||
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 {
143  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_