LCOV - code coverage report
Current view: top level - src/libplatform - default-platform.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 131 138 94.9 %
Date: 2017-10-20 Functions: 28 30 93.3 %

          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/platform/platform.h"
      14             : #include "src/base/platform/time.h"
      15             : #include "src/base/sys-info.h"
      16             : #include "src/libplatform/worker-thread.h"
      17             : 
      18             : namespace v8 {
      19             : namespace platform {
      20             : 
      21             : namespace {
      22             : 
      23           0 : void PrintStackTrace() {
      24           0 :   v8::base::debug::StackTrace trace;
      25           0 :   trace.Print();
      26             :   // Avoid dumping duplicate stack trace on abort signal.
      27           0 :   v8::base::debug::DisableSignalStackDump();
      28           0 : }
      29             : 
      30             : }  // namespace
      31             : 
      32       54006 : v8::Platform* CreateDefaultPlatform(
      33             :     int thread_pool_size, IdleTaskSupport idle_task_support,
      34             :     InProcessStackDumping in_process_stack_dumping,
      35             :     v8::TracingController* tracing_controller) {
      36       54006 :   if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
      37       54006 :     v8::base::debug::EnableInProcessStackDumping();
      38             :   }
      39             :   DefaultPlatform* platform =
      40       54006 :       new DefaultPlatform(idle_task_support, tracing_controller);
      41       54006 :   platform->SetThreadPoolSize(thread_pool_size);
      42       54006 :   platform->EnsureInitialized();
      43       54006 :   return platform;
      44             : }
      45             : 
      46      223299 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate,
      47             :                      MessageLoopBehavior behavior) {
      48             :   return static_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate,
      49      223299 :                                                                   behavior);
      50             : }
      51             : 
      52       44529 : void EnsureEventLoopInitialized(v8::Platform* platform, v8::Isolate* isolate) {
      53             :   return static_cast<DefaultPlatform*>(platform)->EnsureEventLoopInitialized(
      54       44529 :       isolate);
      55             : }
      56             : 
      57      148243 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
      58             :                   double idle_time_in_seconds) {
      59             :   static_cast<DefaultPlatform*>(platform)->RunIdleTasks(isolate,
      60      148243 :                                                         idle_time_in_seconds);
      61      148243 : }
      62             : 
      63           0 : void SetTracingController(
      64             :     v8::Platform* platform,
      65             :     v8::platform::tracing::TracingController* tracing_controller) {
      66             :   static_cast<DefaultPlatform*>(platform)->SetTracingController(
      67             :       tracing_controller);
      68           0 : }
      69             : 
      70             : const int DefaultPlatform::kMaxThreadPoolSize = 8;
      71             : 
      72       54012 : DefaultPlatform::DefaultPlatform(IdleTaskSupport idle_task_support,
      73             :                                  v8::TracingController* tracing_controller)
      74             :     : initialized_(false),
      75             :       thread_pool_size_(0),
      76      162036 :       idle_task_support_(idle_task_support) {
      77       54012 :   if (tracing_controller) {
      78             :     tracing_controller_.reset(tracing_controller);
      79             :   } else {
      80       54012 :     tracing::TracingController* controller = new tracing::TracingController();
      81       54012 :     controller->Initialize(nullptr);
      82             :     tracing_controller_.reset(controller);
      83             :   }
      84       54012 : }
      85             : 
      86      212622 : DefaultPlatform::~DefaultPlatform() {
      87       53157 :   base::LockGuard<base::Mutex> guard(&lock_);
      88       53157 :   queue_.Terminate();
      89       53157 :   if (initialized_) {
      90      478359 :     for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
      91      372057 :       delete *i;
      92             :     }
      93             :   }
      94      115288 :   for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
      95             :        ++i) {
      96        9186 :     while (!i->second.empty()) {
      97         212 :       delete i->second.front();
      98             :       i->second.pop();
      99             :     }
     100             :   }
     101      106712 :   for (auto i = main_thread_delayed_queue_.begin();
     102             :        i != main_thread_delayed_queue_.end(); ++i) {
     103         794 :     while (!i->second.empty()) {
     104         396 :       delete i->second.top().second;
     105         396 :       i->second.pop();
     106             :     }
     107             :   }
     108      108910 :   for (auto& i : main_thread_idle_queue_) {
     109        2599 :     while (!i.second.empty()) {
     110           3 :       delete i.second.front();
     111             :       i.second.pop();
     112             :     }
     113             :   }
     114      106308 : }
     115             : 
     116             : 
     117       54006 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
     118       54006 :   base::LockGuard<base::Mutex> guard(&lock_);
     119             :   DCHECK_GE(thread_pool_size, 0);
     120       54006 :   if (thread_pool_size < 1) {
     121       54006 :     thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
     122             :   }
     123             :   thread_pool_size_ =
     124      108012 :       std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
     125       54006 : }
     126             : 
     127             : 
     128      861517 : void DefaultPlatform::EnsureInitialized() {
     129      861517 :   base::LockGuard<base::Mutex> guard(&lock_);
     130     1723036 :   if (initialized_) return;
     131       54006 :   initialized_ = true;
     132             : 
     133      432048 :   for (int i = 0; i < thread_pool_size_; ++i)
     134      756084 :     thread_pool_.push_back(new WorkerThread(&queue_));
     135             : }
     136             : 
     137             : 
     138      223311 : Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
     139             :   auto it = main_thread_queue_.find(isolate);
     140      294753 :   if (it == main_thread_queue_.end() || it->second.empty()) {
     141             :     return nullptr;
     142             :   }
     143       50275 :   Task* task = it->second.front();
     144             :   it->second.pop();
     145       50275 :   return task;
     146             : }
     147             : 
     148             : 
     149      223323 : Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
     150             :   auto it = main_thread_delayed_queue_.find(isolate);
     151      227845 :   if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
     152             :     return nullptr;
     153             :   }
     154        4503 :   double now = MonotonicallyIncreasingTime();
     155        4503 :   std::pair<double, Task*> deadline_and_task = it->second.top();
     156        4503 :   if (deadline_and_task.first > now) {
     157             :     return nullptr;
     158             :   }
     159          12 :   it->second.pop();
     160          12 :   return deadline_and_task.second;
     161             : }
     162             : 
     163      153811 : IdleTask* DefaultPlatform::PopTaskInMainThreadIdleQueue(v8::Isolate* isolate) {
     164             :   auto it = main_thread_idle_queue_.find(isolate);
     165      175997 :   if (it == main_thread_idle_queue_.end() || it->second.empty()) {
     166             :     return nullptr;
     167             :   }
     168        5590 :   IdleTask* task = it->second.front();
     169             :   it->second.pop();
     170        5590 :   return task;
     171             : }
     172             : 
     173       44529 : void DefaultPlatform::EnsureEventLoopInitialized(v8::Isolate* isolate) {
     174       44529 :   base::LockGuard<base::Mutex> guard(&lock_);
     175       44529 :   if (event_loop_control_.count(isolate) == 0) {
     176             :     event_loop_control_.insert(std::make_pair(
     177       53650 :         isolate, std::unique_ptr<base::Semaphore>(new base::Semaphore(0))));
     178             :   }
     179       44529 : }
     180             : 
     181         193 : void DefaultPlatform::WaitForForegroundWork(v8::Isolate* isolate) {
     182             :   base::Semaphore* semaphore = nullptr;
     183             :   {
     184         193 :     base::LockGuard<base::Mutex> guard(&lock_);
     185             :     DCHECK_EQ(event_loop_control_.count(isolate), 1);
     186         193 :     semaphore = event_loop_control_[isolate].get();
     187             :   }
     188             :   DCHECK_NOT_NULL(semaphore);
     189         193 :   semaphore->Wait();
     190         193 : }
     191             : 
     192      223311 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate,
     193             :                                       MessageLoopBehavior behavior) {
     194      223311 :   if (behavior == MessageLoopBehavior::kWaitForWork) {
     195         193 :     WaitForForegroundWork(isolate);
     196             :   }
     197             :   Task* task = nullptr;
     198             :   {
     199      223311 :     base::LockGuard<base::Mutex> guard(&lock_);
     200             : 
     201             :     // Move delayed tasks that hit their deadline to the main queue.
     202      223311 :     task = PopTaskInMainThreadDelayedQueue(isolate);
     203      446634 :     while (task != nullptr) {
     204          12 :       ScheduleOnForegroundThread(isolate, task);
     205          12 :       task = PopTaskInMainThreadDelayedQueue(isolate);
     206             :     }
     207             : 
     208      223311 :     task = PopTaskInMainThreadQueue(isolate);
     209             : 
     210      223311 :     if (task == nullptr) {
     211             :       return behavior == MessageLoopBehavior::kWaitForWork;
     212             :     }
     213             :   }
     214       50275 :   task->Run();
     215       50275 :   delete task;
     216             :   return true;
     217             : }
     218             : 
     219      148244 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
     220             :                                    double idle_time_in_seconds) {
     221             :   DCHECK_EQ(IdleTaskSupport::kEnabled, idle_task_support_);
     222             :   double deadline_in_seconds =
     223      148244 :       MonotonicallyIncreasingTime() + idle_time_in_seconds;
     224      302078 :   while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
     225             :     {
     226             :       IdleTask* task;
     227             :       {
     228      153811 :         base::LockGuard<base::Mutex> guard(&lock_);
     229      153811 :         task = PopTaskInMainThreadIdleQueue(isolate);
     230             :       }
     231      302055 :       if (task == nullptr) return;
     232        5590 :       task->Run(deadline_in_seconds);
     233        5590 :       delete task;
     234             :     }
     235             :   }
     236             : }
     237             : 
     238      807511 : void DefaultPlatform::CallOnBackgroundThread(Task* task,
     239             :                                              ExpectedRuntime expected_runtime) {
     240      807511 :   EnsureInitialized();
     241      807512 :   queue_.Append(task);
     242      807512 : }
     243             : 
     244       50814 : void DefaultPlatform::ScheduleOnForegroundThread(v8::Isolate* isolate,
     245             :                                                  Task* task) {
     246       50814 :   main_thread_queue_[isolate].push(task);
     247       50814 :   if (event_loop_control_.count(isolate) != 0) {
     248       70216 :     event_loop_control_[isolate]->Signal();
     249             :   }
     250       50814 : }
     251             : 
     252       50802 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
     253       50802 :   base::LockGuard<base::Mutex> guard(&lock_);
     254       50802 :   ScheduleOnForegroundThread(isolate, task);
     255       50802 : }
     256             : 
     257             : 
     258         409 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
     259             :                                                     Task* task,
     260             :                                                     double delay_in_seconds) {
     261         409 :   base::LockGuard<base::Mutex> guard(&lock_);
     262         409 :   double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
     263         409 :   main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
     264         409 : }
     265             : 
     266        5593 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
     267             :                                                  IdleTask* task) {
     268        5593 :   base::LockGuard<base::Mutex> guard(&lock_);
     269        5593 :   main_thread_idle_queue_[isolate].push(task);
     270        5593 : }
     271             : 
     272      158101 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
     273      158101 :   return idle_task_support_ == IdleTaskSupport::kEnabled;
     274             : }
     275             : 
     276     7748983 : double DefaultPlatform::MonotonicallyIncreasingTime() {
     277    23248269 :   return base::TimeTicks::HighResolutionNow().ToInternalValue() /
     278    15499286 :          static_cast<double>(base::Time::kMicrosecondsPerSecond);
     279             : }
     280             : 
     281      184368 : double DefaultPlatform::CurrentClockTimeMillis() {
     282      184368 :   return base::OS::TimeCurrentMillis();
     283             : }
     284             : 
     285     1594309 : TracingController* DefaultPlatform::GetTracingController() {
     286     1594309 :   return tracing_controller_.get();
     287             : }
     288             : 
     289          29 : void DefaultPlatform::SetTracingController(
     290             :     v8::TracingController* tracing_controller) {
     291             :   DCHECK_NOT_NULL(tracing_controller);
     292             :   tracing_controller_.reset(tracing_controller);
     293          29 : }
     294             : 
     295      418911 : size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() {
     296      418911 :   return static_cast<size_t>(thread_pool_size_);
     297             : }
     298             : 
     299       53977 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
     300       53977 :   return PrintStackTrace;
     301             : }
     302             : 
     303             : }  // namespace platform
     304             : }  // namespace v8

Generated by: LCOV version 1.10