V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
default-platform.cc
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 void PrintStackTrace() {
27  trace.Print();
28  // Avoid dumping duplicate stack trace on abort signal.
29  v8::base::debug::DisableSignalStackDump();
30 }
31 
32 } // namespace
33 
34 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  if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
39  v8::base::debug::EnableInProcessStackDumping();
40  }
41  std::unique_ptr<DefaultPlatform> platform(
42  new DefaultPlatform(idle_task_support, std::move(tracing_controller)));
43  platform->SetThreadPoolSize(thread_pool_size);
44  platform->EnsureBackgroundTaskRunnerInitialized();
45  return std::move(platform);
46 }
47 
48 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  .release();
56 }
57 
58 bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
59  MessageLoopBehavior behavior) {
60  return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
61  behavior);
62 }
63 
64 void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
65  double idle_time_in_seconds) {
66  static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
67  idle_time_in_seconds);
68 }
69 
70 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 }
76 
77 const int DefaultPlatform::kMaxThreadPoolSize = 8;
78 
79 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  time_function_for_testing_(nullptr) {
87  if (!tracing_controller_) {
88  tracing::TracingController* controller = new tracing::TracingController();
89  controller->Initialize(nullptr);
90  tracing_controller_.reset(controller);
91  }
92 }
93 
94 DefaultPlatform::~DefaultPlatform() {
95  base::MutexGuard guard(&lock_);
96  if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
97  for (auto it : foreground_task_runner_map_) {
98  it.second->Terminate();
99  }
100 }
101 
102 void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
103  base::MutexGuard guard(&lock_);
104  DCHECK_GE(thread_pool_size, 0);
105  if (thread_pool_size < 1) {
106  thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
107  }
108  thread_pool_size_ =
109  std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
110 }
111 
112 void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
113  base::MutexGuard guard(&lock_);
114  if (!worker_threads_task_runner_) {
115  worker_threads_task_runner_ =
116  std::make_shared<DefaultWorkerThreadsTaskRunner>(thread_pool_size_);
117  }
118 }
119 
120 namespace {
121 
122 double DefaultTimeFunction() {
123  return base::TimeTicks::HighResolutionNow().ToInternalValue() /
124  static_cast<double>(base::Time::kMicrosecondsPerSecond);
125 }
126 
127 } // namespace
128 
129 void DefaultPlatform::SetTimeFunctionForTesting(
130  DefaultPlatform::TimeFunction time_function) {
131  base::MutexGuard guard(&lock_);
132  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 }
136 
137 bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
138  MessageLoopBehavior wait_for_work) {
139  bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
140  std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
141  {
142  base::MutexGuard guard(&lock_);
143  auto it = foreground_task_runner_map_.find(isolate);
144  if (it == foreground_task_runner_map_.end()) return failed_result;
145  task_runner = it->second;
146  }
147 
148  std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
149  if (!task) return failed_result;
150 
151  task->Run();
152  return true;
153 }
154 
155 void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
156  double idle_time_in_seconds) {
157  DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
158  std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
159  {
160  base::MutexGuard guard(&lock_);
161  if (foreground_task_runner_map_.find(isolate) ==
162  foreground_task_runner_map_.end()) {
163  return;
164  }
165  task_runner = foreground_task_runner_map_[isolate];
166  }
167  double deadline_in_seconds =
168  MonotonicallyIncreasingTime() + idle_time_in_seconds;
169 
170  while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
171  std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
172  if (!task) return;
173  task->Run(deadline_in_seconds);
174  }
175 }
176 
177 std::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
178  v8::Isolate* isolate) {
179  base::MutexGuard guard(&lock_);
180  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  : DefaultTimeFunction)));
187  }
188  return foreground_task_runner_map_[isolate];
189 }
190 
191 void DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
192  EnsureBackgroundTaskRunnerInitialized();
193  worker_threads_task_runner_->PostTask(std::move(task));
194 }
195 
196 void DefaultPlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
197  double delay_in_seconds) {
198  EnsureBackgroundTaskRunnerInitialized();
199  worker_threads_task_runner_->PostDelayedTask(std::move(task),
200  delay_in_seconds);
201 }
202 
203 void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
204  GetForegroundTaskRunner(isolate)->PostTask(std::unique_ptr<Task>(task));
205 }
206 
207 void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
208  Task* task,
209  double delay_in_seconds) {
210  GetForegroundTaskRunner(isolate)->PostDelayedTask(std::unique_ptr<Task>(task),
211  delay_in_seconds);
212 }
213 
214 void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
215  IdleTask* task) {
216  GetForegroundTaskRunner(isolate)->PostIdleTask(
217  std::unique_ptr<IdleTask>(task));
218 }
219 
220 bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
221  return idle_task_support_ == IdleTaskSupport::kEnabled;
222 }
223 
224 double DefaultPlatform::MonotonicallyIncreasingTime() {
225  if (time_function_for_testing_) return time_function_for_testing_();
226  return DefaultTimeFunction();
227 }
228 
229 double DefaultPlatform::CurrentClockTimeMillis() {
230  return base::OS::TimeCurrentMillis();
231 }
232 
233 TracingController* DefaultPlatform::GetTracingController() {
234  return tracing_controller_.get();
235 }
236 
237 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 }
242 
243 int DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
244 
245 Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
246  return PrintStackTrace;
247 }
248 
249 v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
250  return page_allocator_.get();
251 }
252 
253 } // namespace platform
254 } // namespace v8
STL namespace.
Definition: libplatform.h:13