/src/node/deps/v8/include/cppgc/internal/pointer-policies.h
Line | Count | Source (jump to first uncovered line) |
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_INTERNAL_POINTER_POLICIES_H_ |
6 | | #define INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_ |
7 | | |
8 | | #include <cstdint> |
9 | | #include <type_traits> |
10 | | |
11 | | #include "cppgc/internal/member-storage.h" |
12 | | #include "cppgc/internal/write-barrier.h" |
13 | | #include "cppgc/sentinel-pointer.h" |
14 | | #include "cppgc/source-location.h" |
15 | | #include "cppgc/type-traits.h" |
16 | | #include "v8config.h" // NOLINT(build/include_directory) |
17 | | |
18 | | namespace cppgc { |
19 | | namespace internal { |
20 | | |
21 | | class HeapBase; |
22 | | class PersistentRegion; |
23 | | class CrossThreadPersistentRegion; |
24 | | |
25 | | // Tags to distinguish between strong and weak member types. |
26 | | class StrongMemberTag; |
27 | | class WeakMemberTag; |
28 | | class UntracedMemberTag; |
29 | | |
30 | | struct DijkstraWriteBarrierPolicy { |
31 | 0 | V8_INLINE static void InitializingBarrier(const void*, const void*) { |
32 | 0 | // Since in initializing writes the source object is always white, having no |
33 | 0 | // barrier doesn't break the tri-color invariant. |
34 | 0 | } |
35 | | |
36 | | template <WriteBarrierSlotType SlotType> |
37 | | V8_INLINE static void AssigningBarrier(const void* slot, const void* value) { |
38 | | #ifdef CPPGC_SLIM_WRITE_BARRIER |
39 | | if (V8_UNLIKELY(WriteBarrier::IsEnabled())) |
40 | | WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot); |
41 | | #else // !CPPGC_SLIM_WRITE_BARRIER |
42 | | WriteBarrier::Params params; |
43 | | const WriteBarrier::Type type = |
44 | | WriteBarrier::GetWriteBarrierType(slot, value, params); |
45 | | WriteBarrier(type, params, slot, value); |
46 | | #endif // !CPPGC_SLIM_WRITE_BARRIER |
47 | | } |
48 | | |
49 | | template <WriteBarrierSlotType SlotType> |
50 | | V8_INLINE static void AssigningBarrier(const void* slot, RawPointer storage) { |
51 | | static_assert( |
52 | | SlotType == WriteBarrierSlotType::kUncompressed, |
53 | | "Assigning storages of Member and UncompressedMember is not supported"); |
54 | | #ifdef CPPGC_SLIM_WRITE_BARRIER |
55 | | if (V8_UNLIKELY(WriteBarrier::IsEnabled())) |
56 | | WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot); |
57 | | #else // !CPPGC_SLIM_WRITE_BARRIER |
58 | | WriteBarrier::Params params; |
59 | | const WriteBarrier::Type type = |
60 | | WriteBarrier::GetWriteBarrierType(slot, storage, params); |
61 | | WriteBarrier(type, params, slot, storage.Load()); |
62 | | #endif // !CPPGC_SLIM_WRITE_BARRIER |
63 | | } |
64 | | |
65 | | #if defined(CPPGC_POINTER_COMPRESSION) |
66 | | template <WriteBarrierSlotType SlotType> |
67 | | V8_INLINE static void AssigningBarrier(const void* slot, |
68 | | CompressedPointer storage) { |
69 | | static_assert( |
70 | | SlotType == WriteBarrierSlotType::kCompressed, |
71 | | "Assigning storages of Member and UncompressedMember is not supported"); |
72 | | #ifdef CPPGC_SLIM_WRITE_BARRIER |
73 | | if (V8_UNLIKELY(WriteBarrier::IsEnabled())) |
74 | | WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot); |
75 | | #else // !CPPGC_SLIM_WRITE_BARRIER |
76 | | WriteBarrier::Params params; |
77 | | const WriteBarrier::Type type = |
78 | | WriteBarrier::GetWriteBarrierType(slot, storage, params); |
79 | | WriteBarrier(type, params, slot, storage.Load()); |
80 | | #endif // !CPPGC_SLIM_WRITE_BARRIER |
81 | | } |
82 | | #endif // defined(CPPGC_POINTER_COMPRESSION) |
83 | | |
84 | | private: |
85 | | V8_INLINE static void WriteBarrier(WriteBarrier::Type type, |
86 | | const WriteBarrier::Params& params, |
87 | 0 | const void* slot, const void* value) { |
88 | 0 | switch (type) { |
89 | 0 | case WriteBarrier::Type::kGenerational: |
90 | 0 | WriteBarrier::GenerationalBarrier< |
91 | 0 | WriteBarrier::GenerationalBarrierType::kPreciseSlot>(params, slot); |
92 | 0 | break; |
93 | 0 | case WriteBarrier::Type::kMarking: |
94 | 0 | WriteBarrier::DijkstraMarkingBarrier(params, value); |
95 | 0 | break; |
96 | 0 | case WriteBarrier::Type::kNone: |
97 | 0 | break; |
98 | 0 | } |
99 | 0 | } |
100 | | }; |
101 | | |
102 | | struct NoWriteBarrierPolicy { |
103 | 0 | V8_INLINE static void InitializingBarrier(const void*, const void*) {} |
104 | | template <WriteBarrierSlotType> |
105 | | V8_INLINE static void AssigningBarrier(const void*, const void*) {} |
106 | | template <WriteBarrierSlotType, typename MemberStorage> |
107 | | V8_INLINE static void AssigningBarrier(const void*, MemberStorage) {} |
108 | | }; |
109 | | |
110 | | class V8_EXPORT SameThreadEnabledCheckingPolicyBase { |
111 | | protected: |
112 | | void CheckPointerImpl(const void* ptr, bool points_to_payload, |
113 | | bool check_off_heap_assignments); |
114 | | |
115 | | const HeapBase* heap_ = nullptr; |
116 | | }; |
117 | | |
118 | | template <bool kCheckOffHeapAssignments> |
119 | | class V8_EXPORT SameThreadEnabledCheckingPolicy |
120 | | : private SameThreadEnabledCheckingPolicyBase { |
121 | | protected: |
122 | | template <typename T> |
123 | | void CheckPointer(const T* ptr) { |
124 | | if (!ptr || (kSentinelPointer == ptr)) return; |
125 | | |
126 | | CheckPointersImplTrampoline<T>::Call(this, ptr); |
127 | | } |
128 | | |
129 | | private: |
130 | | template <typename T, bool = IsCompleteV<T>> |
131 | | struct CheckPointersImplTrampoline { |
132 | | static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) { |
133 | | policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments); |
134 | | } |
135 | | }; |
136 | | |
137 | | template <typename T> |
138 | | struct CheckPointersImplTrampoline<T, true> { |
139 | | static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) { |
140 | | policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>, |
141 | | kCheckOffHeapAssignments); |
142 | | } |
143 | | }; |
144 | | }; |
145 | | |
146 | | class DisabledCheckingPolicy { |
147 | | protected: |
148 | 0 | V8_INLINE void CheckPointer(const void*) {} |
149 | | }; |
150 | | |
151 | | #ifdef DEBUG |
152 | | // Off heap members are not connected to object graph and thus cannot ressurect |
153 | | // dead objects. |
154 | | using DefaultMemberCheckingPolicy = |
155 | | SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>; |
156 | | using DefaultPersistentCheckingPolicy = |
157 | | SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>; |
158 | | #else // !DEBUG |
159 | | using DefaultMemberCheckingPolicy = DisabledCheckingPolicy; |
160 | | using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy; |
161 | | #endif // !DEBUG |
162 | | // For CT(W)P neither marking information (for value), nor objectstart bitmap |
163 | | // (for slot) are guaranteed to be present because there's no synchronization |
164 | | // between heaps after marking. |
165 | | using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy; |
166 | | |
167 | | class KeepLocationPolicy { |
168 | | public: |
169 | 0 | constexpr const SourceLocation& Location() const { return location_; } |
170 | | |
171 | | protected: |
172 | | constexpr KeepLocationPolicy() = default; |
173 | | constexpr explicit KeepLocationPolicy(const SourceLocation& location) |
174 | 0 | : location_(location) {} |
175 | | |
176 | | // KeepLocationPolicy must not copy underlying source locations. |
177 | | KeepLocationPolicy(const KeepLocationPolicy&) = delete; |
178 | | KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete; |
179 | | |
180 | | // Location of the original moved from object should be preserved. |
181 | | KeepLocationPolicy(KeepLocationPolicy&&) = default; |
182 | | KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default; |
183 | | |
184 | | private: |
185 | | SourceLocation location_; |
186 | | }; |
187 | | |
188 | | class IgnoreLocationPolicy { |
189 | | public: |
190 | 0 | constexpr SourceLocation Location() const { return {}; } |
191 | | |
192 | | protected: |
193 | | constexpr IgnoreLocationPolicy() = default; |
194 | 0 | constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {} |
195 | | }; |
196 | | |
197 | | #if CPPGC_SUPPORTS_OBJECT_NAMES |
198 | | using DefaultLocationPolicy = KeepLocationPolicy; |
199 | | #else |
200 | | using DefaultLocationPolicy = IgnoreLocationPolicy; |
201 | | #endif |
202 | | |
203 | | struct StrongPersistentPolicy { |
204 | | using IsStrongPersistent = std::true_type; |
205 | | static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object); |
206 | | }; |
207 | | |
208 | | struct WeakPersistentPolicy { |
209 | | using IsStrongPersistent = std::false_type; |
210 | | static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object); |
211 | | }; |
212 | | |
213 | | struct StrongCrossThreadPersistentPolicy { |
214 | | using IsStrongPersistent = std::true_type; |
215 | | static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion( |
216 | | const void* object); |
217 | | }; |
218 | | |
219 | | struct WeakCrossThreadPersistentPolicy { |
220 | | using IsStrongPersistent = std::false_type; |
221 | | static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion( |
222 | | const void* object); |
223 | | }; |
224 | | |
225 | | // Forward declarations setting up the default policies. |
226 | | template <typename T, typename WeaknessPolicy, |
227 | | typename LocationPolicy = DefaultLocationPolicy, |
228 | | typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy> |
229 | | class BasicCrossThreadPersistent; |
230 | | template <typename T, typename WeaknessPolicy, |
231 | | typename LocationPolicy = DefaultLocationPolicy, |
232 | | typename CheckingPolicy = DefaultPersistentCheckingPolicy> |
233 | | class BasicPersistent; |
234 | | template <typename T, typename WeaknessTag, typename WriteBarrierPolicy, |
235 | | typename CheckingPolicy = DefaultMemberCheckingPolicy, |
236 | | typename StorageType = DefaultMemberStorage> |
237 | | class BasicMember; |
238 | | |
239 | | } // namespace internal |
240 | | |
241 | | } // namespace cppgc |
242 | | |
243 | | #endif // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_ |