Coverage Report

Created: 2025-07-04 09:33

/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_