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 59468 : v8::Platform* CreateDefaultPlatform(int thread_pool_size,
33 : IdleTaskSupport idle_task_support) {
34 59468 : v8::base::debug::EnableInProcessStackDumping();
35 59468 : DefaultPlatform* platform = new DefaultPlatform(idle_task_support);
36 59468 : platform->SetThreadPoolSize(thread_pool_size);
37 59468 : platform->EnsureInitialized();
38 59468 : return platform;
39 : }
40 :
41 :
42 183763 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
43 183763 : return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
44 : }
45 :
46 146019 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
47 : double idle_time_in_seconds) {
48 : reinterpret_cast<DefaultPlatform*>(platform)->RunIdleTasks(
49 146019 : isolate, idle_time_in_seconds);
50 146019 : }
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 59474 : DefaultPlatform::DefaultPlatform(IdleTaskSupport idle_task_support)
62 : : initialized_(false),
63 : thread_pool_size_(0),
64 178422 : idle_task_support_(idle_task_support) {}
65 :
66 234910 : DefaultPlatform::~DefaultPlatform() {
67 58729 : if (tracing_controller_) {
68 0 : tracing_controller_->StopTracing();
69 : tracing_controller_.reset();
70 : }
71 :
72 58729 : base::LockGuard<base::Mutex> guard(&lock_);
73 58729 : queue_.Terminate();
74 58729 : if (initialized_) {
75 528507 : for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
76 411061 : delete *i;
77 : }
78 : }
79 118246 : for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
80 : ++i) {
81 818 : while (!i->second.empty()) {
82 30 : delete i->second.front();
83 : i->second.pop();
84 : }
85 : }
86 117718 : for (auto i = main_thread_delayed_queue_.begin();
87 : i != main_thread_delayed_queue_.end(); ++i) {
88 518 : while (!i->second.empty()) {
89 258 : delete i->second.top().second;
90 258 : i->second.pop();
91 : }
92 : }
93 120908 : for (auto& i : main_thread_idle_queue_) {
94 3494 : while (!i.second.empty()) {
95 44 : delete i.second.front();
96 : i.second.pop();
97 : }
98 : }
99 117452 : }
100 :
101 :
102 59468 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
103 59468 : base::LockGuard<base::Mutex> guard(&lock_);
104 : DCHECK(thread_pool_size >= 0);
105 59468 : if (thread_pool_size < 1) {
106 59468 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
107 : }
108 : thread_pool_size_ =
109 118936 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
110 59468 : }
111 :
112 :
113 692229 : void DefaultPlatform::EnsureInitialized() {
114 692229 : base::LockGuard<base::Mutex> guard(&lock_);
115 1384458 : if (initialized_) return;
116 59468 : initialized_ = true;
117 :
118 475744 : for (int i = 0; i < thread_pool_size_; ++i)
119 832552 : thread_pool_.push_back(new WorkerThread(&queue_));
120 : }
121 :
122 :
123 183775 : Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
124 : auto it = main_thread_queue_.find(isolate);
125 195328 : if (it == main_thread_queue_.end() || it->second.empty()) {
126 : return NULL;
127 : }
128 9230 : Task* task = it->second.front();
129 : it->second.pop();
130 9230 : return task;
131 : }
132 :
133 :
134 183791 : Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
135 : auto it = main_thread_delayed_queue_.find(isolate);
136 187206 : if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
137 : return NULL;
138 : }
139 3385 : double now = MonotonicallyIncreasingTime();
140 3385 : std::pair<double, Task*> deadline_and_task = it->second.top();
141 3385 : if (deadline_and_task.first > now) {
142 : return NULL;
143 : }
144 16 : it->second.pop();
145 16 : return deadline_and_task.second;
146 : }
147 :
148 155113 : IdleTask* DefaultPlatform::PopTaskInMainThreadIdleQueue(v8::Isolate* isolate) {
149 : auto it = main_thread_idle_queue_.find(isolate);
150 185691 : if (it == main_thread_idle_queue_.end() || it->second.empty()) {
151 : return nullptr;
152 : }
153 9102 : IdleTask* task = it->second.front();
154 : it->second.pop();
155 9102 : return task;
156 : }
157 :
158 183775 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
159 183775 : Task* task = NULL;
160 : {
161 183775 : base::LockGuard<base::Mutex> guard(&lock_);
162 :
163 : // Move delayed tasks that hit their deadline to the main queue.
164 183775 : task = PopTaskInMainThreadDelayedQueue(isolate);
165 367566 : while (task != NULL) {
166 16 : main_thread_queue_[isolate].push(task);
167 16 : task = PopTaskInMainThreadDelayedQueue(isolate);
168 : }
169 :
170 183775 : task = PopTaskInMainThreadQueue(isolate);
171 :
172 183775 : if (task == NULL) {
173 : return false;
174 : }
175 : }
176 9230 : task->Run();
177 9230 : delete task;
178 : return true;
179 : }
180 :
181 146020 : 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 146020 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
186 301142 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
187 : {
188 : IdleTask* task;
189 : {
190 155113 : base::LockGuard<base::Mutex> guard(&lock_);
191 155113 : task = PopTaskInMainThreadIdleQueue(isolate);
192 : }
193 301133 : if (task == nullptr) return;
194 9102 : task->Run(deadline_in_seconds);
195 9102 : delete task;
196 : }
197 : }
198 : }
199 :
200 632761 : void DefaultPlatform::CallOnBackgroundThread(Task* task,
201 : ExpectedRuntime expected_runtime) {
202 632761 : EnsureInitialized();
203 632761 : queue_.Append(task);
204 632761 : }
205 :
206 :
207 9288 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
208 9288 : base::LockGuard<base::Mutex> guard(&lock_);
209 9292 : main_thread_queue_[isolate].push(task);
210 9292 : }
211 :
212 :
213 274 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
214 : Task* task,
215 : double delay_in_seconds) {
216 274 : base::LockGuard<base::Mutex> guard(&lock_);
217 274 : double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
218 274 : main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
219 274 : }
220 :
221 9146 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
222 : IdleTask* task) {
223 9146 : base::LockGuard<base::Mutex> guard(&lock_);
224 9146 : main_thread_idle_queue_[isolate].push(task);
225 9146 : }
226 :
227 16017 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
228 16017 : return idle_task_support_ == IdleTaskSupport::kEnabled;
229 : }
230 :
231 7440181 : double DefaultPlatform::MonotonicallyIncreasingTime() {
232 22320561 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
233 14880380 : 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 1345761 : const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
261 1345761 : 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 321595 : size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() {
281 321595 : return static_cast<size_t>(thread_pool_size_);
282 : }
283 :
284 59454 : void DefaultPlatform::AddTraceStateObserver(TraceStateObserver* observer) {
285 118908 : if (!tracing_controller_) return;
286 20 : tracing_controller_->AddTraceStateObserver(observer);
287 : }
288 :
289 58743 : void DefaultPlatform::RemoveTraceStateObserver(TraceStateObserver* observer) {
290 117486 : if (!tracing_controller_) return;
291 20 : tracing_controller_->RemoveTraceStateObserver(observer);
292 : }
293 :
294 59434 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
295 59434 : return PrintStackTrace;
296 : }
297 :
298 : } // namespace platform
299 : } // namespace v8
|