1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef INCLUDE_V8_HANDLE_BASE_H_
#define INCLUDE_V8_HANDLE_BASE_H_
#include "v8-internal.h" // NOLINT(build/include_directory)
namespace v8::api_internal {
template <bool check_statically_enabled>
class StackAllocated {
public:
V8_INLINE StackAllocated() = default;
protected:
struct no_checking_tag {};
static constexpr no_checking_tag do_not_check{};
V8_INLINE explicit StackAllocated(no_checking_tag) {}
V8_INLINE explicit StackAllocated(const StackAllocated& other,
no_checking_tag) {}
V8_INLINE void VerifyOnStack() const {}
};
template <>
class V8_TRIVIAL_ABI StackAllocated<true> : public StackAllocated<false> {
public:
V8_INLINE StackAllocated() { VerifyOnStack(); }
#if V8_HAS_ATTRIBUTE_TRIVIAL_ABI
// In this case, StackAllocated becomes not trivially copyable.
V8_INLINE StackAllocated(const StackAllocated& other) { VerifyOnStack(); }
StackAllocated& operator=(const StackAllocated&) = default;
#endif
protected:
V8_INLINE explicit StackAllocated(no_checking_tag tag)
: StackAllocated<false>(tag) {}
V8_INLINE explicit StackAllocated(const StackAllocated& other,
no_checking_tag tag)
: StackAllocated<false>(other, tag) {}
#ifdef ENABLE_SLOW_DCHECKS
V8_EXPORT void VerifyOnStack() const;
#else
V8_INLINE V8_EXPORT void VerifyOnStack() const {}
#endif
};
/**
* A base class for abstract handles containing indirect pointers.
* These are useful regardless of whether direct local support is enabled.
*/
class IndirectHandleBase {
public:
// Returns true if the handle is empty.
V8_INLINE bool IsEmpty() const { return location_ == nullptr; }
// Sets the handle to be empty. IsEmpty() will then return true.
V8_INLINE void Clear() { location_ = nullptr; }
protected:
friend class internal::ValueHelper;
friend class internal::HandleHelper;
V8_INLINE IndirectHandleBase() = default;
V8_INLINE IndirectHandleBase(const IndirectHandleBase& other) = default;
V8_INLINE IndirectHandleBase& operator=(const IndirectHandleBase& that) =
default;
V8_INLINE explicit IndirectHandleBase(internal::Address* location)
: location_(location) {}
// Returns the address of the actual heap object (tagged).
// This method must be called only if the handle is not empty, otherwise it
// will crash.
V8_INLINE internal::Address ptr() const { return *location_; }
// Returns a reference to the slot (indirect pointer).
V8_INLINE internal::Address* const& slot() const { return location_; }
V8_INLINE internal::Address*& slot() { return location_; }
// Returns the handler's "value" (direct or indirect pointer, depending on
// whether direct local support is enabled).
template <typename T, bool check_null = false>
V8_INLINE T* value() const {
return internal::ValueHelper::SlotAsValue<T, check_null>(slot());
}
#ifdef V8_ENABLE_DIRECT_HANDLE
V8_INLINE internal::ValueHelper::InternalRepresentationType repr() const {
return location_ ? *location_ : internal::ValueHelper::kEmpty;
}
#else
V8_INLINE internal::ValueHelper::InternalRepresentationType repr() const {
return location_;
}
#endif // V8_ENABLE_DIRECT_HANDLE
private:
internal::Address* location_ = nullptr;
};
#ifdef V8_ENABLE_DIRECT_HANDLE
/**
* A base class for abstract handles containing direct pointers.
* These are only possible when conservative stack scanning is enabled.
*/
class DirectHandleBase {
public:
// Returns true if the handle is empty.
V8_INLINE bool IsEmpty() const {
return ptr_ == internal::ValueHelper::kEmpty;
}
// Sets the handle to be empty. IsEmpty() will then return true.
V8_INLINE void Clear() { ptr_ = internal::ValueHelper::kEmpty; }
protected:
friend class internal::ValueHelper;
friend class internal::HandleHelper;
V8_INLINE DirectHandleBase() = default;
V8_INLINE DirectHandleBase(const DirectHandleBase& other) = default;
V8_INLINE DirectHandleBase& operator=(const DirectHandleBase& that) = default;
V8_INLINE explicit DirectHandleBase(internal::Address ptr) : ptr_(ptr) {}
// Returns the address of the referenced object.
V8_INLINE internal::Address ptr() const { return ptr_; }
// Returns the handler's "value" (direct pointer, as direct local support
// is guaranteed to be enabled here).
template <typename T, bool check_null = false>
V8_INLINE T* value() const {
return reinterpret_cast<T*>(ptr_);
}
V8_INLINE internal::ValueHelper::InternalRepresentationType repr() const {
return ptr_;
}
private:
internal::Address ptr_ = internal::ValueHelper::kEmpty;
};
#endif // V8_ENABLE_DIRECT_HANDLE
} // namespace v8::api_internal
#endif // INCLUDE_V8_HANDLE_BASE_H_
|