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