v8 10.2.154 (node 18.16.0)
V8 is Google's open source JavaScript engine
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
member.h
Go to the documentation of this file.
1// Copyright 2020 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_CPPGC_MEMBER_H_
6#define INCLUDE_CPPGC_MEMBER_H_
7
8#include <atomic>
9#include <cstddef>
10#include <type_traits>
11
14#include "cppgc/type-traits.h"
15#include "v8config.h" // NOLINT(build/include_directory)
16
17namespace cppgc {
18
19class Visitor;
20
21namespace internal {
22
23// MemberBase always refers to the object as const object and defers to
24// BasicMember on casting to the right type as needed.
26 protected:
28
29 MemberBase() : raw_(nullptr) {}
30 explicit MemberBase(const void* value) : raw_(value) {}
31 MemberBase(const void* value, AtomicInitializerTag) { SetRawAtomic(value); }
32
33 const void** GetRawSlot() const { return &raw_; }
34 const void* GetRaw() const { return raw_; }
35 void SetRaw(void* value) { raw_ = value; }
36
37 const void* GetRawAtomic() const {
38 return reinterpret_cast<const std::atomic<const void*>*>(&raw_)->load(
39 std::memory_order_relaxed);
40 }
41 void SetRawAtomic(const void* value) {
42 reinterpret_cast<std::atomic<const void*>*>(&raw_)->store(
43 value, std::memory_order_relaxed);
44 }
45
46 void ClearFromGC() const { raw_ = nullptr; }
47
48 private:
49 // All constructors initialize `raw_`. Do not add a default value here as it
50 // results in a non-atomic write on some builds, even when the atomic version
51 // of the constructor is used.
52 mutable const void* raw_;
53};
54
55// The basic class from which all Member classes are 'generated'.
56template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
57 typename CheckingPolicy>
58class BasicMember final : private MemberBase, private CheckingPolicy {
59 public:
60 using PointeeType = T;
61
62 constexpr BasicMember() = default;
63 constexpr BasicMember(std::nullptr_t) {} // NOLINT
65 BasicMember(T* raw) : MemberBase(raw) { // NOLINT
66 InitializingWriteBarrier();
67 this->CheckPointer(Get());
68 }
69 BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
70 // Atomic ctor. Using the AtomicInitializerTag forces BasicMember to
71 // initialize using atomic assignments. This is required for preventing
72 // data races with concurrent marking.
74 BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
75 : MemberBase(nullptr, atomic) {}
77 : MemberBase(s, atomic) {}
78 BasicMember(T* raw, AtomicInitializerTag atomic) : MemberBase(raw, atomic) {
79 InitializingWriteBarrier();
80 this->CheckPointer(Get());
81 }
83 : BasicMember(&raw, atomic) {}
84 // Copy ctor.
85 BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
86 // Allow heterogeneous construction.
87 template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
88 typename OtherCheckingPolicy,
89 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
90 BasicMember( // NOLINT
91 const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
92 OtherCheckingPolicy>& other)
93 : BasicMember(other.Get()) {}
94 // Move ctor.
95 BasicMember(BasicMember&& other) noexcept : BasicMember(other.Get()) {
96 other.Clear();
97 }
98 // Allow heterogeneous move construction.
99 template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
100 typename OtherCheckingPolicy,
101 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
102 BasicMember(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
103 OtherCheckingPolicy>&& other) noexcept
104 : BasicMember(other.Get()) {
105 other.Clear();
106 }
107 // Construction from Persistent.
108 template <typename U, typename PersistentWeaknessPolicy,
109 typename PersistentLocationPolicy,
110 typename PersistentCheckingPolicy,
111 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
112 BasicMember(const BasicPersistent<U, PersistentWeaknessPolicy,
113 PersistentLocationPolicy,
114 PersistentCheckingPolicy>& p)
115 : BasicMember(p.Get()) {}
116
117 // Copy assignment.
119 return operator=(other.Get());
120 }
121 // Allow heterogeneous copy assignment.
122 template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
123 typename OtherCheckingPolicy,
124 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
126 const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
127 OtherCheckingPolicy>& other) {
128 return operator=(other.Get());
129 }
130 // Move assignment.
131 BasicMember& operator=(BasicMember&& other) noexcept {
132 operator=(other.Get());
133 other.Clear();
134 return *this;
135 }
136 // Heterogeneous move assignment.
137 template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
138 typename OtherCheckingPolicy,
139 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
140 BasicMember& operator=(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
141 OtherCheckingPolicy>&& other) noexcept {
142 operator=(other.Get());
143 other.Clear();
144 return *this;
145 }
146 // Assignment from Persistent.
147 template <typename U, typename PersistentWeaknessPolicy,
148 typename PersistentLocationPolicy,
149 typename PersistentCheckingPolicy,
150 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
152 const BasicPersistent<U, PersistentWeaknessPolicy,
153 PersistentLocationPolicy, PersistentCheckingPolicy>&
154 other) {
155 return operator=(other.Get());
156 }
158 SetRawAtomic(other);
159 AssigningWriteBarrier();
160 this->CheckPointer(Get());
161 return *this;
162 }
163 BasicMember& operator=(std::nullptr_t) {
164 Clear();
165 return *this;
166 }
168 SetRawAtomic(s);
169 return *this;
170 }
171
172 template <typename OtherWeaknessTag, typename OtherBarrierPolicy,
173 typename OtherCheckingPolicy>
174 void Swap(BasicMember<T, OtherWeaknessTag, OtherBarrierPolicy,
175 OtherCheckingPolicy>& other) {
176 T* tmp = Get();
177 *this = other;
178 other = tmp;
179 }
180
181 explicit operator bool() const { return Get(); }
182 operator T*() const { return Get(); }
183 T* operator->() const { return Get(); }
184 T& operator*() const { return *Get(); }
185
186 // CFI cast exemption to allow passing SentinelPointer through T* and support
187 // heterogeneous assignments between different Member and Persistent handles
188 // based on their actual types.
189 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
190 // Executed by the mutator, hence non atomic load.
191 //
192 // The const_cast below removes the constness from MemberBase storage. The
193 // following static_cast re-adds any constness if specified through the
194 // user-visible template parameter T.
195 return static_cast<T*>(const_cast<void*>(MemberBase::GetRaw()));
196 }
197
198 void Clear() { SetRawAtomic(nullptr); }
199
200 T* Release() {
201 T* result = Get();
202 Clear();
203 return result;
204 }
205
206 const T** GetSlotForTesting() const {
207 return reinterpret_cast<const T**>(GetRawSlot());
208 }
209
210 private:
211 const T* GetRawAtomic() const {
212 return static_cast<const T*>(MemberBase::GetRawAtomic());
213 }
214
215 void InitializingWriteBarrier() const {
216 WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw());
217 }
218 void AssigningWriteBarrier() const {
219 WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw());
220 }
221
222 void ClearFromGC() const { MemberBase::ClearFromGC(); }
223
224 T* GetFromGC() const { return Get(); }
225
226 friend class cppgc::Visitor;
227 template <typename U>
228 friend struct cppgc::TraceTrait;
229};
230
231template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
232 typename CheckingPolicy1, typename T2, typename WeaknessTag2,
233 typename WriteBarrierPolicy2, typename CheckingPolicy2>
234bool operator==(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
235 CheckingPolicy1>& member1,
236 const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
237 CheckingPolicy2>& member2) {
238 return member1.Get() == member2.Get();
239}
240
241template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
242 typename CheckingPolicy1, typename T2, typename WeaknessTag2,
243 typename WriteBarrierPolicy2, typename CheckingPolicy2>
244bool operator!=(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
245 CheckingPolicy1>& member1,
246 const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
247 CheckingPolicy2>& member2) {
248 return !(member1 == member2);
249}
250
251template <typename T, typename WriteBarrierPolicy, typename CheckingPolicy>
252struct IsWeak<
253 internal::BasicMember<T, WeakMemberTag, WriteBarrierPolicy, CheckingPolicy>>
254 : std::true_type {};
255
256} // namespace internal
257
263template <typename T>
264using Member = internal::BasicMember<T, internal::StrongMemberTag,
266
275template <typename T>
276using WeakMember = internal::BasicMember<T, internal::WeakMemberTag,
278
285template <typename T>
286using UntracedMember = internal::BasicMember<T, internal::UntracedMemberTag,
288
289} // namespace cppgc
290
291#endif // INCLUDE_CPPGC_MEMBER_H_
BasicMember & operator=(std::nullptr_t)
Definition member.h:163
BasicMember & operator=(BasicMember &&other) noexcept
Definition member.h:131
BasicMember(const BasicMember &other)
Definition member.h:85
BasicMember(BasicMember &&other) noexcept
Definition member.h:95
BasicMember(const BasicPersistent< U, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &p)
Definition member.h:112
BasicMember(const BasicMember< U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy > &other)
Definition member.h:90
V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T *Get() const
Definition member.h:189
BasicMember(T *raw, AtomicInitializerTag atomic)
Definition member.h:78
BasicMember & operator=(const BasicPersistent< U, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &other)
Definition member.h:151
BasicMember & operator=(T *other)
Definition member.h:157
BasicMember & operator=(const BasicMember &other)
Definition member.h:118
BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
Definition member.h:74
void Swap(BasicMember< T, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy > &other)
Definition member.h:174
const T ** GetSlotForTesting() const
Definition member.h:206
BasicMember(BasicMember< U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy > &&other) noexcept
Definition member.h:102
BasicMember(SentinelPointer s)
Definition member.h:64
BasicMember(SentinelPointer s, AtomicInitializerTag atomic)
Definition member.h:76
constexpr BasicMember()=default
BasicMember & operator=(BasicMember< U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy > &&other) noexcept
Definition member.h:140
BasicMember & operator=(SentinelPointer s)
Definition member.h:167
constexpr BasicMember(std::nullptr_t)
Definition member.h:63
BasicMember(T &raw, AtomicInitializerTag atomic)
Definition member.h:82
BasicMember & operator=(const BasicMember< U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy > &other)
Definition member.h:125
void SetRawAtomic(const void *value)
Definition member.h:41
const void * GetRaw() const
Definition member.h:34
void ClearFromGC() const
Definition member.h:46
const void ** GetRawSlot() const
Definition member.h:33
void SetRaw(void *value)
Definition member.h:35
MemberBase(const void *value, AtomicInitializerTag)
Definition member.h:31
MemberBase(const void *value)
Definition member.h:30
const void * GetRawAtomic() const
Definition member.h:37
bool operator!=(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1 > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2 > &member2)
Definition member.h:244
bool operator==(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1 > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2 > &member2)
Definition member.h:234