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 59608 : 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 59608 : if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
39 29536 : v8::base::debug::EnableInProcessStackDumping();
40 : }
41 : std::unique_ptr<DefaultPlatform> platform(
42 119216 : new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
43 59608 : platform->SetThreadPoolSize(thread_pool_size);
44 59608 : platform->EnsureBackgroundTaskRunnerInitialized();
45 59608 : return std::move(platform);
46 : }
47 :
48 244470 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
49 : MessageLoopBehavior behavior) {
50 : return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
51 244470 : behavior);
52 : }
53 :
54 159240 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
55 : double idle_time_in_seconds) {
56 : static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
57 159240 : idle_time_in_seconds);
58 159240 : }
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 59619 : 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 178857 : time_function_for_testing_(nullptr) {
77 59619 : if (!tracing_controller_) {
78 59618 : tracing::TracingController* controller = new tracing::TracingController();
79 59618 : controller->Initialize(nullptr);
80 : tracing_controller_.reset(controller);
81 : }
82 59619 : }
83 :
84 169720 : DefaultPlatform::~DefaultPlatform() {
85 56577 : base::MutexGuard guard(&lock_);
86 56577 : if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
87 172260 : for (auto it : foreground_task_runner_map_) {
88 59106 : it.second->Terminate();
89 : }
90 113143 : }
91 :
92 59610 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
93 59610 : base::MutexGuard guard(&lock_);
94 : DCHECK_GE(thread_pool_size, 0);
95 59610 : if (thread_pool_size < 1) {
96 59608 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
97 : }
98 : thread_pool_size_ =
99 119220 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
100 59610 : }
101 :
102 1427514 : void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
103 1427514 : base::MutexGuard guard(&lock_);
104 1427514 : if (!worker_threads_task_runner_) {
105 119218 : worker_threads_task_runner_ =
106 : std::make_shared<DefaultWorkerThreadsTaskRunner>(thread_pool_size_);
107 : }
108 1427514 : }
109 :
110 : namespace {
111 :
112 35804 : double DefaultTimeFunction() {
113 87038205 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
114 29048944 : static_cast<double>(base::Time::kMicrosecondsPerSecond);
115 : }
116 :
117 : } // namespace
118 :
119 8 : void DefaultPlatform::SetTimeFunctionForTesting(
120 : DefaultPlatform::TimeFunction time_function) {
121 8 : base::MutexGuard guard(&lock_);
122 8 : time_function_for_testing_ = time_function;
123 : // The time function has to be right after the construction of the platform.
124 : DCHECK(foreground_task_runner_map_.empty());
125 8 : }
126 :
127 244490 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
128 : MessageLoopBehavior wait_for_work) {
129 : bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
130 244490 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
131 : {
132 244490 : base::MutexGuard guard(&lock_);
133 : auto it = foreground_task_runner_map_.find(isolate);
134 244490 : if (it == foreground_task_runner_map_.end()) return failed_result;
135 : task_runner = it->second;
136 : }
137 :
138 244487 : std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
139 244487 : if (!task) return failed_result;
140 :
141 58449 : task->Run();
142 58449 : return true;
143 : }
144 :
145 159242 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
146 : double idle_time_in_seconds) {
147 : DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
148 159242 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
149 : {
150 159242 : base::MutexGuard guard(&lock_);
151 159242 : if (foreground_task_runner_map_.find(isolate) ==
152 : foreground_task_runner_map_.end()) {
153 : return;
154 : }
155 159242 : task_runner = foreground_task_runner_map_[isolate];
156 : }
157 : double deadline_in_seconds =
158 159242 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
159 :
160 322438 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
161 163152 : std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
162 163152 : if (!task) return;
163 3954 : task->Run(deadline_in_seconds);
164 : }
165 : }
166 :
167 251047 : std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
168 : v8::Isolate* isolate) {
169 251047 : base::MutexGuard guard(&lock_);
170 251048 : if (foreground_task_runner_map_.find(isolate) ==
171 : foreground_task_runner_map_.end()) {
172 : foreground_task_runner_map_.insert(std::make_pair(
173 : isolate, std::make_shared<DefaultForegroundTaskRunner>(
174 : idle_task_support_, time_function_for_testing_
175 : ? time_function_for_testing_
176 181107 : : DefaultTimeFunction)));
177 : }
178 502096 : return foreground_task_runner_map_[isolate];
179 : }
180 :
181 1367876 : void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
182 1367876 : EnsureBackgroundTaskRunnerInitialized();
183 4103628 : worker_threads_task_runner_->PostTask(std::move(task));
184 1367876 : }
185 :
186 30 : void DefaultPlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
187 : double delay_in_seconds) {
188 30 : EnsureBackgroundTaskRunnerInitialized();
189 30 : worker_threads_task_runner_->PostDelayedTask(std::move(task),
190 90 : delay_in_seconds);
191 30 : }
192 :
193 3 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
194 12 : GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<Task>(task));
195 3 : }
196 :
197 4 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
198 : Task* task,
199 : double delay_in_seconds) {
200 8 : GetForegroundTaskRunner(isolate)->PostDelayedTask(std::unique_ptr<Task>(task),
201 12 : delay_in_seconds);
202 4 : }
203 :
204 2 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
205 : IdleTask* task) {
206 4 : GetForegroundTaskRunner(isolate)->PostIdleTask(
207 6 : std::unique_ptr<IdleTask>(task));
208 2 : }
209 :
210 164819 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
211 164819 : return idle_task_support_ == IdleTaskSupport::kEnabled;
212 : }
213 :
214 28976127 : double DefaultPlatform::MonotonicallyIncreasingTime() {
215 28976127 : if (time_function_for_testing_) return time_function_for_testing_();
216 28977336 : return DefaultTimeFunction();
217 : }
218 :
219 165177 : double DefaultPlatform::CurrentClockTimeMillis() {
220 165177 : return base::OS::TimeCurrentMillis();
221 : }
222 :
223 1920776 : TracingController* DefaultPlatform::GetTracingController() {
224 1920776 : return tracing_controller_.get();
225 : }
226 :
227 25 : void DefaultPlatform::SetTracingController(
228 : std::unique_ptr<v8::TracingController> tracing_controller) {
229 : DCHECK_NOT_NULL(tracing_controller.get());
230 : tracing_controller_ = std::move(tracing_controller);
231 25 : }
232 :
233 1277501 : int DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
234 :
235 59583 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
236 59583 : return PrintStackTrace;
237 : }
238 :
239 59579 : v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
240 59579 : return page_allocator_.get();
241 : }
242 :
243 : } // namespace platform
244 : } // namespace v8
|