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