1// Copyright 2023 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef INCLUDE_V8_HANDLE_BASE_H_ 6#define INCLUDE_V8_HANDLE_BASE_H_ 7 8#include "v8-internal.h" // NOLINT(build/include_directory) 9 10namespace v8 { 11 12namespace internal { 13 14// Helper functions about values contained in handles. 15// A value is either an indirect pointer or a direct pointer, depending on 16// whether direct local support is enabled. 17class ValueHelper final { 18 public: 19#ifdef V8_ENABLE_DIRECT_LOCAL 20 static constexpr Address kTaggedNullAddress = 1; 21 static constexpr Address kEmpty = kTaggedNullAddress; 22#else 23 static constexpr Address kEmpty = kNullAddress; 24#endif // V8_ENABLE_DIRECT_LOCAL 25 26 template <typename T> 27 V8_INLINE static bool IsEmpty(T* value) { 28 return reinterpret_cast<Address>(value) == kEmpty; 29 } 30 31 // Returns a handle's "value" for all kinds of abstract handles. For Local, 32 // it is equivalent to `*handle`. The variadic parameters support handle 33 // types with extra type parameters, like `Persistent<T, M>`. 34 template <template <typename T, typename... Ms> typename H, typename T, 35 typename... Ms> 36 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) { 37 return handle.template value<T>(); 38 } 39 40#ifdef V8_ENABLE_DIRECT_LOCAL 41 42 template <typename T> 43 V8_INLINE static Address ValueAsAddress(const T* value) { 44 return reinterpret_cast<Address>(value); 45 } 46 47 template <typename T, typename S> 48 V8_INLINE static T* SlotAsValue(S* slot) { 49 return *reinterpret_cast<T**>(slot); 50 } 51 52 template <typename T> 53 V8_INLINE static T* ValueAsSlot(T* const& value) { 54 return reinterpret_cast<T*>(const_cast<T**>(&value)); 55 } 56 57#else // !V8_ENABLE_DIRECT_LOCAL 58 59 template <typename T> 60 V8_INLINE static Address ValueAsAddress(const T* value) { 61 return *reinterpret_cast<const Address*>(value); 62 } 63 64 template <typename T, typename S> 65 V8_INLINE static T* SlotAsValue(S* slot) { 66 return reinterpret_cast<T*>(slot); 67 } 68 69 template <typename T> 70 V8_INLINE static T* ValueAsSlot(T* const& value) { 71 return value; 72 } 73 74#endif // V8_ENABLE_DIRECT_LOCAL 75}; 76 77/** 78 * Helper functions about handles. 79 */ 80class HandleHelper final { 81 public: 82 /** 83 * Checks whether two handles are equal. 84 * They are equal iff they are both empty or they are both non-empty and the 85 * objects to which they refer are physically equal. 86 * 87 * If both handles refer to JS objects, this is the same as strict equality. 88 * For primitives, such as numbers or strings, a `false` return value does not 89 * indicate that the values aren't equal in the JavaScript sense. 90 * Use `Value::StrictEquals()` to check primitives for equality. 91 */ 92 template <typename T1, typename T2> 93 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) { 94 if (lhs.IsEmpty()) return rhs.IsEmpty(); 95 if (rhs.IsEmpty()) return false; 96 return lhs.ptr() == rhs.ptr(); 97 } 98}; 99 100} // namespace internal 101 102/** 103 * A base class for abstract handles containing indirect pointers. 104 * These are useful regardless of whether direct local support is enabled. 105 */ 106class IndirectHandleBase { 107 public: 108 // Returns true if the handle is empty. 109 V8_INLINE bool IsEmpty() const { return location_ == nullptr; } 110 111 // Sets the handle to be empty. IsEmpty() will then return true. 112 V8_INLINE void Clear() { location_ = nullptr; } 113 114 protected: 115 friend class internal::ValueHelper; 116 friend class internal::HandleHelper; 117 118 V8_INLINE IndirectHandleBase() = default; 119 V8_INLINE IndirectHandleBase(const IndirectHandleBase& other) = default; 120 V8_INLINE IndirectHandleBase& operator=(const IndirectHandleBase& that) = 121 default; 122 123 V8_INLINE explicit IndirectHandleBase(internal::Address* location) 124 : location_(location) {} 125 126 // Returns the address of the actual heap object (tagged). 127 // This method must be called only if the handle is not empty, otherwise it 128 // will crash. 129 V8_INLINE internal::Address ptr() const { return *location_; } 130 131 // Returns a reference to the slot (indirect pointer). 132 V8_INLINE internal::Address* const& slot() const { return location_; } 133 V8_INLINE internal::Address*& slot() { return location_; } 134 135 // Returns the handler's "value" (direct or indirect pointer, depending on 136 // whether direct local support is enabled). 137 template <typename T> 138 V8_INLINE T* value() const { 139 return internal::ValueHelper::SlotAsValue<T>(slot()); 140 } 141 142 private: 143 internal::Address* location_ = nullptr; 144}; 145 146#ifdef V8_ENABLE_DIRECT_LOCAL 147 148/** 149 * A base class for abstract handles containing direct pointers. 150 * These are only possible when conservative stack scanning is enabled. 151 */ 152class DirectHandleBase { 153 public: 154 // Returns true if the handle is empty. 155 V8_INLINE bool IsEmpty() const { 156 return ptr_ == internal::ValueHelper::kEmpty; 157 } 158 159 // Sets the handle to be empty. IsEmpty() will then return true. 160 V8_INLINE void Clear() { ptr_ = internal::ValueHelper::kEmpty; } 161 162 protected: 163 friend class internal::ValueHelper; 164 friend class internal::HandleHelper; 165 166 V8_INLINE DirectHandleBase() = default; 167 V8_INLINE DirectHandleBase(const DirectHandleBase& other) = default; 168 V8_INLINE DirectHandleBase& operator=(const DirectHandleBase& that) = default; 169 170 V8_INLINE explicit DirectHandleBase(internal::Address ptr) : ptr_(ptr) {} 171 172 // Returns the address of the referenced object. 173 V8_INLINE internal::Address ptr() const { return ptr_; } 174 175 // Returns the handler's "value" (direct pointer, as direct local support 176 // is guaranteed to be enabled here). 177 template <typename T> 178 V8_INLINE T* value() const { 179 return reinterpret_cast<T*>(ptr_); 180 } 181 182 private: 183 internal::Address ptr_ = internal::ValueHelper::kEmpty; 184}; 185 186#endif // V8_ENABLE_DIRECT_LOCAL 187 188} // namespace v8 189 190#endif // INCLUDE_V8_HANDLE_BASE_H_ 191