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