11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <cstdint>
91cb0ef41Sopenharmony_ci#include <type_traits>
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#include "cppgc/internal/write-barrier.h"
121cb0ef41Sopenharmony_ci#include "cppgc/sentinel-pointer.h"
131cb0ef41Sopenharmony_ci#include "cppgc/source-location.h"
141cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h"
151cb0ef41Sopenharmony_ci#include "v8config.h"  // NOLINT(build/include_directory)
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_cinamespace cppgc {
181cb0ef41Sopenharmony_cinamespace internal {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciclass HeapBase;
211cb0ef41Sopenharmony_ciclass PersistentRegion;
221cb0ef41Sopenharmony_ciclass CrossThreadPersistentRegion;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Tags to distinguish between strong and weak member types.
251cb0ef41Sopenharmony_ciclass StrongMemberTag;
261cb0ef41Sopenharmony_ciclass WeakMemberTag;
271cb0ef41Sopenharmony_ciclass UntracedMemberTag;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cistruct DijkstraWriteBarrierPolicy {
301cb0ef41Sopenharmony_ci  static void InitializingBarrier(const void*, const void*) {
311cb0ef41Sopenharmony_ci    // Since in initializing writes the source object is always white, having no
321cb0ef41Sopenharmony_ci    // barrier doesn't break the tri-color invariant.
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci  static void AssigningBarrier(const void* slot, const void* value) {
351cb0ef41Sopenharmony_ci    WriteBarrier::Params params;
361cb0ef41Sopenharmony_ci    switch (WriteBarrier::GetWriteBarrierType(slot, value, params)) {
371cb0ef41Sopenharmony_ci      case WriteBarrier::Type::kGenerational:
381cb0ef41Sopenharmony_ci        WriteBarrier::GenerationalBarrier(params, slot);
391cb0ef41Sopenharmony_ci        break;
401cb0ef41Sopenharmony_ci      case WriteBarrier::Type::kMarking:
411cb0ef41Sopenharmony_ci        WriteBarrier::DijkstraMarkingBarrier(params, value);
421cb0ef41Sopenharmony_ci        break;
431cb0ef41Sopenharmony_ci      case WriteBarrier::Type::kNone:
441cb0ef41Sopenharmony_ci        break;
451cb0ef41Sopenharmony_ci    }
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci};
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_cistruct NoWriteBarrierPolicy {
501cb0ef41Sopenharmony_ci  static void InitializingBarrier(const void*, const void*) {}
511cb0ef41Sopenharmony_ci  static void AssigningBarrier(const void*, const void*) {}
521cb0ef41Sopenharmony_ci};
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciclass V8_EXPORT SameThreadEnabledCheckingPolicyBase {
551cb0ef41Sopenharmony_ci protected:
561cb0ef41Sopenharmony_ci  void CheckPointerImpl(const void* ptr, bool points_to_payload,
571cb0ef41Sopenharmony_ci                        bool check_off_heap_assignments);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  const HeapBase* heap_ = nullptr;
601cb0ef41Sopenharmony_ci};
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_citemplate <bool kCheckOffHeapAssignments>
631cb0ef41Sopenharmony_ciclass V8_EXPORT SameThreadEnabledCheckingPolicy
641cb0ef41Sopenharmony_ci    : private SameThreadEnabledCheckingPolicyBase {
651cb0ef41Sopenharmony_ci protected:
661cb0ef41Sopenharmony_ci  template <typename T>
671cb0ef41Sopenharmony_ci  void CheckPointer(const T* ptr) {
681cb0ef41Sopenharmony_ci    if (!ptr || (kSentinelPointer == ptr)) return;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci    CheckPointersImplTrampoline<T>::Call(this, ptr);
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci private:
741cb0ef41Sopenharmony_ci  template <typename T, bool = IsCompleteV<T>>
751cb0ef41Sopenharmony_ci  struct CheckPointersImplTrampoline {
761cb0ef41Sopenharmony_ci    static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
771cb0ef41Sopenharmony_ci      policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
781cb0ef41Sopenharmony_ci    }
791cb0ef41Sopenharmony_ci  };
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  template <typename T>
821cb0ef41Sopenharmony_ci  struct CheckPointersImplTrampoline<T, true> {
831cb0ef41Sopenharmony_ci    static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
841cb0ef41Sopenharmony_ci      policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
851cb0ef41Sopenharmony_ci                               kCheckOffHeapAssignments);
861cb0ef41Sopenharmony_ci    }
871cb0ef41Sopenharmony_ci  };
881cb0ef41Sopenharmony_ci};
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ciclass DisabledCheckingPolicy {
911cb0ef41Sopenharmony_ci protected:
921cb0ef41Sopenharmony_ci  void CheckPointer(const void*) {}
931cb0ef41Sopenharmony_ci};
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci#ifdef DEBUG
961cb0ef41Sopenharmony_ci// Off heap members are not connected to object graph and thus cannot ressurect
971cb0ef41Sopenharmony_ci// dead objects.
981cb0ef41Sopenharmony_ciusing DefaultMemberCheckingPolicy =
991cb0ef41Sopenharmony_ci    SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
1001cb0ef41Sopenharmony_ciusing DefaultPersistentCheckingPolicy =
1011cb0ef41Sopenharmony_ci    SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
1021cb0ef41Sopenharmony_ci#else   // !DEBUG
1031cb0ef41Sopenharmony_ciusing DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
1041cb0ef41Sopenharmony_ciusing DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
1051cb0ef41Sopenharmony_ci#endif  // !DEBUG
1061cb0ef41Sopenharmony_ci// For CT(W)P neither marking information (for value), nor objectstart bitmap
1071cb0ef41Sopenharmony_ci// (for slot) are guaranteed to be present because there's no synchronization
1081cb0ef41Sopenharmony_ci// between heaps after marking.
1091cb0ef41Sopenharmony_ciusing DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy;
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciclass KeepLocationPolicy {
1121cb0ef41Sopenharmony_ci public:
1131cb0ef41Sopenharmony_ci  constexpr const SourceLocation& Location() const { return location_; }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci protected:
1161cb0ef41Sopenharmony_ci  constexpr KeepLocationPolicy() = default;
1171cb0ef41Sopenharmony_ci  constexpr explicit KeepLocationPolicy(const SourceLocation& location)
1181cb0ef41Sopenharmony_ci      : location_(location) {}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  // KeepLocationPolicy must not copy underlying source locations.
1211cb0ef41Sopenharmony_ci  KeepLocationPolicy(const KeepLocationPolicy&) = delete;
1221cb0ef41Sopenharmony_ci  KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  // Location of the original moved from object should be preserved.
1251cb0ef41Sopenharmony_ci  KeepLocationPolicy(KeepLocationPolicy&&) = default;
1261cb0ef41Sopenharmony_ci  KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default;
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci private:
1291cb0ef41Sopenharmony_ci  SourceLocation location_;
1301cb0ef41Sopenharmony_ci};
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ciclass IgnoreLocationPolicy {
1331cb0ef41Sopenharmony_ci public:
1341cb0ef41Sopenharmony_ci  constexpr SourceLocation Location() const { return {}; }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci protected:
1371cb0ef41Sopenharmony_ci  constexpr IgnoreLocationPolicy() = default;
1381cb0ef41Sopenharmony_ci  constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {}
1391cb0ef41Sopenharmony_ci};
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci#if CPPGC_SUPPORTS_OBJECT_NAMES
1421cb0ef41Sopenharmony_ciusing DefaultLocationPolicy = KeepLocationPolicy;
1431cb0ef41Sopenharmony_ci#else
1441cb0ef41Sopenharmony_ciusing DefaultLocationPolicy = IgnoreLocationPolicy;
1451cb0ef41Sopenharmony_ci#endif
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cistruct StrongPersistentPolicy {
1481cb0ef41Sopenharmony_ci  using IsStrongPersistent = std::true_type;
1491cb0ef41Sopenharmony_ci  static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
1501cb0ef41Sopenharmony_ci};
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_cistruct WeakPersistentPolicy {
1531cb0ef41Sopenharmony_ci  using IsStrongPersistent = std::false_type;
1541cb0ef41Sopenharmony_ci  static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
1551cb0ef41Sopenharmony_ci};
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_cistruct StrongCrossThreadPersistentPolicy {
1581cb0ef41Sopenharmony_ci  using IsStrongPersistent = std::true_type;
1591cb0ef41Sopenharmony_ci  static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
1601cb0ef41Sopenharmony_ci      const void* object);
1611cb0ef41Sopenharmony_ci};
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_cistruct WeakCrossThreadPersistentPolicy {
1641cb0ef41Sopenharmony_ci  using IsStrongPersistent = std::false_type;
1651cb0ef41Sopenharmony_ci  static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
1661cb0ef41Sopenharmony_ci      const void* object);
1671cb0ef41Sopenharmony_ci};
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci// Forward declarations setting up the default policies.
1701cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessPolicy,
1711cb0ef41Sopenharmony_ci          typename LocationPolicy = DefaultLocationPolicy,
1721cb0ef41Sopenharmony_ci          typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy>
1731cb0ef41Sopenharmony_ciclass BasicCrossThreadPersistent;
1741cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessPolicy,
1751cb0ef41Sopenharmony_ci          typename LocationPolicy = DefaultLocationPolicy,
1761cb0ef41Sopenharmony_ci          typename CheckingPolicy = DefaultPersistentCheckingPolicy>
1771cb0ef41Sopenharmony_ciclass BasicPersistent;
1781cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
1791cb0ef41Sopenharmony_ci          typename CheckingPolicy = DefaultMemberCheckingPolicy>
1801cb0ef41Sopenharmony_ciclass BasicMember;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci}  // namespace internal
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci}  // namespace cppgc
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
187