File indexing completed on 2026-01-02 09:57:12
0001
0002
0003
0004
0005 #ifndef INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
0006 #define INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
0007
0008 #include <cstdint>
0009 #include <type_traits>
0010
0011 #include "cppgc/internal/member-storage.h"
0012 #include "cppgc/internal/write-barrier.h"
0013 #include "cppgc/sentinel-pointer.h"
0014 #include "cppgc/source-location.h"
0015 #include "cppgc/type-traits.h"
0016 #include "v8config.h" // NOLINT(build/include_directory)
0017
0018 namespace cppgc {
0019 namespace internal {
0020
0021 class HeapBase;
0022 class PersistentRegion;
0023 class CrossThreadPersistentRegion;
0024
0025
0026 class StrongMemberTag;
0027 class WeakMemberTag;
0028 class UntracedMemberTag;
0029
0030 struct DijkstraWriteBarrierPolicy {
0031
0032
0033 V8_INLINE static void InitializingBarrier(const void*, const void*) {}
0034 V8_INLINE static void InitializingBarrier(const void*, RawPointer storage) {
0035 }
0036 #if defined(CPPGC_POINTER_COMPRESSION)
0037 V8_INLINE static void InitializingBarrier(const void*,
0038 CompressedPointer storage) {}
0039 #endif
0040
0041 template <WriteBarrierSlotType SlotType>
0042 V8_INLINE static void AssigningBarrier(const void* slot,
0043 const void* value) {
0044 #ifdef CPPGC_SLIM_WRITE_BARRIER
0045 if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0046 WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0047 #else
0048 WriteBarrier::Params params;
0049 const WriteBarrier::Type type =
0050 WriteBarrier::GetWriteBarrierType(slot, value, params);
0051 WriteBarrier(type, params, slot, value);
0052 #endif
0053 }
0054
0055 template <WriteBarrierSlotType SlotType>
0056 V8_INLINE static void AssigningBarrier(const void* slot, RawPointer storage) {
0057 static_assert(
0058 SlotType == WriteBarrierSlotType::kUncompressed,
0059 "Assigning storages of Member and UncompressedMember is not supported");
0060 #ifdef CPPGC_SLIM_WRITE_BARRIER
0061 if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0062 WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0063 #else
0064 WriteBarrier::Params params;
0065 const WriteBarrier::Type type =
0066 WriteBarrier::GetWriteBarrierType(slot, storage, params);
0067 WriteBarrier(type, params, slot, storage.Load());
0068 #endif
0069 }
0070
0071 #if defined(CPPGC_POINTER_COMPRESSION)
0072 template <WriteBarrierSlotType SlotType>
0073 V8_INLINE static void AssigningBarrier(const void* slot,
0074 CompressedPointer storage) {
0075 static_assert(
0076 SlotType == WriteBarrierSlotType::kCompressed,
0077 "Assigning storages of Member and UncompressedMember is not supported");
0078 #ifdef CPPGC_SLIM_WRITE_BARRIER
0079 if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0080 WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0081 #else
0082 WriteBarrier::Params params;
0083 const WriteBarrier::Type type =
0084 WriteBarrier::GetWriteBarrierType(slot, storage, params);
0085 WriteBarrier(type, params, slot, storage.Load());
0086 #endif
0087 }
0088 #endif
0089
0090 private:
0091 V8_INLINE static void WriteBarrier(WriteBarrier::Type type,
0092 const WriteBarrier::Params& params,
0093 const void* slot, const void* value) {
0094 switch (type) {
0095 case WriteBarrier::Type::kGenerational:
0096 WriteBarrier::GenerationalBarrier<
0097 WriteBarrier::GenerationalBarrierType::kPreciseSlot>(params, slot);
0098 break;
0099 case WriteBarrier::Type::kMarking:
0100 WriteBarrier::DijkstraMarkingBarrier(params, value);
0101 break;
0102 case WriteBarrier::Type::kNone:
0103 break;
0104 }
0105 }
0106 };
0107
0108 struct NoWriteBarrierPolicy {
0109 V8_INLINE static void InitializingBarrier(const void*, const void*) {}
0110 V8_INLINE static void InitializingBarrier(const void*, RawPointer storage) {}
0111 #if defined(CPPGC_POINTER_COMPRESSION)
0112 V8_INLINE static void InitializingBarrier(const void*,
0113 CompressedPointer storage) {}
0114 #endif
0115 template <WriteBarrierSlotType>
0116 V8_INLINE static void AssigningBarrier(const void*, const void*) {}
0117 template <WriteBarrierSlotType, typename MemberStorage>
0118 V8_INLINE static void AssigningBarrier(const void*, MemberStorage) {}
0119 };
0120
0121 class V8_EXPORT SameThreadEnabledCheckingPolicyBase {
0122 protected:
0123 void CheckPointerImpl(const void* ptr, bool points_to_payload,
0124 bool check_off_heap_assignments);
0125
0126 const HeapBase* heap_ = nullptr;
0127 };
0128
0129 template <bool kCheckOffHeapAssignments>
0130 class V8_EXPORT SameThreadEnabledCheckingPolicy
0131 : private SameThreadEnabledCheckingPolicyBase {
0132 protected:
0133 template <typename T>
0134 V8_INLINE void CheckPointer(RawPointer raw_pointer) {
0135 if (raw_pointer.IsCleared() || raw_pointer.IsSentinel()) {
0136 return;
0137 }
0138 CheckPointersImplTrampoline<T>::Call(
0139 this, static_cast<const T*>(raw_pointer.Load()));
0140 }
0141 #if defined(CPPGC_POINTER_COMPRESSION)
0142 template <typename T>
0143 V8_INLINE void CheckPointer(CompressedPointer compressed_pointer) {
0144 if (compressed_pointer.IsCleared() || compressed_pointer.IsSentinel()) {
0145 return;
0146 }
0147 CheckPointersImplTrampoline<T>::Call(
0148 this, static_cast<const T*>(compressed_pointer.Load()));
0149 }
0150 #endif
0151 template <typename T>
0152 void CheckPointer(const T* ptr) {
0153 if (!ptr || (kSentinelPointer == ptr)) {
0154 return;
0155 }
0156 CheckPointersImplTrampoline<T>::Call(this, ptr);
0157 }
0158
0159 private:
0160 template <typename T, bool = IsCompleteV<T>>
0161 struct CheckPointersImplTrampoline {
0162 static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
0163 policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
0164 }
0165 };
0166
0167 template <typename T>
0168 struct CheckPointersImplTrampoline<T, true> {
0169 static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
0170 policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
0171 kCheckOffHeapAssignments);
0172 }
0173 };
0174 };
0175
0176 class DisabledCheckingPolicy {
0177 protected:
0178 template <typename T>
0179 V8_INLINE void CheckPointer(T*) {}
0180 template <typename T>
0181 V8_INLINE void CheckPointer(RawPointer) {}
0182 #if defined(CPPGC_POINTER_COMPRESSION)
0183 template <typename T>
0184 V8_INLINE void CheckPointer(CompressedPointer) {}
0185 #endif
0186 };
0187
0188 #ifdef CPPGC_ENABLE_SLOW_API_CHECKS
0189
0190
0191 using DefaultMemberCheckingPolicy =
0192 SameThreadEnabledCheckingPolicy<false >;
0193 using DefaultPersistentCheckingPolicy =
0194 SameThreadEnabledCheckingPolicy<true >;
0195 #else
0196 using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
0197 using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
0198 #endif
0199
0200
0201
0202 using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy;
0203
0204 class KeepLocationPolicy {
0205 public:
0206 constexpr const SourceLocation& Location() const { return location_; }
0207
0208 protected:
0209 constexpr KeepLocationPolicy() = default;
0210 constexpr explicit KeepLocationPolicy(const SourceLocation& location)
0211 : location_(location) {}
0212
0213
0214 KeepLocationPolicy(const KeepLocationPolicy&) = delete;
0215 KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
0216
0217
0218 KeepLocationPolicy(KeepLocationPolicy&&) = default;
0219 KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default;
0220
0221 private:
0222 SourceLocation location_;
0223 };
0224
0225 class IgnoreLocationPolicy {
0226 public:
0227 constexpr SourceLocation Location() const { return {}; }
0228
0229 protected:
0230 constexpr IgnoreLocationPolicy() = default;
0231 constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {}
0232 };
0233
0234 #if CPPGC_SUPPORTS_OBJECT_NAMES
0235 using DefaultLocationPolicy = KeepLocationPolicy;
0236 #else
0237 using DefaultLocationPolicy = IgnoreLocationPolicy;
0238 #endif
0239
0240 struct StrongPersistentPolicy {
0241 using IsStrongPersistent = std::true_type;
0242 static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
0243 };
0244
0245 struct WeakPersistentPolicy {
0246 using IsStrongPersistent = std::false_type;
0247 static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
0248 };
0249
0250 struct StrongCrossThreadPersistentPolicy {
0251 using IsStrongPersistent = std::true_type;
0252 static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
0253 const void* object);
0254 };
0255
0256 struct WeakCrossThreadPersistentPolicy {
0257 using IsStrongPersistent = std::false_type;
0258 static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
0259 const void* object);
0260 };
0261
0262
0263 template <typename T, typename WeaknessPolicy,
0264 typename LocationPolicy = DefaultLocationPolicy,
0265 typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy>
0266 class BasicCrossThreadPersistent;
0267 template <typename T, typename WeaknessPolicy,
0268 typename LocationPolicy = DefaultLocationPolicy,
0269 typename CheckingPolicy = DefaultPersistentCheckingPolicy>
0270 class BasicPersistent;
0271 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0272 typename CheckingPolicy = DefaultMemberCheckingPolicy,
0273 typename StorageType = DefaultMemberStorage>
0274 class BasicMember;
0275
0276 }
0277
0278 }
0279
0280 #endif