11cb0ef41Sopenharmony_ci// Copyright 2023 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_HANDLE_BASE_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_V8_HANDLE_BASE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "v8-internal.h"  // NOLINT(build/include_directory)
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace internal {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci// Helper functions about values contained in handles.
151cb0ef41Sopenharmony_ci// A value is either an indirect pointer or a direct pointer, depending on
161cb0ef41Sopenharmony_ci// whether direct local support is enabled.
171cb0ef41Sopenharmony_ciclass ValueHelper final {
181cb0ef41Sopenharmony_ci public:
191cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_DIRECT_LOCAL
201cb0ef41Sopenharmony_ci  static constexpr Address kTaggedNullAddress = 1;
211cb0ef41Sopenharmony_ci  static constexpr Address kEmpty = kTaggedNullAddress;
221cb0ef41Sopenharmony_ci#else
231cb0ef41Sopenharmony_ci  static constexpr Address kEmpty = kNullAddress;
241cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_DIRECT_LOCAL
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci  template <typename T>
271cb0ef41Sopenharmony_ci  V8_INLINE static bool IsEmpty(T* value) {
281cb0ef41Sopenharmony_ci    return reinterpret_cast<Address>(value) == kEmpty;
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  // Returns a handle's "value" for all kinds of abstract handles. For Local,
321cb0ef41Sopenharmony_ci  // it is equivalent to `*handle`. The variadic parameters support handle
331cb0ef41Sopenharmony_ci  // types with extra type parameters, like `Persistent<T, M>`.
341cb0ef41Sopenharmony_ci  template <template <typename T, typename... Ms> typename H, typename T,
351cb0ef41Sopenharmony_ci            typename... Ms>
361cb0ef41Sopenharmony_ci  V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
371cb0ef41Sopenharmony_ci    return handle.template value<T>();
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_DIRECT_LOCAL
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  template <typename T>
431cb0ef41Sopenharmony_ci  V8_INLINE static Address ValueAsAddress(const T* value) {
441cb0ef41Sopenharmony_ci    return reinterpret_cast<Address>(value);
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  template <typename T, typename S>
481cb0ef41Sopenharmony_ci  V8_INLINE static T* SlotAsValue(S* slot) {
491cb0ef41Sopenharmony_ci    return *reinterpret_cast<T**>(slot);
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  template <typename T>
531cb0ef41Sopenharmony_ci  V8_INLINE static T* ValueAsSlot(T* const& value) {
541cb0ef41Sopenharmony_ci    return reinterpret_cast<T*>(const_cast<T**>(&value));
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci#else  // !V8_ENABLE_DIRECT_LOCAL
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  template <typename T>
601cb0ef41Sopenharmony_ci  V8_INLINE static Address ValueAsAddress(const T* value) {
611cb0ef41Sopenharmony_ci    return *reinterpret_cast<const Address*>(value);
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  template <typename T, typename S>
651cb0ef41Sopenharmony_ci  V8_INLINE static T* SlotAsValue(S* slot) {
661cb0ef41Sopenharmony_ci    return reinterpret_cast<T*>(slot);
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  template <typename T>
701cb0ef41Sopenharmony_ci  V8_INLINE static T* ValueAsSlot(T* const& value) {
711cb0ef41Sopenharmony_ci    return value;
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_DIRECT_LOCAL
751cb0ef41Sopenharmony_ci};
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci/**
781cb0ef41Sopenharmony_ci * Helper functions about handles.
791cb0ef41Sopenharmony_ci */
801cb0ef41Sopenharmony_ciclass HandleHelper final {
811cb0ef41Sopenharmony_ci public:
821cb0ef41Sopenharmony_ci  /**
831cb0ef41Sopenharmony_ci   * Checks whether two handles are equal.
841cb0ef41Sopenharmony_ci   * They are equal iff they are both empty or they are both non-empty and the
851cb0ef41Sopenharmony_ci   * objects to which they refer are physically equal.
861cb0ef41Sopenharmony_ci   *
871cb0ef41Sopenharmony_ci   * If both handles refer to JS objects, this is the same as strict equality.
881cb0ef41Sopenharmony_ci   * For primitives, such as numbers or strings, a `false` return value does not
891cb0ef41Sopenharmony_ci   * indicate that the values aren't equal in the JavaScript sense.
901cb0ef41Sopenharmony_ci   * Use `Value::StrictEquals()` to check primitives for equality.
911cb0ef41Sopenharmony_ci   */
921cb0ef41Sopenharmony_ci  template <typename T1, typename T2>
931cb0ef41Sopenharmony_ci  V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
941cb0ef41Sopenharmony_ci    if (lhs.IsEmpty()) return rhs.IsEmpty();
951cb0ef41Sopenharmony_ci    if (rhs.IsEmpty()) return false;
961cb0ef41Sopenharmony_ci    return lhs.ptr() == rhs.ptr();
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci};
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci}  // namespace internal
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci/**
1031cb0ef41Sopenharmony_ci * A base class for abstract handles containing indirect pointers.
1041cb0ef41Sopenharmony_ci * These are useful regardless of whether direct local support is enabled.
1051cb0ef41Sopenharmony_ci */
1061cb0ef41Sopenharmony_ciclass IndirectHandleBase {
1071cb0ef41Sopenharmony_ci public:
1081cb0ef41Sopenharmony_ci  // Returns true if the handle is empty.
1091cb0ef41Sopenharmony_ci  V8_INLINE bool IsEmpty() const { return location_ == nullptr; }
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  // Sets the handle to be empty. IsEmpty() will then return true.
1121cb0ef41Sopenharmony_ci  V8_INLINE void Clear() { location_ = nullptr; }
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci protected:
1151cb0ef41Sopenharmony_ci  friend class internal::ValueHelper;
1161cb0ef41Sopenharmony_ci  friend class internal::HandleHelper;
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  V8_INLINE IndirectHandleBase() = default;
1191cb0ef41Sopenharmony_ci  V8_INLINE IndirectHandleBase(const IndirectHandleBase& other) = default;
1201cb0ef41Sopenharmony_ci  V8_INLINE IndirectHandleBase& operator=(const IndirectHandleBase& that) =
1211cb0ef41Sopenharmony_ci      default;
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  V8_INLINE explicit IndirectHandleBase(internal::Address* location)
1241cb0ef41Sopenharmony_ci      : location_(location) {}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci  // Returns the address of the actual heap object (tagged).
1271cb0ef41Sopenharmony_ci  // This method must be called only if the handle is not empty, otherwise it
1281cb0ef41Sopenharmony_ci  // will crash.
1291cb0ef41Sopenharmony_ci  V8_INLINE internal::Address ptr() const { return *location_; }
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  // Returns a reference to the slot (indirect pointer).
1321cb0ef41Sopenharmony_ci  V8_INLINE internal::Address* const& slot() const { return location_; }
1331cb0ef41Sopenharmony_ci  V8_INLINE internal::Address*& slot() { return location_; }
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  // Returns the handler's "value" (direct or indirect pointer, depending on
1361cb0ef41Sopenharmony_ci  // whether direct local support is enabled).
1371cb0ef41Sopenharmony_ci  template <typename T>
1381cb0ef41Sopenharmony_ci  V8_INLINE T* value() const {
1391cb0ef41Sopenharmony_ci    return internal::ValueHelper::SlotAsValue<T>(slot());
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci private:
1431cb0ef41Sopenharmony_ci  internal::Address* location_ = nullptr;
1441cb0ef41Sopenharmony_ci};
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_DIRECT_LOCAL
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci/**
1491cb0ef41Sopenharmony_ci * A base class for abstract handles containing direct pointers.
1501cb0ef41Sopenharmony_ci * These are only possible when conservative stack scanning is enabled.
1511cb0ef41Sopenharmony_ci */
1521cb0ef41Sopenharmony_ciclass DirectHandleBase {
1531cb0ef41Sopenharmony_ci public:
1541cb0ef41Sopenharmony_ci  // Returns true if the handle is empty.
1551cb0ef41Sopenharmony_ci  V8_INLINE bool IsEmpty() const {
1561cb0ef41Sopenharmony_ci    return ptr_ == internal::ValueHelper::kEmpty;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  // Sets the handle to be empty. IsEmpty() will then return true.
1601cb0ef41Sopenharmony_ci  V8_INLINE void Clear() { ptr_ = internal::ValueHelper::kEmpty; }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci protected:
1631cb0ef41Sopenharmony_ci  friend class internal::ValueHelper;
1641cb0ef41Sopenharmony_ci  friend class internal::HandleHelper;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  V8_INLINE DirectHandleBase() = default;
1671cb0ef41Sopenharmony_ci  V8_INLINE DirectHandleBase(const DirectHandleBase& other) = default;
1681cb0ef41Sopenharmony_ci  V8_INLINE DirectHandleBase& operator=(const DirectHandleBase& that) = default;
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  V8_INLINE explicit DirectHandleBase(internal::Address ptr) : ptr_(ptr) {}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  // Returns the address of the referenced object.
1731cb0ef41Sopenharmony_ci  V8_INLINE internal::Address ptr() const { return ptr_; }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // Returns the handler's "value" (direct pointer, as direct local support
1761cb0ef41Sopenharmony_ci  // is guaranteed to be enabled here).
1771cb0ef41Sopenharmony_ci  template <typename T>
1781cb0ef41Sopenharmony_ci  V8_INLINE T* value() const {
1791cb0ef41Sopenharmony_ci    return reinterpret_cast<T*>(ptr_);
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci private:
1831cb0ef41Sopenharmony_ci  internal::Address ptr_ = internal::ValueHelper::kEmpty;
1841cb0ef41Sopenharmony_ci};
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_DIRECT_LOCAL
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci}  // namespace v8
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci#endif  // INCLUDE_V8_HANDLE_BASE_H_
191