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_WRITE_BARRIER_H_ 61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <cstddef> 91cb0ef41Sopenharmony_ci#include <cstdint> 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci#include "cppgc/heap-handle.h" 121cb0ef41Sopenharmony_ci#include "cppgc/heap-state.h" 131cb0ef41Sopenharmony_ci#include "cppgc/internal/api-constants.h" 141cb0ef41Sopenharmony_ci#include "cppgc/internal/atomic-entry-flag.h" 151cb0ef41Sopenharmony_ci#include "cppgc/internal/base-page-handle.h" 161cb0ef41Sopenharmony_ci#include "cppgc/internal/member-storage.h" 171cb0ef41Sopenharmony_ci#include "cppgc/platform.h" 181cb0ef41Sopenharmony_ci#include "cppgc/sentinel-pointer.h" 191cb0ef41Sopenharmony_ci#include "cppgc/trace-trait.h" 201cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 231cb0ef41Sopenharmony_ci#include "cppgc/internal/caged-heap-local-data.h" 241cb0ef41Sopenharmony_ci#include "cppgc/internal/caged-heap.h" 251cb0ef41Sopenharmony_ci#endif 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cinamespace cppgc { 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciclass HeapHandle; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cinamespace internal { 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 341cb0ef41Sopenharmony_ciclass WriteBarrierTypeForCagedHeapPolicy; 351cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 361cb0ef41Sopenharmony_ciclass WriteBarrierTypeForNonCagedHeapPolicy; 371cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrier final { 401cb0ef41Sopenharmony_ci public: 411cb0ef41Sopenharmony_ci enum class Type : uint8_t { 421cb0ef41Sopenharmony_ci kNone, 431cb0ef41Sopenharmony_ci kMarking, 441cb0ef41Sopenharmony_ci kGenerational, 451cb0ef41Sopenharmony_ci }; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci enum class GenerationalBarrierType : uint8_t { 481cb0ef41Sopenharmony_ci kPreciseSlot, 491cb0ef41Sopenharmony_ci kPreciseUncompressedSlot, 501cb0ef41Sopenharmony_ci kImpreciseSlot, 511cb0ef41Sopenharmony_ci }; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci struct Params { 541cb0ef41Sopenharmony_ci HeapHandle* heap = nullptr; 551cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 561cb0ef41Sopenharmony_ci Type type = Type::kNone; 571cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 581cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 591cb0ef41Sopenharmony_ci uintptr_t slot_offset = 0; 601cb0ef41Sopenharmony_ci uintptr_t value_offset = 0; 611cb0ef41Sopenharmony_ci#endif // CPPGC_CAGED_HEAP 621cb0ef41Sopenharmony_ci }; 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci enum class ValueMode { 651cb0ef41Sopenharmony_ci kValuePresent, 661cb0ef41Sopenharmony_ci kNoValuePresent, 671cb0ef41Sopenharmony_ci }; 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `slot` and `value`. 701cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* slot, const void* value, 711cb0ef41Sopenharmony_ci Params& params); 721cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `slot` and `value`. 731cb0ef41Sopenharmony_ci template <typename MemberStorage> 741cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* slot, MemberStorage, 751cb0ef41Sopenharmony_ci Params& params); 761cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `slot`. 771cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 781cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* slot, Params& params, 791cb0ef41Sopenharmony_ci HeapHandleCallback callback); 801cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `value`. 811cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* value, Params& params); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci#ifdef CPPGC_SLIM_WRITE_BARRIER 841cb0ef41Sopenharmony_ci // A write barrier that combines `GenerationalBarrier()` and 851cb0ef41Sopenharmony_ci // `DijkstraMarkingBarrier()`. We only pass a single parameter here to clobber 861cb0ef41Sopenharmony_ci // as few registers as possible. 871cb0ef41Sopenharmony_ci template <WriteBarrierSlotType> 881cb0ef41Sopenharmony_ci static V8_NOINLINE void V8_PRESERVE_MOST 891cb0ef41Sopenharmony_ci CombinedWriteBarrierSlow(const void* slot); 901cb0ef41Sopenharmony_ci#endif // CPPGC_SLIM_WRITE_BARRIER 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci static V8_INLINE void DijkstraMarkingBarrier(const Params& params, 931cb0ef41Sopenharmony_ci const void* object); 941cb0ef41Sopenharmony_ci static V8_INLINE void DijkstraMarkingBarrierRange( 951cb0ef41Sopenharmony_ci const Params& params, const void* first_element, size_t element_size, 961cb0ef41Sopenharmony_ci size_t number_of_elements, TraceCallback trace_callback); 971cb0ef41Sopenharmony_ci static V8_INLINE void SteeleMarkingBarrier(const Params& params, 981cb0ef41Sopenharmony_ci const void* object); 991cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 1001cb0ef41Sopenharmony_ci template <GenerationalBarrierType> 1011cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrier(const Params& params, 1021cb0ef41Sopenharmony_ci const void* slot); 1031cb0ef41Sopenharmony_ci#else // !CPPGC_YOUNG_GENERATION 1041cb0ef41Sopenharmony_ci template <GenerationalBarrierType> 1051cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrier(const Params& params, 1061cb0ef41Sopenharmony_ci const void* slot){} 1071cb0ef41Sopenharmony_ci#endif // CPPGC_YOUNG_GENERATION 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 1101cb0ef41Sopenharmony_ci static void CheckParams(Type expected_type, const Params& params); 1111cb0ef41Sopenharmony_ci#else // !V8_ENABLE_CHECKS 1121cb0ef41Sopenharmony_ci static void CheckParams(Type expected_type, const Params& params) {} 1131cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci // The FlagUpdater class allows cppgc internal to update 1161cb0ef41Sopenharmony_ci // |write_barrier_enabled_|. 1171cb0ef41Sopenharmony_ci class FlagUpdater; 1181cb0ef41Sopenharmony_ci static bool IsEnabled() { return write_barrier_enabled_.MightBeEntered(); } 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci private: 1211cb0ef41Sopenharmony_ci WriteBarrier() = delete; 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 1241cb0ef41Sopenharmony_ci using WriteBarrierTypePolicy = WriteBarrierTypeForCagedHeapPolicy; 1251cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 1261cb0ef41Sopenharmony_ci using WriteBarrierTypePolicy = WriteBarrierTypeForNonCagedHeapPolicy; 1271cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierSlow(const void* value); 1301cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierSlowWithSentinelCheck(const void* value); 1311cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierRangeSlow(HeapHandle& heap_handle, 1321cb0ef41Sopenharmony_ci const void* first_element, 1331cb0ef41Sopenharmony_ci size_t element_size, 1341cb0ef41Sopenharmony_ci size_t number_of_elements, 1351cb0ef41Sopenharmony_ci TraceCallback trace_callback); 1361cb0ef41Sopenharmony_ci static void SteeleMarkingBarrierSlow(const void* value); 1371cb0ef41Sopenharmony_ci static void SteeleMarkingBarrierSlowWithSentinelCheck(const void* value); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 1401cb0ef41Sopenharmony_ci static CagedHeapLocalData& GetLocalData(HeapHandle&); 1411cb0ef41Sopenharmony_ci static void GenerationalBarrierSlow(const CagedHeapLocalData& local_data, 1421cb0ef41Sopenharmony_ci const AgeTable& age_table, 1431cb0ef41Sopenharmony_ci const void* slot, uintptr_t value_offset, 1441cb0ef41Sopenharmony_ci HeapHandle* heap_handle); 1451cb0ef41Sopenharmony_ci static void GenerationalBarrierForUncompressedSlotSlow( 1461cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data, const AgeTable& age_table, 1471cb0ef41Sopenharmony_ci const void* slot, uintptr_t value_offset, HeapHandle* heap_handle); 1481cb0ef41Sopenharmony_ci static void GenerationalBarrierForSourceObjectSlow( 1491cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data, const void* object, 1501cb0ef41Sopenharmony_ci HeapHandle* heap_handle); 1511cb0ef41Sopenharmony_ci#endif // CPPGC_YOUNG_GENERATION 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci static AtomicEntryFlag write_barrier_enabled_; 1541cb0ef41Sopenharmony_ci}; 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_citemplate <WriteBarrier::Type type> 1571cb0ef41Sopenharmony_ciV8_INLINE WriteBarrier::Type SetAndReturnType(WriteBarrier::Params& params) { 1581cb0ef41Sopenharmony_ci if constexpr (type == WriteBarrier::Type::kNone) 1591cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 1601cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 1611cb0ef41Sopenharmony_ci params.type = type; 1621cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 1631cb0ef41Sopenharmony_ci return type; 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 1671cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrierTypeForCagedHeapPolicy final { 1681cb0ef41Sopenharmony_ci public: 1691cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 1701cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 1711cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1721cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 1731cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value, params, callback); 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback, 1771cb0ef41Sopenharmony_ci typename MemberStorage> 1781cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, MemberStorage value, 1791cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1801cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 1811cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value, params, callback); 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 1851cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* value, 1861cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1871cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 1881cb0ef41Sopenharmony_ci return GetNoSlot(value, params, callback); 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci private: 1921cb0ef41Sopenharmony_ci WriteBarrierTypeForCagedHeapPolicy() = delete; 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 1951cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type GetNoSlot(const void* value, 1961cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1971cb0ef41Sopenharmony_ci HeapHandleCallback) { 1981cb0ef41Sopenharmony_ci const bool within_cage = CagedHeapBase::IsWithinCage(value); 1991cb0ef41Sopenharmony_ci if (!within_cage) return WriteBarrier::Type::kNone; 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci // We know that |value| points either within the normal page or to the 2021cb0ef41Sopenharmony_ci // beginning of large-page, so extract the page header by bitmasking. 2031cb0ef41Sopenharmony_ci BasePageHandle* page = 2041cb0ef41Sopenharmony_ci BasePageHandle::FromPayload(const_cast<void*>(value)); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci HeapHandle& heap_handle = page->heap_handle(); 2071cb0ef41Sopenharmony_ci if (V8_UNLIKELY(heap_handle.is_incremental_marking_in_progress())) { 2081cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 2091cb0ef41Sopenharmony_ci } 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode> 2151cb0ef41Sopenharmony_ci struct ValueModeDispatch; 2161cb0ef41Sopenharmony_ci}; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_citemplate <> 2191cb0ef41Sopenharmony_cistruct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch< 2201cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kValuePresent> { 2211cb0ef41Sopenharmony_ci template <typename HeapHandleCallback, typename MemberStorage> 2221cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, 2231cb0ef41Sopenharmony_ci MemberStorage storage, 2241cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2251cb0ef41Sopenharmony_ci HeapHandleCallback) { 2261cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsEnabled())) 2271cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci return BarrierEnabledGet(slot, storage.Load(), params); 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 2331cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 2341cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2351cb0ef41Sopenharmony_ci HeapHandleCallback) { 2361cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsEnabled())) 2371cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci return BarrierEnabledGet(slot, value, params); 2401cb0ef41Sopenharmony_ci } 2411cb0ef41Sopenharmony_ci 2421cb0ef41Sopenharmony_ci private: 2431cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type BarrierEnabledGet( 2441cb0ef41Sopenharmony_ci const void* slot, const void* value, WriteBarrier::Params& params) { 2451cb0ef41Sopenharmony_ci const bool within_cage = CagedHeapBase::AreWithinCage(slot, value); 2461cb0ef41Sopenharmony_ci if (!within_cage) return WriteBarrier::Type::kNone; 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // We know that |value| points either within the normal page or to the 2491cb0ef41Sopenharmony_ci // beginning of large-page, so extract the page header by bitmasking. 2501cb0ef41Sopenharmony_ci BasePageHandle* page = 2511cb0ef41Sopenharmony_ci BasePageHandle::FromPayload(const_cast<void*>(value)); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci HeapHandle& heap_handle = page->heap_handle(); 2541cb0ef41Sopenharmony_ci if (V8_LIKELY(!heap_handle.is_incremental_marking_in_progress())) { 2551cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 2561cb0ef41Sopenharmony_ci if (!heap_handle.is_young_generation_enabled()) 2571cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 2581cb0ef41Sopenharmony_ci params.heap = &heap_handle; 2591cb0ef41Sopenharmony_ci params.slot_offset = CagedHeapBase::OffsetFromAddress(slot); 2601cb0ef41Sopenharmony_ci params.value_offset = CagedHeapBase::OffsetFromAddress(value); 2611cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kGenerational>(params); 2621cb0ef41Sopenharmony_ci#else // !CPPGC_YOUNG_GENERATION 2631cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2641cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci // Use marking barrier. 2681cb0ef41Sopenharmony_ci params.heap = &heap_handle; 2691cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci}; 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_citemplate <> 2741cb0ef41Sopenharmony_cistruct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch< 2751cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kNoValuePresent> { 2761cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 2771cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void*, 2781cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2791cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 2801cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsEnabled())) 2811cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci HeapHandle& handle = callback(); 2841cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 2851cb0ef41Sopenharmony_ci if (V8_LIKELY(!handle.is_incremental_marking_in_progress())) { 2861cb0ef41Sopenharmony_ci if (!handle.is_young_generation_enabled()) { 2871cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci params.heap = &handle; 2901cb0ef41Sopenharmony_ci // Check if slot is on stack. 2911cb0ef41Sopenharmony_ci if (V8_UNLIKELY(!CagedHeapBase::IsWithinCage(slot))) { 2921cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2931cb0ef41Sopenharmony_ci } 2941cb0ef41Sopenharmony_ci params.slot_offset = CagedHeapBase::OffsetFromAddress(slot); 2951cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kGenerational>(params); 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci#else // !defined(CPPGC_YOUNG_GENERATION) 2981cb0ef41Sopenharmony_ci if (V8_UNLIKELY(!handle.is_incremental_marking_in_progress())) { 2991cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci#endif // !defined(CPPGC_YOUNG_GENERATION) 3021cb0ef41Sopenharmony_ci params.heap = &handle; 3031cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci}; 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci#endif // CPPGC_CAGED_HEAP 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrierTypeForNonCagedHeapPolicy final { 3101cb0ef41Sopenharmony_ci public: 3111cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 3121cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 3131cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3141cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3151cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value, params, callback); 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 3191cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, RawPointer value, 3201cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3211cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3221cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value.Load(), params, 3231cb0ef41Sopenharmony_ci callback); 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 3271cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* value, 3281cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3291cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3301cb0ef41Sopenharmony_ci // The slot will never be used in `Get()` below. 3311cb0ef41Sopenharmony_ci return Get<WriteBarrier::ValueMode::kValuePresent>(nullptr, value, params, 3321cb0ef41Sopenharmony_ci callback); 3331cb0ef41Sopenharmony_ci } 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci private: 3361cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode> 3371cb0ef41Sopenharmony_ci struct ValueModeDispatch; 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci WriteBarrierTypeForNonCagedHeapPolicy() = delete; 3401cb0ef41Sopenharmony_ci}; 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_citemplate <> 3431cb0ef41Sopenharmony_cistruct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< 3441cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kValuePresent> { 3451cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 3461cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void*, const void* object, 3471cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3481cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3491cb0ef41Sopenharmony_ci // The following check covers nullptr as well as sentinel pointer. 3501cb0ef41Sopenharmony_ci if (object <= static_cast<void*>(kSentinelPointer)) { 3511cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsEnabled())) { 3541cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci // We know that |object| is within the normal page or in the beginning of a 3571cb0ef41Sopenharmony_ci // large page, so extract the page header by bitmasking. 3581cb0ef41Sopenharmony_ci BasePageHandle* page = 3591cb0ef41Sopenharmony_ci BasePageHandle::FromPayload(const_cast<void*>(object)); 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci HeapHandle& heap_handle = page->heap_handle(); 3621cb0ef41Sopenharmony_ci if (V8_LIKELY(heap_handle.is_incremental_marking_in_progress())) { 3631cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 3641cb0ef41Sopenharmony_ci } 3651cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3661cb0ef41Sopenharmony_ci } 3671cb0ef41Sopenharmony_ci}; 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_citemplate <> 3701cb0ef41Sopenharmony_cistruct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< 3711cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kNoValuePresent> { 3721cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 3731cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void*, const void*, 3741cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3751cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3761cb0ef41Sopenharmony_ci if (V8_UNLIKELY(WriteBarrier::IsEnabled())) { 3771cb0ef41Sopenharmony_ci HeapHandle& handle = callback(); 3781cb0ef41Sopenharmony_ci if (V8_LIKELY(handle.is_incremental_marking_in_progress())) { 3791cb0ef41Sopenharmony_ci params.heap = &handle; 3801cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci } 3831cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci}; 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci// static 3881cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 3891cb0ef41Sopenharmony_ci const void* slot, const void* value, WriteBarrier::Params& params) { 3901cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(slot, value, 3911cb0ef41Sopenharmony_ci params, []() {}); 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci// static 3951cb0ef41Sopenharmony_citemplate <typename MemberStorage> 3961cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 3971cb0ef41Sopenharmony_ci const void* slot, MemberStorage value, WriteBarrier::Params& params) { 3981cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(slot, value, 3991cb0ef41Sopenharmony_ci params, []() {}); 4001cb0ef41Sopenharmony_ci} 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci// static 4031cb0ef41Sopenharmony_citemplate <typename HeapHandleCallback> 4041cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 4051cb0ef41Sopenharmony_ci const void* slot, WriteBarrier::Params& params, 4061cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 4071cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kNoValuePresent>( 4081cb0ef41Sopenharmony_ci slot, nullptr, params, callback); 4091cb0ef41Sopenharmony_ci} 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci// static 4121cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 4131cb0ef41Sopenharmony_ci const void* value, WriteBarrier::Params& params) { 4141cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(value, params, 4151cb0ef41Sopenharmony_ci []() {}); 4161cb0ef41Sopenharmony_ci} 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci// static 4191cb0ef41Sopenharmony_civoid WriteBarrier::DijkstraMarkingBarrier(const Params& params, 4201cb0ef41Sopenharmony_ci const void* object) { 4211cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 4221cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 4231cb0ef41Sopenharmony_ci // Caged heap already filters out sentinels. 4241cb0ef41Sopenharmony_ci DijkstraMarkingBarrierSlow(object); 4251cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 4261cb0ef41Sopenharmony_ci DijkstraMarkingBarrierSlowWithSentinelCheck(object); 4271cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 4281cb0ef41Sopenharmony_ci} 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci// static 4311cb0ef41Sopenharmony_civoid WriteBarrier::DijkstraMarkingBarrierRange(const Params& params, 4321cb0ef41Sopenharmony_ci const void* first_element, 4331cb0ef41Sopenharmony_ci size_t element_size, 4341cb0ef41Sopenharmony_ci size_t number_of_elements, 4351cb0ef41Sopenharmony_ci TraceCallback trace_callback) { 4361cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 4371cb0ef41Sopenharmony_ci DijkstraMarkingBarrierRangeSlow(*params.heap, first_element, element_size, 4381cb0ef41Sopenharmony_ci number_of_elements, trace_callback); 4391cb0ef41Sopenharmony_ci} 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci// static 4421cb0ef41Sopenharmony_civoid WriteBarrier::SteeleMarkingBarrier(const Params& params, 4431cb0ef41Sopenharmony_ci const void* object) { 4441cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 4451cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 4461cb0ef41Sopenharmony_ci // Caged heap already filters out sentinels. 4471cb0ef41Sopenharmony_ci SteeleMarkingBarrierSlow(object); 4481cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 4491cb0ef41Sopenharmony_ci SteeleMarkingBarrierSlowWithSentinelCheck(object); 4501cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 4511cb0ef41Sopenharmony_ci} 4521cb0ef41Sopenharmony_ci 4531cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci// static 4561cb0ef41Sopenharmony_citemplate <WriteBarrier::GenerationalBarrierType type> 4571cb0ef41Sopenharmony_civoid WriteBarrier::GenerationalBarrier(const Params& params, const void* slot) { 4581cb0ef41Sopenharmony_ci CheckParams(Type::kGenerational, params); 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data = CagedHeapLocalData::Get(); 4611cb0ef41Sopenharmony_ci const AgeTable& age_table = local_data.age_table; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci // Bail out if the slot (precise or imprecise) is in young generation. 4641cb0ef41Sopenharmony_ci if (V8_LIKELY(age_table.GetAge(params.slot_offset) == AgeTable::Age::kYoung)) 4651cb0ef41Sopenharmony_ci return; 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci // Dispatch between different types of barriers. 4681cb0ef41Sopenharmony_ci // TODO(chromium:1029379): Consider reload local_data in the slow path to 4691cb0ef41Sopenharmony_ci // reduce register pressure. 4701cb0ef41Sopenharmony_ci if constexpr (type == GenerationalBarrierType::kPreciseSlot) { 4711cb0ef41Sopenharmony_ci GenerationalBarrierSlow(local_data, age_table, slot, params.value_offset, 4721cb0ef41Sopenharmony_ci params.heap); 4731cb0ef41Sopenharmony_ci } else if constexpr (type == 4741cb0ef41Sopenharmony_ci GenerationalBarrierType::kPreciseUncompressedSlot) { 4751cb0ef41Sopenharmony_ci GenerationalBarrierForUncompressedSlotSlow( 4761cb0ef41Sopenharmony_ci local_data, age_table, slot, params.value_offset, params.heap); 4771cb0ef41Sopenharmony_ci } else { 4781cb0ef41Sopenharmony_ci GenerationalBarrierForSourceObjectSlow(local_data, slot, params.heap); 4791cb0ef41Sopenharmony_ci } 4801cb0ef41Sopenharmony_ci} 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci} // namespace internal 4851cb0ef41Sopenharmony_ci} // namespace cppgc 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci#endif // INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ 488