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