11cb0ef41Sopenharmony_ci// Copyright 2021 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_V8_TRACED_HANDLE_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_V8_TRACED_HANDLE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <stddef.h>
91cb0ef41Sopenharmony_ci#include <stdint.h>
101cb0ef41Sopenharmony_ci#include <stdio.h>
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <atomic>
131cb0ef41Sopenharmony_ci#include <memory>
141cb0ef41Sopenharmony_ci#include <type_traits>
151cb0ef41Sopenharmony_ci#include <utility>
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci#include "v8-internal.h"            // NOLINT(build/include_directory)
181cb0ef41Sopenharmony_ci#include "v8-local-handle.h"        // NOLINT(build/include_directory)
191cb0ef41Sopenharmony_ci#include "v8-weak-callback-info.h"  // NOLINT(build/include_directory)
201cb0ef41Sopenharmony_ci#include "v8config.h"               // NOLINT(build/include_directory)
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace v8 {
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciclass Value;
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace internal {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciclass BasicTracedReferenceExtractor;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_cienum class GlobalHandleStoreMode {
311cb0ef41Sopenharmony_ci  kInitializingStore,
321cb0ef41Sopenharmony_ci  kAssigningStore,
331cb0ef41Sopenharmony_ci};
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciV8_EXPORT internal::Address* GlobalizeTracedReference(
361cb0ef41Sopenharmony_ci    internal::Isolate* isolate, internal::Address value,
371cb0ef41Sopenharmony_ci    internal::Address* slot, GlobalHandleStoreMode store_mode);
381cb0ef41Sopenharmony_ciV8_EXPORT void MoveTracedReference(internal::Address** from,
391cb0ef41Sopenharmony_ci                                   internal::Address** to);
401cb0ef41Sopenharmony_ciV8_EXPORT void CopyTracedReference(const internal::Address* const* from,
411cb0ef41Sopenharmony_ci                                   internal::Address** to);
421cb0ef41Sopenharmony_ciV8_EXPORT void DisposeTracedReference(internal::Address* global_handle);
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci}  // namespace internal
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci/**
471cb0ef41Sopenharmony_ci * An indirect handle, where the indirect pointer points to a GlobalHandles
481cb0ef41Sopenharmony_ci * node.
491cb0ef41Sopenharmony_ci */
501cb0ef41Sopenharmony_ciclass TracedReferenceBase : public IndirectHandleBase {
511cb0ef41Sopenharmony_ci public:
521cb0ef41Sopenharmony_ci  /**
531cb0ef41Sopenharmony_ci   * If non-empty, destroy the underlying storage cell. |IsEmpty| will return
541cb0ef41Sopenharmony_ci   * true after this call.
551cb0ef41Sopenharmony_ci   */
561cb0ef41Sopenharmony_ci  V8_INLINE void Reset();
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  /**
591cb0ef41Sopenharmony_ci   * Construct a Local<Value> from this handle.
601cb0ef41Sopenharmony_ci   */
611cb0ef41Sopenharmony_ci  V8_INLINE Local<Value> Get(Isolate* isolate) const {
621cb0ef41Sopenharmony_ci    if (IsEmpty()) return Local<Value>();
631cb0ef41Sopenharmony_ci    return Local<Value>::New(isolate, this->value<Value>());
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  /**
671cb0ef41Sopenharmony_ci   * Returns true if this TracedReference is empty, i.e., has not been
681cb0ef41Sopenharmony_ci   * assigned an object. This version of IsEmpty is thread-safe.
691cb0ef41Sopenharmony_ci   */
701cb0ef41Sopenharmony_ci  bool IsEmptyThreadSafe() const {
711cb0ef41Sopenharmony_ci    return this->GetSlotThreadSafe() == nullptr;
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  /**
751cb0ef41Sopenharmony_ci   * Assigns a wrapper class ID to the handle.
761cb0ef41Sopenharmony_ci   */
771cb0ef41Sopenharmony_ci  V8_INLINE void SetWrapperClassId(uint16_t class_id);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  /**
801cb0ef41Sopenharmony_ci   * Returns the class ID previously assigned to this handle or 0 if no class ID
811cb0ef41Sopenharmony_ci   * was previously assigned.
821cb0ef41Sopenharmony_ci   */
831cb0ef41Sopenharmony_ci  V8_INLINE uint16_t WrapperClassId() const;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci protected:
861cb0ef41Sopenharmony_ci  V8_INLINE TracedReferenceBase() = default;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  /**
891cb0ef41Sopenharmony_ci   * Update this reference in a thread-safe way.
901cb0ef41Sopenharmony_ci   */
911cb0ef41Sopenharmony_ci  void SetSlotThreadSafe(void* new_val) {
921cb0ef41Sopenharmony_ci    reinterpret_cast<std::atomic<void*>*>(&slot())->store(
931cb0ef41Sopenharmony_ci        new_val, std::memory_order_relaxed);
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  /**
971cb0ef41Sopenharmony_ci   * Get this reference in a thread-safe way
981cb0ef41Sopenharmony_ci   */
991cb0ef41Sopenharmony_ci  const void* GetSlotThreadSafe() const {
1001cb0ef41Sopenharmony_ci    return reinterpret_cast<std::atomic<const void*> const*>(&slot())->load(
1011cb0ef41Sopenharmony_ci        std::memory_order_relaxed);
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  V8_EXPORT void CheckValue() const;
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  friend class internal::BasicTracedReferenceExtractor;
1071cb0ef41Sopenharmony_ci  template <typename F>
1081cb0ef41Sopenharmony_ci  friend class Local;
1091cb0ef41Sopenharmony_ci  template <typename U>
1101cb0ef41Sopenharmony_ci  friend bool operator==(const TracedReferenceBase&, const Local<U>&);
1111cb0ef41Sopenharmony_ci  friend bool operator==(const TracedReferenceBase&,
1121cb0ef41Sopenharmony_ci                         const TracedReferenceBase&);
1131cb0ef41Sopenharmony_ci};
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci/**
1161cb0ef41Sopenharmony_ci * A traced handle with copy and move semantics. The handle is to be used
1171cb0ef41Sopenharmony_ci * together as part of GarbageCollected objects (see v8-cppgc.h) or from stack
1181cb0ef41Sopenharmony_ci * and specifies edges from C++ objects to JavaScript.
1191cb0ef41Sopenharmony_ci *
1201cb0ef41Sopenharmony_ci * The exact semantics are:
1211cb0ef41Sopenharmony_ci * - Tracing garbage collections using CppHeap.
1221cb0ef41Sopenharmony_ci * - Non-tracing garbage collections refer to
1231cb0ef41Sopenharmony_ci *   |v8::EmbedderRootsHandler::IsRoot()| whether the handle should
1241cb0ef41Sopenharmony_ci * be treated as root or not.
1251cb0ef41Sopenharmony_ci *
1261cb0ef41Sopenharmony_ci * Note that the base class cannot be instantiated itself, use |TracedReference|
1271cb0ef41Sopenharmony_ci * instead.
1281cb0ef41Sopenharmony_ci */
1291cb0ef41Sopenharmony_citemplate <typename T>
1301cb0ef41Sopenharmony_ciclass BasicTracedReference : public TracedReferenceBase {
1311cb0ef41Sopenharmony_ci public:
1321cb0ef41Sopenharmony_ci  /**
1331cb0ef41Sopenharmony_ci   * Construct a Local<T> from this handle.
1341cb0ef41Sopenharmony_ci   */
1351cb0ef41Sopenharmony_ci  Local<T> Get(Isolate* isolate) const { return Local<T>::New(isolate, *this); }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  template <class S>
1381cb0ef41Sopenharmony_ci  V8_INLINE BasicTracedReference<S>& As() const {
1391cb0ef41Sopenharmony_ci    return reinterpret_cast<BasicTracedReference<S>&>(
1401cb0ef41Sopenharmony_ci        const_cast<BasicTracedReference<T>&>(*this));
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  V8_DEPRECATE_SOON("Use Get to convert to Local instead")
1441cb0ef41Sopenharmony_ci  V8_INLINE T* operator->() const {
1451cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_CHECKS
1461cb0ef41Sopenharmony_ci    CheckValue();
1471cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_CHECKS
1481cb0ef41Sopenharmony_ci    return this->template value<T>();
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  V8_DEPRECATE_SOON("Use Get to convert to Local instead")
1521cb0ef41Sopenharmony_ci  V8_INLINE T* operator*() const { return this->operator->(); }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci private:
1551cb0ef41Sopenharmony_ci  /**
1561cb0ef41Sopenharmony_ci   * An empty BasicTracedReference without storage cell.
1571cb0ef41Sopenharmony_ci   */
1581cb0ef41Sopenharmony_ci  BasicTracedReference() = default;
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  V8_INLINE static internal::Address* New(
1611cb0ef41Sopenharmony_ci      Isolate* isolate, T* that, internal::Address** slot,
1621cb0ef41Sopenharmony_ci      internal::GlobalHandleStoreMode store_mode);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  template <typename F>
1651cb0ef41Sopenharmony_ci  friend class Local;
1661cb0ef41Sopenharmony_ci  friend class Object;
1671cb0ef41Sopenharmony_ci  template <typename F>
1681cb0ef41Sopenharmony_ci  friend class TracedReference;
1691cb0ef41Sopenharmony_ci  template <typename F>
1701cb0ef41Sopenharmony_ci  friend class BasicTracedReference;
1711cb0ef41Sopenharmony_ci  template <typename F>
1721cb0ef41Sopenharmony_ci  friend class ReturnValue;
1731cb0ef41Sopenharmony_ci};
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci/**
1761cb0ef41Sopenharmony_ci * A traced handle without destructor that clears the handle. The embedder needs
1771cb0ef41Sopenharmony_ci * to ensure that the handle is not accessed once the V8 object has been
1781cb0ef41Sopenharmony_ci * reclaimed. For more details see BasicTracedReference.
1791cb0ef41Sopenharmony_ci */
1801cb0ef41Sopenharmony_citemplate <typename T>
1811cb0ef41Sopenharmony_ciclass TracedReference : public BasicTracedReference<T> {
1821cb0ef41Sopenharmony_ci public:
1831cb0ef41Sopenharmony_ci  using BasicTracedReference<T>::Reset;
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  /**
1861cb0ef41Sopenharmony_ci   * An empty TracedReference without storage cell.
1871cb0ef41Sopenharmony_ci   */
1881cb0ef41Sopenharmony_ci  V8_INLINE TracedReference() = default;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  /**
1911cb0ef41Sopenharmony_ci   * Construct a TracedReference from a Local.
1921cb0ef41Sopenharmony_ci   *
1931cb0ef41Sopenharmony_ci   * When the Local is non-empty, a new storage cell is created
1941cb0ef41Sopenharmony_ci   * pointing to the same object.
1951cb0ef41Sopenharmony_ci   */
1961cb0ef41Sopenharmony_ci  template <class S>
1971cb0ef41Sopenharmony_ci  TracedReference(Isolate* isolate, Local<S> that) : BasicTracedReference<T>() {
1981cb0ef41Sopenharmony_ci    this->slot() =
1991cb0ef41Sopenharmony_ci        this->New(isolate, *that, &this->slot(),
2001cb0ef41Sopenharmony_ci                  internal::GlobalHandleStoreMode::kInitializingStore);
2011cb0ef41Sopenharmony_ci    static_assert(std::is_base_of<T, S>::value, "type check");
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  /**
2051cb0ef41Sopenharmony_ci   * Move constructor initializing TracedReference from an
2061cb0ef41Sopenharmony_ci   * existing one.
2071cb0ef41Sopenharmony_ci   */
2081cb0ef41Sopenharmony_ci  V8_INLINE TracedReference(TracedReference&& other) noexcept {
2091cb0ef41Sopenharmony_ci    // Forward to operator=.
2101cb0ef41Sopenharmony_ci    *this = std::move(other);
2111cb0ef41Sopenharmony_ci  }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  /**
2141cb0ef41Sopenharmony_ci   * Move constructor initializing TracedReference from an
2151cb0ef41Sopenharmony_ci   * existing one.
2161cb0ef41Sopenharmony_ci   */
2171cb0ef41Sopenharmony_ci  template <typename S>
2181cb0ef41Sopenharmony_ci  V8_INLINE TracedReference(TracedReference<S>&& other) noexcept {
2191cb0ef41Sopenharmony_ci    // Forward to operator=.
2201cb0ef41Sopenharmony_ci    *this = std::move(other);
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  /**
2241cb0ef41Sopenharmony_ci   * Copy constructor initializing TracedReference from an
2251cb0ef41Sopenharmony_ci   * existing one.
2261cb0ef41Sopenharmony_ci   */
2271cb0ef41Sopenharmony_ci  V8_INLINE TracedReference(const TracedReference& other) {
2281cb0ef41Sopenharmony_ci    // Forward to operator=;
2291cb0ef41Sopenharmony_ci    *this = other;
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  /**
2331cb0ef41Sopenharmony_ci   * Copy constructor initializing TracedReference from an
2341cb0ef41Sopenharmony_ci   * existing one.
2351cb0ef41Sopenharmony_ci   */
2361cb0ef41Sopenharmony_ci  template <typename S>
2371cb0ef41Sopenharmony_ci  V8_INLINE TracedReference(const TracedReference<S>& other) {
2381cb0ef41Sopenharmony_ci    // Forward to operator=;
2391cb0ef41Sopenharmony_ci    *this = other;
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  /**
2431cb0ef41Sopenharmony_ci   * Move assignment operator initializing TracedReference from an existing one.
2441cb0ef41Sopenharmony_ci   */
2451cb0ef41Sopenharmony_ci  V8_INLINE TracedReference& operator=(TracedReference&& rhs) noexcept;
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  /**
2481cb0ef41Sopenharmony_ci   * Move assignment operator initializing TracedReference from an existing one.
2491cb0ef41Sopenharmony_ci   */
2501cb0ef41Sopenharmony_ci  template <class S>
2511cb0ef41Sopenharmony_ci  V8_INLINE TracedReference& operator=(TracedReference<S>&& rhs) noexcept;
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  /**
2541cb0ef41Sopenharmony_ci   * Copy assignment operator initializing TracedReference from an existing one.
2551cb0ef41Sopenharmony_ci   */
2561cb0ef41Sopenharmony_ci  V8_INLINE TracedReference& operator=(const TracedReference& rhs);
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  /**
2591cb0ef41Sopenharmony_ci   * Copy assignment operator initializing TracedReference from an existing one.
2601cb0ef41Sopenharmony_ci   */
2611cb0ef41Sopenharmony_ci  template <class S>
2621cb0ef41Sopenharmony_ci  V8_INLINE TracedReference& operator=(const TracedReference<S>& rhs);
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci  /**
2651cb0ef41Sopenharmony_ci   * If non-empty, destroy the underlying storage cell and create a new one with
2661cb0ef41Sopenharmony_ci   * the contents of other if other is non empty
2671cb0ef41Sopenharmony_ci   */
2681cb0ef41Sopenharmony_ci  template <class S>
2691cb0ef41Sopenharmony_ci  V8_INLINE void Reset(Isolate* isolate, const Local<S>& other);
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  template <class S>
2721cb0ef41Sopenharmony_ci  V8_INLINE TracedReference<S>& As() const {
2731cb0ef41Sopenharmony_ci    return reinterpret_cast<TracedReference<S>&>(
2741cb0ef41Sopenharmony_ci        const_cast<TracedReference<T>&>(*this));
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci};
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci// --- Implementation ---
2791cb0ef41Sopenharmony_citemplate <class T>
2801cb0ef41Sopenharmony_ciinternal::Address* BasicTracedReference<T>::New(
2811cb0ef41Sopenharmony_ci    Isolate* isolate, T* that, internal::Address** slot,
2821cb0ef41Sopenharmony_ci    internal::GlobalHandleStoreMode store_mode) {
2831cb0ef41Sopenharmony_ci  if (internal::ValueHelper::IsEmpty(that)) return nullptr;
2841cb0ef41Sopenharmony_ci  return internal::GlobalizeTracedReference(
2851cb0ef41Sopenharmony_ci      reinterpret_cast<internal::Isolate*>(isolate),
2861cb0ef41Sopenharmony_ci      internal::ValueHelper::ValueAsAddress(that),
2871cb0ef41Sopenharmony_ci      reinterpret_cast<internal::Address*>(slot), store_mode);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_civoid TracedReferenceBase::Reset() {
2911cb0ef41Sopenharmony_ci  if (IsEmpty()) return;
2921cb0ef41Sopenharmony_ci  internal::DisposeTracedReference(slot());
2931cb0ef41Sopenharmony_ci  SetSlotThreadSafe(nullptr);
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ciV8_INLINE bool operator==(const TracedReferenceBase& lhs,
2971cb0ef41Sopenharmony_ci                          const TracedReferenceBase& rhs) {
2981cb0ef41Sopenharmony_ci  return internal::HandleHelper::EqualHandles(lhs, rhs);
2991cb0ef41Sopenharmony_ci}
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_citemplate <typename U>
3021cb0ef41Sopenharmony_ciV8_INLINE bool operator==(const TracedReferenceBase& lhs,
3031cb0ef41Sopenharmony_ci                          const v8::Local<U>& rhs) {
3041cb0ef41Sopenharmony_ci  return internal::HandleHelper::EqualHandles(lhs, rhs);
3051cb0ef41Sopenharmony_ci}
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_citemplate <typename U>
3081cb0ef41Sopenharmony_ciV8_INLINE bool operator==(const v8::Local<U>& lhs,
3091cb0ef41Sopenharmony_ci                          const TracedReferenceBase& rhs) {
3101cb0ef41Sopenharmony_ci  return rhs == lhs;
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ciV8_INLINE bool operator!=(const TracedReferenceBase& lhs,
3141cb0ef41Sopenharmony_ci                          const TracedReferenceBase& rhs) {
3151cb0ef41Sopenharmony_ci  return !(lhs == rhs);
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_citemplate <typename U>
3191cb0ef41Sopenharmony_ciV8_INLINE bool operator!=(const TracedReferenceBase& lhs,
3201cb0ef41Sopenharmony_ci                          const v8::Local<U>& rhs) {
3211cb0ef41Sopenharmony_ci  return !(lhs == rhs);
3221cb0ef41Sopenharmony_ci}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_citemplate <typename U>
3251cb0ef41Sopenharmony_ciV8_INLINE bool operator!=(const v8::Local<U>& lhs,
3261cb0ef41Sopenharmony_ci                          const TracedReferenceBase& rhs) {
3271cb0ef41Sopenharmony_ci  return !(rhs == lhs);
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_citemplate <class T>
3311cb0ef41Sopenharmony_citemplate <class S>
3321cb0ef41Sopenharmony_civoid TracedReference<T>::Reset(Isolate* isolate, const Local<S>& other) {
3331cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
3341cb0ef41Sopenharmony_ci  this->Reset();
3351cb0ef41Sopenharmony_ci  if (other.IsEmpty()) return;
3361cb0ef41Sopenharmony_ci  this->SetSlotThreadSafe(
3371cb0ef41Sopenharmony_ci      this->New(isolate, *other, &this->slot(),
3381cb0ef41Sopenharmony_ci                internal::GlobalHandleStoreMode::kAssigningStore));
3391cb0ef41Sopenharmony_ci}
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_citemplate <class T>
3421cb0ef41Sopenharmony_citemplate <class S>
3431cb0ef41Sopenharmony_ciTracedReference<T>& TracedReference<T>::operator=(
3441cb0ef41Sopenharmony_ci    TracedReference<S>&& rhs) noexcept {
3451cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
3461cb0ef41Sopenharmony_ci  *this = std::move(rhs.template As<T>());
3471cb0ef41Sopenharmony_ci  return *this;
3481cb0ef41Sopenharmony_ci}
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_citemplate <class T>
3511cb0ef41Sopenharmony_citemplate <class S>
3521cb0ef41Sopenharmony_ciTracedReference<T>& TracedReference<T>::operator=(
3531cb0ef41Sopenharmony_ci    const TracedReference<S>& rhs) {
3541cb0ef41Sopenharmony_ci  static_assert(std::is_base_of<T, S>::value, "type check");
3551cb0ef41Sopenharmony_ci  *this = rhs.template As<T>();
3561cb0ef41Sopenharmony_ci  return *this;
3571cb0ef41Sopenharmony_ci}
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_citemplate <class T>
3601cb0ef41Sopenharmony_ciTracedReference<T>& TracedReference<T>::operator=(
3611cb0ef41Sopenharmony_ci    TracedReference&& rhs) noexcept {
3621cb0ef41Sopenharmony_ci  if (this != &rhs) {
3631cb0ef41Sopenharmony_ci    internal::MoveTracedReference(&rhs.slot(), &this->slot());
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci  return *this;
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_citemplate <class T>
3691cb0ef41Sopenharmony_ciTracedReference<T>& TracedReference<T>::operator=(const TracedReference& rhs) {
3701cb0ef41Sopenharmony_ci  if (this != &rhs) {
3711cb0ef41Sopenharmony_ci    this->Reset();
3721cb0ef41Sopenharmony_ci    if (!rhs.IsEmpty()) {
3731cb0ef41Sopenharmony_ci      internal::CopyTracedReference(&rhs.slot(), &this->slot());
3741cb0ef41Sopenharmony_ci    }
3751cb0ef41Sopenharmony_ci  }
3761cb0ef41Sopenharmony_ci  return *this;
3771cb0ef41Sopenharmony_ci}
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_civoid TracedReferenceBase::SetWrapperClassId(uint16_t class_id) {
3801cb0ef41Sopenharmony_ci  using I = internal::Internals;
3811cb0ef41Sopenharmony_ci  if (IsEmpty()) return;
3821cb0ef41Sopenharmony_ci  uint8_t* addr =
3831cb0ef41Sopenharmony_ci      reinterpret_cast<uint8_t*>(slot()) + I::kTracedNodeClassIdOffset;
3841cb0ef41Sopenharmony_ci  *reinterpret_cast<uint16_t*>(addr) = class_id;
3851cb0ef41Sopenharmony_ci}
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ciuint16_t TracedReferenceBase::WrapperClassId() const {
3881cb0ef41Sopenharmony_ci  using I = internal::Internals;
3891cb0ef41Sopenharmony_ci  if (IsEmpty()) return 0;
3901cb0ef41Sopenharmony_ci  uint8_t* addr =
3911cb0ef41Sopenharmony_ci      reinterpret_cast<uint8_t*>(slot()) + I::kTracedNodeClassIdOffset;
3921cb0ef41Sopenharmony_ci  return *reinterpret_cast<uint16_t*>(addr);
3931cb0ef41Sopenharmony_ci}
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci}  // namespace v8
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci#endif  // INCLUDE_V8_TRACED_HANDLE_H_
398