Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:42:25

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   V8_INLINE static void InitializingBarrier(const void*, const void*) {
0032     // Since in initializing writes the source object is always white, having no
0033     // barrier doesn't break the tri-color invariant.
0034   }
0035 
0036   template <WriteBarrierSlotType SlotType>
0037   V8_INLINE static void AssigningBarrier(const void* slot, const void* value) {
0038 #ifdef CPPGC_SLIM_WRITE_BARRIER
0039     if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0040       WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0041 #else   // !CPPGC_SLIM_WRITE_BARRIER
0042     WriteBarrier::Params params;
0043     const WriteBarrier::Type type =
0044         WriteBarrier::GetWriteBarrierType(slot, value, params);
0045     WriteBarrier(type, params, slot, value);
0046 #endif  // !CPPGC_SLIM_WRITE_BARRIER
0047   }
0048 
0049   template <WriteBarrierSlotType SlotType>
0050   V8_INLINE static void AssigningBarrier(const void* slot, RawPointer storage) {
0051     static_assert(
0052         SlotType == WriteBarrierSlotType::kUncompressed,
0053         "Assigning storages of Member and UncompressedMember is not supported");
0054 #ifdef CPPGC_SLIM_WRITE_BARRIER
0055     if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0056       WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0057 #else   // !CPPGC_SLIM_WRITE_BARRIER
0058     WriteBarrier::Params params;
0059     const WriteBarrier::Type type =
0060         WriteBarrier::GetWriteBarrierType(slot, storage, params);
0061     WriteBarrier(type, params, slot, storage.Load());
0062 #endif  // !CPPGC_SLIM_WRITE_BARRIER
0063   }
0064 
0065 #if defined(CPPGC_POINTER_COMPRESSION)
0066   template <WriteBarrierSlotType SlotType>
0067   V8_INLINE static void AssigningBarrier(const void* slot,
0068                                          CompressedPointer storage) {
0069     static_assert(
0070         SlotType == WriteBarrierSlotType::kCompressed,
0071         "Assigning storages of Member and UncompressedMember is not supported");
0072 #ifdef CPPGC_SLIM_WRITE_BARRIER
0073     if (V8_UNLIKELY(WriteBarrier::IsEnabled()))
0074       WriteBarrier::CombinedWriteBarrierSlow<SlotType>(slot);
0075 #else   // !CPPGC_SLIM_WRITE_BARRIER
0076     WriteBarrier::Params params;
0077     const WriteBarrier::Type type =
0078         WriteBarrier::GetWriteBarrierType(slot, storage, params);
0079     WriteBarrier(type, params, slot, storage.Load());
0080 #endif  // !CPPGC_SLIM_WRITE_BARRIER
0081   }
0082 #endif  // defined(CPPGC_POINTER_COMPRESSION)
0083 
0084  private:
0085   V8_INLINE static void WriteBarrier(WriteBarrier::Type type,
0086                                      const WriteBarrier::Params& params,
0087                                      const void* slot, const void* value) {
0088     switch (type) {
0089       case WriteBarrier::Type::kGenerational:
0090         WriteBarrier::GenerationalBarrier<
0091             WriteBarrier::GenerationalBarrierType::kPreciseSlot>(params, slot);
0092         break;
0093       case WriteBarrier::Type::kMarking:
0094         WriteBarrier::DijkstraMarkingBarrier(params, value);
0095         break;
0096       case WriteBarrier::Type::kNone:
0097         break;
0098     }
0099   }
0100 };
0101 
0102 struct NoWriteBarrierPolicy {
0103   V8_INLINE static void InitializingBarrier(const void*, const void*) {}
0104   template <WriteBarrierSlotType>
0105   V8_INLINE static void AssigningBarrier(const void*, const void*) {}
0106   template <WriteBarrierSlotType, typename MemberStorage>
0107   V8_INLINE static void AssigningBarrier(const void*, MemberStorage) {}
0108 };
0109 
0110 class V8_EXPORT SameThreadEnabledCheckingPolicyBase {
0111  protected:
0112   void CheckPointerImpl(const void* ptr, bool points_to_payload,
0113                         bool check_off_heap_assignments);
0114 
0115   const HeapBase* heap_ = nullptr;
0116 };
0117 
0118 template <bool kCheckOffHeapAssignments>
0119 class V8_EXPORT SameThreadEnabledCheckingPolicy
0120     : private SameThreadEnabledCheckingPolicyBase {
0121  protected:
0122   template <typename T>
0123   void CheckPointer(const T* ptr) {
0124     if (!ptr || (kSentinelPointer == ptr)) return;
0125 
0126     CheckPointersImplTrampoline<T>::Call(this, ptr);
0127   }
0128 
0129  private:
0130   template <typename T, bool = IsCompleteV<T>>
0131   struct CheckPointersImplTrampoline {
0132     static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
0133       policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
0134     }
0135   };
0136 
0137   template <typename T>
0138   struct CheckPointersImplTrampoline<T, true> {
0139     static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
0140       policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
0141                                kCheckOffHeapAssignments);
0142     }
0143   };
0144 };
0145 
0146 class DisabledCheckingPolicy {
0147  protected:
0148   V8_INLINE void CheckPointer(const void*) {}
0149 };
0150 
0151 #ifdef DEBUG
0152 // Off heap members are not connected to object graph and thus cannot ressurect
0153 // dead objects.
0154 using DefaultMemberCheckingPolicy =
0155     SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
0156 using DefaultPersistentCheckingPolicy =
0157     SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
0158 #else   // !DEBUG
0159 using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
0160 using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
0161 #endif  // !DEBUG
0162 // For CT(W)P neither marking information (for value), nor objectstart bitmap
0163 // (for slot) are guaranteed to be present because there's no synchronization
0164 // between heaps after marking.
0165 using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy;
0166 
0167 class KeepLocationPolicy {
0168  public:
0169   constexpr const SourceLocation& Location() const { return location_; }
0170 
0171  protected:
0172   constexpr KeepLocationPolicy() = default;
0173   constexpr explicit KeepLocationPolicy(const SourceLocation& location)
0174       : location_(location) {}
0175 
0176   // KeepLocationPolicy must not copy underlying source locations.
0177   KeepLocationPolicy(const KeepLocationPolicy&) = delete;
0178   KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
0179 
0180   // Location of the original moved from object should be preserved.
0181   KeepLocationPolicy(KeepLocationPolicy&&) = default;
0182   KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default;
0183 
0184  private:
0185   SourceLocation location_;
0186 };
0187 
0188 class IgnoreLocationPolicy {
0189  public:
0190   constexpr SourceLocation Location() const { return {}; }
0191 
0192  protected:
0193   constexpr IgnoreLocationPolicy() = default;
0194   constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {}
0195 };
0196 
0197 #if CPPGC_SUPPORTS_OBJECT_NAMES
0198 using DefaultLocationPolicy = KeepLocationPolicy;
0199 #else
0200 using DefaultLocationPolicy = IgnoreLocationPolicy;
0201 #endif
0202 
0203 struct StrongPersistentPolicy {
0204   using IsStrongPersistent = std::true_type;
0205   static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
0206 };
0207 
0208 struct WeakPersistentPolicy {
0209   using IsStrongPersistent = std::false_type;
0210   static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
0211 };
0212 
0213 struct StrongCrossThreadPersistentPolicy {
0214   using IsStrongPersistent = std::true_type;
0215   static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
0216       const void* object);
0217 };
0218 
0219 struct WeakCrossThreadPersistentPolicy {
0220   using IsStrongPersistent = std::false_type;
0221   static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
0222       const void* object);
0223 };
0224 
0225 // Forward declarations setting up the default policies.
0226 template <typename T, typename WeaknessPolicy,
0227           typename LocationPolicy = DefaultLocationPolicy,
0228           typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy>
0229 class BasicCrossThreadPersistent;
0230 template <typename T, typename WeaknessPolicy,
0231           typename LocationPolicy = DefaultLocationPolicy,
0232           typename CheckingPolicy = DefaultPersistentCheckingPolicy>
0233 class BasicPersistent;
0234 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0235           typename CheckingPolicy = DefaultMemberCheckingPolicy,
0236           typename StorageType = DefaultMemberStorage>
0237 class BasicMember;
0238 
0239 }  // namespace internal
0240 
0241 }  // namespace cppgc
0242 
0243 #endif  // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_