Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-02 09:57:12

0001 // Copyright 2020 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
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 // Tags to distinguish between strong and weak member types.
0026 class StrongMemberTag;
0027 class WeakMemberTag;
0028 class UntracedMemberTag;
0029 
0030 struct DijkstraWriteBarrierPolicy {
0031     // Since in initializing writes the source object is always white, having no
0032     // barrier doesn't break the tri-color invariant.
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   // !CPPGC_SLIM_WRITE_BARRIER
0048     WriteBarrier::Params params;
0049     const WriteBarrier::Type type =
0050         WriteBarrier::GetWriteBarrierType(slot, value, params);
0051     WriteBarrier(type, params, slot, value);
0052 #endif  // !CPPGC_SLIM_WRITE_BARRIER
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   // !CPPGC_SLIM_WRITE_BARRIER
0064     WriteBarrier::Params params;
0065     const WriteBarrier::Type type =
0066         WriteBarrier::GetWriteBarrierType(slot, storage, params);
0067     WriteBarrier(type, params, slot, storage.Load());
0068 #endif  // !CPPGC_SLIM_WRITE_BARRIER
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   // !CPPGC_SLIM_WRITE_BARRIER
0082     WriteBarrier::Params params;
0083     const WriteBarrier::Type type =
0084         WriteBarrier::GetWriteBarrierType(slot, storage, params);
0085     WriteBarrier(type, params, slot, storage.Load());
0086 #endif  // !CPPGC_SLIM_WRITE_BARRIER
0087   }
0088 #endif  // defined(CPPGC_POINTER_COMPRESSION)
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 // Off heap members are not connected to object graph and thus cannot ressurect
0190 // dead objects.
0191 using DefaultMemberCheckingPolicy =
0192     SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
0193 using DefaultPersistentCheckingPolicy =
0194     SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
0195 #else   // !CPPGC_ENABLE_SLOW_API_CHECKS
0196 using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
0197 using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
0198 #endif  // !CPPGC_ENABLE_SLOW_API_CHECKS
0199 // For CT(W)P neither marking information (for value), nor objectstart bitmap
0200 // (for slot) are guaranteed to be present because there's no synchronization
0201 // between heaps after marking.
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   // KeepLocationPolicy must not copy underlying source locations.
0214   KeepLocationPolicy(const KeepLocationPolicy&) = delete;
0215   KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
0216 
0217   // Location of the original moved from object should be preserved.
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 // Forward declarations setting up the default policies.
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 }  // namespace internal
0277 
0278 }  // namespace cppgc
0279 
0280 #endif  // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_