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 17 namespace cppgc { 18 namespace internal { 19 20 class HeapBase; 21 class PersistentRegion; 22 class CrossThreadPersistentRegion; 23 24 // Tags to distinguish between strong and weak member types. 25 class StrongMemberTag; 26 class WeakMemberTag; 27 class UntracedMemberTag; 28 29 struct DijkstraWriteBarrierPolicy { InitializingBarrierDijkstraWriteBarrierPolicy30 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 } AssigningBarrierDijkstraWriteBarrierPolicy34 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 49 struct NoWriteBarrierPolicy { InitializingBarrierNoWriteBarrierPolicy50 static void InitializingBarrier(const void*, const void*) {} AssigningBarrierNoWriteBarrierPolicy51 static void AssigningBarrier(const void*, const void*) {} 52 }; 53 54 class 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 62 template <bool kCheckOffHeapAssignments> 63 class V8_EXPORT SameThreadEnabledCheckingPolicy 64 : private SameThreadEnabledCheckingPolicyBase { 65 protected: 66 template <typename T> CheckPointer(const T * ptr)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 { CallCheckPointersImplTrampoline76 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 90 class 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. 98 using DefaultMemberCheckingPolicy = 99 SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>; 100 using DefaultPersistentCheckingPolicy = 101 SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>; 102 #else // !DEBUG 103 using DefaultMemberCheckingPolicy = DisabledCheckingPolicy; 104 using 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. 109 using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy; 110 111 class 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 132 class 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 142 using DefaultLocationPolicy = KeepLocationPolicy; 143 #else 144 using DefaultLocationPolicy = IgnoreLocationPolicy; 145 #endif 146 147 struct StrongPersistentPolicy { 148 using IsStrongPersistent = std::true_type; 149 static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object); 150 }; 151 152 struct WeakPersistentPolicy { 153 using IsStrongPersistent = std::false_type; 154 static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object); 155 }; 156 157 struct StrongCrossThreadPersistentPolicy { 158 using IsStrongPersistent = std::true_type; 159 static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion( 160 const void* object); 161 }; 162 163 struct 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. 170 template <typename T, typename WeaknessPolicy, 171 typename LocationPolicy = DefaultLocationPolicy, 172 typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy> 173 class BasicCrossThreadPersistent; 174 template <typename T, typename WeaknessPolicy, 175 typename LocationPolicy = DefaultLocationPolicy, 176 typename CheckingPolicy = DefaultPersistentCheckingPolicy> 177 class BasicPersistent; 178 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy, 179 typename CheckingPolicy = DefaultMemberCheckingPolicy> 180 class BasicMember; 181 182 } // namespace internal 183 184 } // namespace cppgc 185 186 #endif // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_ 187