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