v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
default-platform.cc
Go to the documentation of this file.
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
6
7#include <algorithm>
8#include <queue>
9
12#include "src/base/logging.h"
16#include "src/base/sys-info.h"
20
21namespace v8 {
22namespace platform {
23
24namespace {
25
26void PrintStackTrace() {
28 trace.Print();
29 // Avoid dumping duplicate stack trace on abort signal.
31}
32
33constexpr int kMaxThreadPoolSize = 16;
34
35int GetActualThreadPoolSize(int thread_pool_size) {
36 DCHECK_GE(thread_pool_size, 0);
37 if (thread_pool_size < 1) {
38 thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
39 }
40 return std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
41}
42
43} // namespace
44
45std::unique_ptr<v8::Platform> NewDefaultPlatform(
46 int thread_pool_size, IdleTaskSupport idle_task_support,
47 InProcessStackDumping in_process_stack_dumping,
48 std::unique_ptr<v8::TracingController> tracing_controller,
49 PriorityMode priority_mode) {
50 if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
52 }
53 thread_pool_size = GetActualThreadPoolSize(thread_pool_size);
54 auto platform = std::make_unique<DefaultPlatform>(
55 thread_pool_size, idle_task_support, std::move(tracing_controller),
56 priority_mode);
57 return platform;
58}
59
60std::unique_ptr<v8::Platform> NewSingleThreadedDefaultPlatform(
61 IdleTaskSupport idle_task_support,
62 InProcessStackDumping in_process_stack_dumping,
63 std::unique_ptr<v8::TracingController> tracing_controller) {
64 if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
66 }
67 auto platform = std::make_unique<DefaultPlatform>(
68 0, idle_task_support, std::move(tracing_controller));
69 return platform;
70}
71
72V8_PLATFORM_EXPORT std::unique_ptr<JobHandle> NewDefaultJobHandle(
74 std::unique_ptr<JobTask> job_task, size_t num_worker_threads) {
75 return std::make_unique<DefaultJobHandle>(std::make_shared<DefaultJobState>(
76 platform, std::move(job_task), priority, num_worker_threads));
77}
78
79bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
80 MessageLoopBehavior behavior) {
81 return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
82 behavior);
83}
84
85void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
86 double idle_time_in_seconds) {
87 static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
88 idle_time_in_seconds);
89}
90
91void NotifyIsolateShutdown(v8::Platform* platform, Isolate* isolate) {
92 static_cast<DefaultPlatform*>(platform)->NotifyIsolateShutdown(isolate);
93}
94
96 int thread_pool_size, IdleTaskSupport idle_task_support,
97 std::unique_ptr<v8::TracingController> tracing_controller,
98 PriorityMode priority_mode)
99 : thread_pool_size_(thread_pool_size),
100 idle_task_support_(idle_task_support),
101 tracing_controller_(std::move(tracing_controller)),
102 page_allocator_(std::make_unique<v8::base::PageAllocator>()),
103 priority_mode_(priority_mode) {
104 if (!tracing_controller_) {
106#if !defined(V8_USE_PERFETTO)
107 controller->Initialize(nullptr);
108#endif
109 tracing_controller_.reset(controller);
110 }
111 if (thread_pool_size_ > 0) {
113 }
114}
115
117 base::MutexGuard guard(&lock_);
119 for (int i = 0; i < num_worker_runners(); i++) {
120 worker_threads_task_runners_[i]->Terminate();
121 }
122 }
123 for (const auto& it : foreground_task_runner_map_) {
124 it.second->Terminate();
125 }
126}
127
128namespace {
129
130double DefaultTimeFunction() {
132 static_cast<double>(base::Time::kMicrosecondsPerSecond);
133}
134
135} // namespace
136
139 for (int i = 0; i < num_worker_runners(); i++) {
141 std::make_shared<DefaultWorkerThreadsTaskRunner>(
144 : DefaultTimeFunction,
146 }
148}
149
151 DefaultPlatform::TimeFunction time_function) {
152 base::MutexGuard guard(&lock_);
153 time_function_for_testing_ = time_function;
154 // The time function has to be right after the construction of the platform.
156}
157
159 MessageLoopBehavior wait_for_work) {
160 bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
161 std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
162 {
163 base::MutexGuard guard(&lock_);
164 auto it = foreground_task_runner_map_.find(isolate);
165 if (it == foreground_task_runner_map_.end()) return failed_result;
166 task_runner = it->second;
167 }
168
169 std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
170 if (!task) return failed_result;
171
173 task->Run();
174 return true;
175}
176
178 double idle_time_in_seconds) {
180 std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
181 {
182 base::MutexGuard guard(&lock_);
183 if (foreground_task_runner_map_.find(isolate) ==
185 return;
186 }
188 }
189 double deadline_in_seconds =
190 MonotonicallyIncreasingTime() + idle_time_in_seconds;
191
192 while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
193 std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
194 if (!task) return;
196 task->Run(deadline_in_seconds);
197 }
198}
199
202 base::MutexGuard guard(&lock_);
203 if (foreground_task_runner_map_.find(isolate) ==
205 foreground_task_runner_map_.insert(std::make_pair(
206 isolate, std::make_shared<DefaultForegroundTaskRunner>(
209 : DefaultTimeFunction)));
210 }
212}
213
215 TaskPriority priority, std::unique_ptr<Task> task,
216 const SourceLocation& location) {
217 // If this DCHECK fires, then this means that either
218 // - V8 is running without the --single-threaded flag but the platform was
219 // created as a single-threaded platform or
220 // - some component in V8 is ignoring --single-threaded and posting a
221 // background task.
222 int index = priority_to_index(priority);
224 worker_threads_task_runners_[index]->PostTask(std::move(task));
225}
226
228 TaskPriority priority, std::unique_ptr<Task> task, double delay_in_seconds,
229 const SourceLocation& location) {
230 // If this DCHECK fires, then this means that either
231 // - V8 is running without the --single-threaded flag but
232 // but the platform was created as a single-threaded platform.
233 // - or some component in V8 is ignoring --single-threaded
234 // and posting a background task.
235 int index = priority_to_index(priority);
237 worker_threads_task_runners_[index]->PostDelayedTask(std::move(task),
238 delay_in_seconds);
239}
240
244
245std::unique_ptr<JobHandle> DefaultPlatform::CreateJobImpl(
246 TaskPriority priority, std::unique_ptr<JobTask> job_task,
247 const SourceLocation& location) {
248 size_t num_worker_threads = NumberOfWorkerThreads();
249 if (priority == TaskPriority::kBestEffort && num_worker_threads > 2) {
250 num_worker_threads = 2;
251 }
252 return NewDefaultJobHandle(this, priority, std::move(job_task),
253 num_worker_threads);
254}
255
258 return DefaultTimeFunction();
259}
260
264
268
270 std::unique_ptr<v8::TracingController> tracing_controller) {
271 DCHECK_NOT_NULL(tracing_controller.get());
272 tracing_controller_ = std::move(tracing_controller);
273}
274
276
280
284
291
293 std::shared_ptr<DefaultForegroundTaskRunner> taskrunner;
294 {
295 base::MutexGuard guard(&lock_);
296 auto it = foreground_task_runner_map_.find(isolate);
297 if (it != foreground_task_runner_map_.end()) {
298 taskrunner = it->second;
300 }
301 }
302 taskrunner->Terminate();
303}
304
305} // namespace platform
306} // namespace v8
void(*) StackTracePrinter()
static double TimeCurrentMillis()
static int NumberOfProcessors()
Definition sys-info.cc:37
static constexpr int64_t kMicrosecondsPerSecond
Definition time.h:49
static TimeTicks Now()
Definition time.cc:736
int64_t ToInternalValue() const
Definition time.h:287
bool IdleTasksEnabled(Isolate *isolate) override
void NotifyIsolateShutdown(Isolate *isolate)
void PostTaskOnWorkerThreadImpl(TaskPriority priority, std::unique_ptr< Task > task, const SourceLocation &location) override
DefaultThreadIsolatedAllocator thread_isolated_allocator_
double MonotonicallyIncreasingTime() override
DefaultPlatform(int thread_pool_size=0, IdleTaskSupport idle_task_support=IdleTaskSupport::kDisabled, std::unique_ptr< v8::TracingController > tracing_controller={}, PriorityMode priority_mode=PriorityMode::kDontApply)
v8::ThreadIsolatedAllocator * GetThreadIsolatedAllocator() override
void RunIdleTasks(v8::Isolate *isolate, double idle_time_in_seconds)
v8::TracingController * GetTracingController() override
std::unique_ptr< PageAllocator > page_allocator_
std::unique_ptr< TracingController > tracing_controller_
base::Thread::Priority priority_from_index(int i) const
void PostDelayedTaskOnWorkerThreadImpl(TaskPriority priority, std::unique_ptr< Task > task, double delay_in_seconds, const SourceLocation &location) override
std::unique_ptr< JobHandle > CreateJobImpl(TaskPriority priority, std::unique_ptr< JobTask > job_state, const SourceLocation &location) override
void SetTimeFunctionForTesting(TimeFunction time_function)
std::shared_ptr< DefaultWorkerThreadsTaskRunner > worker_threads_task_runners_[static_cast< int >(TaskPriority::kMaxPriority)+1]
v8::PageAllocator * GetPageAllocator() override
void SetTracingController(std::unique_ptr< v8::TracingController > tracing_controller)
int priority_to_index(TaskPriority priority) const
std::shared_ptr< TaskRunner > GetForegroundTaskRunner(v8::Isolate *isolate, TaskPriority priority) override
double CurrentClockTimeMillis() override
bool PumpMessageLoop(v8::Isolate *isolate, MessageLoopBehavior behavior=MessageLoopBehavior::kDoNotWait)
StackTracePrinter GetStackTracePrinter() override
std::map< v8::Isolate *, std::shared_ptr< DefaultForegroundTaskRunner > > foreground_task_runner_map_
void Initialize(TraceBuffer *trace_buffer)
cppgc::PageAllocator * page_allocator_
Definition cpp-heap.cc:194
Isolate * isolate
OptionalOpIndex index
#define V8_PLATFORM_EXPORT
size_t priority
STL namespace.
V8_BASE_EXPORT bool EnableInProcessStackDumping()
V8_BASE_EXPORT void DisableSignalStackDump()
std::unique_ptr< v8::Platform > NewSingleThreadedDefaultPlatform(IdleTaskSupport idle_task_support, InProcessStackDumping in_process_stack_dumping, std::unique_ptr< v8::TracingController > tracing_controller)
void RunIdleTasks(v8::Platform *platform, v8::Isolate *isolate, double idle_time_in_seconds)
V8_PLATFORM_EXPORT std::unique_ptr< JobHandle > NewDefaultJobHandle(Platform *platform, TaskPriority priority, std::unique_ptr< JobTask > job_task, size_t num_worker_threads)
void NotifyIsolateShutdown(v8::Platform *platform, Isolate *isolate)
std::unique_ptr< v8::Platform > NewDefaultPlatform(int thread_pool_size, IdleTaskSupport idle_task_support, InProcessStackDumping in_process_stack_dumping, std::unique_ptr< v8::TracingController > tracing_controller, PriorityMode priority_mode)
bool PumpMessageLoop(v8::Platform *platform, v8::Isolate *isolate, MessageLoopBehavior behavior)
TaskPriority
Definition v8-platform.h:24
#define DCHECK_NULL(val)
Definition logging.h:491
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485