11cb0ef41Sopenharmony_ci// Copyright 2013 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/libplatform/default-platform.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <algorithm>
81cb0ef41Sopenharmony_ci#include <queue>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "include/libplatform/libplatform.h"
111cb0ef41Sopenharmony_ci#include "src/base/bounded-page-allocator.h"
121cb0ef41Sopenharmony_ci#include "src/base/debug/stack_trace.h"
131cb0ef41Sopenharmony_ci#include "src/base/logging.h"
141cb0ef41Sopenharmony_ci#include "src/base/page-allocator.h"
151cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
161cb0ef41Sopenharmony_ci#include "src/base/platform/time.h"
171cb0ef41Sopenharmony_ci#include "src/base/sys-info.h"
181cb0ef41Sopenharmony_ci#include "src/libplatform/default-foreground-task-runner.h"
191cb0ef41Sopenharmony_ci#include "src/libplatform/default-job.h"
201cb0ef41Sopenharmony_ci#include "src/libplatform/default-worker-threads-task-runner.h"
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cinamespace v8 {
231cb0ef41Sopenharmony_cinamespace platform {
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_cinamespace {
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_civoid PrintStackTrace() {
281cb0ef41Sopenharmony_ci  v8::base::debug::StackTrace trace;
291cb0ef41Sopenharmony_ci  trace.Print();
301cb0ef41Sopenharmony_ci  // Avoid dumping duplicate stack trace on abort signal.
311cb0ef41Sopenharmony_ci  v8::base::debug::DisableSignalStackDump();
321cb0ef41Sopenharmony_ci}
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciconstexpr int kMaxThreadPoolSize = 16;
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ciint GetActualThreadPoolSize(int thread_pool_size) {
371cb0ef41Sopenharmony_ci  DCHECK_GE(thread_pool_size, 0);
381cb0ef41Sopenharmony_ci  if (thread_pool_size < 1) {
391cb0ef41Sopenharmony_ci    thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
401cb0ef41Sopenharmony_ci  }
411cb0ef41Sopenharmony_ci  return std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci}  // namespace
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_cistd::unique_ptr<v8::Platform> NewDefaultPlatform(
471cb0ef41Sopenharmony_ci    int thread_pool_size, IdleTaskSupport idle_task_support,
481cb0ef41Sopenharmony_ci    InProcessStackDumping in_process_stack_dumping,
491cb0ef41Sopenharmony_ci    std::unique_ptr<v8::TracingController> tracing_controller) {
501cb0ef41Sopenharmony_ci  if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
511cb0ef41Sopenharmony_ci    v8::base::debug::EnableInProcessStackDumping();
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci  thread_pool_size = GetActualThreadPoolSize(thread_pool_size);
541cb0ef41Sopenharmony_ci  auto platform = std::make_unique<DefaultPlatform>(
551cb0ef41Sopenharmony_ci      thread_pool_size, idle_task_support, std::move(tracing_controller));
561cb0ef41Sopenharmony_ci  return platform;
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_cistd::unique_ptr<v8::Platform> NewSingleThreadedDefaultPlatform(
601cb0ef41Sopenharmony_ci    IdleTaskSupport idle_task_support,
611cb0ef41Sopenharmony_ci    InProcessStackDumping in_process_stack_dumping,
621cb0ef41Sopenharmony_ci    std::unique_ptr<v8::TracingController> tracing_controller) {
631cb0ef41Sopenharmony_ci  if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
641cb0ef41Sopenharmony_ci    v8::base::debug::EnableInProcessStackDumping();
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci  auto platform = std::make_unique<DefaultPlatform>(
671cb0ef41Sopenharmony_ci      0, idle_task_support, std::move(tracing_controller));
681cb0ef41Sopenharmony_ci  return platform;
691cb0ef41Sopenharmony_ci}
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciV8_PLATFORM_EXPORT std::unique_ptr<JobHandle> NewDefaultJobHandle(
721cb0ef41Sopenharmony_ci    Platform* platform, TaskPriority priority,
731cb0ef41Sopenharmony_ci    std::unique_ptr<JobTask> job_task, size_t num_worker_threads) {
741cb0ef41Sopenharmony_ci  return std::make_unique<DefaultJobHandle>(std::make_shared<DefaultJobState>(
751cb0ef41Sopenharmony_ci      platform, std::move(job_task), priority, num_worker_threads));
761cb0ef41Sopenharmony_ci}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_cibool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
791cb0ef41Sopenharmony_ci                     MessageLoopBehavior behavior) {
801cb0ef41Sopenharmony_ci  return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
811cb0ef41Sopenharmony_ci                                                                  behavior);
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_civoid RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
851cb0ef41Sopenharmony_ci                  double idle_time_in_seconds) {
861cb0ef41Sopenharmony_ci  static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
871cb0ef41Sopenharmony_ci                                                        idle_time_in_seconds);
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_civoid NotifyIsolateShutdown(v8::Platform* platform, Isolate* isolate) {
911cb0ef41Sopenharmony_ci  static_cast<DefaultPlatform*>(platform)->NotifyIsolateShutdown(isolate);
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ciDefaultPlatform::DefaultPlatform(
951cb0ef41Sopenharmony_ci    int thread_pool_size, IdleTaskSupport idle_task_support,
961cb0ef41Sopenharmony_ci    std::unique_ptr<v8::TracingController> tracing_controller)
971cb0ef41Sopenharmony_ci    : thread_pool_size_(thread_pool_size),
981cb0ef41Sopenharmony_ci      idle_task_support_(idle_task_support),
991cb0ef41Sopenharmony_ci      tracing_controller_(std::move(tracing_controller)),
1001cb0ef41Sopenharmony_ci      page_allocator_(std::make_unique<v8::base::PageAllocator>()) {
1011cb0ef41Sopenharmony_ci  if (!tracing_controller_) {
1021cb0ef41Sopenharmony_ci    tracing::TracingController* controller = new tracing::TracingController();
1031cb0ef41Sopenharmony_ci#if !defined(V8_USE_PERFETTO)
1041cb0ef41Sopenharmony_ci    controller->Initialize(nullptr);
1051cb0ef41Sopenharmony_ci#endif
1061cb0ef41Sopenharmony_ci    tracing_controller_.reset(controller);
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci  if (thread_pool_size_ > 0) {
1091cb0ef41Sopenharmony_ci    EnsureBackgroundTaskRunnerInitialized();
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci}
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ciDefaultPlatform::~DefaultPlatform() {
1141cb0ef41Sopenharmony_ci  base::MutexGuard guard(&lock_);
1151cb0ef41Sopenharmony_ci  if (worker_threads_task_runner_) worker_threads_task_runner_->Terminate();
1161cb0ef41Sopenharmony_ci  for (const auto& it : foreground_task_runner_map_) {
1171cb0ef41Sopenharmony_ci    it.second->Terminate();
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_cinamespace {
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_cidouble DefaultTimeFunction() {
1241cb0ef41Sopenharmony_ci  return base::TimeTicks::Now().ToInternalValue() /
1251cb0ef41Sopenharmony_ci         static_cast<double>(base::Time::kMicrosecondsPerSecond);
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci}  // namespace
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_civoid DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
1311cb0ef41Sopenharmony_ci  DCHECK_NULL(worker_threads_task_runner_);
1321cb0ef41Sopenharmony_ci  worker_threads_task_runner_ =
1331cb0ef41Sopenharmony_ci      std::make_shared<DefaultWorkerThreadsTaskRunner>(
1341cb0ef41Sopenharmony_ci          thread_pool_size_, time_function_for_testing_
1351cb0ef41Sopenharmony_ci                                 ? time_function_for_testing_
1361cb0ef41Sopenharmony_ci                                 : DefaultTimeFunction);
1371cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(worker_threads_task_runner_);
1381cb0ef41Sopenharmony_ci}
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_civoid DefaultPlatform::SetTimeFunctionForTesting(
1411cb0ef41Sopenharmony_ci    DefaultPlatform::TimeFunction time_function) {
1421cb0ef41Sopenharmony_ci  base::MutexGuard guard(&lock_);
1431cb0ef41Sopenharmony_ci  time_function_for_testing_ = time_function;
1441cb0ef41Sopenharmony_ci  // The time function has to be right after the construction of the platform.
1451cb0ef41Sopenharmony_ci  DCHECK(foreground_task_runner_map_.empty());
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_cibool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
1491cb0ef41Sopenharmony_ci                                      MessageLoopBehavior wait_for_work) {
1501cb0ef41Sopenharmony_ci  bool failed_result = wait_for_work == MessageLoopBehavior::kWaitForWork;
1511cb0ef41Sopenharmony_ci  std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
1521cb0ef41Sopenharmony_ci  {
1531cb0ef41Sopenharmony_ci    base::MutexGuard guard(&lock_);
1541cb0ef41Sopenharmony_ci    auto it = foreground_task_runner_map_.find(isolate);
1551cb0ef41Sopenharmony_ci    if (it == foreground_task_runner_map_.end()) return failed_result;
1561cb0ef41Sopenharmony_ci    task_runner = it->second;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  std::unique_ptr<Task> task = task_runner->PopTaskFromQueue(wait_for_work);
1601cb0ef41Sopenharmony_ci  if (!task) return failed_result;
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  DefaultForegroundTaskRunner::RunTaskScope scope(task_runner);
1631cb0ef41Sopenharmony_ci  task->Run();
1641cb0ef41Sopenharmony_ci  return true;
1651cb0ef41Sopenharmony_ci}
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_civoid DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
1681cb0ef41Sopenharmony_ci                                   double idle_time_in_seconds) {
1691cb0ef41Sopenharmony_ci  DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
1701cb0ef41Sopenharmony_ci  std::shared_ptr<DefaultForegroundTaskRunner> task_runner;
1711cb0ef41Sopenharmony_ci  {
1721cb0ef41Sopenharmony_ci    base::MutexGuard guard(&lock_);
1731cb0ef41Sopenharmony_ci    if (foreground_task_runner_map_.find(isolate) ==
1741cb0ef41Sopenharmony_ci        foreground_task_runner_map_.end()) {
1751cb0ef41Sopenharmony_ci      return;
1761cb0ef41Sopenharmony_ci    }
1771cb0ef41Sopenharmony_ci    task_runner = foreground_task_runner_map_[isolate];
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci  double deadline_in_seconds =
1801cb0ef41Sopenharmony_ci      MonotonicallyIncreasingTime() + idle_time_in_seconds;
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
1831cb0ef41Sopenharmony_ci    std::unique_ptr<IdleTask> task = task_runner->PopTaskFromIdleQueue();
1841cb0ef41Sopenharmony_ci    if (!task) return;
1851cb0ef41Sopenharmony_ci    DefaultForegroundTaskRunner::RunTaskScope scope(task_runner);
1861cb0ef41Sopenharmony_ci    task->Run(deadline_in_seconds);
1871cb0ef41Sopenharmony_ci  }
1881cb0ef41Sopenharmony_ci}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_cistd::shared_ptr<TaskRunner> DefaultPlatform::GetForegroundTaskRunner(
1911cb0ef41Sopenharmony_ci    v8::Isolate* isolate) {
1921cb0ef41Sopenharmony_ci  base::MutexGuard guard(&lock_);
1931cb0ef41Sopenharmony_ci  if (foreground_task_runner_map_.find(isolate) ==
1941cb0ef41Sopenharmony_ci      foreground_task_runner_map_.end()) {
1951cb0ef41Sopenharmony_ci    foreground_task_runner_map_.insert(std::make_pair(
1961cb0ef41Sopenharmony_ci        isolate, std::make_shared<DefaultForegroundTaskRunner>(
1971cb0ef41Sopenharmony_ci                     idle_task_support_, time_function_for_testing_
1981cb0ef41Sopenharmony_ci                                             ? time_function_for_testing_
1991cb0ef41Sopenharmony_ci                                             : DefaultTimeFunction)));
2001cb0ef41Sopenharmony_ci  }
2011cb0ef41Sopenharmony_ci  return foreground_task_runner_map_[isolate];
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_civoid DefaultPlatform::CallOnWorkerThread(std::unique_ptr<Task> task) {
2051cb0ef41Sopenharmony_ci  // If this DCHECK fires, then this means that either
2061cb0ef41Sopenharmony_ci  // - V8 is running without the --single-threaded flag but
2071cb0ef41Sopenharmony_ci  //   but the platform was created as a single-threaded platform.
2081cb0ef41Sopenharmony_ci  // - or some component in V8 is ignoring --single-threaded
2091cb0ef41Sopenharmony_ci  //   and posting a background task.
2101cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(worker_threads_task_runner_);
2111cb0ef41Sopenharmony_ci  worker_threads_task_runner_->PostTask(std::move(task));
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_civoid DefaultPlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
2151cb0ef41Sopenharmony_ci                                                double delay_in_seconds) {
2161cb0ef41Sopenharmony_ci  // If this DCHECK fires, then this means that either
2171cb0ef41Sopenharmony_ci  // - V8 is running without the --single-threaded flag but
2181cb0ef41Sopenharmony_ci  //   but the platform was created as a single-threaded platform.
2191cb0ef41Sopenharmony_ci  // - or some component in V8 is ignoring --single-threaded
2201cb0ef41Sopenharmony_ci  //   and posting a background task.
2211cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(worker_threads_task_runner_);
2221cb0ef41Sopenharmony_ci  worker_threads_task_runner_->PostDelayedTask(std::move(task),
2231cb0ef41Sopenharmony_ci                                               delay_in_seconds);
2241cb0ef41Sopenharmony_ci}
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_cibool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
2271cb0ef41Sopenharmony_ci  return idle_task_support_ == IdleTaskSupport::kEnabled;
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_cistd::unique_ptr<JobHandle> DefaultPlatform::PostJob(
2311cb0ef41Sopenharmony_ci    TaskPriority priority, std::unique_ptr<JobTask> job_task) {
2321cb0ef41Sopenharmony_ci  size_t num_worker_threads = NumberOfWorkerThreads();
2331cb0ef41Sopenharmony_ci  if (priority == TaskPriority::kBestEffort && num_worker_threads > 2) {
2341cb0ef41Sopenharmony_ci    num_worker_threads = 2;
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci  return NewDefaultJobHandle(this, priority, std::move(job_task),
2371cb0ef41Sopenharmony_ci                             num_worker_threads);
2381cb0ef41Sopenharmony_ci}
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_cidouble DefaultPlatform::MonotonicallyIncreasingTime() {
2411cb0ef41Sopenharmony_ci  if (time_function_for_testing_) return time_function_for_testing_();
2421cb0ef41Sopenharmony_ci  return DefaultTimeFunction();
2431cb0ef41Sopenharmony_ci}
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_cidouble DefaultPlatform::CurrentClockTimeMillis() {
2461cb0ef41Sopenharmony_ci  return base::OS::TimeCurrentMillis();
2471cb0ef41Sopenharmony_ci}
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ciTracingController* DefaultPlatform::GetTracingController() {
2501cb0ef41Sopenharmony_ci  return tracing_controller_.get();
2511cb0ef41Sopenharmony_ci}
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_civoid DefaultPlatform::SetTracingController(
2541cb0ef41Sopenharmony_ci    std::unique_ptr<v8::TracingController> tracing_controller) {
2551cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(tracing_controller.get());
2561cb0ef41Sopenharmony_ci  tracing_controller_ = std::move(tracing_controller);
2571cb0ef41Sopenharmony_ci}
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ciint DefaultPlatform::NumberOfWorkerThreads() { return thread_pool_size_; }
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ciPlatform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
2621cb0ef41Sopenharmony_ci  return PrintStackTrace;
2631cb0ef41Sopenharmony_ci}
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_civ8::PageAllocator* DefaultPlatform::GetPageAllocator() {
2661cb0ef41Sopenharmony_ci  return page_allocator_.get();
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_civoid DefaultPlatform::NotifyIsolateShutdown(Isolate* isolate) {
2701cb0ef41Sopenharmony_ci  base::MutexGuard guard(&lock_);
2711cb0ef41Sopenharmony_ci  auto it = foreground_task_runner_map_.find(isolate);
2721cb0ef41Sopenharmony_ci  if (it != foreground_task_runner_map_.end()) {
2731cb0ef41Sopenharmony_ci    it->second->Terminate();
2741cb0ef41Sopenharmony_ci    foreground_task_runner_map_.erase(it);
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci}
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci}  // namespace platform
2791cb0ef41Sopenharmony_ci}  // namespace v8
280