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 61022 : 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 61022 : if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
39 30092 : v8::base::debug::EnableInProcessStackDumping();
40 : }
41 : std::unique_ptr<DefaultPlatform> platform(
42 122044 : new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
43 61022 : platform->SetThreadPoolSize(thread_pool_size);
44 61022 : platform->EnsureBackgroundTaskRunnerInitialized();
45 61022 : return std::move(platform);
46 : }
47 :
48 247551 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
49 : MessageLoopBehavior behavior) {
50 : return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
51 247551 : behavior);
52 : }
53 :
54 162208 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
55 : double idle_time_in_seconds) {
56 : static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
57 162208 : idle_time_in_seconds);
58 162208 : }
59 :
60 0 : void SetTracingController(
61 : v8::Platform* platform,
62 : v8::platform::tracing::TracingController* tracing_controller) {
63 : static_cast<DefaultPlatform*>(platform)->SetTracingController(
64 : std::unique_ptr<v8::TracingController>(tracing_controller));
65 0 : }
66 :
67 : const int DefaultPlatform::kMaxThreadPoolSize = 8;
68 :
69 61033 : DefaultPlatform::DefaultPlatform(
70 : IdleTaskSupport idle_task_support,
71 : std::unique_ptr<v8::TracingController> tracing_controller)
72 : : thread_pool_size_(0),
73 : idle_task_support_(idle_task_support),
74 : tracing_controller_(std::move(tracing_controller)),
75 : page_allocator_(new v8::base::PageAllocator()),
76 183099 : time_function_for_testing_(nullptr) {
77 61033 : if (!tracing_controller_) {
78 61032 : tracing::TracingController* controller = new tracing::TracingController();
79 61032 : controller->Initialize(nullptr);
80 : tracing_controller_.reset(controller);
81 : }
82 61033 : }
83 :
84 231749 : DefaultPlatform::~DefaultPlatform() {
85 57940 : base::MutexGuard guard(&lock_);
86 57940 : if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
87 118256 : for (auto it : foreground_task_runner_map_) {
88 60316 : it.second->Terminate();
89 : }
90 115869 : }
91 :
92 61024 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
93 61024 : base::MutexGuard guard(&lock_);
94 : DCHECK_GE(thread_pool_size, 0);
95 61024 : if (thread_pool_size < 1) {
96 61022 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
97 : }
98 : thread_pool_size_ =
99 122048 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
100 61024 : }
101 :
102 : namespace {
103 :
104 4114300 : double DefaultTimeFunction() {
105 110199136 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
106 40852231 : static_cast<double>(base::Time::kMicrosecondsPerSecond);
107 : }
108 :
109 : } // namespace
110 :
111 1832328 : void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
112 1832328 : base::MutexGuard guard(&lock_);
113 1832328 : if (!worker_threads_task_runner_) {
114 : worker_threads_task_runner_ =
115 122046 : std::make_shared<DefaultWorkerThreadsTaskRunner>(
116 61023 : thread_pool_size_, time_function_for_testing_
117 : ? time_function_for_testing_
118 : : DefaultTimeFunction);
119 : }
120 1832327 : }
121 :
122 8 : void DefaultPlatform::SetTimeFunctionForTesting(
123 : DefaultPlatform::TimeFunction time_function) {
124 8 : base::MutexGuard guard(&lock_);
125 8 : time_function_for_testing_ = time_function;
126 : // The time function has to be right after the construction of the platform.
127 : DCHECK(foreground_task_runner_map_.empty());
128 8 : }
129 :
130 247571 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
131 : MessageLoopBehavior wait_for_work) {
132 : bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
133 247571 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
134 : {
135 247571 : base::MutexGuard guard(&lock_);
136 : auto it = foreground_task_runner_map_.find(isolate);
137 247571 : if (it == foreground_task_runner_map_.end()) return failed_result;
138 : task_runner = it->second;
139 : }
140 :
141 247568 : std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
142 247568 : if (!task) return failed_result;
143 :
144 57860 : task->Run();
145 57860 : return true;
146 : }
147 :
148 162210 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
149 : double idle_time_in_seconds) {
150 : DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
151 162210 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
152 : {
153 162210 : base::MutexGuard guard(&lock_);
154 162210 : if (foreground_task_runner_map_.find(isolate) ==
155 : foreground_task_runner_map_.end()) {
156 : return;
157 : }
158 162210 : task_runner = foreground_task_runner_map_[isolate];
159 : }
160 : double deadline_in_seconds =
161 162210 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
162 :
163 165953 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
164 165942 : std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
165 165942 : if (!task) return;
166 3743 : task->Run(deadline_in_seconds);
167 : }
168 : }
169 :
170 253084 : std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
171 : v8::Isolate* isolate) {
172 253084 : base::MutexGuard guard(&lock_);
173 253084 : if (foreground_task_runner_map_.find(isolate) ==
174 : foreground_task_runner_map_.end()) {
175 61603 : foreground_task_runner_map_.insert(std::make_pair(
176 123206 : isolate, std::make_shared<DefaultForegroundTaskRunner>(
177 61603 : idle_task_support_, time_function_for_testing_
178 : ? time_function_for_testing_
179 : : DefaultTimeFunction)));
180 : }
181 506168 : return foreground_task_runner_map_[isolate];
182 : }
183 :
184 1771276 : void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
185 1771276 : EnsureBackgroundTaskRunnerInitialized();
186 5313826 : worker_threads_task_runner_->PostTask(std::move(task));
187 1771276 : }
188 :
189 30 : void DefaultPlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
190 : double delay_in_seconds) {
191 30 : EnsureBackgroundTaskRunnerInitialized();
192 30 : worker_threads_task_runner_->PostDelayedTask(std::move(task),
193 60 : delay_in_seconds);
194 30 : }
195 :
196 3 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
197 12 : GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<Task>(task));
198 3 : }
199 :
200 4 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
201 : Task* task,
202 : double delay_in_seconds) {
203 12 : GetForegroundTaskRunner(isolate)->PostDelayedTask(std::unique_ptr<Task>(task),
204 8 : delay_in_seconds);
205 4 : }
206 :
207 2 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
208 : IdleTask* task) {
209 6 : GetForegroundTaskRunner(isolate)->PostIdleTask(
210 4 : std::unique_ptr<IdleTask>(task));
211 2 : }
212 :
213 168396 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
214 168396 : return idle_task_support_ == IdleTaskSupport::kEnabled;
215 : }
216 :
217 32608982 : double DefaultPlatform::MonotonicallyIncreasingTime() {
218 32608982 : if (time_function_for_testing_) return time_function_for_testing_();
219 32623629 : return DefaultTimeFunction();
220 : }
221 :
222 1155073 : double DefaultPlatform::CurrentClockTimeMillis() {
223 1155073 : return base::OS::TimeCurrentMillis();
224 : }
225 :
226 2426330 : TracingController* DefaultPlatform::GetTracingController() {
227 2426330 : return tracing_controller_.get();
228 : }
229 :
230 30 : void DefaultPlatform::SetTracingController(
231 : std::unique_ptr<v8::TracingController> tracing_controller) {
232 : DCHECK_NOT_NULL(tracing_controller.get());
233 : tracing_controller_ = std::move(tracing_controller);
234 30 : }
235 :
236 1276897 : int DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
237 :
238 60992 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
239 60992 : return PrintStackTrace;
240 : }
241 :
242 60988 : v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
243 60988 : return page_allocator_.get();
244 : }
245 :
246 : } // namespace platform
247 : } // namespace v8
|