11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <atomic>
91cb0ef41Sopenharmony_ci#include <cstdint>
101cb0ef41Sopenharmony_ci#include <type_traits>
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "cppgc/internal/finalizer-trait.h"
131cb0ef41Sopenharmony_ci#include "cppgc/internal/name-trait.h"
141cb0ef41Sopenharmony_ci#include "cppgc/trace-trait.h"
151cb0ef41Sopenharmony_ci#include "v8config.h"  // NOLINT(build/include_directory)
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace cppgc {
181cb0ef41Sopenharmony_cinamespace internal {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciusing GCInfoIndex = uint16_t;
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cistruct V8_EXPORT EnsureGCInfoIndexTrait final {
231cb0ef41Sopenharmony_ci  // Acquires a new GC info object and returns the index. In addition, also
241cb0ef41Sopenharmony_ci  // updates `registered_index` atomically.
251cb0ef41Sopenharmony_ci  template <typename T>
261cb0ef41Sopenharmony_ci  V8_INLINE static GCInfoIndex EnsureIndex(
271cb0ef41Sopenharmony_ci      std::atomic<GCInfoIndex>& registered_index) {
281cb0ef41Sopenharmony_ci    return EnsureGCInfoIndexTraitDispatch<T>{}(registered_index);
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci private:
321cb0ef41Sopenharmony_ci  template <typename T, bool = std::is_polymorphic<T>::value,
331cb0ef41Sopenharmony_ci            bool = FinalizerTrait<T>::HasFinalizer(),
341cb0ef41Sopenharmony_ci            bool = NameTrait<T>::HasNonHiddenName()>
351cb0ef41Sopenharmony_ci  struct EnsureGCInfoIndexTraitDispatch;
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
381cb0ef41Sopenharmony_ci                                                  TraceCallback,
391cb0ef41Sopenharmony_ci                                                  FinalizationCallback,
401cb0ef41Sopenharmony_ci                                                  NameCallback);
411cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
421cb0ef41Sopenharmony_ci                                                  TraceCallback,
431cb0ef41Sopenharmony_ci                                                  FinalizationCallback);
441cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
451cb0ef41Sopenharmony_ci                                                  TraceCallback, NameCallback);
461cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexPolymorphic(std::atomic<GCInfoIndex>&,
471cb0ef41Sopenharmony_ci                                                  TraceCallback);
481cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
491cb0ef41Sopenharmony_ci                                                     TraceCallback,
501cb0ef41Sopenharmony_ci                                                     FinalizationCallback,
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci                                                     NameCallback);
531cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
541cb0ef41Sopenharmony_ci                                                     TraceCallback,
551cb0ef41Sopenharmony_ci                                                     FinalizationCallback);
561cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
571cb0ef41Sopenharmony_ci                                                     TraceCallback,
581cb0ef41Sopenharmony_ci                                                     NameCallback);
591cb0ef41Sopenharmony_ci  static GCInfoIndex EnsureGCInfoIndexNonPolymorphic(std::atomic<GCInfoIndex>&,
601cb0ef41Sopenharmony_ci                                                     TraceCallback);
611cb0ef41Sopenharmony_ci};
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci#define DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function) \
641cb0ef41Sopenharmony_ci  template <typename T>                                                        \
651cb0ef41Sopenharmony_ci  struct EnsureGCInfoIndexTrait::EnsureGCInfoIndexTraitDispatch<               \
661cb0ef41Sopenharmony_ci      T, is_polymorphic, has_finalizer, has_non_hidden_name> {                 \
671cb0ef41Sopenharmony_ci    V8_INLINE GCInfoIndex                                                      \
681cb0ef41Sopenharmony_ci    operator()(std::atomic<GCInfoIndex>& registered_index) {                   \
691cb0ef41Sopenharmony_ci      return function;                                                         \
701cb0ef41Sopenharmony_ci    }                                                                          \
711cb0ef41Sopenharmony_ci  };
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci// --------------------------------------------------------------------- //
741cb0ef41Sopenharmony_ci// DISPATCH(is_polymorphic, has_finalizer, has_non_hidden_name, function)
751cb0ef41Sopenharmony_ci// --------------------------------------------------------------------- //
761cb0ef41Sopenharmony_ciDISPATCH(true, true, true,                                               //
771cb0ef41Sopenharmony_ci         EnsureGCInfoIndexPolymorphic(registered_index,                  //
781cb0ef41Sopenharmony_ci                                      TraceTrait<T>::Trace,              //
791cb0ef41Sopenharmony_ci                                      FinalizerTrait<T>::kCallback,      //
801cb0ef41Sopenharmony_ci                                      NameTrait<T>::GetName))            //
811cb0ef41Sopenharmony_ciDISPATCH(true, true, false,                                              //
821cb0ef41Sopenharmony_ci         EnsureGCInfoIndexPolymorphic(registered_index,                  //
831cb0ef41Sopenharmony_ci                                      TraceTrait<T>::Trace,              //
841cb0ef41Sopenharmony_ci                                      FinalizerTrait<T>::kCallback))     //
851cb0ef41Sopenharmony_ciDISPATCH(true, false, true,                                              //
861cb0ef41Sopenharmony_ci         EnsureGCInfoIndexPolymorphic(registered_index,                  //
871cb0ef41Sopenharmony_ci                                      TraceTrait<T>::Trace,              //
881cb0ef41Sopenharmony_ci                                      NameTrait<T>::GetName))            //
891cb0ef41Sopenharmony_ciDISPATCH(true, false, false,                                             //
901cb0ef41Sopenharmony_ci         EnsureGCInfoIndexPolymorphic(registered_index,                  //
911cb0ef41Sopenharmony_ci                                      TraceTrait<T>::Trace))             //
921cb0ef41Sopenharmony_ciDISPATCH(false, true, true,                                              //
931cb0ef41Sopenharmony_ci         EnsureGCInfoIndexNonPolymorphic(registered_index,               //
941cb0ef41Sopenharmony_ci                                         TraceTrait<T>::Trace,           //
951cb0ef41Sopenharmony_ci                                         FinalizerTrait<T>::kCallback,   //
961cb0ef41Sopenharmony_ci                                         NameTrait<T>::GetName))         //
971cb0ef41Sopenharmony_ciDISPATCH(false, true, false,                                             //
981cb0ef41Sopenharmony_ci         EnsureGCInfoIndexNonPolymorphic(registered_index,               //
991cb0ef41Sopenharmony_ci                                         TraceTrait<T>::Trace,           //
1001cb0ef41Sopenharmony_ci                                         FinalizerTrait<T>::kCallback))  //
1011cb0ef41Sopenharmony_ciDISPATCH(false, false, true,                                             //
1021cb0ef41Sopenharmony_ci         EnsureGCInfoIndexNonPolymorphic(registered_index,               //
1031cb0ef41Sopenharmony_ci                                         TraceTrait<T>::Trace,           //
1041cb0ef41Sopenharmony_ci                                         NameTrait<T>::GetName))         //
1051cb0ef41Sopenharmony_ciDISPATCH(false, false, false,                                            //
1061cb0ef41Sopenharmony_ci         EnsureGCInfoIndexNonPolymorphic(registered_index,               //
1071cb0ef41Sopenharmony_ci                                         TraceTrait<T>::Trace))          //
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci#undef DISPATCH
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci// Fold types based on finalizer behavior. Note that finalizer characteristics
1121cb0ef41Sopenharmony_ci// align with trace behavior, i.e., destructors are virtual when trace methods
1131cb0ef41Sopenharmony_ci// are and vice versa.
1141cb0ef41Sopenharmony_citemplate <typename T, typename ParentMostGarbageCollectedType>
1151cb0ef41Sopenharmony_cistruct GCInfoFolding {
1161cb0ef41Sopenharmony_ci  static constexpr bool kHasVirtualDestructorAtBase =
1171cb0ef41Sopenharmony_ci      std::has_virtual_destructor<ParentMostGarbageCollectedType>::value;
1181cb0ef41Sopenharmony_ci  static constexpr bool kBothTypesAreTriviallyDestructible =
1191cb0ef41Sopenharmony_ci      std::is_trivially_destructible<ParentMostGarbageCollectedType>::value &&
1201cb0ef41Sopenharmony_ci      std::is_trivially_destructible<T>::value;
1211cb0ef41Sopenharmony_ci  static constexpr bool kHasCustomFinalizerDispatchAtBase =
1221cb0ef41Sopenharmony_ci      internal::HasFinalizeGarbageCollectedObject<
1231cb0ef41Sopenharmony_ci          ParentMostGarbageCollectedType>::value;
1241cb0ef41Sopenharmony_ci#ifdef CPPGC_SUPPORTS_OBJECT_NAMES
1251cb0ef41Sopenharmony_ci  static constexpr bool kWantsDetailedObjectNames = true;
1261cb0ef41Sopenharmony_ci#else   // !CPPGC_SUPPORTS_OBJECT_NAMES
1271cb0ef41Sopenharmony_ci  static constexpr bool kWantsDetailedObjectNames = false;
1281cb0ef41Sopenharmony_ci#endif  // !CPPGC_SUPPORTS_OBJECT_NAMES
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  // Folding would regresses name resolution when deriving names from C++
1311cb0ef41Sopenharmony_ci  // class names as it would just folds a name to the base class name.
1321cb0ef41Sopenharmony_ci  using ResultType = std::conditional_t<(kHasVirtualDestructorAtBase ||
1331cb0ef41Sopenharmony_ci                                         kBothTypesAreTriviallyDestructible ||
1341cb0ef41Sopenharmony_ci                                         kHasCustomFinalizerDispatchAtBase) &&
1351cb0ef41Sopenharmony_ci                                            !kWantsDetailedObjectNames,
1361cb0ef41Sopenharmony_ci                                        ParentMostGarbageCollectedType, T>;
1371cb0ef41Sopenharmony_ci};
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci// Trait determines how the garbage collector treats objects wrt. to traversing,
1401cb0ef41Sopenharmony_ci// finalization, and naming.
1411cb0ef41Sopenharmony_citemplate <typename T>
1421cb0ef41Sopenharmony_cistruct GCInfoTrait final {
1431cb0ef41Sopenharmony_ci  V8_INLINE static GCInfoIndex Index() {
1441cb0ef41Sopenharmony_ci    static_assert(sizeof(T), "T must be fully defined");
1451cb0ef41Sopenharmony_ci    static std::atomic<GCInfoIndex>
1461cb0ef41Sopenharmony_ci        registered_index;  // Uses zero initialization.
1471cb0ef41Sopenharmony_ci    const GCInfoIndex index = registered_index.load(std::memory_order_acquire);
1481cb0ef41Sopenharmony_ci    return index ? index
1491cb0ef41Sopenharmony_ci                 : EnsureGCInfoIndexTrait::EnsureIndex<T>(registered_index);
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci};
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci}  // namespace internal
1541cb0ef41Sopenharmony_ci}  // namespace cppgc
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_INTERNAL_GC_INFO_H_
157