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