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, &params.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