Line data Source code
1 : // Copyright 2013 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 : #include "src/libplatform/default-platform.h"
6 :
7 : #include <algorithm>
8 : #include <queue>
9 :
10 : #include "include/libplatform/libplatform.h"
11 : #include "src/base/debug/stack_trace.h"
12 : #include "src/base/logging.h"
13 : #include "src/base/platform/platform.h"
14 : #include "src/base/platform/time.h"
15 : #include "src/base/sys-info.h"
16 : #include "src/libplatform/worker-thread.h"
17 :
18 : namespace v8 {
19 : namespace platform {
20 :
21 : namespace {
22 :
23 0 : void PrintStackTrace() {
24 0 : v8::base::debug::StackTrace trace;
25 0 : trace.Print();
26 : // Avoid dumping duplicate stack trace on abort signal.
27 0 : v8::base::debug::DisableSignalStackDump();
28 0 : }
29 :
30 : } // namespace
31 :
32 59495 : v8::Platform* CreateDefaultPlatform(int thread_pool_size,
33 : IdleTaskSupport idle_task_support) {
34 59495 : v8::base::debug::EnableInProcessStackDumping();
35 59495 : DefaultPlatform* platform = new DefaultPlatform(idle_task_support);
36 59495 : platform->SetThreadPoolSize(thread_pool_size);
37 59495 : platform->EnsureInitialized();
38 59495 : return platform;
39 : }
40 :
41 :
42 184043 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
43 184043 : return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
44 : }
45 :
46 146141 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
47 : double idle_time_in_seconds) {
48 : reinterpret_cast<DefaultPlatform*>(platform)->RunIdleTasks(
49 146141 : isolate, idle_time_in_seconds);
50 146141 : }
51 :
52 34 : void SetTracingController(
53 : v8::Platform* platform,
54 : v8::platform::tracing::TracingController* tracing_controller) {
55 : return reinterpret_cast<DefaultPlatform*>(platform)->SetTracingController(
56 34 : tracing_controller);
57 : }
58 :
59 : const int DefaultPlatform::kMaxThreadPoolSize = 8;
60 :
61 59501 : DefaultPlatform::DefaultPlatform(IdleTaskSupport idle_task_support)
62 : : initialized_(false),
63 : thread_pool_size_(0),
64 178503 : idle_task_support_(idle_task_support) {}
65 :
66 234994 : DefaultPlatform::~DefaultPlatform() {
67 58750 : if (tracing_controller_) {
68 0 : tracing_controller_->StopTracing();
69 : tracing_controller_.reset();
70 : }
71 :
72 58750 : base::LockGuard<base::Mutex> guard(&lock_);
73 58750 : queue_.Terminate();
74 58750 : if (initialized_) {
75 528696 : for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
76 411208 : delete *i;
77 : }
78 : }
79 118291 : for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
80 : ++i) {
81 823 : while (!i->second.empty()) {
82 32 : delete i->second.front();
83 : i->second.pop();
84 : }
85 : }
86 117762 : for (auto i = main_thread_delayed_queue_.begin();
87 : i != main_thread_delayed_queue_.end(); ++i) {
88 522 : while (!i->second.empty()) {
89 260 : delete i->second.top().second;
90 260 : i->second.pop();
91 : }
92 : }
93 120953 : for (auto& i : main_thread_idle_queue_) {
94 3497 : while (!i.second.empty()) {
95 44 : delete i.second.front();
96 : i.second.pop();
97 : }
98 : }
99 117494 : }
100 :
101 :
102 59495 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
103 59495 : base::LockGuard<base::Mutex> guard(&lock_);
104 : DCHECK(thread_pool_size >= 0);
105 59495 : if (thread_pool_size < 1) {
106 59495 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
107 : }
108 : thread_pool_size_ =
109 118990 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
110 59495 : }
111 :
112 :
113 692894 : void DefaultPlatform::EnsureInitialized() {
114 692894 : base::LockGuard<base::Mutex> guard(&lock_);
115 1385788 : if (initialized_) return;
116 59495 : initialized_ = true;
117 :
118 475960 : for (int i = 0; i < thread_pool_size_; ++i)
119 832930 : thread_pool_.push_back(new WorkerThread(&queue_));
120 : }
121 :
122 :
123 184055 : Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
124 : auto it = main_thread_queue_.find(isolate);
125 195792 : if (it == main_thread_queue_.end() || it->second.empty()) {
126 : return NULL;
127 : }
128 9388 : Task* task = it->second.front();
129 : it->second.pop();
130 9388 : return task;
131 : }
132 :
133 :
134 184068 : Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
135 : auto it = main_thread_delayed_queue_.find(isolate);
136 187519 : if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
137 : return NULL;
138 : }
139 3427 : double now = MonotonicallyIncreasingTime();
140 3427 : std::pair<double, Task*> deadline_and_task = it->second.top();
141 3427 : if (deadline_and_task.first > now) {
142 : return NULL;
143 : }
144 13 : it->second.pop();
145 13 : return deadline_and_task.second;
146 : }
147 :
148 155211 : IdleTask* DefaultPlatform::PopTaskInMainThreadIdleQueue(v8::Isolate* isolate) {
149 : auto it = main_thread_idle_queue_.find(isolate);
150 185783 : if (it == main_thread_idle_queue_.end() || it->second.empty()) {
151 : return nullptr;
152 : }
153 9083 : IdleTask* task = it->second.front();
154 : it->second.pop();
155 9083 : return task;
156 : }
157 :
158 184055 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
159 184055 : Task* task = NULL;
160 : {
161 184055 : base::LockGuard<base::Mutex> guard(&lock_);
162 :
163 : // Move delayed tasks that hit their deadline to the main queue.
164 184055 : task = PopTaskInMainThreadDelayedQueue(isolate);
165 368123 : while (task != NULL) {
166 13 : main_thread_queue_[isolate].push(task);
167 13 : task = PopTaskInMainThreadDelayedQueue(isolate);
168 : }
169 :
170 184055 : task = PopTaskInMainThreadQueue(isolate);
171 :
172 184055 : if (task == NULL) {
173 : return false;
174 : }
175 : }
176 9388 : task->Run();
177 9388 : delete task;
178 : return true;
179 : }
180 :
181 146142 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
182 : double idle_time_in_seconds) {
183 : DCHECK(IdleTaskSupport::kEnabled == idle_task_support_);
184 : double deadline_in_seconds =
185 146142 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
186 301367 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
187 : {
188 : IdleTask* task;
189 : {
190 155211 : base::LockGuard<base::Mutex> guard(&lock_);
191 155211 : task = PopTaskInMainThreadIdleQueue(isolate);
192 : }
193 301353 : if (task == nullptr) return;
194 9083 : task->Run(deadline_in_seconds);
195 9083 : delete task;
196 : }
197 : }
198 : }
199 :
200 633399 : void DefaultPlatform::CallOnBackgroundThread(Task* task,
201 : ExpectedRuntime expected_runtime) {
202 633399 : EnsureInitialized();
203 633399 : queue_.Append(task);
204 633399 : }
205 :
206 :
207 9454 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
208 9454 : base::LockGuard<base::Mutex> guard(&lock_);
209 9455 : main_thread_queue_[isolate].push(task);
210 9455 : }
211 :
212 :
213 273 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
214 : Task* task,
215 : double delay_in_seconds) {
216 273 : base::LockGuard<base::Mutex> guard(&lock_);
217 273 : double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
218 273 : main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
219 273 : }
220 :
221 9127 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
222 : IdleTask* task) {
223 9127 : base::LockGuard<base::Mutex> guard(&lock_);
224 9127 : main_thread_idle_queue_[isolate].push(task);
225 9127 : }
226 :
227 16471 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
228 16471 : return idle_task_support_ == IdleTaskSupport::kEnabled;
229 : }
230 :
231 7458360 : double DefaultPlatform::MonotonicallyIncreasingTime() {
232 22375102 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
233 14916742 : static_cast<double>(base::Time::kMicrosecondsPerSecond);
234 : }
235 :
236 188 : uint64_t DefaultPlatform::AddTraceEvent(
237 : char phase, const uint8_t* category_enabled_flag, const char* name,
238 : const char* scope, uint64_t id, uint64_t bind_id, int num_args,
239 : const char** arg_names, const uint8_t* arg_types,
240 : const uint64_t* arg_values,
241 : std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
242 : unsigned int flags) {
243 188 : if (tracing_controller_) {
244 : return tracing_controller_->AddTraceEvent(
245 : phase, category_enabled_flag, name, scope, id, bind_id, num_args,
246 188 : arg_names, arg_types, arg_values, arg_convertables, flags);
247 : }
248 :
249 : return 0;
250 : }
251 :
252 0 : void DefaultPlatform::UpdateTraceEventDuration(
253 : const uint8_t* category_enabled_flag, const char* name, uint64_t handle) {
254 0 : if (tracing_controller_) {
255 : tracing_controller_->UpdateTraceEventDuration(category_enabled_flag, name,
256 0 : handle);
257 : }
258 0 : }
259 :
260 1346656 : const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
261 1346656 : if (tracing_controller_) {
262 319 : return tracing_controller_->GetCategoryGroupEnabled(name);
263 : }
264 : static uint8_t no = 0;
265 : return &no;
266 : }
267 :
268 :
269 0 : const char* DefaultPlatform::GetCategoryGroupName(
270 : const uint8_t* category_enabled_flag) {
271 : static const char dummy[] = "dummy";
272 0 : return dummy;
273 : }
274 :
275 0 : void DefaultPlatform::SetTracingController(
276 : tracing::TracingController* tracing_controller) {
277 : tracing_controller_.reset(tracing_controller);
278 0 : }
279 :
280 321890 : size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() {
281 321890 : return static_cast<size_t>(thread_pool_size_);
282 : }
283 :
284 59481 : void DefaultPlatform::AddTraceStateObserver(TraceStateObserver* observer) {
285 118962 : if (!tracing_controller_) return;
286 20 : tracing_controller_->AddTraceStateObserver(observer);
287 : }
288 :
289 58764 : void DefaultPlatform::RemoveTraceStateObserver(TraceStateObserver* observer) {
290 117528 : if (!tracing_controller_) return;
291 20 : tracing_controller_->RemoveTraceStateObserver(observer);
292 : }
293 :
294 59461 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
295 59461 : return PrintStackTrace;
296 : }
297 :
298 : } // namespace platform
299 : } // namespace v8
|