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/write-barrier.h"
12#include "cppgc/sentinel-pointer.h"
13#include "cppgc/source-location.h"
14#include "cppgc/type-traits.h"
15#include "v8config.h"  // NOLINT(build/include_directory)
16
17namespace cppgc {
18namespace internal {
19
20class HeapBase;
21class PersistentRegion;
22class CrossThreadPersistentRegion;
23
24// Tags to distinguish between strong and weak member types.
25class StrongMemberTag;
26class WeakMemberTag;
27class UntracedMemberTag;
28
29struct DijkstraWriteBarrierPolicy {
30  static void InitializingBarrier(const void*, const void*) {
31    // Since in initializing writes the source object is always white, having no
32    // barrier doesn't break the tri-color invariant.
33  }
34  static void AssigningBarrier(const void* slot, const void* value) {
35    WriteBarrier::Params params;
36    switch (WriteBarrier::GetWriteBarrierType(slot, value, params)) {
37      case WriteBarrier::Type::kGenerational:
38        WriteBarrier::GenerationalBarrier(params, slot);
39        break;
40      case WriteBarrier::Type::kMarking:
41        WriteBarrier::DijkstraMarkingBarrier(params, value);
42        break;
43      case WriteBarrier::Type::kNone:
44        break;
45    }
46  }
47};
48
49struct NoWriteBarrierPolicy {
50  static void InitializingBarrier(const void*, const void*) {}
51  static void AssigningBarrier(const void*, const void*) {}
52};
53
54class V8_EXPORT SameThreadEnabledCheckingPolicyBase {
55 protected:
56  void CheckPointerImpl(const void* ptr, bool points_to_payload,
57                        bool check_off_heap_assignments);
58
59  const HeapBase* heap_ = nullptr;
60};
61
62template <bool kCheckOffHeapAssignments>
63class V8_EXPORT SameThreadEnabledCheckingPolicy
64    : private SameThreadEnabledCheckingPolicyBase {
65 protected:
66  template <typename T>
67  void CheckPointer(const T* ptr) {
68    if (!ptr || (kSentinelPointer == ptr)) return;
69
70    CheckPointersImplTrampoline<T>::Call(this, ptr);
71  }
72
73 private:
74  template <typename T, bool = IsCompleteV<T>>
75  struct CheckPointersImplTrampoline {
76    static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
77      policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
78    }
79  };
80
81  template <typename T>
82  struct CheckPointersImplTrampoline<T, true> {
83    static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
84      policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
85                               kCheckOffHeapAssignments);
86    }
87  };
88};
89
90class DisabledCheckingPolicy {
91 protected:
92  void CheckPointer(const void*) {}
93};
94
95#ifdef DEBUG
96// Off heap members are not connected to object graph and thus cannot ressurect
97// dead objects.
98using DefaultMemberCheckingPolicy =
99    SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
100using DefaultPersistentCheckingPolicy =
101    SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
102#else   // !DEBUG
103using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
104using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
105#endif  // !DEBUG
106// For CT(W)P neither marking information (for value), nor objectstart bitmap
107// (for slot) are guaranteed to be present because there's no synchronization
108// between heaps after marking.
109using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy;
110
111class KeepLocationPolicy {
112 public:
113  constexpr const SourceLocation& Location() const { return location_; }
114
115 protected:
116  constexpr KeepLocationPolicy() = default;
117  constexpr explicit KeepLocationPolicy(const SourceLocation& location)
118      : location_(location) {}
119
120  // KeepLocationPolicy must not copy underlying source locations.
121  KeepLocationPolicy(const KeepLocationPolicy&) = delete;
122  KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
123
124  // Location of the original moved from object should be preserved.
125  KeepLocationPolicy(KeepLocationPolicy&&) = default;
126  KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default;
127
128 private:
129  SourceLocation location_;
130};
131
132class IgnoreLocationPolicy {
133 public:
134  constexpr SourceLocation Location() const { return {}; }
135
136 protected:
137  constexpr IgnoreLocationPolicy() = default;
138  constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {}
139};
140
141#if CPPGC_SUPPORTS_OBJECT_NAMES
142using DefaultLocationPolicy = KeepLocationPolicy;
143#else
144using DefaultLocationPolicy = IgnoreLocationPolicy;
145#endif
146
147struct StrongPersistentPolicy {
148  using IsStrongPersistent = std::true_type;
149  static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
150};
151
152struct WeakPersistentPolicy {
153  using IsStrongPersistent = std::false_type;
154  static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
155};
156
157struct StrongCrossThreadPersistentPolicy {
158  using IsStrongPersistent = std::true_type;
159  static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
160      const void* object);
161};
162
163struct WeakCrossThreadPersistentPolicy {
164  using IsStrongPersistent = std::false_type;
165  static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
166      const void* object);
167};
168
169// Forward declarations setting up the default policies.
170template <typename T, typename WeaknessPolicy,
171          typename LocationPolicy = DefaultLocationPolicy,
172          typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy>
173class BasicCrossThreadPersistent;
174template <typename T, typename WeaknessPolicy,
175          typename LocationPolicy = DefaultLocationPolicy,
176          typename CheckingPolicy = DefaultPersistentCheckingPolicy>
177class BasicPersistent;
178template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
179          typename CheckingPolicy = DefaultMemberCheckingPolicy>
180class BasicMember;
181
182}  // namespace internal
183
184}  // namespace cppgc
185
186#endif  // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
187