v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
scavenger.h
Go to the documentation of this file.
1// Copyright 2015 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_SCAVENGER_H_
6#define V8_HEAP_SCAVENGER_H_
7
8#include <atomic>
9
20#include "src/heap/slot-set.h"
21
22namespace v8 {
23namespace internal {
24
25class RootScavengeVisitor;
26class Scavenger;
27class ScavengeVisitor;
28
34
36 std::unordered_map<Tagged<HeapObject>, Tagged<Map>, Object::Hasher>;
38 std::pair<Tagged<HeapObject>, Tagged<Map>>;
39
41
42class Scavenger {
43 public:
44 static constexpr int kCopiedListSegmentSize = 256;
45 static constexpr int kPinnedListSegmentSize = 64;
46 static constexpr int kPromotedListSegmentSize = 256;
47
48 using CopiedList =
50
51 using ObjectAndMap = std::pair<Tagged<HeapObject>, Tagged<Map>>;
52 using PinnedList =
54
62
64
65 Scavenger(ScavengerCollector* collector, Heap* heap, bool is_logging,
66 EmptyChunksList* empty_chunks, CopiedList* copied_list,
67 PinnedList* pinned_list, PromotedList* promoted_list,
68 EphemeronRememberedSet::TableList* ephemeron_table_list);
69
70 // Entry point for scavenging an old generation page. For scavenging single
71 // objects see RootScavengingVisitor and ScavengeVisitor below.
73
74 // Processes remaining work (=objects) after single objects have been
75 // manually scavenged using ScavengeObject or CheckAndScavengeObject.
76 void Process(JobDelegate* delegate = nullptr);
77
78 // Finalize the Scavenger. Needs to be called from the main thread.
79 void Finalize();
80 void Publish();
81
83
84 // Returns true if the object is a large young object, and false otherwise.
86
88 MapWord map_word);
89 void VisitPinnedObjects();
90
91 size_t bytes_copied() const { return copied_size_; }
92 size_t bytes_promoted() const { return promoted_size_; }
93
94 private:
96
97 // Number of objects to process before interrupting for potentially waking
98 // up other tasks.
99 static const int kInterruptThreshold = 128;
100
101 inline Heap* heap() { return heap_; }
102
103 inline void SynchronizePageAccess(Tagged<MaybeObject> object) const;
104
106
107 // Potentially scavenges an object referenced from |slot| if it is
108 // indeed a HeapObject and resides in from space.
109 template <typename TSlot>
110 inline SlotCallbackResult CheckAndScavengeObject(Heap* heap, TSlot slot);
111
112 template <typename TSlot>
115 TSlot slot);
118 SlotType slot_type,
119 Address slot_address,
121
122 // Scavenges an object |object| referenced from slot |p|. |object| is required
123 // to be in from space.
124 template <typename THeapObjectSlot>
125 inline SlotCallbackResult ScavengeObject(THeapObjectSlot p,
126 Tagged<HeapObject> object);
127
128 // Copies |source| to |target| and sets the forwarding pointer in |source|.
130 Tagged<HeapObject> target, int size,
131 PromotionHeapChoice promotion_heap_choice);
132
133 V8_INLINE SlotCallbackResult
135
136 template <typename THeapObjectSlot>
138 Tagged<Map> map, THeapObjectSlot slot, Tagged<HeapObject> object,
139 int object_size, ObjectFields object_fields);
140
141 template <typename THeapObjectSlot,
142 PromotionHeapChoice promotion_heap_choice = kPromoteIntoLocalHeap>
144 THeapObjectSlot slot,
145 Tagged<HeapObject> object,
146 int object_size,
147 ObjectFields object_fields);
148
149 template <typename THeapObjectSlot>
150 V8_INLINE SlotCallbackResult EvacuateObject(THeapObjectSlot slot,
151 Tagged<Map> map,
152 Tagged<HeapObject> source);
153
155 int object_size, ObjectFields object_fields);
156
157 // Different cases for object evacuation.
158 template <typename THeapObjectSlot,
159 PromotionHeapChoice promotion_heap_choice = kPromoteIntoLocalHeap>
161 Tagged<Map> map, THeapObjectSlot slot, Tagged<HeapObject> object,
162 int object_size, ObjectFields object_fields);
163
164 template <typename THeapObjectSlot>
165 inline SlotCallbackResult EvacuateThinString(Tagged<Map> map,
166 THeapObjectSlot slot,
167 Tagged<ThinString> object,
168 int object_size);
169
170 template <typename THeapObjectSlot>
171 inline SlotCallbackResult EvacuateShortcutCandidate(Tagged<Map> map,
172 THeapObjectSlot slot,
173 Tagged<ConsString> object,
174 int object_size);
175
176 template <typename THeapObjectSlot>
177 inline SlotCallbackResult EvacuateInPlaceInternalizableString(
178 Tagged<Map> map, THeapObjectSlot slot, Tagged<String> string,
179 int object_size, ObjectFields object_fields);
180
182 Tagged<Map> map, int size);
184
186
188 int object_size);
190 int object_size);
191
193 Heap* const heap_;
202 size_t copied_size_{0};
203 size_t promoted_size_{0};
205
206 const bool is_logging_;
210
213 friend class ScavengeVisitor;
214};
215
216// Helper class for turning the scavenger into an object visitor that is also
217// filtering out non-HeapObjects and objects which do not reside in new space.
218class RootScavengeVisitor final : public RootVisitor {
219 public:
220 explicit RootScavengeVisitor(Scavenger& scavenger);
221 ~RootScavengeVisitor() final;
222
223 void VisitRootPointer(Root root, const char* description,
224 FullObjectSlot p) final;
225 void VisitRootPointers(Root root, const char* description,
227
228 private:
230
232};
233
235 public:
241 using PinnedObjects = std::vector<PinnedObjectEntry>;
242
243 static const int kMaxScavengerTasks = 8;
244 static const int kMainThreadId = 0;
245
246 explicit ScavengerCollector(Heap* heap);
247
248 void CollectGarbage();
249
251
252 private:
253 class JobTask : public v8::JobTask {
254 public:
255 JobTask(ScavengerCollector* collector,
256 std::vector<std::unique_ptr<Scavenger>>* scavengers,
257 std::vector<std::pair<ParallelWorkItem, MutablePageMetadata*>>
258 old_to_new_chunks,
259 const Scavenger::CopiedList& copied_list,
260 const Scavenger::PinnedList& pinned_list,
261 const Scavenger::PromotedList& promoted_list);
262
263 void Run(JobDelegate* delegate) override;
264 size_t GetMaxConcurrency(size_t worker_count) const override;
265
266 uint64_t trace_id() const { return trace_id_; }
267
268 private:
269 void ProcessItems(JobDelegate* delegate, Scavenger* scavenger);
270 void ConcurrentScavengePages(Scavenger* scavenger);
272
274
275 std::vector<std::unique_ptr<Scavenger>>* scavengers_;
276 std::vector<std::pair<ParallelWorkItem, MutablePageMetadata*>>
278 std::atomic<size_t> remaining_memory_chunks_{0};
280
284
285 const uint64_t trace_id_;
286 };
287
288 // Quarantined pages must be swept before the next GC. If the next GC uses
289 // conservative scanning and encounters a stale object left over from a
290 // previous GC, this can result in memory corruptions.
292 public:
295 if (IsSweeping()) {
297 }
298 }
299
300 void StartSweeping(const PinnedObjects&& pinned_objects);
301 void FinishSweeping();
302 bool IsSweeping() const {
304 return job_handle_.get();
305 }
306
307 private:
308 class JobTask : public v8::JobTask {
309 public:
310 JobTask(Heap* heap, const PinnedObjects&& pinned_objects);
312 DCHECK(is_done_.load(std::memory_order_relaxed));
314 DCHECK(pinned_objects_.empty());
315 }
316
317 void Run(JobDelegate* delegate) override;
318
319 size_t GetMaxConcurrency(size_t worker_count) const override {
320 return is_done_.load(std::memory_order_relaxed) ? 0 : 1;
321 }
322
323 uint64_t trace_id() const { return trace_id_; }
324
325 private:
326 using ObjectsAndSizes = std::vector<std::pair<Address, size_t>>;
328 std::unordered_map<MemoryChunk*, ObjectsAndSizes,
331 std::function<void(Heap*, Address, size_t, bool)>;
332 static void CreateFillerFreeSpaceHandler(Heap* heap, Address address,
333 size_t size, bool should_zap);
334 static void AddToFreeListFreeSpaceHandler(Heap* heap, Address address,
335 size_t size, bool should_zap);
336
337 size_t SweepPage(FreeSpaceHandler free_space_handler, MemoryChunk* chunk,
338 PageMetadata* page,
339 ObjectsAndSizes& pinned_objects_on_page);
340 void CreateFillerFreeHandler(Address address, size_t size);
341
342 Heap* const heap_;
343 const uint64_t trace_id_;
344 const bool should_zap_;
346
347 std::atomic_bool is_done_{false};
349 PinnedObjectPerPage::iterator next_page_iterator_;
350 };
351
352 Heap* const heap_;
353 std::unique_ptr<JobHandle> job_handle_;
354 };
355
357 const SurvivingNewLargeObjectsMap& objects);
358
360
362 EphemeronRememberedSet::TableList* ephemeron_table_list);
364 EphemeronRememberedSet::TableList* ephemeron_table_list);
365 void ClearOldEphemerons();
367
369
371 const size_t estimate =
372 estimate_concurrency_.exchange(0, std::memory_order_relaxed);
373 return estimate == 0 ? 1 : estimate;
374 }
375
377 Heap* const heap_;
379 std::atomic<size_t> estimate_concurrency_{0};
381
382 friend class Scavenger;
383};
384
385} // namespace internal
386} // namespace v8
387
388#endif // V8_HEAP_SCAVENGER_H_
std::unordered_map< Tagged< EphemeronHashTable >, IndicesSet, Object::Hasher > TableMap
std::unordered_map< Tagged< AllocationSite >, size_t, Object::Hasher > PretenuringFeedbackMap
RootScavengeVisitor(Scavenger &scavenger)
void VisitRootPointer(Root root, const char *description, FullObjectSlot p) final
void VisitRootPointers(Root root, const char *description, FullObjectSlot start, FullObjectSlot end) final
void ScavengePointer(FullObjectSlot p)
size_t GetMaxConcurrency(size_t worker_count) const override
Definition scavenger.cc:251
void ProcessItems(JobDelegate *delegate, Scavenger *scavenger)
Definition scavenger.cc:266
void Run(JobDelegate *delegate) override
Definition scavenger.cc:228
void ConcurrentScavengePages(Scavenger *scavenger)
Definition scavenger.cc:284
JobTask(ScavengerCollector *collector, std::vector< std::unique_ptr< Scavenger > > *scavengers, std::vector< std::pair< ParallelWorkItem, MutablePageMetadata * > > old_to_new_chunks, const Scavenger::CopiedList &copied_list, const Scavenger::PinnedList &pinned_list, const Scavenger::PromotedList &promoted_list)
Definition scavenger.cc:208
const Scavenger::PromotedList & promoted_list_
Definition scavenger.h:283
const Scavenger::PinnedList & pinned_list_
Definition scavenger.h:282
const Scavenger::CopiedList & copied_list_
Definition scavenger.h:281
void VisitPinnedObjects(Scavenger *scavenger)
std::vector< std::pair< ParallelWorkItem, MutablePageMetadata * > > old_to_new_chunks_
Definition scavenger.h:277
std::atomic< size_t > remaining_memory_chunks_
Definition scavenger.h:278
std::vector< std::unique_ptr< Scavenger > > * scavengers_
Definition scavenger.h:275
size_t SweepPage(FreeSpaceHandler free_space_handler, MemoryChunk *chunk, PageMetadata *page, ObjectsAndSizes &pinned_objects_on_page)
Definition scavenger.cc:762
static void AddToFreeListFreeSpaceHandler(Heap *heap, Address address, size_t size, bool should_zap)
Definition scavenger.cc:751
std::unordered_map< MemoryChunk *, ObjectsAndSizes, base::hash< MemoryChunk * > > PinnedObjectPerPage
Definition scavenger.h:327
std::vector< std::pair< Address, size_t > > ObjectsAndSizes
Definition scavenger.h:326
JobTask(Heap *heap, const PinnedObjects &&pinned_objects)
Definition scavenger.cc:668
size_t GetMaxConcurrency(size_t worker_count) const override
Definition scavenger.h:319
static void CreateFillerFreeSpaceHandler(Heap *heap, Address address, size_t size, bool should_zap)
Definition scavenger.cc:741
std::function< void(Heap *, Address, size_t, bool)> FreeSpaceHandler
Definition scavenger.h:330
void StartSweeping(const PinnedObjects &&pinned_objects)
Definition scavenger.cc:788
void MergeSurvivingNewLargeObjects(const SurvivingNewLargeObjectsMap &objects)
QuarantinedPageSweeper quarantined_page_sweeper_
Definition scavenger.h:380
void ClearYoungEphemerons(EphemeronRememberedSet::TableList *ephemeron_table_list)
static const int kMaxScavengerTasks
Definition scavenger.h:243
std::atomic< size_t > estimate_concurrency_
Definition scavenger.h:379
void ProcessWeakReferences(EphemeronRememberedSet::TableList *ephemeron_table_list)
SurvivingNewLargeObjectsMap surviving_new_large_objects_
Definition scavenger.h:378
std::vector< PinnedObjectEntry > PinnedObjects
Definition scavenger.h:241
static constexpr int kPromotedListSegmentSize
Definition scavenger.h:46
V8_INLINE SlotCallbackResult EvacuateObject(THeapObjectSlot slot, Tagged< Map > map, Tagged< HeapObject > source)
EvacuationAllocator allocator_
Definition scavenger.h:204
EphemeronRememberedSet::TableList::Local local_ephemeron_table_list_
Definition scavenger.h:198
void PushPinnedObject(Tagged< HeapObject > object, Tagged< Map > map, int object_size)
ScavengerCollector *const collector_
Definition scavenger.h:192
PretenuringHandler::PretenuringFeedbackMap local_pretenuring_feedback_
Definition scavenger.h:199
void RememberPromotedEphemeron(Tagged< EphemeronHashTable > table, int index)
V8_INLINE SlotCallbackResult RememberedSetEntryNeeded(CopyAndForwardResult result)
void AddEphemeronHashTable(Tagged< EphemeronHashTable > table)
const bool shared_string_table_
Definition scavenger.h:207
size_t bytes_copied() const
Definition scavenger.h:91
EmptyChunksList::Local local_empty_chunks_
Definition scavenger.h:194
V8_INLINE CopyAndForwardResult PromoteObject(Tagged< Map > map, THeapObjectSlot slot, Tagged< HeapObject > object, int object_size, ObjectFields object_fields)
std::pair< Tagged< HeapObject >, Tagged< Map > > ObjectAndMap
Definition scavenger.h:51
PromotedList::Local local_promoted_list_
Definition scavenger.h:197
void SynchronizePageAccess(Tagged< MaybeObject > object) const
SlotCallbackResult EvacuateThinString(Tagged< Map > map, THeapObjectSlot slot, Tagged< ThinString > object, int object_size)
V8_INLINE bool ShouldEagerlyProcessPromotedList() const
static const int kInterruptThreshold
Definition scavenger.h:99
SlotCallbackResult EvacuateInPlaceInternalizableString(Tagged< Map > map, THeapObjectSlot slot, Tagged< String > string, int object_size, ObjectFields object_fields)
void AddPageToSweeperIfNecessary(MutablePageMetadata *page)
void IterateAndScavengePromotedObject(Tagged< HeapObject > target, Tagged< Map > map, int size)
SlotCallbackResult ScavengeObject(THeapObjectSlot p, Tagged< HeapObject > object)
const bool mark_shared_heap_
Definition scavenger.h:208
V8_INLINE SlotCallbackResult EvacuateObjectDefault(Tagged< Map > map, THeapObjectSlot slot, Tagged< HeapObject > object, int object_size, ObjectFields object_fields)
V8_INLINE CopyAndForwardResult SemiSpaceCopyObject(Tagged< Map > map, THeapObjectSlot slot, Tagged< HeapObject > object, int object_size, ObjectFields object_fields)
V8_INLINE bool MigrateObject(Tagged< Map > map, Tagged< HeapObject > source, Tagged< HeapObject > target, int size, PromotionHeapChoice promotion_heap_choice)
static constexpr int kPinnedListSegmentSize
Definition scavenger.h:45
V8_INLINE bool HandleLargeObject(Tagged< Map > map, Tagged< HeapObject > object, int object_size, ObjectFields object_fields)
bool PromoteIfLargeObject(Tagged< HeapObject > object)
SlotCallbackResult EvacuateShortcutCandidate(Tagged< Map > map, THeapObjectSlot slot, Tagged< ConsString > object, int object_size)
SlotCallbackResult CheckAndScavengeObject(Heap *heap, TSlot slot)
CopiedList::Local local_copied_list_
Definition scavenger.h:195
const bool shortcut_strings_
Definition scavenger.h:209
void Process(JobDelegate *delegate=nullptr)
PinnedList::Local local_pinned_list_
Definition scavenger.h:196
void CheckOldToNewSlotForSharedUntyped(MemoryChunk *chunk, MutablePageMetadata *page, TSlot slot)
size_t bytes_promoted() const
Definition scavenger.h:92
void ScavengePage(MutablePageMetadata *page)
void CheckOldToNewSlotForSharedTyped(MemoryChunk *chunk, MutablePageMetadata *page, SlotType slot_type, Address slot_address, Tagged< MaybeObject > new_target)
SurvivingNewLargeObjectsMap local_surviving_new_large_objects_
Definition scavenger.h:201
EphemeronRememberedSet::TableMap local_ephemeron_remembered_set_
Definition scavenger.h:200
static constexpr int kCopiedListSegmentSize
Definition scavenger.h:44
void PushPinnedPromotedObject(Tagged< HeapObject > object, Tagged< Map > map, int object_size)
void PinAndPushObject(MemoryChunk *chunk, Tagged< HeapObject > object, MapWord map_word)
int start
int end
DirectHandle< Object > new_target
Definition execution.cc:75
ZoneVector< RpoNumber > & result
std::pair< Tagged< HeapObject >, Tagged< Map > > SurvivingNewLargeObjectMapEntry
Definition scavenger.h:37
std::unordered_map< Tagged< HeapObject >, Tagged< Map >, Object::Hasher > SurvivingNewLargeObjectsMap
Definition scavenger.h:35
use conservative stack scanning use direct handles with conservative stack scanning Treat some precise references as conservative references to stress test object pinning in Scavenger minor_gc_task Enables random stressing of object pinning in Scavenger
Definition flags.cc:502
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define V8_INLINE
Definition v8config.h:500