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-state.h" 121cb0ef41Sopenharmony_ci#include "cppgc/internal/api-constants.h" 131cb0ef41Sopenharmony_ci#include "cppgc/internal/atomic-entry-flag.h" 141cb0ef41Sopenharmony_ci#include "cppgc/platform.h" 151cb0ef41Sopenharmony_ci#include "cppgc/sentinel-pointer.h" 161cb0ef41Sopenharmony_ci#include "cppgc/trace-trait.h" 171cb0ef41Sopenharmony_ci#include "v8config.h" // NOLINT(build/include_directory) 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 201cb0ef41Sopenharmony_ci#include "cppgc/internal/caged-heap-local-data.h" 211cb0ef41Sopenharmony_ci#endif 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace cppgc { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ciclass HeapHandle; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cinamespace internal { 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 301cb0ef41Sopenharmony_ciclass WriteBarrierTypeForCagedHeapPolicy; 311cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 321cb0ef41Sopenharmony_ciclass WriteBarrierTypeForNonCagedHeapPolicy; 331cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrier final { 361cb0ef41Sopenharmony_ci public: 371cb0ef41Sopenharmony_ci enum class Type : uint8_t { 381cb0ef41Sopenharmony_ci kNone, 391cb0ef41Sopenharmony_ci kMarking, 401cb0ef41Sopenharmony_ci kGenerational, 411cb0ef41Sopenharmony_ci }; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci struct Params { 441cb0ef41Sopenharmony_ci HeapHandle* heap = nullptr; 451cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 461cb0ef41Sopenharmony_ci Type type = Type::kNone; 471cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 481cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 491cb0ef41Sopenharmony_ci uintptr_t start = 0; 501cb0ef41Sopenharmony_ci CagedHeapLocalData& caged_heap() const { 511cb0ef41Sopenharmony_ci return *reinterpret_cast<CagedHeapLocalData*>(start); 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci uintptr_t slot_offset = 0; 541cb0ef41Sopenharmony_ci uintptr_t value_offset = 0; 551cb0ef41Sopenharmony_ci#endif // CPPGC_CAGED_HEAP 561cb0ef41Sopenharmony_ci }; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci enum class ValueMode { 591cb0ef41Sopenharmony_ci kValuePresent, 601cb0ef41Sopenharmony_ci kNoValuePresent, 611cb0ef41Sopenharmony_ci }; 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `slot` and `value`. 641cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* slot, const void* value, 651cb0ef41Sopenharmony_ci Params& params); 661cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `slot`. 671cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 681cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* slot, Params& params, 691cb0ef41Sopenharmony_ci HeapHandleCallback callback); 701cb0ef41Sopenharmony_ci // Returns the required write barrier for a given `value`. 711cb0ef41Sopenharmony_ci static V8_INLINE Type GetWriteBarrierType(const void* value, Params& params); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci static V8_INLINE void DijkstraMarkingBarrier(const Params& params, 741cb0ef41Sopenharmony_ci const void* object); 751cb0ef41Sopenharmony_ci static V8_INLINE void DijkstraMarkingBarrierRange( 761cb0ef41Sopenharmony_ci const Params& params, const void* first_element, size_t element_size, 771cb0ef41Sopenharmony_ci size_t number_of_elements, TraceCallback trace_callback); 781cb0ef41Sopenharmony_ci static V8_INLINE void SteeleMarkingBarrier(const Params& params, 791cb0ef41Sopenharmony_ci const void* object); 801cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 811cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrier(const Params& params, 821cb0ef41Sopenharmony_ci const void* slot); 831cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrierForSourceObject( 841cb0ef41Sopenharmony_ci const Params& params, const void* inner_pointer); 851cb0ef41Sopenharmony_ci#else // !CPPGC_YOUNG_GENERATION 861cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrier(const Params& params, 871cb0ef41Sopenharmony_ci const void* slot) {} 881cb0ef41Sopenharmony_ci static V8_INLINE void GenerationalBarrierForSourceObject( 891cb0ef41Sopenharmony_ci const Params& params, const void* inner_pointer) {} 901cb0ef41Sopenharmony_ci#endif // CPPGC_YOUNG_GENERATION 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 931cb0ef41Sopenharmony_ci static void CheckParams(Type expected_type, const Params& params); 941cb0ef41Sopenharmony_ci#else // !V8_ENABLE_CHECKS 951cb0ef41Sopenharmony_ci static void CheckParams(Type expected_type, const Params& params) {} 961cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci // The IncrementalOrConcurrentUpdater class allows cppgc internal to update 991cb0ef41Sopenharmony_ci // |incremental_or_concurrent_marking_flag_|. 1001cb0ef41Sopenharmony_ci class IncrementalOrConcurrentMarkingFlagUpdater; 1011cb0ef41Sopenharmony_ci static bool IsAnyIncrementalOrConcurrentMarking() { 1021cb0ef41Sopenharmony_ci return incremental_or_concurrent_marking_flag_.MightBeEntered(); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci private: 1061cb0ef41Sopenharmony_ci WriteBarrier() = delete; 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 1091cb0ef41Sopenharmony_ci using WriteBarrierTypePolicy = WriteBarrierTypeForCagedHeapPolicy; 1101cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 1111cb0ef41Sopenharmony_ci using WriteBarrierTypePolicy = WriteBarrierTypeForNonCagedHeapPolicy; 1121cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierSlow(const void* value); 1151cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierSlowWithSentinelCheck(const void* value); 1161cb0ef41Sopenharmony_ci static void DijkstraMarkingBarrierRangeSlow(HeapHandle& heap_handle, 1171cb0ef41Sopenharmony_ci const void* first_element, 1181cb0ef41Sopenharmony_ci size_t element_size, 1191cb0ef41Sopenharmony_ci size_t number_of_elements, 1201cb0ef41Sopenharmony_ci TraceCallback trace_callback); 1211cb0ef41Sopenharmony_ci static void SteeleMarkingBarrierSlow(const void* value); 1221cb0ef41Sopenharmony_ci static void SteeleMarkingBarrierSlowWithSentinelCheck(const void* value); 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 1251cb0ef41Sopenharmony_ci static CagedHeapLocalData& GetLocalData(HeapHandle&); 1261cb0ef41Sopenharmony_ci static void GenerationalBarrierSlow(const CagedHeapLocalData& local_data, 1271cb0ef41Sopenharmony_ci const AgeTable& age_table, 1281cb0ef41Sopenharmony_ci const void* slot, uintptr_t value_offset); 1291cb0ef41Sopenharmony_ci static void GenerationalBarrierForSourceObjectSlow( 1301cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data, const void* object); 1311cb0ef41Sopenharmony_ci#endif // CPPGC_YOUNG_GENERATION 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci static AtomicEntryFlag incremental_or_concurrent_marking_flag_; 1341cb0ef41Sopenharmony_ci}; 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_citemplate <WriteBarrier::Type type> 1371cb0ef41Sopenharmony_ciV8_INLINE WriteBarrier::Type SetAndReturnType(WriteBarrier::Params& params) { 1381cb0ef41Sopenharmony_ci if (type == WriteBarrier::Type::kNone) return WriteBarrier::Type::kNone; 1391cb0ef41Sopenharmony_ci#if V8_ENABLE_CHECKS 1401cb0ef41Sopenharmony_ci params.type = type; 1411cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_CHECKS 1421cb0ef41Sopenharmony_ci return type; 1431cb0ef41Sopenharmony_ci} 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 1461cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrierTypeForCagedHeapPolicy final { 1471cb0ef41Sopenharmony_ci public: 1481cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 1491cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 1501cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1511cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 1521cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value, params, callback); 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 1561cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* value, 1571cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1581cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 1591cb0ef41Sopenharmony_ci return GetNoSlot(value, params, callback); 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci private: 1631cb0ef41Sopenharmony_ci WriteBarrierTypeForCagedHeapPolicy() = delete; 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 1661cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type GetNoSlot(const void* value, 1671cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 1681cb0ef41Sopenharmony_ci HeapHandleCallback) { 1691cb0ef41Sopenharmony_ci if (!TryGetCagedHeap(value, value, params)) { 1701cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci if (V8_UNLIKELY(params.caged_heap().is_incremental_marking_in_progress)) { 1731cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 1741cb0ef41Sopenharmony_ci } 1751cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode> 1791cb0ef41Sopenharmony_ci struct ValueModeDispatch; 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci static V8_INLINE bool TryGetCagedHeap(const void* slot, const void* value, 1821cb0ef41Sopenharmony_ci WriteBarrier::Params& params) { 1831cb0ef41Sopenharmony_ci // TODO(chromium:1056170): Check if the null check can be folded in with 1841cb0ef41Sopenharmony_ci // the rest of the write barrier. 1851cb0ef41Sopenharmony_ci if (!value) return false; 1861cb0ef41Sopenharmony_ci params.start = reinterpret_cast<uintptr_t>(value) & 1871cb0ef41Sopenharmony_ci ~(api_constants::kCagedHeapReservationAlignment - 1); 1881cb0ef41Sopenharmony_ci const uintptr_t slot_offset = 1891cb0ef41Sopenharmony_ci reinterpret_cast<uintptr_t>(slot) - params.start; 1901cb0ef41Sopenharmony_ci if (slot_offset > api_constants::kCagedHeapReservationSize) { 1911cb0ef41Sopenharmony_ci // Check if slot is on stack or value is sentinel or nullptr. This relies 1921cb0ef41Sopenharmony_ci // on the fact that kSentinelPointer is encoded as 0x1. 1931cb0ef41Sopenharmony_ci return false; 1941cb0ef41Sopenharmony_ci } 1951cb0ef41Sopenharmony_ci return true; 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci // Returns whether marking is in progress. If marking is not in progress 1991cb0ef41Sopenharmony_ci // sets the start of the cage accordingly. 2001cb0ef41Sopenharmony_ci // 2011cb0ef41Sopenharmony_ci // TODO(chromium:1056170): Create fast path on API. 2021cb0ef41Sopenharmony_ci static bool IsMarking(const HeapHandle&, WriteBarrier::Params&); 2031cb0ef41Sopenharmony_ci}; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_citemplate <> 2061cb0ef41Sopenharmony_cistruct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch< 2071cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kValuePresent> { 2081cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 2091cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 2101cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2111cb0ef41Sopenharmony_ci HeapHandleCallback) { 2121cb0ef41Sopenharmony_ci#if !defined(CPPGC_YOUNG_GENERATION) 2131cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) { 2141cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2151cb0ef41Sopenharmony_ci } 2161cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 2171cb0ef41Sopenharmony_ci bool within_cage = TryGetCagedHeap(slot, value, params); 2181cb0ef41Sopenharmony_ci if (!within_cage) { 2191cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci if (V8_LIKELY(!params.caged_heap().is_incremental_marking_in_progress)) { 2221cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 2231cb0ef41Sopenharmony_ci params.heap = reinterpret_cast<HeapHandle*>(params.start); 2241cb0ef41Sopenharmony_ci params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start; 2251cb0ef41Sopenharmony_ci params.value_offset = reinterpret_cast<uintptr_t>(value) - params.start; 2261cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kGenerational>(params); 2271cb0ef41Sopenharmony_ci#else // !CPPGC_YOUNG_GENERATION 2281cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2291cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci params.heap = reinterpret_cast<HeapHandle*>(params.start); 2321cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci}; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_citemplate <> 2371cb0ef41Sopenharmony_cistruct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch< 2381cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kNoValuePresent> { 2391cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 2401cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void*, 2411cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2421cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 2431cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 2441cb0ef41Sopenharmony_ci HeapHandle& handle = callback(); 2451cb0ef41Sopenharmony_ci if (V8_LIKELY(!IsMarking(handle, params))) { 2461cb0ef41Sopenharmony_ci // params.start is populated by IsMarking(). 2471cb0ef41Sopenharmony_ci params.heap = &handle; 2481cb0ef41Sopenharmony_ci params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start; 2491cb0ef41Sopenharmony_ci // params.value_offset stays 0. 2501cb0ef41Sopenharmony_ci if (params.slot_offset > api_constants::kCagedHeapReservationSize) { 2511cb0ef41Sopenharmony_ci // Check if slot is on stack. 2521cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kGenerational>(params); 2551cb0ef41Sopenharmony_ci } 2561cb0ef41Sopenharmony_ci#else // !CPPGC_YOUNG_GENERATION 2571cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) { 2581cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci HeapHandle& handle = callback(); 2611cb0ef41Sopenharmony_ci if (V8_UNLIKELY(!subtle::HeapState::IsMarking(handle))) { 2621cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 2651cb0ef41Sopenharmony_ci params.heap = &handle; 2661cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci}; 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci#endif // CPPGC_CAGED_HEAP 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ciclass V8_EXPORT WriteBarrierTypeForNonCagedHeapPolicy final { 2731cb0ef41Sopenharmony_ci public: 2741cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 2751cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value, 2761cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2771cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 2781cb0ef41Sopenharmony_ci return ValueModeDispatch<value_mode>::Get(slot, value, params, callback); 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback> 2821cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void* value, 2831cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 2841cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 2851cb0ef41Sopenharmony_ci // The slot will never be used in `Get()` below. 2861cb0ef41Sopenharmony_ci return Get<WriteBarrier::ValueMode::kValuePresent>(nullptr, value, params, 2871cb0ef41Sopenharmony_ci callback); 2881cb0ef41Sopenharmony_ci } 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_ci private: 2911cb0ef41Sopenharmony_ci template <WriteBarrier::ValueMode value_mode> 2921cb0ef41Sopenharmony_ci struct ValueModeDispatch; 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci // TODO(chromium:1056170): Create fast path on API. 2951cb0ef41Sopenharmony_ci static bool IsMarking(const void*, HeapHandle**); 2961cb0ef41Sopenharmony_ci // TODO(chromium:1056170): Create fast path on API. 2971cb0ef41Sopenharmony_ci static bool IsMarking(HeapHandle&); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci WriteBarrierTypeForNonCagedHeapPolicy() = delete; 3001cb0ef41Sopenharmony_ci}; 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_citemplate <> 3031cb0ef41Sopenharmony_cistruct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< 3041cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kValuePresent> { 3051cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 3061cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void*, const void* object, 3071cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3081cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3091cb0ef41Sopenharmony_ci // The following check covers nullptr as well as sentinel pointer. 3101cb0ef41Sopenharmony_ci if (object <= static_cast<void*>(kSentinelPointer)) { 3111cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci if (V8_LIKELY(!WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) { 3141cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3151cb0ef41Sopenharmony_ci } 3161cb0ef41Sopenharmony_ci if (IsMarking(object, ¶ms.heap)) { 3171cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kNone>(params); 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci}; 3221cb0ef41Sopenharmony_ci 3231cb0ef41Sopenharmony_citemplate <> 3241cb0ef41Sopenharmony_cistruct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< 3251cb0ef41Sopenharmony_ci WriteBarrier::ValueMode::kNoValuePresent> { 3261cb0ef41Sopenharmony_ci template <typename HeapHandleCallback> 3271cb0ef41Sopenharmony_ci static V8_INLINE WriteBarrier::Type Get(const void*, const void*, 3281cb0ef41Sopenharmony_ci WriteBarrier::Params& params, 3291cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3301cb0ef41Sopenharmony_ci if (V8_UNLIKELY(WriteBarrier::IsAnyIncrementalOrConcurrentMarking())) { 3311cb0ef41Sopenharmony_ci HeapHandle& handle = callback(); 3321cb0ef41Sopenharmony_ci if (IsMarking(handle)) { 3331cb0ef41Sopenharmony_ci params.heap = &handle; 3341cb0ef41Sopenharmony_ci return SetAndReturnType<WriteBarrier::Type::kMarking>(params); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci return WriteBarrier::Type::kNone; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci}; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci// static 3421cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 3431cb0ef41Sopenharmony_ci const void* slot, const void* value, WriteBarrier::Params& params) { 3441cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(slot, value, 3451cb0ef41Sopenharmony_ci params, []() {}); 3461cb0ef41Sopenharmony_ci} 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci// static 3491cb0ef41Sopenharmony_citemplate <typename HeapHandleCallback> 3501cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 3511cb0ef41Sopenharmony_ci const void* slot, WriteBarrier::Params& params, 3521cb0ef41Sopenharmony_ci HeapHandleCallback callback) { 3531cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kNoValuePresent>( 3541cb0ef41Sopenharmony_ci slot, nullptr, params, callback); 3551cb0ef41Sopenharmony_ci} 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci// static 3581cb0ef41Sopenharmony_ciWriteBarrier::Type WriteBarrier::GetWriteBarrierType( 3591cb0ef41Sopenharmony_ci const void* value, WriteBarrier::Params& params) { 3601cb0ef41Sopenharmony_ci return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(value, params, 3611cb0ef41Sopenharmony_ci []() {}); 3621cb0ef41Sopenharmony_ci} 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci// static 3651cb0ef41Sopenharmony_civoid WriteBarrier::DijkstraMarkingBarrier(const Params& params, 3661cb0ef41Sopenharmony_ci const void* object) { 3671cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 3681cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 3691cb0ef41Sopenharmony_ci // Caged heap already filters out sentinels. 3701cb0ef41Sopenharmony_ci DijkstraMarkingBarrierSlow(object); 3711cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 3721cb0ef41Sopenharmony_ci DijkstraMarkingBarrierSlowWithSentinelCheck(object); 3731cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 3741cb0ef41Sopenharmony_ci} 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci// static 3771cb0ef41Sopenharmony_civoid WriteBarrier::DijkstraMarkingBarrierRange(const Params& params, 3781cb0ef41Sopenharmony_ci const void* first_element, 3791cb0ef41Sopenharmony_ci size_t element_size, 3801cb0ef41Sopenharmony_ci size_t number_of_elements, 3811cb0ef41Sopenharmony_ci TraceCallback trace_callback) { 3821cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 3831cb0ef41Sopenharmony_ci DijkstraMarkingBarrierRangeSlow(*params.heap, first_element, element_size, 3841cb0ef41Sopenharmony_ci number_of_elements, trace_callback); 3851cb0ef41Sopenharmony_ci} 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci// static 3881cb0ef41Sopenharmony_civoid WriteBarrier::SteeleMarkingBarrier(const Params& params, 3891cb0ef41Sopenharmony_ci const void* object) { 3901cb0ef41Sopenharmony_ci CheckParams(Type::kMarking, params); 3911cb0ef41Sopenharmony_ci#if defined(CPPGC_CAGED_HEAP) 3921cb0ef41Sopenharmony_ci // Caged heap already filters out sentinels. 3931cb0ef41Sopenharmony_ci SteeleMarkingBarrierSlow(object); 3941cb0ef41Sopenharmony_ci#else // !CPPGC_CAGED_HEAP 3951cb0ef41Sopenharmony_ci SteeleMarkingBarrierSlowWithSentinelCheck(object); 3961cb0ef41Sopenharmony_ci#endif // !CPPGC_CAGED_HEAP 3971cb0ef41Sopenharmony_ci} 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci#if defined(CPPGC_YOUNG_GENERATION) 4001cb0ef41Sopenharmony_ci// static 4011cb0ef41Sopenharmony_civoid WriteBarrier::GenerationalBarrier(const Params& params, const void* slot) { 4021cb0ef41Sopenharmony_ci CheckParams(Type::kGenerational, params); 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data = params.caged_heap(); 4051cb0ef41Sopenharmony_ci const AgeTable& age_table = local_data.age_table; 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci // Bail out if the slot is in young generation. 4081cb0ef41Sopenharmony_ci if (V8_LIKELY(age_table.GetAge(params.slot_offset) == AgeTable::Age::kYoung)) 4091cb0ef41Sopenharmony_ci return; 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci GenerationalBarrierSlow(local_data, age_table, slot, params.value_offset); 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci// static 4151cb0ef41Sopenharmony_civoid WriteBarrier::GenerationalBarrierForSourceObject( 4161cb0ef41Sopenharmony_ci const Params& params, const void* inner_pointer) { 4171cb0ef41Sopenharmony_ci CheckParams(Type::kGenerational, params); 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci const CagedHeapLocalData& local_data = params.caged_heap(); 4201cb0ef41Sopenharmony_ci const AgeTable& age_table = local_data.age_table; 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci // Assume that if the first element is in young generation, the whole range is 4231cb0ef41Sopenharmony_ci // in young generation. 4241cb0ef41Sopenharmony_ci if (V8_LIKELY(age_table.GetAge(params.slot_offset) == AgeTable::Age::kYoung)) 4251cb0ef41Sopenharmony_ci return; 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci GenerationalBarrierForSourceObjectSlow(local_data, inner_pointer); 4281cb0ef41Sopenharmony_ci} 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci#endif // !CPPGC_YOUNG_GENERATION 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci} // namespace internal 4331cb0ef41Sopenharmony_ci} // namespace cppgc 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci#endif // INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_ 436