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 61018 : 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 61018 : if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
39 30088 : v8::base::debug::EnableInProcessStackDumping();
40 : }
41 : std::unique_ptr<DefaultPlatform> platform(
42 122036 : new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
43 61018 : platform->SetThreadPoolSize(thread_pool_size);
44 61018 : platform->EnsureBackgroundTaskRunnerInitialized();
45 61018 : return std::move(platform);
46 : }
47 :
48 247294 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
49 : MessageLoopBehavior behavior) {
50 : return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
51 247294 : behavior);
52 : }
53 :
54 162184 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
55 : double idle_time_in_seconds) {
56 : static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
57 162184 : idle_time_in_seconds);
58 162184 : }
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 61029 : 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 183087 : time_function_for_testing_(nullptr) {
77 61029 : if (!tracing_controller_) {
78 61028 : tracing::TracingController* controller = new tracing::TracingController();
79 61028 : controller->Initialize(nullptr);
80 : tracing_controller_.reset(controller);
81 : }
82 61029 : }
83 :
84 231733 : DefaultPlatform::~DefaultPlatform() {
85 57936 : base::MutexGuard guard(&lock_);
86 57936 : if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
87 118254 : for (auto it : foreground_task_runner_map_) {
88 60318 : it.second->Terminate();
89 : }
90 115861 : }
91 :
92 61020 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
93 61020 : base::MutexGuard guard(&lock_);
94 : DCHECK_GE(thread_pool_size, 0);
95 61020 : if (thread_pool_size < 1) {
96 61018 : thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
97 : }
98 : thread_pool_size_ =
99 122040 : std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
100 61020 : }
101 :
102 : namespace {
103 :
104 3859409 : double DefaultTimeFunction() {
105 108561612 : return base::TimeTicks::HighResolutionNow().ToInternalValue() /
106 40051492 : static_cast<double>(base::Time::kMicrosecondsPerSecond);
107 : }
108 :
109 : } // namespace
110 :
111 1687816 : void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
112 1687816 : base::MutexGuard guard(&lock_);
113 1687818 : if (!worker_threads_task_runner_) {
114 : worker_threads_task_runner_ =
115 122038 : std::make_shared<DefaultWorkerThreadsTaskRunner>(
116 61019 : thread_pool_size_, time_function_for_testing_
117 : ? time_function_for_testing_
118 : : DefaultTimeFunction);
119 : }
120 1687818 : }
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 247314 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
131 : MessageLoopBehavior wait_for_work) {
132 : bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
133 247314 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
134 : {
135 247314 : base::MutexGuard guard(&lock_);
136 : auto it = foreground_task_runner_map_.find(isolate);
137 247314 : if (it == foreground_task_runner_map_.end()) return failed_result;
138 : task_runner = it->second;
139 : }
140 :
141 247311 : std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
142 247311 : if (!task) return failed_result;
143 :
144 57627 : task->Run();
145 57627 : return true;
146 : }
147 :
148 162186 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
149 : double idle_time_in_seconds) {
150 : DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
151 162186 : std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
152 : {
153 162186 : base::MutexGuard guard(&lock_);
154 162186 : if (foreground_task_runner_map_.find(isolate) ==
155 : foreground_task_runner_map_.end()) {
156 : return;
157 : }
158 162186 : task_runner = foreground_task_runner_map_[isolate];
159 : }
160 : double deadline_in_seconds =
161 162186 : MonotonicallyIncreasingTime() + idle_time_in_seconds;
162 :
163 165923 : while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
164 165906 : std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
165 165906 : if (!task) return;
166 3737 : task->Run(deadline_in_seconds);
167 : }
168 : }
169 :
170 252704 : std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
171 : v8::Isolate* isolate) {
172 252704 : base::MutexGuard guard(&lock_);
173 252704 : if (foreground_task_runner_map_.find(isolate) ==
174 : foreground_task_runner_map_.end()) {
175 61605 : foreground_task_runner_map_.insert(std::make_pair(
176 123210 : isolate, std::make_shared<DefaultForegroundTaskRunner>(
177 61605 : idle_task_support_, time_function_for_testing_
178 : ? time_function_for_testing_
179 : : DefaultTimeFunction)));
180 : }
181 505408 : return foreground_task_runner_map_[isolate];
182 : }
183 :
184 1626768 : void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
185 1626768 : EnsureBackgroundTaskRunnerInitialized();
186 4880310 : worker_threads_task_runner_->PostTask(std::move(task));
187 1626770 : }
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 168467 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
214 168467 : return idle_task_support_ == IdleTaskSupport::kEnabled;
215 : }
216 :
217 32318041 : double DefaultPlatform::MonotonicallyIncreasingTime() {
218 32318041 : if (time_function_for_testing_) return time_function_for_testing_();
219 32332676 : return DefaultTimeFunction();
220 : }
221 :
222 1204179 : double DefaultPlatform::CurrentClockTimeMillis() {
223 1204179 : return base::OS::TimeCurrentMillis();
224 : }
225 :
226 2428130 : TracingController* DefaultPlatform::GetTracingController() {
227 2428130 : 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 1276232 : int DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
237 :
238 60988 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
239 60988 : return PrintStackTrace;
240 : }
241 :
242 60984 : v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
243 60984 : return page_allocator_.get();
244 : }
245 :
246 : } // namespace platform
247 : } // namespace v8
|