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_VISITOR_H_ 61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_VISITOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "cppgc/custom-space.h" 91cb0ef41Sopenharmony_ci#include "cppgc/ephemeron-pair.h" 101cb0ef41Sopenharmony_ci#include "cppgc/garbage-collected.h" 111cb0ef41Sopenharmony_ci#include "cppgc/internal/logging.h" 121cb0ef41Sopenharmony_ci#include "cppgc/internal/pointer-policies.h" 131cb0ef41Sopenharmony_ci#include "cppgc/liveness-broker.h" 141cb0ef41Sopenharmony_ci#include "cppgc/member.h" 151cb0ef41Sopenharmony_ci#include "cppgc/sentinel-pointer.h" 161cb0ef41Sopenharmony_ci#include "cppgc/source-location.h" 171cb0ef41Sopenharmony_ci#include "cppgc/trace-trait.h" 181cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h" 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cinamespace cppgc { 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cinamespace internal { 231cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessPolicy, typename LocationPolicy, 241cb0ef41Sopenharmony_ci typename CheckingPolicy> 251cb0ef41Sopenharmony_ciclass BasicCrossThreadPersistent; 261cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessPolicy, typename LocationPolicy, 271cb0ef41Sopenharmony_ci typename CheckingPolicy> 281cb0ef41Sopenharmony_ciclass BasicPersistent; 291cb0ef41Sopenharmony_ciclass ConservativeTracingVisitor; 301cb0ef41Sopenharmony_ciclass VisitorBase; 311cb0ef41Sopenharmony_ciclass VisitorFactory; 321cb0ef41Sopenharmony_ci} // namespace internal 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciusing WeakCallback = void (*)(const LivenessBroker&, const void*); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci/** 371cb0ef41Sopenharmony_ci * Visitor passed to trace methods. All managed pointers must have called the 381cb0ef41Sopenharmony_ci * Visitor's trace method on them. 391cb0ef41Sopenharmony_ci * 401cb0ef41Sopenharmony_ci * \code 411cb0ef41Sopenharmony_ci * class Foo final : public GarbageCollected<Foo> { 421cb0ef41Sopenharmony_ci * public: 431cb0ef41Sopenharmony_ci * void Trace(Visitor* visitor) const { 441cb0ef41Sopenharmony_ci * visitor->Trace(foo_); 451cb0ef41Sopenharmony_ci * visitor->Trace(weak_foo_); 461cb0ef41Sopenharmony_ci * } 471cb0ef41Sopenharmony_ci * private: 481cb0ef41Sopenharmony_ci * Member<Foo> foo_; 491cb0ef41Sopenharmony_ci * WeakMember<Foo> weak_foo_; 501cb0ef41Sopenharmony_ci * }; 511cb0ef41Sopenharmony_ci * \endcode 521cb0ef41Sopenharmony_ci */ 531cb0ef41Sopenharmony_ciclass V8_EXPORT Visitor { 541cb0ef41Sopenharmony_ci public: 551cb0ef41Sopenharmony_ci class Key { 561cb0ef41Sopenharmony_ci private: 571cb0ef41Sopenharmony_ci Key() = default; 581cb0ef41Sopenharmony_ci friend class internal::VisitorFactory; 591cb0ef41Sopenharmony_ci }; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci explicit Visitor(Key) {} 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci virtual ~Visitor() = default; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci /** 661cb0ef41Sopenharmony_ci * Trace method for Member. 671cb0ef41Sopenharmony_ci * 681cb0ef41Sopenharmony_ci * \param member Member reference retaining an object. 691cb0ef41Sopenharmony_ci */ 701cb0ef41Sopenharmony_ci template <typename T> 711cb0ef41Sopenharmony_ci void Trace(const Member<T>& member) { 721cb0ef41Sopenharmony_ci const T* value = member.GetRawAtomic(); 731cb0ef41Sopenharmony_ci CPPGC_DCHECK(value != kSentinelPointer); 741cb0ef41Sopenharmony_ci TraceImpl(value); 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci /** 781cb0ef41Sopenharmony_ci * Trace method for WeakMember. 791cb0ef41Sopenharmony_ci * 801cb0ef41Sopenharmony_ci * \param weak_member WeakMember reference weakly retaining an object. 811cb0ef41Sopenharmony_ci */ 821cb0ef41Sopenharmony_ci template <typename T> 831cb0ef41Sopenharmony_ci void Trace(const WeakMember<T>& weak_member) { 841cb0ef41Sopenharmony_ci static_assert(sizeof(T), "Pointee type must be fully defined."); 851cb0ef41Sopenharmony_ci static_assert(internal::IsGarbageCollectedOrMixinType<T>::value, 861cb0ef41Sopenharmony_ci "T must be GarbageCollected or GarbageCollectedMixin type"); 871cb0ef41Sopenharmony_ci static_assert(!internal::IsAllocatedOnCompactableSpace<T>::value, 881cb0ef41Sopenharmony_ci "Weak references to compactable objects are not allowed"); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci const T* value = weak_member.GetRawAtomic(); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci // Bailout assumes that WeakMember emits write barrier. 931cb0ef41Sopenharmony_ci if (!value) { 941cb0ef41Sopenharmony_ci return; 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci CPPGC_DCHECK(value != kSentinelPointer); 981cb0ef41Sopenharmony_ci VisitWeak(value, TraceTrait<T>::GetTraceDescriptor(value), 991cb0ef41Sopenharmony_ci &HandleWeak<WeakMember<T>>, &weak_member); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci#if defined(CPPGC_POINTER_COMPRESSION) 1031cb0ef41Sopenharmony_ci /** 1041cb0ef41Sopenharmony_ci * Trace method for UncompressedMember. 1051cb0ef41Sopenharmony_ci * 1061cb0ef41Sopenharmony_ci * \param member UncompressedMember reference retaining an object. 1071cb0ef41Sopenharmony_ci */ 1081cb0ef41Sopenharmony_ci template <typename T> 1091cb0ef41Sopenharmony_ci void Trace(const subtle::UncompressedMember<T>& member) { 1101cb0ef41Sopenharmony_ci const T* value = member.GetRawAtomic(); 1111cb0ef41Sopenharmony_ci CPPGC_DCHECK(value != kSentinelPointer); 1121cb0ef41Sopenharmony_ci TraceImpl(value); 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci#endif // defined(CPPGC_POINTER_COMPRESSION) 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci /** 1171cb0ef41Sopenharmony_ci * Trace method for inlined objects that are not allocated themselves but 1181cb0ef41Sopenharmony_ci * otherwise follow managed heap layout and have a Trace() method. 1191cb0ef41Sopenharmony_ci * 1201cb0ef41Sopenharmony_ci * \param object reference of the inlined object. 1211cb0ef41Sopenharmony_ci */ 1221cb0ef41Sopenharmony_ci template <typename T> 1231cb0ef41Sopenharmony_ci void Trace(const T& object) { 1241cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 1251cb0ef41Sopenharmony_ci // This object is embedded in potentially multiple nested objects. The 1261cb0ef41Sopenharmony_ci // outermost object must not be in construction as such objects are (a) not 1271cb0ef41Sopenharmony_ci // processed immediately, and (b) only processed conservatively if not 1281cb0ef41Sopenharmony_ci // otherwise possible. 1291cb0ef41Sopenharmony_ci CheckObjectNotInConstruction(&object); 1301cb0ef41Sopenharmony_ci#endif // V8_ENABLE_CHECKS 1311cb0ef41Sopenharmony_ci TraceTrait<T>::Trace(this, &object); 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci /** 1351cb0ef41Sopenharmony_ci * Registers a weak callback method on the object of type T. See 1361cb0ef41Sopenharmony_ci * LivenessBroker for an usage example. 1371cb0ef41Sopenharmony_ci * 1381cb0ef41Sopenharmony_ci * \param object of type T specifying a weak callback method. 1391cb0ef41Sopenharmony_ci */ 1401cb0ef41Sopenharmony_ci template <typename T, void (T::*method)(const LivenessBroker&)> 1411cb0ef41Sopenharmony_ci void RegisterWeakCallbackMethod(const T* object) { 1421cb0ef41Sopenharmony_ci RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, object); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci /** 1461cb0ef41Sopenharmony_ci * Trace method for EphemeronPair. 1471cb0ef41Sopenharmony_ci * 1481cb0ef41Sopenharmony_ci * \param ephemeron_pair EphemeronPair reference weakly retaining a key object 1491cb0ef41Sopenharmony_ci * and strongly retaining a value object in case the key object is alive. 1501cb0ef41Sopenharmony_ci */ 1511cb0ef41Sopenharmony_ci template <typename K, typename V> 1521cb0ef41Sopenharmony_ci void Trace(const EphemeronPair<K, V>& ephemeron_pair) { 1531cb0ef41Sopenharmony_ci TraceEphemeron(ephemeron_pair.key, &ephemeron_pair.value); 1541cb0ef41Sopenharmony_ci RegisterWeakCallbackMethod<EphemeronPair<K, V>, 1551cb0ef41Sopenharmony_ci &EphemeronPair<K, V>::ClearValueIfKeyIsDead>( 1561cb0ef41Sopenharmony_ci &ephemeron_pair); 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci /** 1601cb0ef41Sopenharmony_ci * Trace method for a single ephemeron. Used for tracing a raw ephemeron in 1611cb0ef41Sopenharmony_ci * which the `key` and `value` are kept separately. 1621cb0ef41Sopenharmony_ci * 1631cb0ef41Sopenharmony_ci * \param weak_member_key WeakMember reference weakly retaining a key object. 1641cb0ef41Sopenharmony_ci * \param member_value Member reference with ephemeron semantics. 1651cb0ef41Sopenharmony_ci */ 1661cb0ef41Sopenharmony_ci template <typename KeyType, typename ValueType> 1671cb0ef41Sopenharmony_ci void TraceEphemeron(const WeakMember<KeyType>& weak_member_key, 1681cb0ef41Sopenharmony_ci const Member<ValueType>* member_value) { 1691cb0ef41Sopenharmony_ci const KeyType* key = weak_member_key.GetRawAtomic(); 1701cb0ef41Sopenharmony_ci if (!key) return; 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci // `value` must always be non-null. 1731cb0ef41Sopenharmony_ci CPPGC_DCHECK(member_value); 1741cb0ef41Sopenharmony_ci const ValueType* value = member_value->GetRawAtomic(); 1751cb0ef41Sopenharmony_ci if (!value) return; 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci // KeyType and ValueType may refer to GarbageCollectedMixin. 1781cb0ef41Sopenharmony_ci TraceDescriptor value_desc = 1791cb0ef41Sopenharmony_ci TraceTrait<ValueType>::GetTraceDescriptor(value); 1801cb0ef41Sopenharmony_ci CPPGC_DCHECK(value_desc.base_object_payload); 1811cb0ef41Sopenharmony_ci const void* key_base_object_payload = 1821cb0ef41Sopenharmony_ci TraceTrait<KeyType>::GetTraceDescriptor(key).base_object_payload; 1831cb0ef41Sopenharmony_ci CPPGC_DCHECK(key_base_object_payload); 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci VisitEphemeron(key_base_object_payload, value, value_desc); 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci /** 1891cb0ef41Sopenharmony_ci * Trace method for a single ephemeron. Used for tracing a raw ephemeron in 1901cb0ef41Sopenharmony_ci * which the `key` and `value` are kept separately. Note that this overload 1911cb0ef41Sopenharmony_ci * is for non-GarbageCollected `value`s that can be traced though. 1921cb0ef41Sopenharmony_ci * 1931cb0ef41Sopenharmony_ci * \param key `WeakMember` reference weakly retaining a key object. 1941cb0ef41Sopenharmony_ci * \param value Reference weakly retaining a value object. Note that 1951cb0ef41Sopenharmony_ci * `ValueType` here should not be `Member`. It is expected that 1961cb0ef41Sopenharmony_ci * `TraceTrait<ValueType>::GetTraceDescriptor(value)` returns a 1971cb0ef41Sopenharmony_ci * `TraceDescriptor` with a null base pointer but a valid trace method. 1981cb0ef41Sopenharmony_ci */ 1991cb0ef41Sopenharmony_ci template <typename KeyType, typename ValueType> 2001cb0ef41Sopenharmony_ci void TraceEphemeron(const WeakMember<KeyType>& weak_member_key, 2011cb0ef41Sopenharmony_ci const ValueType* value) { 2021cb0ef41Sopenharmony_ci static_assert(!IsGarbageCollectedOrMixinTypeV<ValueType>, 2031cb0ef41Sopenharmony_ci "garbage-collected types must use WeakMember and Member"); 2041cb0ef41Sopenharmony_ci const KeyType* key = weak_member_key.GetRawAtomic(); 2051cb0ef41Sopenharmony_ci if (!key) return; 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci // `value` must always be non-null. 2081cb0ef41Sopenharmony_ci CPPGC_DCHECK(value); 2091cb0ef41Sopenharmony_ci TraceDescriptor value_desc = 2101cb0ef41Sopenharmony_ci TraceTrait<ValueType>::GetTraceDescriptor(value); 2111cb0ef41Sopenharmony_ci // `value_desc.base_object_payload` must be null as this override is only 2121cb0ef41Sopenharmony_ci // taken for non-garbage-collected values. 2131cb0ef41Sopenharmony_ci CPPGC_DCHECK(!value_desc.base_object_payload); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci // KeyType might be a GarbageCollectedMixin. 2161cb0ef41Sopenharmony_ci const void* key_base_object_payload = 2171cb0ef41Sopenharmony_ci TraceTrait<KeyType>::GetTraceDescriptor(key).base_object_payload; 2181cb0ef41Sopenharmony_ci CPPGC_DCHECK(key_base_object_payload); 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci VisitEphemeron(key_base_object_payload, value, value_desc); 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci /** 2241cb0ef41Sopenharmony_ci * Trace method that strongifies a WeakMember. 2251cb0ef41Sopenharmony_ci * 2261cb0ef41Sopenharmony_ci * \param weak_member WeakMember reference retaining an object. 2271cb0ef41Sopenharmony_ci */ 2281cb0ef41Sopenharmony_ci template <typename T> 2291cb0ef41Sopenharmony_ci void TraceStrongly(const WeakMember<T>& weak_member) { 2301cb0ef41Sopenharmony_ci const T* value = weak_member.GetRawAtomic(); 2311cb0ef41Sopenharmony_ci CPPGC_DCHECK(value != kSentinelPointer); 2321cb0ef41Sopenharmony_ci TraceImpl(value); 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci /** 2361cb0ef41Sopenharmony_ci * Trace method for retaining containers strongly. 2371cb0ef41Sopenharmony_ci * 2381cb0ef41Sopenharmony_ci * \param object reference to the container. 2391cb0ef41Sopenharmony_ci */ 2401cb0ef41Sopenharmony_ci template <typename T> 2411cb0ef41Sopenharmony_ci void TraceStrongContainer(const T* object) { 2421cb0ef41Sopenharmony_ci TraceImpl(object); 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci /** 2461cb0ef41Sopenharmony_ci * Trace method for retaining containers weakly. Note that weak containers 2471cb0ef41Sopenharmony_ci * should emit write barriers. 2481cb0ef41Sopenharmony_ci * 2491cb0ef41Sopenharmony_ci * \param object reference to the container. 2501cb0ef41Sopenharmony_ci * \param callback to be invoked. 2511cb0ef41Sopenharmony_ci * \param callback_data custom data that is passed to the callback. 2521cb0ef41Sopenharmony_ci */ 2531cb0ef41Sopenharmony_ci template <typename T> 2541cb0ef41Sopenharmony_ci void TraceWeakContainer(const T* object, WeakCallback callback, 2551cb0ef41Sopenharmony_ci const void* callback_data) { 2561cb0ef41Sopenharmony_ci if (!object) return; 2571cb0ef41Sopenharmony_ci VisitWeakContainer(object, TraceTrait<T>::GetTraceDescriptor(object), 2581cb0ef41Sopenharmony_ci TraceTrait<T>::GetWeakTraceDescriptor(object), callback, 2591cb0ef41Sopenharmony_ci callback_data); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci /** 2631cb0ef41Sopenharmony_ci * Registers a slot containing a reference to an object allocated on a 2641cb0ef41Sopenharmony_ci * compactable space. Such references maybe be arbitrarily moved by the GC. 2651cb0ef41Sopenharmony_ci * 2661cb0ef41Sopenharmony_ci * \param slot location of reference to object that might be moved by the GC. 2671cb0ef41Sopenharmony_ci * The slot must contain an uncompressed pointer. 2681cb0ef41Sopenharmony_ci */ 2691cb0ef41Sopenharmony_ci template <typename T> 2701cb0ef41Sopenharmony_ci void RegisterMovableReference(const T** slot) { 2711cb0ef41Sopenharmony_ci static_assert(internal::IsAllocatedOnCompactableSpace<T>::value, 2721cb0ef41Sopenharmony_ci "Only references to objects allocated on compactable spaces " 2731cb0ef41Sopenharmony_ci "should be registered as movable slots."); 2741cb0ef41Sopenharmony_ci static_assert(!IsGarbageCollectedMixinTypeV<T>, 2751cb0ef41Sopenharmony_ci "Mixin types do not support compaction."); 2761cb0ef41Sopenharmony_ci HandleMovableReference(reinterpret_cast<const void**>(slot)); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci /** 2801cb0ef41Sopenharmony_ci * Registers a weak callback that is invoked during garbage collection. 2811cb0ef41Sopenharmony_ci * 2821cb0ef41Sopenharmony_ci * \param callback to be invoked. 2831cb0ef41Sopenharmony_ci * \param data custom data that is passed to the callback. 2841cb0ef41Sopenharmony_ci */ 2851cb0ef41Sopenharmony_ci virtual void RegisterWeakCallback(WeakCallback callback, const void* data) {} 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci /** 2881cb0ef41Sopenharmony_ci * Defers tracing an object from a concurrent thread to the mutator thread. 2891cb0ef41Sopenharmony_ci * Should be called by Trace methods of types that are not safe to trace 2901cb0ef41Sopenharmony_ci * concurrently. 2911cb0ef41Sopenharmony_ci * 2921cb0ef41Sopenharmony_ci * \param parameter tells the trace callback which object was deferred. 2931cb0ef41Sopenharmony_ci * \param callback to be invoked for tracing on the mutator thread. 2941cb0ef41Sopenharmony_ci * \param deferred_size size of deferred object. 2951cb0ef41Sopenharmony_ci * 2961cb0ef41Sopenharmony_ci * \returns false if the object does not need to be deferred (i.e. currently 2971cb0ef41Sopenharmony_ci * traced on the mutator thread) and true otherwise (i.e. currently traced on 2981cb0ef41Sopenharmony_ci * a concurrent thread). 2991cb0ef41Sopenharmony_ci */ 3001cb0ef41Sopenharmony_ci virtual V8_WARN_UNUSED_RESULT bool DeferTraceToMutatorThreadIfConcurrent( 3011cb0ef41Sopenharmony_ci const void* parameter, TraceCallback callback, size_t deferred_size) { 3021cb0ef41Sopenharmony_ci // By default tracing is not deferred. 3031cb0ef41Sopenharmony_ci return false; 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci protected: 3071cb0ef41Sopenharmony_ci virtual void Visit(const void* self, TraceDescriptor) {} 3081cb0ef41Sopenharmony_ci virtual void VisitWeak(const void* self, TraceDescriptor, WeakCallback, 3091cb0ef41Sopenharmony_ci const void* weak_member) {} 3101cb0ef41Sopenharmony_ci virtual void VisitEphemeron(const void* key, const void* value, 3111cb0ef41Sopenharmony_ci TraceDescriptor value_desc) {} 3121cb0ef41Sopenharmony_ci virtual void VisitWeakContainer(const void* self, TraceDescriptor strong_desc, 3131cb0ef41Sopenharmony_ci TraceDescriptor weak_desc, 3141cb0ef41Sopenharmony_ci WeakCallback callback, const void* data) {} 3151cb0ef41Sopenharmony_ci virtual void HandleMovableReference(const void**) {} 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci private: 3181cb0ef41Sopenharmony_ci template <typename T, void (T::*method)(const LivenessBroker&)> 3191cb0ef41Sopenharmony_ci static void WeakCallbackMethodDelegate(const LivenessBroker& info, 3201cb0ef41Sopenharmony_ci const void* self) { 3211cb0ef41Sopenharmony_ci // Callback is registered through a potential const Trace method but needs 3221cb0ef41Sopenharmony_ci // to be able to modify fields. See HandleWeak. 3231cb0ef41Sopenharmony_ci (const_cast<T*>(static_cast<const T*>(self))->*method)(info); 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci template <typename PointerType> 3271cb0ef41Sopenharmony_ci static void HandleWeak(const LivenessBroker& info, const void* object) { 3281cb0ef41Sopenharmony_ci const PointerType* weak = static_cast<const PointerType*>(object); 3291cb0ef41Sopenharmony_ci auto* raw_ptr = weak->GetFromGC(); 3301cb0ef41Sopenharmony_ci if (!info.IsHeapObjectAlive(raw_ptr)) { 3311cb0ef41Sopenharmony_ci weak->ClearFromGC(); 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci template <typename T> 3361cb0ef41Sopenharmony_ci void TraceImpl(const T* t) { 3371cb0ef41Sopenharmony_ci static_assert(sizeof(T), "Pointee type must be fully defined."); 3381cb0ef41Sopenharmony_ci static_assert(internal::IsGarbageCollectedOrMixinType<T>::value, 3391cb0ef41Sopenharmony_ci "T must be GarbageCollected or GarbageCollectedMixin type"); 3401cb0ef41Sopenharmony_ci if (!t) { 3411cb0ef41Sopenharmony_ci return; 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci Visit(t, TraceTrait<T>::GetTraceDescriptor(t)); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 3471cb0ef41Sopenharmony_ci void CheckObjectNotInConstruction(const void* address); 3481cb0ef41Sopenharmony_ci#endif // V8_ENABLE_CHECKS 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci template <typename T, typename WeaknessPolicy, typename LocationPolicy, 3511cb0ef41Sopenharmony_ci typename CheckingPolicy> 3521cb0ef41Sopenharmony_ci friend class internal::BasicCrossThreadPersistent; 3531cb0ef41Sopenharmony_ci template <typename T, typename WeaknessPolicy, typename LocationPolicy, 3541cb0ef41Sopenharmony_ci typename CheckingPolicy> 3551cb0ef41Sopenharmony_ci friend class internal::BasicPersistent; 3561cb0ef41Sopenharmony_ci friend class internal::ConservativeTracingVisitor; 3571cb0ef41Sopenharmony_ci friend class internal::VisitorBase; 3581cb0ef41Sopenharmony_ci}; 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_cinamespace internal { 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ciclass V8_EXPORT RootVisitor { 3631cb0ef41Sopenharmony_ci public: 3641cb0ef41Sopenharmony_ci explicit RootVisitor(Visitor::Key) {} 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci virtual ~RootVisitor() = default; 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci template <typename AnyStrongPersistentType, 3691cb0ef41Sopenharmony_ci std::enable_if_t< 3701cb0ef41Sopenharmony_ci AnyStrongPersistentType::IsStrongPersistent::value>* = nullptr> 3711cb0ef41Sopenharmony_ci void Trace(const AnyStrongPersistentType& p) { 3721cb0ef41Sopenharmony_ci using PointeeType = typename AnyStrongPersistentType::PointeeType; 3731cb0ef41Sopenharmony_ci const void* object = Extract(p); 3741cb0ef41Sopenharmony_ci if (!object) { 3751cb0ef41Sopenharmony_ci return; 3761cb0ef41Sopenharmony_ci } 3771cb0ef41Sopenharmony_ci VisitRoot(object, TraceTrait<PointeeType>::GetTraceDescriptor(object), 3781cb0ef41Sopenharmony_ci p.Location()); 3791cb0ef41Sopenharmony_ci } 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci template <typename AnyWeakPersistentType, 3821cb0ef41Sopenharmony_ci std::enable_if_t< 3831cb0ef41Sopenharmony_ci !AnyWeakPersistentType::IsStrongPersistent::value>* = nullptr> 3841cb0ef41Sopenharmony_ci void Trace(const AnyWeakPersistentType& p) { 3851cb0ef41Sopenharmony_ci using PointeeType = typename AnyWeakPersistentType::PointeeType; 3861cb0ef41Sopenharmony_ci static_assert(!internal::IsAllocatedOnCompactableSpace<PointeeType>::value, 3871cb0ef41Sopenharmony_ci "Weak references to compactable objects are not allowed"); 3881cb0ef41Sopenharmony_ci const void* object = Extract(p); 3891cb0ef41Sopenharmony_ci if (!object) { 3901cb0ef41Sopenharmony_ci return; 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci VisitWeakRoot(object, TraceTrait<PointeeType>::GetTraceDescriptor(object), 3931cb0ef41Sopenharmony_ci &HandleWeak<AnyWeakPersistentType>, &p, p.Location()); 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci protected: 3971cb0ef41Sopenharmony_ci virtual void VisitRoot(const void*, TraceDescriptor, const SourceLocation&) {} 3981cb0ef41Sopenharmony_ci virtual void VisitWeakRoot(const void* self, TraceDescriptor, WeakCallback, 3991cb0ef41Sopenharmony_ci const void* weak_root, const SourceLocation&) {} 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci private: 4021cb0ef41Sopenharmony_ci template <typename AnyPersistentType> 4031cb0ef41Sopenharmony_ci static const void* Extract(AnyPersistentType& p) { 4041cb0ef41Sopenharmony_ci using PointeeType = typename AnyPersistentType::PointeeType; 4051cb0ef41Sopenharmony_ci static_assert(sizeof(PointeeType), 4061cb0ef41Sopenharmony_ci "Persistent's pointee type must be fully defined"); 4071cb0ef41Sopenharmony_ci static_assert(internal::IsGarbageCollectedOrMixinType<PointeeType>::value, 4081cb0ef41Sopenharmony_ci "Persistent's pointee type must be GarbageCollected or " 4091cb0ef41Sopenharmony_ci "GarbageCollectedMixin"); 4101cb0ef41Sopenharmony_ci return p.GetFromGC(); 4111cb0ef41Sopenharmony_ci } 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci template <typename PointerType> 4141cb0ef41Sopenharmony_ci static void HandleWeak(const LivenessBroker& info, const void* object) { 4151cb0ef41Sopenharmony_ci const PointerType* weak = static_cast<const PointerType*>(object); 4161cb0ef41Sopenharmony_ci auto* raw_ptr = weak->GetFromGC(); 4171cb0ef41Sopenharmony_ci if (!info.IsHeapObjectAlive(raw_ptr)) { 4181cb0ef41Sopenharmony_ci weak->ClearFromGC(); 4191cb0ef41Sopenharmony_ci } 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci}; 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci} // namespace internal 4241cb0ef41Sopenharmony_ci} // namespace cppgc 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci#endif // INCLUDE_CPPGC_VISITOR_H_ 427