v8  9.0.257(node16.0.0)
V8 is Google's open source JavaScript engine
write-barrier.h
Go to the documentation of this file.
1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
6 #define INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
7 
8 #include "cppgc/heap-state.h"
9 #include "cppgc/internal/api-constants.h"
10 #include "cppgc/internal/atomic-entry-flag.h"
11 #include "cppgc/sentinel-pointer.h"
12 #include "cppgc/trace-trait.h"
13 #include "v8config.h" // NOLINT(build/include_directory)
14 
15 #if defined(CPPGC_CAGED_HEAP)
16 #include "cppgc/internal/caged-heap-local-data.h"
17 #endif
18 
19 namespace cppgc {
20 
21 class HeapHandle;
22 
23 namespace internal {
24 
25 class WriteBarrierTypeForCagedHeapPolicy;
26 class WriteBarrierTypeForNonCagedHeapPolicy;
27 
28 class V8_EXPORT WriteBarrier final {
29  public:
30  enum class Type : uint8_t {
31  kNone,
32  kMarking,
34  };
35 
36  struct Params {
37  HeapHandle* heap = nullptr;
38 #if V8_ENABLE_CHECKS
39  Type type = Type::kNone;
40 #endif // !V8_ENABLE_CHECKS
41 #if defined(CPPGC_CAGED_HEAP)
42  uintptr_t start = 0;
44  return *reinterpret_cast<CagedHeapLocalData*>(start);
45  }
48 #endif // CPPGC_CAGED_HEAP
49  };
50 
51  enum class ValueMode {
54  };
55 
56  // Returns the required write barrier for a given `slot` and `value`.
57  static V8_INLINE Type GetWriteBarrierType(const void* slot, const void* value,
58  Params& params);
59  // Returns the required write barrier for a given `slot`.
60  template <typename HeapHandleCallback>
61  static V8_INLINE Type GetWriteBarrierType(const void* slot, Params& params,
62  HeapHandleCallback callback);
63 
64  template <typename HeapHandleCallback>
66  const void* value, Params& params, HeapHandleCallback callback);
67 
68  static V8_INLINE void DijkstraMarkingBarrier(const Params& params,
69  const void* object);
71  const Params& params, const void* first_element, size_t element_size,
72  size_t number_of_elements, TraceCallback trace_callback);
73  static V8_INLINE void SteeleMarkingBarrier(const Params& params,
74  const void* object);
75 #if defined(CPPGC_YOUNG_GENERATION)
76  static V8_INLINE void GenerationalBarrier(const Params& params,
77  const void* slot);
78 #else // !CPPGC_YOUNG_GENERATION
79  static V8_INLINE void GenerationalBarrier(const Params& params,
80  const void* slot) {}
81 #endif // CPPGC_YOUNG_GENERATION
82 
83 #if V8_ENABLE_CHECKS
84  static void CheckParams(Type expected_type, const Params& params);
85 #else // !V8_ENABLE_CHECKS
86  static void CheckParams(Type expected_type, const Params& params) {}
87 #endif // !V8_ENABLE_CHECKS
88 
89  // The IncrementalOrConcurrentUpdater class allows cppgc internal to update
90  // |incremental_or_concurrent_marking_flag_|.
91  class IncrementalOrConcurrentMarkingFlagUpdater;
93  return incremental_or_concurrent_marking_flag_.MightBeEntered();
94  }
95 
96  private:
97  WriteBarrier() = delete;
98 
99 #if defined(CPPGC_CAGED_HEAP)
100  using WriteBarrierTypePolicy = WriteBarrierTypeForCagedHeapPolicy;
101 #else // !CPPGC_CAGED_HEAP
102  using WriteBarrierTypePolicy = WriteBarrierTypeForNonCagedHeapPolicy;
103 #endif // !CPPGC_CAGED_HEAP
104 
105  static void DijkstraMarkingBarrierSlow(const void* value);
106  static void DijkstraMarkingBarrierSlowWithSentinelCheck(const void* value);
107  static void DijkstraMarkingBarrierRangeSlow(HeapHandle& heap_handle,
108  const void* first_element,
109  size_t element_size,
110  size_t number_of_elements,
111  TraceCallback trace_callback);
112  static void SteeleMarkingBarrierSlow(const void* value);
113  static void SteeleMarkingBarrierSlowWithSentinelCheck(const void* value);
114 
115 #if defined(CPPGC_YOUNG_GENERATION)
116  static CagedHeapLocalData& GetLocalData(HeapHandle&);
117  static void GenerationalBarrierSlow(const CagedHeapLocalData& local_data,
118  const AgeTable& ageTable,
119  const void* slot, uintptr_t value_offset);
120 #endif // CPPGC_YOUNG_GENERATION
121 
122  static AtomicEntryFlag incremental_or_concurrent_marking_flag_;
123 };
124 
125 template <WriteBarrier::Type type>
126 V8_INLINE WriteBarrier::Type SetAndReturnType(WriteBarrier::Params& params) {
127  if (type == WriteBarrier::Type::kNone) return WriteBarrier::Type::kNone;
128 #if V8_ENABLE_CHECKS
129  params.type = type;
130 #endif // !V8_ENABLE_CHECKS
131  return type;
132 }
133 
134 #if defined(CPPGC_CAGED_HEAP)
136  public:
138  static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
142  }
143 
144  template <typename HeapHandleCallback>
147  if (!TryGetCagedHeap(value, value, params)) {
148  return WriteBarrier::Type::kNone;
149  }
152  }
154  }
155 
156  private:
158 
159  template <WriteBarrier::ValueMode value_mode>
160  struct ValueModeDispatch;
161 
162  static V8_INLINE bool TryGetCagedHeap(const void* slot, const void* value,
164  params.start = reinterpret_cast<uintptr_t>(value) &
166  const uintptr_t slot_offset =
167  reinterpret_cast<uintptr_t>(slot) - params.start;
169  // Check if slot is on stack or value is sentinel or nullptr. This relies
170  // on the fact that kSentinelPointer is encoded as 0x1.
171  return false;
172  }
173  return true;
174  }
175 
176  // Returns whether marking is in progress. If marking is not in progress
177  // sets the start of the cage accordingly.
178  //
179  // TODO(chromium:1056170): Create fast path on API.
180  static bool IsMarking(const HeapHandle&, WriteBarrier::Params&);
181 };
182 
183 template <>
186  template <typename HeapHandleCallback>
187  static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
191  if (!within_cage) {
192  return WriteBarrier::Type::kNone;
193  }
195 #if defined(CPPGC_YOUNG_GENERATION)
196  params.heap = reinterpret_cast<HeapHandle*>(params.start);
197  params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start;
198  params.value_offset = reinterpret_cast<uintptr_t>(value) - params.start;
200 #else // !CPPGC_YOUNG_GENERATION
202 #endif // !CPPGC_YOUNG_GENERATION
203  }
204  params.heap = reinterpret_cast<HeapHandle*>(params.start);
206  }
207 };
208 
209 template <>
212  template <typename HeapHandleCallback>
213  static V8_INLINE WriteBarrier::Type Get(const void* slot, const void*,
216 #if defined(CPPGC_YOUNG_GENERATION)
218  if (V8_LIKELY(!IsMarking(handle, params))) {
219  // params.start is populated by IsMarking().
220  params.heap = &handle;
221  params.slot_offset = reinterpret_cast<uintptr_t>(slot) - params.start;
222  // params.value_offset stays 0.
224  // Check if slot is on stack.
226  }
228  }
229 #else // !CPPGC_YOUNG_GENERATION
232  }
236  }
237 #endif // !CPPGC_YOUNG_GENERATION
238  params.heap = &handle;
240  }
241 };
242 
243 #endif // CPPGC_CAGED_HEAP
244 
245 class V8_EXPORT WriteBarrierTypeForNonCagedHeapPolicy final {
246  public:
247  template <WriteBarrier::ValueMode value_mode, typename HeapHandleCallback>
248  static V8_INLINE WriteBarrier::Type Get(const void* slot, const void* value,
249  WriteBarrier::Params& params,
250  HeapHandleCallback callback) {
251  return ValueModeDispatch<value_mode>::Get(slot, value, params, callback);
252  }
253 
254  template <typename HeapHandleCallback>
256  const void* value, WriteBarrier::Params& params,
257  HeapHandleCallback callback) {
258  // The slot will never be used in `Get()` below.
259  return Get<WriteBarrier::ValueMode::kValuePresent>(nullptr, value, params,
260  callback);
261  }
262 
263  private:
264  template <WriteBarrier::ValueMode value_mode>
265  struct ValueModeDispatch;
266 
267  // TODO(chromium:1056170): Create fast path on API.
268  static bool IsMarking(const void*, HeapHandle**);
269  // TODO(chromium:1056170): Create fast path on API.
270  static bool IsMarking(HeapHandle&);
271 
272  WriteBarrierTypeForNonCagedHeapPolicy() = delete;
273 };
274 
275 template <>
276 struct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch<
277  WriteBarrier::ValueMode::kValuePresent> {
278  template <typename HeapHandleCallback>
279  static V8_INLINE WriteBarrier::Type Get(const void*, const void* object,
280  WriteBarrier::Params& params,
281  HeapHandleCallback callback) {
282  // The following check covers nullptr as well as sentinel pointer.
283  if (object <= static_cast<void*>(kSentinelPointer)) {
284  return WriteBarrier::Type::kNone;
285  }
286  if (IsMarking(object, &params.heap)) {
287  return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
288  }
289  return SetAndReturnType<WriteBarrier::Type::kNone>(params);
290  }
291 };
292 
293 template <>
294 struct WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch<
295  WriteBarrier::ValueMode::kNoValuePresent> {
296  template <typename HeapHandleCallback>
297  static V8_INLINE WriteBarrier::Type Get(const void*, const void*,
298  WriteBarrier::Params& params,
299  HeapHandleCallback callback) {
301  HeapHandle& handle = callback();
302  if (IsMarking(handle)) {
303  params.heap = &handle;
304  return SetAndReturnType<WriteBarrier::Type::kMarking>(params);
305  }
306  }
307  return WriteBarrier::Type::kNone;
308  }
309 };
310 
311 // static
312 WriteBarrier::Type WriteBarrier::GetWriteBarrierType(
313  const void* slot, const void* value, WriteBarrier::Params& params) {
314  return WriteBarrierTypePolicy::Get<ValueMode::kValuePresent>(slot, value,
315  params, []() {});
316 }
317 
318 // static
319 template <typename HeapHandleCallback>
320 WriteBarrier::Type WriteBarrier::GetWriteBarrierType(
321  const void* slot, WriteBarrier::Params& params,
322  HeapHandleCallback callback) {
323  return WriteBarrierTypePolicy::Get<ValueMode::kNoValuePresent>(
324  slot, nullptr, params, callback);
325 }
326 
327 // static
328 template <typename HeapHandleCallback>
329 WriteBarrier::Type
331  const void* value, Params& params, HeapHandleCallback callback) {
332  return WriteBarrierTypePolicy::GetForExternallyReferenced(value, params,
333  callback);
334 }
335 
336 // static
337 void WriteBarrier::DijkstraMarkingBarrier(const Params& params,
338  const void* object) {
340 #if defined(CPPGC_CAGED_HEAP)
341  // Caged heap already filters out sentinels.
342  DijkstraMarkingBarrierSlow(object);
343 #else // !CPPGC_CAGED_HEAP
344  DijkstraMarkingBarrierSlowWithSentinelCheck(object);
345 #endif // !CPPGC_CAGED_HEAP
346 }
347 
348 // static
349 void WriteBarrier::DijkstraMarkingBarrierRange(const Params& params,
350  const void* first_element,
351  size_t element_size,
352  size_t number_of_elements,
353  TraceCallback trace_callback) {
355  DijkstraMarkingBarrierRangeSlow(*params.heap, first_element, element_size,
356  number_of_elements, trace_callback);
357 }
358 
359 // static
360 void WriteBarrier::SteeleMarkingBarrier(const Params& params,
361  const void* object) {
363 #if defined(CPPGC_CAGED_HEAP)
364  // Caged heap already filters out sentinels.
365  SteeleMarkingBarrierSlow(object);
366 #else // !CPPGC_CAGED_HEAP
367  SteeleMarkingBarrierSlowWithSentinelCheck(object);
368 #endif // !CPPGC_CAGED_HEAP
369 }
370 
371 #if defined(CPPGC_YOUNG_GENERATION)
372 // static
373 void WriteBarrier::GenerationalBarrier(const Params& params, const void* slot) {
375 
378 
379  // Bail out if the slot is in young generation.
381 
383 }
384 
385 #endif // !CPPGC_YOUNG_GENERATION
386 
387 } // namespace internal
388 } // namespace cppgc
389 
390 #endif // INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
cppgc::internal::SetAndReturnType
V8_INLINE WriteBarrier::Type SetAndReturnType(WriteBarrier::Params &params)
Definition: write-barrier.h:126
V8_UNLIKELY
#define V8_UNLIKELY(condition)
Definition: v8config.h:443
cppgc::internal::WriteBarrier::DijkstraMarkingBarrierRange
static V8_INLINE void DijkstraMarkingBarrierRange(const Params &params, const void *first_element, size_t element_size, size_t number_of_elements, TraceCallback trace_callback)
Definition: write-barrier.h:349
cppgc::internal::WriteBarrier::GenerationalBarrier
static V8_INLINE void GenerationalBarrier(const Params &params, const void *slot)
Definition: write-barrier.h:79
cppgc::internal::WriteBarrier::Type::kGenerational
@ kGenerational
cppgc::internal::WriteBarrierTypeForNonCagedHeapPolicy::Get
static V8_INLINE WriteBarrier::Type Get(const void *slot, const void *value, WriteBarrier::Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:248
cppgc::internal::WriteBarrier::ValueMode::kNoValuePresent
@ kNoValuePresent
V8_INLINE
#define V8_INLINE
Definition: v8config.h:380
cppgc::internal::WriteBarrier::Type::kMarking
@ kMarking
cppgc::internal::WriteBarrier::IsAnyIncrementalOrConcurrentMarking
static bool IsAnyIncrementalOrConcurrentMarking()
Definition: write-barrier.h:92
cppgc::internal::WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< WriteBarrier::ValueMode::kNoValuePresent >::Get
static V8_INLINE WriteBarrier::Type Get(const void *, const void *, WriteBarrier::Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:297
cppgc::internal::WriteBarrier::GetWriteBarrierType
WriteBarrier::Type GetWriteBarrierType(const void *slot, WriteBarrier::Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:320
cppgc::internal::WriteBarrier::Type::kNone
@ kNone
cppgc::internal::AtomicEntryFlag::MightBeEntered
bool MightBeEntered() const
Definition: atomic-entry-flag.h:37
cppgc
Definition: allocation.h:17
V8_EXPORT
#define V8_EXPORT
Definition: v8config.h:512
cppgc::internal::WriteBarrierTypeForNonCagedHeapPolicy::ValueModeDispatch< WriteBarrier::ValueMode::kValuePresent >::Get
static V8_INLINE WriteBarrier::Type Get(const void *, const void *object, WriteBarrier::Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:279
cppgc::internal::WriteBarrier::ValueMode
ValueMode
Definition: write-barrier.h:51
cppgc::internal::WriteBarrier::ValueMode::kValuePresent
@ kValuePresent
cppgc::internal::WriteBarrier::Params
Definition: write-barrier.h:36
cppgc::internal::WriteBarrier::Type
Type
Definition: write-barrier.h:30
cppgc::kSentinelPointer
constexpr internal::SentinelPointer kSentinelPointer
Definition: sentinel-pointer.h:28
cppgc::internal::WriteBarrier::DijkstraMarkingBarrier
static V8_INLINE void DijkstraMarkingBarrier(const Params &params, const void *object)
Definition: write-barrier.h:337
cppgc::internal::WriteBarrierTypeForNonCagedHeapPolicy::GetForExternallyReferenced
static V8_INLINE WriteBarrier::Type GetForExternallyReferenced(const void *value, WriteBarrier::Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:255
cppgc::internal::WriteBarrier::GetWriteBarrierType
static V8_INLINE Type GetWriteBarrierType(const void *slot, const void *value, Params &params)
Definition: write-barrier.h:312
cppgc::internal::WriteBarrier::SteeleMarkingBarrier
static V8_INLINE void SteeleMarkingBarrier(const Params &params, const void *object)
Definition: write-barrier.h:360
cppgc::internal::WriteBarrier::GetWriteBarrierTypeForExternallyReferencedObject
WriteBarrier::Type GetWriteBarrierTypeForExternallyReferencedObject(const void *value, Params &params, HeapHandleCallback callback)
Definition: write-barrier.h:330
cppgc::internal
Definition: allocation.h:22
cppgc::internal::WriteBarrier::Params::heap
HeapHandle * heap
Definition: write-barrier.h:37
cppgc::internal::WriteBarrier::CheckParams
static void CheckParams(Type expected_type, const Params &params)
Definition: write-barrier.h:86