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_HEAP_CONSISTENCY_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_HEAP_CONSISTENCY_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <cstddef>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "cppgc/internal/write-barrier.h"
111cb0ef41Sopenharmony_ci#include "cppgc/macros.h"
121cb0ef41Sopenharmony_ci#include "cppgc/member.h"
131cb0ef41Sopenharmony_ci#include "cppgc/trace-trait.h"
141cb0ef41Sopenharmony_ci#include "v8config.h"  // NOLINT(build/include_directory)
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cinamespace cppgc {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciclass HeapHandle;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cinamespace subtle {
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci/**
231cb0ef41Sopenharmony_ci * **DO NOT USE: Use the appropriate managed types.**
241cb0ef41Sopenharmony_ci *
251cb0ef41Sopenharmony_ci * Consistency helpers that aid in maintaining a consistent internal state of
261cb0ef41Sopenharmony_ci * the garbage collector.
271cb0ef41Sopenharmony_ci */
281cb0ef41Sopenharmony_ciclass HeapConsistency final {
291cb0ef41Sopenharmony_ci public:
301cb0ef41Sopenharmony_ci  using WriteBarrierParams = internal::WriteBarrier::Params;
311cb0ef41Sopenharmony_ci  using WriteBarrierType = internal::WriteBarrier::Type;
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  /**
341cb0ef41Sopenharmony_ci   * Gets the required write barrier type for a specific write.
351cb0ef41Sopenharmony_ci   *
361cb0ef41Sopenharmony_ci   * \param slot Slot containing the pointer to the object. The slot itself
371cb0ef41Sopenharmony_ci   *   must reside in an object that has been allocated using
381cb0ef41Sopenharmony_ci   *   `MakeGarbageCollected()`.
391cb0ef41Sopenharmony_ci   * \param value The pointer to the object. May be an interior pointer to an
401cb0ef41Sopenharmony_ci   *   interface of the actual object.
411cb0ef41Sopenharmony_ci   * \param params Parameters that may be used for actual write barrier calls.
421cb0ef41Sopenharmony_ci   *   Only filled if return value indicates that a write barrier is needed. The
431cb0ef41Sopenharmony_ci   *   contents of the `params` are an implementation detail.
441cb0ef41Sopenharmony_ci   * \returns whether a write barrier is needed and which barrier to invoke.
451cb0ef41Sopenharmony_ci   */
461cb0ef41Sopenharmony_ci  static V8_INLINE WriteBarrierType GetWriteBarrierType(
471cb0ef41Sopenharmony_ci      const void* slot, const void* value, WriteBarrierParams& params) {
481cb0ef41Sopenharmony_ci    return internal::WriteBarrier::GetWriteBarrierType(slot, value, params);
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  /**
521cb0ef41Sopenharmony_ci   * Gets the required write barrier type for a specific write. This override is
531cb0ef41Sopenharmony_ci   * only used for all the BasicMember types.
541cb0ef41Sopenharmony_ci   *
551cb0ef41Sopenharmony_ci   * \param slot Slot containing the pointer to the object. The slot itself
561cb0ef41Sopenharmony_ci   *   must reside in an object that has been allocated using
571cb0ef41Sopenharmony_ci   *   `MakeGarbageCollected()`.
581cb0ef41Sopenharmony_ci   * \param value The pointer to the object held via `BasicMember`.
591cb0ef41Sopenharmony_ci   * \param params Parameters that may be used for actual write barrier calls.
601cb0ef41Sopenharmony_ci   *   Only filled if return value indicates that a write barrier is needed. The
611cb0ef41Sopenharmony_ci   *   contents of the `params` are an implementation detail.
621cb0ef41Sopenharmony_ci   * \returns whether a write barrier is needed and which barrier to invoke.
631cb0ef41Sopenharmony_ci   */
641cb0ef41Sopenharmony_ci  template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
651cb0ef41Sopenharmony_ci            typename CheckingPolicy, typename StorageType>
661cb0ef41Sopenharmony_ci  static V8_INLINE WriteBarrierType GetWriteBarrierType(
671cb0ef41Sopenharmony_ci      const internal::BasicMember<T, WeaknessTag, WriteBarrierPolicy,
681cb0ef41Sopenharmony_ci                                  CheckingPolicy, StorageType>& value,
691cb0ef41Sopenharmony_ci      WriteBarrierParams& params) {
701cb0ef41Sopenharmony_ci    return internal::WriteBarrier::GetWriteBarrierType(
711cb0ef41Sopenharmony_ci        value.GetRawSlot(), value.GetRawStorage(), params);
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  /**
751cb0ef41Sopenharmony_ci   * Gets the required write barrier type for a specific write.
761cb0ef41Sopenharmony_ci   *
771cb0ef41Sopenharmony_ci   * \param slot Slot to some part of an object. The object must not necessarily
781cb0ef41Sopenharmony_ci       have been allocated using `MakeGarbageCollected()` but can also live
791cb0ef41Sopenharmony_ci       off-heap or on stack.
801cb0ef41Sopenharmony_ci   * \param params Parameters that may be used for actual write barrier calls.
811cb0ef41Sopenharmony_ci   *   Only filled if return value indicates that a write barrier is needed. The
821cb0ef41Sopenharmony_ci   *   contents of the `params` are an implementation detail.
831cb0ef41Sopenharmony_ci   * \param callback Callback returning the corresponding heap handle. The
841cb0ef41Sopenharmony_ci   *   callback is only invoked if the heap cannot otherwise be figured out. The
851cb0ef41Sopenharmony_ci   *   callback must not allocate.
861cb0ef41Sopenharmony_ci   * \returns whether a write barrier is needed and which barrier to invoke.
871cb0ef41Sopenharmony_ci   */
881cb0ef41Sopenharmony_ci  template <typename HeapHandleCallback>
891cb0ef41Sopenharmony_ci  static V8_INLINE WriteBarrierType
901cb0ef41Sopenharmony_ci  GetWriteBarrierType(const void* slot, WriteBarrierParams& params,
911cb0ef41Sopenharmony_ci                      HeapHandleCallback callback) {
921cb0ef41Sopenharmony_ci    return internal::WriteBarrier::GetWriteBarrierType(slot, params, callback);
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  /**
961cb0ef41Sopenharmony_ci   * Gets the required write barrier type for a specific write.
971cb0ef41Sopenharmony_ci   * This version is meant to be used in conjunction with with a marking write
981cb0ef41Sopenharmony_ci   * barrier barrier which doesn't consider the slot.
991cb0ef41Sopenharmony_ci   *
1001cb0ef41Sopenharmony_ci   * \param value The pointer to the object. May be an interior pointer to an
1011cb0ef41Sopenharmony_ci   *   interface of the actual object.
1021cb0ef41Sopenharmony_ci   * \param params Parameters that may be used for actual write barrier calls.
1031cb0ef41Sopenharmony_ci   *   Only filled if return value indicates that a write barrier is needed. The
1041cb0ef41Sopenharmony_ci   *   contents of the `params` are an implementation detail.
1051cb0ef41Sopenharmony_ci   * \returns whether a write barrier is needed and which barrier to invoke.
1061cb0ef41Sopenharmony_ci   */
1071cb0ef41Sopenharmony_ci  static V8_INLINE WriteBarrierType
1081cb0ef41Sopenharmony_ci  GetWriteBarrierType(const void* value, WriteBarrierParams& params) {
1091cb0ef41Sopenharmony_ci    return internal::WriteBarrier::GetWriteBarrierType(value, params);
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  /**
1131cb0ef41Sopenharmony_ci   * Conservative Dijkstra-style write barrier that processes an object if it
1141cb0ef41Sopenharmony_ci   * has not yet been processed.
1151cb0ef41Sopenharmony_ci   *
1161cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1171cb0ef41Sopenharmony_ci   * \param object The pointer to the object. May be an interior pointer to a
1181cb0ef41Sopenharmony_ci   *   an interface of the actual object.
1191cb0ef41Sopenharmony_ci   */
1201cb0ef41Sopenharmony_ci  static V8_INLINE void DijkstraWriteBarrier(const WriteBarrierParams& params,
1211cb0ef41Sopenharmony_ci                                             const void* object) {
1221cb0ef41Sopenharmony_ci    internal::WriteBarrier::DijkstraMarkingBarrier(params, object);
1231cb0ef41Sopenharmony_ci  }
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  /**
1261cb0ef41Sopenharmony_ci   * Conservative Dijkstra-style write barrier that processes a range of
1271cb0ef41Sopenharmony_ci   * elements if they have not yet been processed.
1281cb0ef41Sopenharmony_ci   *
1291cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1301cb0ef41Sopenharmony_ci   * \param first_element Pointer to the first element that should be processed.
1311cb0ef41Sopenharmony_ci   *   The slot itself must reside in an object that has been allocated using
1321cb0ef41Sopenharmony_ci   *   `MakeGarbageCollected()`.
1331cb0ef41Sopenharmony_ci   * \param element_size Size of the element in bytes.
1341cb0ef41Sopenharmony_ci   * \param number_of_elements Number of elements that should be processed,
1351cb0ef41Sopenharmony_ci   *   starting with `first_element`.
1361cb0ef41Sopenharmony_ci   * \param trace_callback The trace callback that should be invoked for each
1371cb0ef41Sopenharmony_ci   *   element if necessary.
1381cb0ef41Sopenharmony_ci   */
1391cb0ef41Sopenharmony_ci  static V8_INLINE void DijkstraWriteBarrierRange(
1401cb0ef41Sopenharmony_ci      const WriteBarrierParams& params, const void* first_element,
1411cb0ef41Sopenharmony_ci      size_t element_size, size_t number_of_elements,
1421cb0ef41Sopenharmony_ci      TraceCallback trace_callback) {
1431cb0ef41Sopenharmony_ci    internal::WriteBarrier::DijkstraMarkingBarrierRange(
1441cb0ef41Sopenharmony_ci        params, first_element, element_size, number_of_elements,
1451cb0ef41Sopenharmony_ci        trace_callback);
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  /**
1491cb0ef41Sopenharmony_ci   * Steele-style write barrier that re-processes an object if it has already
1501cb0ef41Sopenharmony_ci   * been processed.
1511cb0ef41Sopenharmony_ci   *
1521cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1531cb0ef41Sopenharmony_ci   * \param object The pointer to the object which must point to an object that
1541cb0ef41Sopenharmony_ci   *   has been allocated using `MakeGarbageCollected()`. Interior pointers are
1551cb0ef41Sopenharmony_ci   *   not supported.
1561cb0ef41Sopenharmony_ci   */
1571cb0ef41Sopenharmony_ci  static V8_INLINE void SteeleWriteBarrier(const WriteBarrierParams& params,
1581cb0ef41Sopenharmony_ci                                           const void* object) {
1591cb0ef41Sopenharmony_ci    internal::WriteBarrier::SteeleMarkingBarrier(params, object);
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  /**
1631cb0ef41Sopenharmony_ci   * Generational barrier for maintaining consistency when running with multiple
1641cb0ef41Sopenharmony_ci   * generations.
1651cb0ef41Sopenharmony_ci   *
1661cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1671cb0ef41Sopenharmony_ci   * \param slot Slot containing the pointer to the object. The slot itself
1681cb0ef41Sopenharmony_ci   *   must reside in an object that has been allocated using
1691cb0ef41Sopenharmony_ci   *   `MakeGarbageCollected()`.
1701cb0ef41Sopenharmony_ci   */
1711cb0ef41Sopenharmony_ci  static V8_INLINE void GenerationalBarrier(const WriteBarrierParams& params,
1721cb0ef41Sopenharmony_ci                                            const void* slot) {
1731cb0ef41Sopenharmony_ci    internal::WriteBarrier::GenerationalBarrier<
1741cb0ef41Sopenharmony_ci        internal::WriteBarrier::GenerationalBarrierType::kPreciseSlot>(params,
1751cb0ef41Sopenharmony_ci                                                                       slot);
1761cb0ef41Sopenharmony_ci  }
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  /**
1791cb0ef41Sopenharmony_ci   * Generational barrier for maintaining consistency when running with multiple
1801cb0ef41Sopenharmony_ci   * generations. This version is used when slot contains uncompressed pointer.
1811cb0ef41Sopenharmony_ci   *
1821cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1831cb0ef41Sopenharmony_ci   * \param slot Uncompressed slot containing the direct pointer to the object.
1841cb0ef41Sopenharmony_ci   * The slot itself must reside in an object that has been allocated using
1851cb0ef41Sopenharmony_ci   *   `MakeGarbageCollected()`.
1861cb0ef41Sopenharmony_ci   */
1871cb0ef41Sopenharmony_ci  static V8_INLINE void GenerationalBarrierForUncompressedSlot(
1881cb0ef41Sopenharmony_ci      const WriteBarrierParams& params, const void* uncompressed_slot) {
1891cb0ef41Sopenharmony_ci    internal::WriteBarrier::GenerationalBarrier<
1901cb0ef41Sopenharmony_ci        internal::WriteBarrier::GenerationalBarrierType::
1911cb0ef41Sopenharmony_ci            kPreciseUncompressedSlot>(params, uncompressed_slot);
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  /**
1951cb0ef41Sopenharmony_ci   * Generational barrier for source object that may contain outgoing pointers
1961cb0ef41Sopenharmony_ci   * to objects in young generation.
1971cb0ef41Sopenharmony_ci   *
1981cb0ef41Sopenharmony_ci   * \param params The parameters retrieved from `GetWriteBarrierType()`.
1991cb0ef41Sopenharmony_ci   * \param inner_pointer Pointer to the source object.
2001cb0ef41Sopenharmony_ci   */
2011cb0ef41Sopenharmony_ci  static V8_INLINE void GenerationalBarrierForSourceObject(
2021cb0ef41Sopenharmony_ci      const WriteBarrierParams& params, const void* inner_pointer) {
2031cb0ef41Sopenharmony_ci    internal::WriteBarrier::GenerationalBarrier<
2041cb0ef41Sopenharmony_ci        internal::WriteBarrier::GenerationalBarrierType::kImpreciseSlot>(
2051cb0ef41Sopenharmony_ci        params, inner_pointer);
2061cb0ef41Sopenharmony_ci  }
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci private:
2091cb0ef41Sopenharmony_ci  HeapConsistency() = delete;
2101cb0ef41Sopenharmony_ci};
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci/**
2131cb0ef41Sopenharmony_ci * Disallows garbage collection finalizations. Any garbage collection triggers
2141cb0ef41Sopenharmony_ci * result in a crash when in this scope.
2151cb0ef41Sopenharmony_ci *
2161cb0ef41Sopenharmony_ci * Note that the garbage collector already covers paths that can lead to garbage
2171cb0ef41Sopenharmony_ci * collections, so user code does not require checking
2181cb0ef41Sopenharmony_ci * `IsGarbageCollectionAllowed()` before allocations.
2191cb0ef41Sopenharmony_ci */
2201cb0ef41Sopenharmony_ciclass V8_EXPORT V8_NODISCARD DisallowGarbageCollectionScope final {
2211cb0ef41Sopenharmony_ci  CPPGC_STACK_ALLOCATED();
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci public:
2241cb0ef41Sopenharmony_ci  /**
2251cb0ef41Sopenharmony_ci   * \returns whether garbage collections are currently allowed.
2261cb0ef41Sopenharmony_ci   */
2271cb0ef41Sopenharmony_ci  static bool IsGarbageCollectionAllowed(HeapHandle& heap_handle);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  /**
2301cb0ef41Sopenharmony_ci   * Enters a disallow garbage collection scope. Must be paired with `Leave()`.
2311cb0ef41Sopenharmony_ci   * Prefer a scope instance of `DisallowGarbageCollectionScope`.
2321cb0ef41Sopenharmony_ci   *
2331cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2341cb0ef41Sopenharmony_ci   */
2351cb0ef41Sopenharmony_ci  static void Enter(HeapHandle& heap_handle);
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  /**
2381cb0ef41Sopenharmony_ci   * Leaves a disallow garbage collection scope. Must be paired with `Enter()`.
2391cb0ef41Sopenharmony_ci   * Prefer a scope instance of `DisallowGarbageCollectionScope`.
2401cb0ef41Sopenharmony_ci   *
2411cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2421cb0ef41Sopenharmony_ci   */
2431cb0ef41Sopenharmony_ci  static void Leave(HeapHandle& heap_handle);
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  /**
2461cb0ef41Sopenharmony_ci   * Constructs a scoped object that automatically enters and leaves a disallow
2471cb0ef41Sopenharmony_ci   * garbage collection scope based on its lifetime.
2481cb0ef41Sopenharmony_ci   *
2491cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2501cb0ef41Sopenharmony_ci   */
2511cb0ef41Sopenharmony_ci  explicit DisallowGarbageCollectionScope(HeapHandle& heap_handle);
2521cb0ef41Sopenharmony_ci  ~DisallowGarbageCollectionScope();
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  DisallowGarbageCollectionScope(const DisallowGarbageCollectionScope&) =
2551cb0ef41Sopenharmony_ci      delete;
2561cb0ef41Sopenharmony_ci  DisallowGarbageCollectionScope& operator=(
2571cb0ef41Sopenharmony_ci      const DisallowGarbageCollectionScope&) = delete;
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci private:
2601cb0ef41Sopenharmony_ci  HeapHandle& heap_handle_;
2611cb0ef41Sopenharmony_ci};
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci/**
2641cb0ef41Sopenharmony_ci * Avoids invoking garbage collection finalizations. Already running garbage
2651cb0ef41Sopenharmony_ci * collection phase are unaffected by this scope.
2661cb0ef41Sopenharmony_ci *
2671cb0ef41Sopenharmony_ci * Should only be used temporarily as the scope has an impact on memory usage
2681cb0ef41Sopenharmony_ci * and follow up garbage collections.
2691cb0ef41Sopenharmony_ci */
2701cb0ef41Sopenharmony_ciclass V8_EXPORT V8_NODISCARD NoGarbageCollectionScope final {
2711cb0ef41Sopenharmony_ci  CPPGC_STACK_ALLOCATED();
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci public:
2741cb0ef41Sopenharmony_ci  /**
2751cb0ef41Sopenharmony_ci   * Enters a no garbage collection scope. Must be paired with `Leave()`. Prefer
2761cb0ef41Sopenharmony_ci   * a scope instance of `NoGarbageCollectionScope`.
2771cb0ef41Sopenharmony_ci   *
2781cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2791cb0ef41Sopenharmony_ci   */
2801cb0ef41Sopenharmony_ci  static void Enter(HeapHandle& heap_handle);
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  /**
2831cb0ef41Sopenharmony_ci   * Leaves a no garbage collection scope. Must be paired with `Enter()`. Prefer
2841cb0ef41Sopenharmony_ci   * a scope instance of `NoGarbageCollectionScope`.
2851cb0ef41Sopenharmony_ci   *
2861cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2871cb0ef41Sopenharmony_ci   */
2881cb0ef41Sopenharmony_ci  static void Leave(HeapHandle& heap_handle);
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  /**
2911cb0ef41Sopenharmony_ci   * Constructs a scoped object that automatically enters and leaves a no
2921cb0ef41Sopenharmony_ci   * garbage collection scope based on its lifetime.
2931cb0ef41Sopenharmony_ci   *
2941cb0ef41Sopenharmony_ci   * \param heap_handle The corresponding heap.
2951cb0ef41Sopenharmony_ci   */
2961cb0ef41Sopenharmony_ci  explicit NoGarbageCollectionScope(HeapHandle& heap_handle);
2971cb0ef41Sopenharmony_ci  ~NoGarbageCollectionScope();
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  NoGarbageCollectionScope(const NoGarbageCollectionScope&) = delete;
3001cb0ef41Sopenharmony_ci  NoGarbageCollectionScope& operator=(const NoGarbageCollectionScope&) = delete;
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci private:
3031cb0ef41Sopenharmony_ci  HeapHandle& heap_handle_;
3041cb0ef41Sopenharmony_ci};
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci}  // namespace subtle
3071cb0ef41Sopenharmony_ci}  // namespace cppgc
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_HEAP_CONSISTENCY_H_
310