v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
young-generation-marking-visitor-inl.h
Go to the documentation of this file.
1// Copyright 2023 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_YOUNG_GENERATION_MARKING_VISITOR_INL_H_
6#define V8_HEAP_YOUNG_GENERATION_MARKING_VISITOR_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11#include "src/common/globals.h"
20
21namespace v8 {
22namespace internal {
23
24template <YoungGenerationMarkingVisitationMode marking_mode>
26 Heap* heap,
27 PretenuringHandler::PretenuringFeedbackMap* local_pretenuring_feedback)
28 : Base(heap->isolate()),
29 isolate_(heap->isolate()),
30 marking_worklists_local_(
31 heap->minor_mark_sweep_collector()->marking_worklists(),
32 heap->cpp_heap()
33 ? CppHeap::From(heap->cpp_heap())->CreateCppMarkingState()
34 : MarkingWorklists::Local::kNoCppMarkingState),
35 ephemeron_table_list_local_(
36 *heap->minor_mark_sweep_collector()->ephemeron_table_list()),
37 pretenuring_handler_(heap->pretenuring_handler()),
38 local_pretenuring_feedback_(local_pretenuring_feedback),
39 shortcut_strings_(heap->CanShortcutStringsDuringGC(
41
42template <YoungGenerationMarkingVisitationMode marking_mode>
44 PublishWorklists();
45
46 // Flush memory chunk live bytes. Atomics are used for incrementing the live
47 // bytes counter of the page, so there is no need to defer flushing to the
48 // main thread.
49 for (auto& pair : live_bytes_data_) {
50 if (pair.first) {
51 pair.first->IncrementLiveBytesAtomically(pair.second);
52 }
53 }
54}
55
56template <YoungGenerationMarkingVisitationMode marking_mode>
59 if (!marking_worklists_local_.cpp_marking_state()) return;
60
61 // The table is not reclaimed in the young generation, so we only need to mark
62 // through to the C++ pointer.
63
64 if (auto cpp_heap_pointer = slot.try_load(isolate_, kAnyCppHeapPointer)) {
65 marking_worklists_local_.cpp_marking_state()->MarkAndPush(
66 reinterpret_cast<void*>(cpp_heap_pointer));
67 }
68}
69
70template <YoungGenerationMarkingVisitationMode marking_mode>
73 MaybeObjectSize maybe_object_size) {
74 object->YoungMarkExtension();
75 return Base::VisitJSArrayBuffer(map, object, maybe_object_size);
76}
77
78template <YoungGenerationMarkingVisitationMode marking_mode>
79template <typename T, typename TBodyDescriptor>
81 Tagged<Map> map, Tagged<T> object, MaybeObjectSize maybe_object_size) {
82 const int object_size =
83 static_cast<int>(Base::template VisitJSObjectSubclass<T, TBodyDescriptor>(
84 map, object, maybe_object_size));
86 isolate_->heap(), map, object, object_size, local_pretenuring_feedback_);
87 return object_size;
88}
89
90template <YoungGenerationMarkingVisitationMode marking_mode>
93 // Register table with Minor MC, so it can take care of the weak keys later.
94 // This allows to only iterate the tables' values, which are treated as strong
95 // independently of whether the key is live.
96 ephemeron_table_list_local_.Push(table);
97 for (InternalIndex i : table->IterateEntries()) {
98 ObjectSlot value_slot =
99 table->RawFieldOfElementAt(EphemeronHashTable::EntryToValueIndex(i));
100 VisitPointer(table, value_slot);
101 }
103}
104
105#ifdef V8_COMPRESS_POINTERS
106template <YoungGenerationMarkingVisitationMode marking_mode>
109 // With sticky mark-bits the host object was already marked (old).
110 DCHECK_IMPLIES(!v8_flags.sticky_mark_bits,
112 DCHECK(!slot.tag_range().IsEmpty());
114
115 // TODO(chromium:337580006): Remove when pointer compression always uses
116 // EPT.
117 if (!slot.HasExternalPointerHandle()) return;
118
119 ExternalPointerHandle handle = slot.Relaxed_LoadHandle();
121 ExternalPointerTable& table = isolate_->external_pointer_table();
122 auto* space = isolate_->heap()->young_external_pointer_space();
123 table.Mark(space, handle, slot.address());
124 }
125
126 // Add to the remset whether the handle is null or not, as the slot could be
127 // set to a non-null value before the marking pause.
128 // TODO(342905179): Avoid adding null handle locations to the remset, and
129 // instead make external pointer writes invoke a marking barrier.
130 auto slot_chunk = MutablePageMetadata::FromHeapObject(host);
131 RememberedSet<SURVIVOR_TO_EXTERNAL_POINTER>::template Insert<
132 AccessMode::ATOMIC>(slot_chunk, slot_chunk->Offset(slot.address()));
133}
134#endif // V8_COMPRESS_POINTERS
135
136template <YoungGenerationMarkingVisitationMode marking_mode>
137template <typename TSlot>
139 Tagged<HeapObject> host, TSlot start, TSlot end) {
140 for (TSlot slot = start; slot < end; ++slot) {
141 if constexpr (marking_mode ==
143 VisitObjectViaSlot<ObjectVisitationMode::kPushToWorklist,
144 SlotTreatmentMode::kReadOnly>(slot);
145 } else {
146 VisitObjectViaSlot<ObjectVisitationMode::kPushToWorklist,
147 SlotTreatmentMode::kReadWrite>(slot);
148 }
149 }
150}
151
152template <YoungGenerationMarkingVisitationMode marking_mode>
153template <typename TSlot>
154V8_INLINE bool
156 TSlot slot) {
157 if constexpr (marking_mode ==
159 return VisitObjectViaSlot<ObjectVisitationMode::kPushToWorklist,
160 SlotTreatmentMode::kReadOnly>(slot);
161 } else {
162 return VisitObjectViaSlot<ObjectVisitationMode::kVisitDirectly,
163 SlotTreatmentMode::kReadWrite>(slot);
164 }
165}
166
167template <YoungGenerationMarkingVisitationMode marking_mode>
168template <typename YoungGenerationMarkingVisitor<
169 marking_mode>::ObjectVisitationMode visitation_mode,
171 marking_mode>::SlotTreatmentMode slot_treatment_mode,
172 typename TSlot>
174 TSlot slot) {
175 const std::optional<Tagged<Object>> optional_object =
176 this->GetObjectFilterReadOnlyAndSmiFast(slot);
177 if (!optional_object) {
178 return false;
179 }
180 typename TSlot::TObject target = *optional_object;
181#ifdef V8_ENABLE_DIRECT_HANDLE
182 if (target.ptr() == kTaggedNullAddress) return false;
183#endif
184 Tagged<HeapObject> heap_object;
185 // Treat weak references as strong.
186 if (!target.GetHeapObject(&heap_object)) {
187 return false;
188 }
189
190#ifdef THREAD_SANITIZER
191 MemoryChunk::FromHeapObject(heap_object)->SynchronizedLoad();
192#endif // THREAD_SANITIZER
193
194 if (!HeapLayout::InYoungGeneration(heap_object)) {
195 return false;
196 }
197
198#ifdef V8_MINORMS_STRING_SHORTCUTTING
199 if (slot_treatment_mode == SlotTreatmentMode::kReadWrite &&
200 !ShortCutStrings(reinterpret_cast<HeapObjectSlot&>(slot), &heap_object)) {
201 return false;
202 }
203#endif // V8_MINORMS_STRING_SHORTCUTTING
204
205 if (!TryMark(heap_object)) return true;
206
207 // Maps won't change in the atomic pause, so the map can be read without
208 // atomics.
209 if constexpr (visitation_mode == ObjectVisitationMode::kVisitDirectly) {
210 Tagged<Map> map = heap_object->map(isolate_);
211 const size_t visited_size = Base::Visit(map, heap_object);
212 if (visited_size) {
213 IncrementLiveBytesCached(
216 ALIGN_TO_ALLOCATION_ALIGNMENT(visited_size));
217 }
218 return true;
219 }
220 // Default case: Visit via worklist.
221 marking_worklists_local_.Push(heap_object);
222
223 return true;
224}
225
226#ifdef V8_MINORMS_STRING_SHORTCUTTING
227template <YoungGenerationMarkingVisitationMode marking_mode>
229 HeapObjectSlot slot, Tagged<HeapObject>* heap_object) {
231 if (shortcut_strings_) {
233#if V8_STATIC_ROOTS_BOOL
234 ObjectSlot map_slot = (*heap_object)->map_slot();
235 Address map_address = map_slot.load_map().ptr();
236 if (map_address == StaticReadOnlyRoot::kThinOneByteStringMap ||
237 map_address == StaticReadOnlyRoot::kThinTwoByteStringMap) {
238 DCHECK_EQ((*heap_object)
240 ->visitor_id(),
241 VisitorId::kVisitThinString);
242 *heap_object = Cast<ThinString>(*heap_object)->actual();
243 // ThinStrings always refer to internalized strings, which are always
244 // in old space.
245 DCHECK(!Heap::InYoungGeneration(*heap_object));
246 slot.StoreHeapObject(*heap_object);
247 return false;
248 } else if (map_address == StaticReadOnlyRoot::kConsOneByteStringMap ||
249 map_address == StaticReadOnlyRoot::kConsTwoByteStringMap) {
250 // Not all ConsString are short cut candidates.
251 const VisitorId visitor_id =
252 (*heap_object)
254 ->visitor_id();
255 if (visitor_id == VisitorId::kVisitShortcutCandidate) {
256 Tagged<ConsString> string = Cast<ConsString>(*heap_object);
257 if (static_cast<Tagged_t>(string->second().ptr()) ==
258 StaticReadOnlyRoot::kempty_string) {
259 *heap_object = string->first();
260 slot.StoreHeapObject(*heap_object);
261 if (!Heap::InYoungGeneration(*heap_object)) {
262 return false;
263 }
264 }
265 }
266 }
267#endif // V8_STATIC_ROOTS_BOOL
268 }
269 return true;
270}
271#endif // V8_MINORMS_STRING_SHORTCUTTING
272
273template <YoungGenerationMarkingVisitationMode marking_mode>
274V8_INLINE void
276 MutablePageMetadata* chunk, intptr_t by) {
279 const size_t hash = base::hash<MutablePageMetadata*>()(chunk) & kEntriesMask;
280 auto& entry = live_bytes_data_[hash];
281 if (entry.first && entry.first != chunk) {
282 entry.first->IncrementLiveBytesAtomically(entry.second);
283 entry.first = chunk;
284 entry.second = 0;
285 } else {
286 entry.first = chunk;
287 }
288 entry.second += by;
289}
290
291} // namespace internal
292} // namespace v8
293
294#endif // V8_HEAP_YOUNG_GENERATION_MARKING_VISITOR_INL_H_
Isolate * isolate_
Address try_load(IsolateForPointerCompression isolate, CppHeapPointerTagRange tag_range) const
Definition slots-inl.h:319
static int SizeOf(Tagged< Map > map, Tagged< HeapObject > object)
ExternalPointerTagRange tag_range() const
Definition slots.h:421
void StoreHeapObject(Tagged< HeapObject > value) const
Definition slots-inl.h:193
Tagged< Map > load_map() const
Definition slots-inl.h:66
static V8_INLINE bool InYoungGeneration(Tagged< Object > object)
static V8_INLINE MemoryChunkMetadata * FromHeapObject(Tagged< HeapObject > o)
static V8_INLINE MemoryChunk * FromHeapObject(Tagged< HeapObject > object)
static MutablePageMetadata * cast(MemoryChunkMetadata *metadata)
static V8_INLINE MutablePageMetadata * FromHeapObject(Tagged< HeapObject > o)
PtrComprCageBase cage_base() const
Definition visitors.h:225
virtual void VisitExternalPointer(Tagged< HeapObject > host, ExternalPointerSlot slot)
Definition visitors.h:188
std::unordered_map< Tagged< AllocationSite >, size_t, Object::Hasher > PretenuringFeedbackMap
static void UpdateAllocationSite(Heap *heap, Tagged< Map > map, Tagged< HeapObject > object, int object_size, PretenuringFeedbackMap *pretenuring_feedback)
Address address() const
Definition slots.h:78
V8_INLINE constexpr StorageType ptr() const
YoungGenerationMarkingVisitor(Heap *heap, PretenuringHandler::PretenuringFeedbackMap *local_pretenuring_feedback)
V8_INLINE void VisitPointersImpl(Tagged< HeapObject > host, TSlot start, TSlot end)
V8_INLINE void VisitCppHeapPointer(Tagged< HeapObject > host, CppHeapPointerSlot slot) override
V8_INLINE size_t VisitJSObjectSubclass(Tagged< Map > map, Tagged< T > object, MaybeObjectSize)
V8_INLINE size_t VisitEphemeronHashTable(Tagged< Map > map, Tagged< EphemeronHashTable > table, MaybeObjectSize)
V8_INLINE void IncrementLiveBytesCached(MutablePageMetadata *chunk, intptr_t by)
V8_INLINE size_t VisitJSArrayBuffer(Tagged< Map > map, Tagged< JSArrayBuffer > object, MaybeObjectSize)
#define V8_COMPRESS_POINTERS_8GB_BOOL
Definition globals.h:608
#define ALIGN_TO_ALLOCATION_ALIGNMENT(value)
Definition globals.h:1796
int start
int end
std::map< const std::string, const std::string > map
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
constexpr Address kTaggedNullAddress
Definition handles.h:53
static V8_INLINE constexpr bool IsSharedExternalPointerType(ExternalPointerTagRange tag_range)
Tagged(T object) -> Tagged< T >
Address Tagged_t
Definition globals.h:547
constexpr intptr_t kObjectAlignment8GbHeap
Definition globals.h:934
constexpr ExternalPointerHandle kNullExternalPointerHandle
V8_EXPORT_PRIVATE FlagValues v8_flags
uint32_t ExternalPointerHandle
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
constexpr CppHeapPointerTagRange kAnyCppHeapPointer(CppHeapPointerTag::kFirstTag, CppHeapPointerTag::kLastTag)
#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
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403
constexpr bool IsEmpty() const
#define V8_STATIC_ROOTS_BOOL
Definition v8config.h:1001
#define V8_INLINE
Definition v8config.h:500