v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
heap-write-barrier-inl.h
Go to the documentation of this file.
1// Copyright 2018 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 V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
6#define V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11// Clients of this interface shouldn't depend on lots of heap internals.
12// Do not include anything from src/heap here!
13
20
21namespace v8::internal {
22
23// static
25 HeapObjectSlot slot,
27 WriteBarrierMode mode) {
29
30 MemoryChunk* host_chunk = MemoryChunk::FromHeapObject(host);
31 MemoryChunk* value_chunk = MemoryChunk::FromHeapObject(value);
32
33 const bool is_marking = host_chunk->IsMarking();
34
35 if (v8_flags.sticky_mark_bits) {
36 // TODO(333906585): Support shared barrier.
37 if (!HeapLayout::InYoungGeneration(host_chunk, host) &&
38 HeapLayout::InYoungGeneration(value_chunk, value)) {
39 // Generational or shared heap write barrier (old-to-new or
40 // old-to-shared).
42 }
43 } else {
44 const bool pointers_from_here_are_interesting =
45 !host_chunk->IsYoungOrSharedChunk();
46 if (pointers_from_here_are_interesting &&
47 value_chunk->IsYoungOrSharedChunk()) {
48 // Generational or shared heap write barrier (old-to-new or
49 // old-to-shared).
51 }
52 }
53
54 // Marking barrier: mark value & record slots when marking is on.
55 if (V8_UNLIKELY(is_marking)) {
56 MarkingSlow(host, HeapObjectSlot(slot), value);
57 }
58}
59
60// static
62 Tagged<HeapObject> object, const DisallowGarbageCollection& promise) {
63 if (v8_flags.disable_write_barriers) {
64 return SKIP_WRITE_BARRIER;
65 }
68 if (chunk->IsMarking()) {
70 }
71 if (HeapLayout::InYoungGeneration(chunk, object)) {
72 return SKIP_WRITE_BARRIER;
73 }
75}
76
77// static
79 // All objects in readonly space are immortal and immovable.
80 return HeapLayout::InReadOnlySpace(object);
81}
82
83// static
85 RelocInfo* rinfo, Tagged<HeapObject> value,
86 WriteBarrierMode mode) {
87 if (mode == SKIP_WRITE_BARRIER) {
88 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
89 return;
90 }
91
92 // Used during InstructionStream initialization where we update the write
93 // barriers together separate from the field writes.
94 if (mode == UNSAFE_SKIP_WRITE_BARRIER) {
95 DCHECK(!DisallowGarbageCollection::IsAllowed());
96 return;
97 }
98
100 GenerationalForRelocInfo(host, rinfo, value);
101 SharedForRelocInfo(host, rinfo, value);
102 MarkingForRelocInfo(host, rinfo, value);
103}
104
105// static
106template <typename T>
108 Tagged<T> value, WriteBarrierMode mode) {
109 if (mode == SKIP_WRITE_BARRIER) {
110 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
111 return;
112 }
113 Tagged<HeapObject> value_object;
114 if (!value.GetHeapObject(&value_object)) {
115 return;
116 }
117 CombinedWriteBarrierInternal(host, HeapObjectSlot(slot), value_object, mode);
118}
119
120// static
121template <typename T>
123 Tagged<T> value, WriteBarrierMode mode) {
124 if (mode == SKIP_WRITE_BARRIER) {
125 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
126 return;
127 }
128 Tagged<HeapObject> value_object;
129 if (!value.GetHeapObject(&value_object)) {
130 return;
131 }
133 value_object, mode);
134}
135
136// static
138 ObjectSlot slot, Tagged<Object> value,
139 WriteBarrierMode mode) {
140 if (mode == SKIP_WRITE_BARRIER) {
141 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
142 return;
143 }
144
146 if (!value.IsHeapObject()) return;
147
148 MemoryChunk* host_chunk = MemoryChunk::FromHeapObject(host);
149
150 Tagged<HeapObject> heap_object_value = Cast<HeapObject>(value);
151 MemoryChunk* value_chunk = MemoryChunk::FromHeapObject(heap_object_value);
152
153 const bool pointers_from_here_are_interesting =
154 !host_chunk->IsYoungOrSharedChunk();
155 const bool is_marking = host_chunk->IsMarking();
156
157 if (pointers_from_here_are_interesting &&
158 value_chunk->IsYoungOrSharedChunk()) {
160 heap_object_value);
161 }
162
163 // Marking barrier: mark value & record slots when marking is on.
164 if (is_marking) {
165 MarkingSlow(host, HeapObjectSlot(slot), heap_object_value);
166 }
167}
168
169// static
172 WriteBarrierMode mode) {
173 if (mode == SKIP_WRITE_BARRIER) {
175 return;
176 }
177 Marking(host, slot);
178}
179
180// static
183 Tagged<HeapObject> value,
184 WriteBarrierMode mode) {
185 // Indirect pointers are only used when the sandbox is enabled.
187 if (mode == SKIP_WRITE_BARRIER) {
188 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
189 return;
190 }
191 // Objects referenced via indirect pointers are currently never allocated in
192 // the young generation.
193 if (!v8_flags.sticky_mark_bits) {
194 DCHECK(!MemoryChunk::FromHeapObject(value)->InYoungGeneration());
195 }
196 Marking(host, slot);
197}
198
199// static
202 WriteBarrierMode mode) {
205 WriteBarrier::VerifyDispatchHandleMarkingState(host, handle, mode));
206 if (mode == SKIP_WRITE_BARRIER) {
207 return;
208 }
209 Marking(host, handle);
210}
211
212// static
216 WriteBarrierMode mode) {
217 if (mode == SKIP_WRITE_BARRIER) {
218 SLOW_DCHECK(!WriteBarrier::IsRequired(host, value));
219 return;
220 }
221 // Protected pointers are only used within trusted and shared trusted space.
222 DCHECK_IMPLIES(!v8_flags.sticky_mark_bits,
224 if (MemoryChunk::FromHeapObject(value)->InWritableSharedSpace()) {
225 SharedSlow(host, slot, value);
226 }
227 Marking(host, slot, value);
228}
229
230// static
232 RelocInfo* rinfo,
233 Tagged<HeapObject> object) {
234 if (!HeapLayout::InYoungGeneration(object)) {
235 return;
236 }
237 GenerationalBarrierForCodeSlow(host, rinfo, object);
238}
239
240// static
244
246 Tagged<Object> value) {
248 if (!value.IsHeapObject()) {
249 return;
250 }
251 Tagged<HeapObject> value_heap_object = Cast<HeapObject>(value);
252 Marking(host, HeapObjectSlot(slot), value_heap_object);
253}
254
256 Tagged<MaybeObject> value) {
257 Tagged<HeapObject> value_heap_object;
258 if (!value.GetHeapObject(&value_heap_object)) {
259 return;
260 }
261 // This barrier is called from generated code and from C++ code.
262 // There must be no stores of InstructionStream values from generated code and
263 // all stores of InstructionStream values in C++ must be handled by
264 // CombinedWriteBarrierInternal().
265 DCHECK(!HeapLayout::InCodeSpace(value_heap_object));
266 Marking(host, HeapObjectSlot(slot), value_heap_object);
267}
268
270 Tagged<HeapObject> value) {
271 if (V8_LIKELY(!IsMarking(host))) {
272 return;
273 }
274 MarkingSlow(host, slot, value);
275}
276
278 RelocInfo* reloc_info,
279 Tagged<HeapObject> value) {
280 if (V8_LIKELY(!IsMarking(host))) {
281 return;
282 }
283 MarkingSlow(host, reloc_info, value);
284}
285
287 RelocInfo* reloc_info,
288 Tagged<HeapObject> value) {
289 MemoryChunk* value_chunk = MemoryChunk::FromHeapObject(value);
290 if (!value_chunk->InWritableSharedSpace()) {
291 return;
292 }
293 SharedSlow(host, reloc_info, value);
294}
295
303
305 int number_of_own_descriptors) {
306 if (V8_LIKELY(!IsMarking(descriptor_array))) {
307 return;
308 }
309 MarkingSlow(descriptor_array, number_of_own_descriptors);
310}
311
313 if (V8_LIKELY(!IsMarking(host))) {
314 return;
315 }
316 MarkingSlow(host, slot);
317}
318
320 if (V8_LIKELY(!IsMarking(host))) {
321 return;
322 }
323 MarkingSlow(host, slot);
324}
325
328 Tagged<TrustedObject> value) {
329 if (V8_LIKELY(!IsMarking(host))) {
330 return;
331 }
332 MarkingSlow(host, slot, value);
333}
334
336 if (V8_LIKELY(!IsMarking(host))) {
337 return;
338 }
339 MarkingSlow(host, handle);
340}
341
342// static
344 if (!value.IsHeapObject()) {
345 return;
346 }
348}
349
350// static
352 CppHeapPointerSlot slot, void* value) {
353 // Note: this is currently a combined barrier for marking both the
354 // CppHeapPointerTable entry and the referenced object.
355
356 if (V8_LIKELY(!IsMarking(host))) {
357#if defined(CPPGC_YOUNG_GENERATION)
358 // There is no young-gen CppHeapPointerTable space so we should not mark
359 // the table entry in this case.
360 if (value) {
362 }
363#endif
364 return;
365 }
366 MarkingBarrier* marking_barrier = CurrentMarkingBarrier(host);
367 if (marking_barrier->is_minor()) {
368 // TODO(v8:13012): We do not currently mark Oilpan objects while MinorMS is
369 // active. Once Oilpan uses a generational GC with incremental marking and
370 // unified heap, this barrier will be needed again.
371 return;
372 }
373
374 MarkingSlowFromCppHeapWrappable(marking_barrier->heap(), host, slot, value);
375}
376
377// static
379 void* value) {
380 if (!value) {
381 return;
382 }
383 auto* memory_chunk = MemoryChunk::FromHeapObject(host);
384 if (V8_LIKELY(HeapLayout::InYoungGeneration(memory_chunk, host))) {
385 return;
386 }
387 auto* cpp_heap = memory_chunk->GetHeap()->cpp_heap();
389 host, value);
390}
391
392#if defined(ENABLE_SLOW_DCHECKS) || defined(V8_ENABLE_DEBUG_CODE)
393// static
394template <typename T>
395bool WriteBarrier::IsRequired(Tagged<HeapObject> host, T value) {
397 return false;
398 }
399 if (IsSmi(value)) {
400 return false;
401 }
402 if (value.IsCleared()) {
403 return false;
404 }
405 Tagged<HeapObject> target = value.GetHeapObject();
406 if (ReadOnlyHeap::Contains(target)) {
407 return false;
408 }
409 return !IsImmortalImmovableHeapObject(target);
410}
411#endif
412
413#ifdef ENABLE_SLOW_DCHECKS
414// static
415template <typename T>
416bool WriteBarrier::IsRequired(const HeapObjectLayout* host, T value) {
418 return false;
419 }
420 if (IsSmi(value)) {
421 return false;
422 }
423 if (value.IsCleared()) {
424 return false;
425 }
426 Tagged<HeapObject> target = value.GetHeapObject();
427 if (ReadOnlyHeap::Contains(target)) {
428 return false;
429 }
430 return !IsImmortalImmovableHeapObject(target);
431}
432#endif
433
434} // namespace v8::internal
435
436#endif // V8_HEAP_HEAP_WRITE_BARRIER_INL_H_
#define SLOW_DCHECK(condition)
Definition checks.h:21
V8_INLINE void RememberCrossHeapReferenceIfNeeded(v8::internal::Tagged< v8::internal::JSObject > host_obj, void *value)
Definition cpp-heap.h:279
static CppHeap * From(v8::CppHeap *heap)
Definition cpp-heap.h:102
static V8_INLINE bool InYoungGeneration(Tagged< Object > object)
static V8_INLINE bool InReadOnlySpace(Tagged< HeapObject > object)
static V8_INLINE bool InCodeSpace(Tagged< HeapObject > object)
V8_INLINE bool InWritableSharedSpace() const
V8_INLINE bool IsYoungOrSharedChunk() const
V8_INLINE bool InYoungGeneration() const
static V8_INLINE MemoryChunk * FromHeapObject(Tagged< HeapObject > object)
V8_INLINE bool IsMarking() const
static V8_EXPORT_PRIVATE bool Contains(Address address)
Address address() const
Definition slots.h:78
static void MarkingFromTracedHandle(Tagged< Object > value)
static void CombinedGenerationalAndSharedEphemeronBarrierSlow(Tagged< EphemeronHashTable > table, Address slot, Tagged< HeapObject > value)
static void Marking(Tagged< HeapObject > host, HeapObjectSlot, Tagged< HeapObject > value)
static void MarkingSlowFromCppHeapWrappable(Heap *heap, Tagged< JSObject > host, CppHeapPointerSlot slot, void *object)
static void ForDescriptorArray(Tagged< DescriptorArray >, int number_of_own_descriptors)
static void CombinedWriteBarrierInternal(Tagged< HeapObject > host, HeapObjectSlot slot, Tagged< HeapObject > value, WriteBarrierMode mode)
static void ForEphemeronHashTable(Tagged< EphemeronHashTable > host, ObjectSlot slot, Tagged< Object > value, WriteBarrierMode mode)
static bool PageFlagsAreConsistent(Tagged< HeapObject > object)
static WriteBarrierMode GetWriteBarrierModeForObject(Tagged< HeapObject > object, const DisallowGarbageCollection &promise)
static bool IsMarking(Tagged< HeapObject > object)
static void ForJSDispatchHandle(Tagged< HeapObject > host, JSDispatchHandle handle, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static MarkingBarrier * CurrentMarkingBarrier(Tagged< HeapObject > verification_candidate)
static void GenerationalForRelocInfo(Tagged< InstructionStream > host, RelocInfo *rinfo, Tagged< HeapObject > object)
static void ForCppHeapPointer(Tagged< JSObject > host, CppHeapPointerSlot slot, void *value)
static void ForRelocInfo(Tagged< InstructionStream > host, RelocInfo *rinfo, Tagged< HeapObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static void SharedSlow(Tagged< TrustedObject > host, ProtectedPointerSlot slot, Tagged< TrustedObject > value)
static bool IsImmortalImmovableHeapObject(Tagged< HeapObject > object)
static void MarkingSlow(Tagged< HeapObject > host, HeapObjectSlot, Tagged< HeapObject > value)
static void MarkingForRelocInfo(Tagged< InstructionStream > host, RelocInfo *, Tagged< HeapObject > value)
static void SharedForRelocInfo(Tagged< InstructionStream > host, RelocInfo *, Tagged< HeapObject > value)
static void MarkingSlowFromTracedHandle(Tagged< HeapObject > value)
static void MarkingForTesting(Tagged< HeapObject > host, ObjectSlot, Tagged< Object > value)
static void ForProtectedPointer(Tagged< TrustedObject > host, ProtectedPointerSlot slot, Tagged< TrustedObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static void ForArrayBufferExtension(Tagged< JSArrayBuffer > host, ArrayBufferExtension *extension)
static void GenerationalBarrierForCodeSlow(Tagged< InstructionStream > host, RelocInfo *rinfo, Tagged< HeapObject > value)
static void ForExternalPointer(Tagged< HeapObject > host, ExternalPointerSlot slot, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static void CombinedGenerationalAndSharedBarrierSlow(Tagged< HeapObject > object, Address slot, Tagged< HeapObject > value)
static void ForIndirectPointer(Tagged< HeapObject > host, IndirectPointerSlot slot, Tagged< HeapObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static void GenerationalBarrierForCppHeapPointer(Tagged< JSObject > host, void *value)
static void ForValue(Tagged< HeapObject > host, MaybeObjectSlot slot, Tagged< T > value, WriteBarrierMode mode)
#define V8_ENABLE_LEAPTIERING_BOOL
Definition globals.h:151
#define V8_ENABLE_SANDBOX_BOOL
Definition globals.h:160
std::string extension
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
static V8_INLINE bool HasWeakHeapObjectTag(const Tagged< Object > value)
Definition objects.h:653
@ SKIP_WRITE_BARRIER
Definition objects.h:52
@ UPDATE_WRITE_BARRIER
Definition objects.h:55
@ UNSAFE_SKIP_WRITE_BARRIER
Definition objects.h:53
SlotTraits::TObjectSlot ObjectSlot
Definition globals.h:1243
Tagged(T object) -> Tagged< T >
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
kInterpreterTrampolineOffset Tagged< HeapObject >
V8_EXPORT_PRIVATE FlagValues v8_flags
SlotTraits::THeapObjectSlot HeapObjectSlot
Definition globals.h:1253
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660