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