v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
marking-worklist.cc
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
6
7#include <algorithm>
8#include <cstddef>
9#include <map>
10
18#include "src/objects/map.h"
20
21namespace v8 {
22namespace internal {
23
25 shared_.Clear();
27 other_.Clear();
28 for (auto& cw : context_worklists_) {
29 cw.worklist->Clear();
30 }
32}
33
35 PrintWorklist("shared", &shared_);
36 PrintWorklist("on_hold", &on_hold_);
37}
38
40 const std::vector<Address>& contexts) {
42 if (contexts.empty()) return;
43
44 context_worklists_.reserve(contexts.size());
45 for (Address context : contexts) {
46 context_worklists_.push_back(
47 {context, std::make_unique<MarkingWorklist>()});
48 }
49}
50
52
53void MarkingWorklists::PrintWorklist(const char* worklist_name,
54 MarkingWorklist* worklist) {
55#ifdef DEBUG
56 std::map<InstanceType, int> count;
57 int total_count = 0;
58 worklist->Iterate([&count, &total_count](Tagged<HeapObject> obj) {
59 ++total_count;
60 count[obj->map()->instance_type()]++;
61 });
62 std::vector<std::pair<int, InstanceType>> rank;
63 rank.reserve(count.size());
64 for (const auto& i : count) {
65 rank.emplace_back(i.second, i.first);
66 }
67 std::map<InstanceType, std::string> instance_type_name;
68#define INSTANCE_TYPE_NAME(name) instance_type_name[name] = #name;
69 INSTANCE_TYPE_LIST(INSTANCE_TYPE_NAME)
70#undef INSTANCE_TYPE_NAME
71 std::sort(rank.begin(), rank.end(),
72 std::greater<std::pair<int, InstanceType>>());
73 PrintF("Worklist %s: %d\n", worklist_name, total_count);
74 for (auto i : rank) {
75 PrintF(" [%s]: %d\n", instance_type_name[i.second].c_str(), i.first);
76 }
77#endif
78}
79
82constexpr std::nullptr_t MarkingWorklists::Local::kNoCppMarkingState;
83
85 MarkingWorklists* global,
86 std::unique_ptr<CppMarkingState> cpp_marking_state)
87 : active_(&shared_),
88 shared_(*global->shared()),
89 on_hold_(*global->on_hold()),
90 active_context_(kSharedContext),
91 is_per_context_mode_(!global->context_worklists().empty()),
92 other_(*global->other()),
93 cpp_marking_state_(std::move(cpp_marking_state)) {
95 context_worklists_.reserve(global->context_worklists().size());
96 int index = 0;
97 for (auto& cw : global->context_worklists()) {
98 context_worklists_.emplace_back(*cw.worklist);
99 worklist_by_context_.Set(cw.context, index);
100 index++;
101 }
102 }
103}
104
106 shared_.Publish();
107 on_hold_.Publish();
108 other_.Publish();
109 if (is_per_context_mode_) {
110 for (auto* entry = worklist_by_context_.Start(); entry != nullptr;
111 entry = worklist_by_context_.Next(entry)) {
112 context_worklists_[entry->value].Publish();
113 }
114 }
115 PublishCppHeapObjects();
116}
117
119 // This function checks the on_hold_ worklist, so it works only for the main
120 // thread.
121 if (!active_->IsLocalEmpty() || !on_hold_.IsLocalEmpty() ||
122 !active_->IsGlobalEmpty() || !on_hold_.IsGlobalEmpty()) {
123 return false;
124 }
125 if (!is_per_context_mode_) {
126 return true;
127 }
128 if (!shared_.IsLocalEmpty() || !other_.IsLocalEmpty() ||
129 !shared_.IsGlobalEmpty() || !other_.IsGlobalEmpty()) {
130 return false;
131 }
132 for (auto* entry = worklist_by_context_.Start(); entry != nullptr;
133 entry = worklist_by_context_.Next(entry)) {
134 auto& worklist = context_worklists_[entry->value];
135 if (entry->key != active_context_ &&
136 !(worklist.IsLocalEmpty() && worklist.IsGlobalEmpty())) {
137 SwitchToContextImpl(entry->key, &worklist);
138 return false;
139 }
140 }
141 return true;
142}
143
145 return !cpp_marking_state_ || cpp_marking_state_->IsLocalEmpty();
146}
147
149 if (!active_->IsLocalEmpty() && active_->IsGlobalEmpty()) {
150 active_->Publish();
151 }
152 if (is_per_context_mode_ && active_context_ != kSharedContext) {
153 if (!shared_.IsLocalEmpty() && shared_.IsGlobalEmpty()) {
154 shared_.Publish();
155 }
156 }
157}
158
160 DCHECK(!is_per_context_mode_);
161 shared_.Publish();
162}
163
165
167 DCHECK(is_per_context_mode_);
168 // As an optimization we first check only the local segments to avoid locks.
169 for (auto* entry = worklist_by_context_.Start(); entry != nullptr;
170 entry = worklist_by_context_.Next(entry)) {
171 auto& worklist = context_worklists_[entry->value];
172 if (entry->key != active_context_ && !worklist.IsLocalEmpty()) {
173 SwitchToContextImpl(entry->key, &worklist);
174 return active_->Pop(object);
175 }
176 }
177 // All local segments are empty. Check global segments.
178 for (auto* entry = worklist_by_context_.Start(); entry != nullptr;
179 entry = worklist_by_context_.Next(entry)) {
180 auto& worklist = context_worklists_[entry->value];
181 if (entry->key != active_context_ && worklist.Pop(object)) {
182 SwitchToContextImpl(entry->key, &worklist);
183 return true;
184 }
185 }
186 // All worklists are empty. Switch to the default shared worklist.
187 SwitchToContext(kSharedContext);
188 return false;
189}
190
192 auto maybe_index = worklist_by_context_.Get(context);
193 if (V8_UNLIKELY(maybe_index.IsNothing())) {
194 // The context passed is not an actual context:
195 // - Shared context that should use the explicit worklist.
196 // - This context was created during marking and should use the other
197 // bucket.
198 if (context == kSharedContext) {
199 SwitchToContextImpl(kSharedContext, &shared_);
200 } else {
201 SwitchToContextImpl(kOtherContext, &other_);
202 }
203 } else {
204 SwitchToContextImpl(context, &(context_worklists_[maybe_index.FromJust()]));
205 }
206 return active_context_;
207}
208
212
213} // namespace internal
214} // namespace v8
void Iterate(Callback callback) const
Definition worklist.h:181
void Merge(Worklist< EntryType, MinSegmentSize > &other)
Definition worklist.h:189
std::vector< MarkingWorklist::Local > context_worklists_
Address SwitchToContextSlow(Address context)
bool PopContext(Tagged< HeapObject > *object)
Local(MarkingWorklists *global, std::unique_ptr< CppMarkingState > cpp_marking_state=kNoCppMarkingState)
static constexpr std::nullptr_t kNoCppMarkingState
static constexpr Address kSharedContext
void CreateContextWorklists(const std::vector< Address > &contexts)
void PrintWorklist(const char *worklist_name, MarkingWorklist *worklist)
const std::vector< ContextWorklistPair > & context_worklists() const
static constexpr Address kSharedContext
static constexpr Address kOtherContext
std::vector< ContextWorklistPair > context_worklists_
void Set(Type value, uint32_t index)
Definition address-map.h:24
bool active_
Definition cpp-heap.cc:596
uint32_t count
Tagged< SharedFunctionInfo > shared_
Definition debug.cc:1741
TNode< Context > context
std::vector< Handle< JSObject > > other_
STL namespace.
void PrintF(const char *format,...)
Definition utils.cc:39
#define INSTANCE_TYPE_LIST(V)
#define DCHECK(condition)
Definition logging.h:482
#define V8_UNLIKELY(condition)
Definition v8config.h:660