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/page-allocator.h"
14 : #include "src/base/platform/platform.h"
15 : #include "src/base/platform/time.h"
16 : #include "src/base/sys-info.h"
17 : #include "src/libplatform/default-foreground-task-runner.h"
18 : #include "src/libplatform/default-worker-threads-task-runner.h"
19 :
20 : namespace v8 {
21 : namespace platform {
22 :
23 : namespace {
24 :
25 0 : void PrintStackTrace() {
26 0 : v8::base::debug::StackTrace trace;
27 0 : trace.Print();
28 : // Avoid dumping duplicate stack trace on abort signal.
29 0 : v8::base::debug::DisableSignalStackDump();
30 0 : }
31 :
32 : } // namespace
33 :
34 61306 : std::unique_ptr<v8::Platform> NewDefaultPlatform(
35 : int thread_pool_size, IdleTaskSupport idle_task_support,
36 : InProcessStackDumping in_process_stack_dumping,
37 : std::unique_ptr<v8::TracingController> tracing_controller) {
38 61306 : if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
39 28763 : v8::base::debug::EnableInProcessStackDumping();
40 : }
41 : std::unique_ptr<DefaultPlatform> platform(
42 122612 : new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
43 61306 : platform->SetThreadPoolSize(thread_pool_size);
44 61306 : platform->EnsureBackgroundTaskRunnerInitialized();
45 61306 : return std::move(platform);
46 : }
47 :
48 0 : v8::Platform* CreateDefaultPlatform(
49 : int thread_pool_size, IdleTaskSupport idle_task_support,
50 : InProcessStackDumping in_process_stack_dumping,
51 : v8::TracingController* tracing_controller) {
52 : return NewDefaultPlatform(
53 : thread_pool_size, idle_task_support, in_process_stack_dumping,
54 : std::unique_ptr<v8::TracingController>(tracing_controller))
55 0 : .release();
56 : }
57 :
58 278645 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
59 : MessageLoopBehavior behavior) {
60 : return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
61 278645 : behavior);
62 : }
63 :
64 158175 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
65 : double idle_time_in_seconds) {
66 : static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
67 158175 : idle_time_in_seconds);
68 158175 : }
69 :
70 0 : void SetTracingController(
71 : v8::Platform* platform,
72 : v8::platform::tracing::TracingController* tracing_controller) {
73 : static_cast<DefaultPlatform*>(platform)->SetTracingController(
74 : std::unique_ptr<v8::TracingController>(tracing_controller));
75 0 : }
76 :
77 : const int DefaultPlatform::kMaxThreadPoolSize = 8;
78 :
79 61317 : DefaultPlatform::DefaultPlatform(
80 : IdleTaskSupport idle_task_support,
81 : std::unique_ptr<v8::TracingController> tracing_controller)
82 : : thread_pool_size_(0),
83 : idle_task_support_(idle_task_support),
84 : tracing_controller_(std::move(tracing_controller)),
85 : page_allocator_(new v8::base::PageAllocator()),
86 183951 : time_function_for_testing_(nullptr) {
87 61317 : if (!tracing_controller_) {
88 61316 : tracing::TracingController* controller = new tracing::TracingController();
89 61316 : controller->Initialize(nullptr);
90 : tracing_controller_.reset(controller);
91 : }
92 61317 : }
93 :
94 174844 : DefaultPlatform::~DefaultPlatform() {
95 58285 : base::MutexGuard guard(&lock_);
96 58285 : if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
97 177503 : for (auto it : foreground_task_runner_map_) {
98 60933 : it.second->Terminate();
99 : }
100 116559 : }
101 :
102 61308 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
103 61308 : base::MutexGuard guard(&lock_);
104 : DCHECK_GE(thread_pool_size, 0);
105 61308 : if (thread_pool_size < 1) {
106 61306 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
107 : }
108 : thread_pool_size_ =
109 122616 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
110 61308 : }
111 :
112 1514738 : void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
113 1514738 : base::MutexGuard guard(&lock_);
114 1514738 : if (!worker_threads_task_runner_) {
115 122614 : worker_threads_task_runner_ =
116 : std::make_shared<DefaultWorkerThreadsTaskRunner>(thread_pool_size_);
117 : }
118 1514738 : }
119 :
120 : namespace {
121 :
122 22819 : double DefaultTimeFunction() {
123 87134210 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
124 29068386 : static_cast<double>(base::Time::kMicrosecondsPerSecond);
125 : }
126 :
127 : } // namespace
128 :
129 8 : void DefaultPlatform::SetTimeFunctionForTesting(
130 : DefaultPlatform::TimeFunction time_function) {
131 8 : base::MutexGuard guard(&lock_);
132 8 : time_function_for_testing_ = time_function;
133 : // The time function has to be right after the construction of the platform.
134 : DCHECK(foreground_task_runner_map_.empty());
135 8 : }
136 :
137 278665 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
138 : MessageLoopBehavior wait_for_work) {
139 : bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
140 278665 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
141 : {
142 278665 : base::MutexGuard guard(&lock_);
143 : auto it = foreground_task_runner_map_.find(isolate);
144 278665 : if (it == foreground_task_runner_map_.end()) return failed_result;
145 : task_runner = it->second;
146 : }
147 :
148 278662 : std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
149 278662 : if (!task) return failed_result;
150 :
151 91156 : task->Run();
152 91156 : return true;
153 : }
154 :
155 158177 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
156 : double idle_time_in_seconds) {
157 : DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
158 158177 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
159 : {
160 158177 : base::MutexGuard guard(&lock_);
161 158177 : if (foreground_task_runner_map_.find(isolate) ==
162 : foreground_task_runner_map_.end()) {
163 : return;
164 : }
165 158177 : task_runner = foreground_task_runner_map_[isolate];
166 : }
167 : double deadline_in_seconds =
168 158177 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
169 :
170 320219 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
171 162008 : std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
172 162008 : if (!task) return;
173 3865 : task->Run(deadline_in_seconds);
174 : }
175 : }
176 :
177 1733424 : std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
178 : v8::Isolate* isolate) {
179 1733424 : base::MutexGuard guard(&lock_);
180 1733426 : if (foreground_task_runner_map_.find(isolate) ==
181 : foreground_task_runner_map_.end()) {
182 : foreground_task_runner_map_.insert(std::make_pair(
183 : isolate, std::make_shared<DefaultForegroundTaskRunner>(
184 : idle_task_support_, time_function_for_testing_
185 : ? time_function_for_testing_
186 186588 : : DefaultTimeFunction)));
187 : }
188 3466852 : return foreground_task_runner_map_[isolate];
189 : }
190 :
191 1453402 : void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
192 1453402 : EnsureBackgroundTaskRunnerInitialized();
193 4360206 : worker_threads_task_runner_->PostTask(std::move(task));
194 1453402 : }
195 :
196 30 : void DefaultPlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
197 : double delay_in_seconds) {
198 30 : EnsureBackgroundTaskRunnerInitialized();
199 30 : worker_threads_task_runner_->PostDelayedTask(std::move(task),
200 90 : delay_in_seconds);
201 30 : }
202 :
203 3 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
204 12 : GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<Task>(task));
205 3 : }
206 :
207 4 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
208 : Task* task,
209 : double delay_in_seconds) {
210 8 : GetForegroundTaskRunner(isolate)->PostDelayedTask(std::unique_ptr<Task>(task),
211 12 : delay_in_seconds);
212 4 : }
213 :
214 2 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
215 : IdleTask* task) {
216 4 : GetForegroundTaskRunner(isolate)->PostIdleTask(
217 6 : std::unique_ptr<IdleTask>(task));
218 2 : }
219 :
220 163669 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
221 163669 : return idle_task_support_ == IdleTaskSupport::kEnabled;
222 : }
223 :
224 29020263 : double DefaultPlatform::MonotonicallyIncreasingTime() {
225 29020263 : if (time_function_for_testing_) return time_function_for_testing_();
226 29022748 : return DefaultTimeFunction();
227 : }
228 :
229 165476 : double DefaultPlatform::CurrentClockTimeMillis() {
230 165476 : return base::OS::TimeCurrentMillis();
231 : }
232 :
233 2036589 : TracingController* DefaultPlatform::GetTracingController() {
234 : return tracing_controller_.get();
235 : }
236 :
237 25 : void DefaultPlatform::SetTracingController(
238 : std::unique_ptr<v8::TracingController> tracing_controller) {
239 : DCHECK_NOT_NULL(tracing_controller.get());
240 : tracing_controller_ = std::move(tracing_controller);
241 25 : }
242 :
243 1570312 : int DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
244 :
245 61281 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
246 61281 : return PrintStackTrace;
247 : }
248 :
249 61279 : v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
250 61279 : return page_allocator_.get();
251 : }
252 :
253 : } // namespace platform
254 : } // namespace v8
|