v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
marking-worklist.h
Go to the documentation of this file.
1// Copyright 2019 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_MARKING_WORKLIST_H_
6#define V8_HEAP_MARKING_WORKLIST_H_
7
8#include <cstddef>
9#include <memory>
10#include <unordered_map>
11#include <vector>
12
17
18namespace v8 {
19namespace internal {
20
21class CppMarkingState;
22class JSObject;
23
24// The index of the main thread task used by concurrent/parallel GC.
25const int kMainThreadTask = 0;
26
28
29// We piggyback on marking to compute object sizes per native context that is
30// needed for the new memory measurement API. The algorithm works as follows:
31// 1) At the start of marking we create a marking worklist for each context.
32// The existing shared, on_hold, and embedder worklists continue to work
33// as they did before, but they hold objects that are not attributed to any
34// context yet.
35// 2) Each marker has an active worklist where it pushes newly discovered
36// objects. Initially the shared worklist is set as active for all markers.
37// 3) When a marker pops an object from the active worklist:
38// a) It checks if the object has a known context (e.g. JSObjects, Maps,
39// Contexts know the context they belong to). If that's the case, then
40// the marker changes its active worklist to the worklist corresponding
41// to the context of the object.
42// b) It account the size of object to the active context.
43// c) It visits all pointers in the object and pushes new objects onto the
44// active worklist.
45// 4) When the active worklist becomes empty the marker selects any other
46// non-empty worklist as the active worklist.
47// 5) The write barrier pushes onto the shared worklist.
48//
49// The main invariant for context worklists:
50// If object X is in the worklist of context C, then either
51// a) X has a context and that context is C.
52// b) X is retained by object Y that has context C.
53//
54// The algorithm allows us to attribute context-independent objects such as
55// strings, numbers, FixedArrays to their retaining contexts. The algorithm is
56// not precise for context-independent objects that are shared between multiple
57// contexts. Such objects may be attributed to any retaining context.
58
59// Named pair of native context address and its marking worklist.
60// Since native contexts are allocated in the old generation, their addresses
61// a stable across Scavenges and stay valid throughout the marking phase.
64 std::unique_ptr<MarkingWorklist> worklist;
65};
66
67// A helper class that owns all global marking worklists.
69 public:
70 class Local;
71 // Fake addresses of special contexts used for per-context accounting.
72 // - kSharedContext is for objects that are not attributed to any context.
73 // - kOtherContext is for objects that are attributed to contexts that are
74 // not being measured.
75 static constexpr Address kSharedContext = 0;
76 static constexpr Address kOtherContext = 8;
77
78 MarkingWorklists() = default;
79
80 // Worklists implicitly check for emptiness on destruction.
81 ~MarkingWorklists() = default;
82
84 MarkingWorklist* on_hold() { return &on_hold_; }
86
87 // A list of (context, worklist) pairs that was set up at the start of
88 // marking by CreateContextWorklists.
89 const std::vector<ContextWorklistPair>& context_worklists() const {
90 return context_worklists_;
91 }
92 // This should be invoked at the start of marking with the list of contexts
93 // that require object size accounting.
94 void CreateContextWorklists(const std::vector<Address>& contexts);
95 // This should be invoked at the end of marking. All worklists must be
96 // empty at that point.
97 void ReleaseContextWorklists();
98 bool IsUsingContextWorklists() const { return !context_worklists_.empty(); }
99
100 void Clear();
101 void Print();
102
103 private:
104 // Prints the stats about the global pool of the worklist.
105 void PrintWorklist(const char* worklist_name, MarkingWorklist* worklist);
106
107 // Worklist used for most objects.
108 // TODO(mlippautz): Rename to "default".
110
111 // Concurrent marking uses this worklist to bail out of marking objects
112 // in new space's linear allocation area. Used to avoid black allocation
113 // for new space. This allow the compiler to remove write barriers
114 // for freshly allocatd objects.
116
117 // Per-context worklists. Objects are in the `shared_` worklist by default.
118 std::vector<ContextWorklistPair> context_worklists_;
119 // Worklist used for objects that are attributed to contexts that are
120 // not being measured.
122};
123
124// A thread-local view of the marking worklists. It owns all local marking
125// worklists and keeps track of the currently active local marking worklist
126// for per-context marking. In order to avoid additional indirections for
127// pushing and popping entries, the active_ worklist is not a pointer to
128// Local but an actual instance of Local with the following invariants:
129// - active_owner == worlist_by_context[active_context_].get()
130// - *active_owner is empty (all fields are null) because its content has
131// been moved to active_.
133 public:
134 static constexpr Address kSharedContext = MarkingWorklists::kSharedContext;
135 static constexpr Address kOtherContext = MarkingWorklists::kOtherContext;
136 static constexpr std::nullptr_t kNoCppMarkingState = nullptr;
137
138 explicit Local(
139 MarkingWorklists* global,
140 std::unique_ptr<CppMarkingState> cpp_marking_state = kNoCppMarkingState);
141
142 // Local worklists implicitly check for emptiness on destruction.
143 ~Local() = default;
144
145 inline void Push(Tagged<HeapObject> object);
146 inline bool Pop(Tagged<HeapObject>* object);
147
148 inline void PushOnHold(Tagged<HeapObject> object);
149 inline bool PopOnHold(Tagged<HeapObject>* object);
150
151 void Publish();
152 bool IsEmpty();
153 bool IsWrapperEmpty() const;
154 // Publishes the local active marking worklist if its global worklist is
155 // empty. In the per-context marking mode it also publishes the shared
156 // worklist.
157 void ShareWork();
158 // Publishes the local active marking worklist. Assume per-context marking
159 // mode is not used.
160 void PublishWork();
161 // Merges the on-hold worklist to the shared worklist.
162 void MergeOnHold();
163
164 // Publishes CppHeap objects.
165 inline void PublishCppHeapObjects();
166
167 // Returns the context of the active worklist.
168 Address Context() const { return active_context_; }
169 inline Address SwitchToContext(Address context);
170 bool IsPerContextMode() const { return is_per_context_mode_; }
171
173 return cpp_marking_state_.get();
174 }
175
176 Address SwitchToSharedForTesting();
177
178 private:
179 inline void SwitchToContextImpl(Address context,
180 MarkingWorklist::Local* worklist);
181
182 bool PopContext(Tagged<HeapObject>* object);
183 Address SwitchToContextSlow(Address context);
184
185 // Points to either `shared_`, `other_` or to a per-context worklist.
186 MarkingWorklist::Local* active_;
187 MarkingWorklist::Local shared_;
188 MarkingWorklist::Local on_hold_;
191
192 std::vector<MarkingWorklist::Local> context_worklists_;
194 MarkingWorklist::Local other_;
195 std::unique_ptr<CppMarkingState> cpp_marking_state_;
196};
197
198} // namespace internal
199} // namespace v8
200
201#endif // V8_HEAP_MARKING_WORKLIST_H_
std::vector< MarkingWorklist::Local > context_worklists_
std::unique_ptr< CppMarkingState > cpp_marking_state_
CppMarkingState * cpp_marking_state() const
const std::vector< ContextWorklistPair > & context_worklists() const
std::vector< ContextWorklistPair > context_worklists_
Tagged< SharedFunctionInfo > shared_
Definition debug.cc:1741
std::vector< Handle< JSObject > > other_
const int kMainThreadTask
#define V8_EXPORT_PRIVATE
Definition macros.h:460
std::unique_ptr< MarkingWorklist > worklist