LCOV - code coverage report
Current view: top level - src/libplatform - default-platform.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 117 131 89.3 %
Date: 2017-04-26 Functions: 26 30 86.7 %

          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       59495 : v8::Platform* CreateDefaultPlatform(int thread_pool_size,
      33             :                                     IdleTaskSupport idle_task_support) {
      34       59495 :   v8::base::debug::EnableInProcessStackDumping();
      35       59495 :   DefaultPlatform* platform = new DefaultPlatform(idle_task_support);
      36       59495 :   platform->SetThreadPoolSize(thread_pool_size);
      37       59495 :   platform->EnsureInitialized();
      38       59495 :   return platform;
      39             : }
      40             : 
      41             : 
      42      184043 : bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
      43      184043 :   return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
      44             : }
      45             : 
      46      146141 : void RunIdleTasks(v8::Platform* platform, v8::Isolate* isolate,
      47             :                   double idle_time_in_seconds) {
      48             :   reinterpret_cast<DefaultPlatform*>(platform)->RunIdleTasks(
      49      146141 :       isolate, idle_time_in_seconds);
      50      146141 : }
      51             : 
      52          34 : void SetTracingController(
      53             :     v8::Platform* platform,
      54             :     v8::platform::tracing::TracingController* tracing_controller) {
      55             :   return reinterpret_cast<DefaultPlatform*>(platform)->SetTracingController(
      56          34 :       tracing_controller);
      57             : }
      58             : 
      59             : const int DefaultPlatform::kMaxThreadPoolSize = 8;
      60             : 
      61       59501 : DefaultPlatform::DefaultPlatform(IdleTaskSupport idle_task_support)
      62             :     : initialized_(false),
      63             :       thread_pool_size_(0),
      64      178503 :       idle_task_support_(idle_task_support) {}
      65             : 
      66      234994 : DefaultPlatform::~DefaultPlatform() {
      67       58750 :   if (tracing_controller_) {
      68           0 :     tracing_controller_->StopTracing();
      69             :     tracing_controller_.reset();
      70             :   }
      71             : 
      72       58750 :   base::LockGuard<base::Mutex> guard(&lock_);
      73       58750 :   queue_.Terminate();
      74       58750 :   if (initialized_) {
      75      528696 :     for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
      76      411208 :       delete *i;
      77             :     }
      78             :   }
      79      118291 :   for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
      80             :        ++i) {
      81         823 :     while (!i->second.empty()) {
      82          32 :       delete i->second.front();
      83             :       i->second.pop();
      84             :     }
      85             :   }
      86      117762 :   for (auto i = main_thread_delayed_queue_.begin();
      87             :        i != main_thread_delayed_queue_.end(); ++i) {
      88         522 :     while (!i->second.empty()) {
      89         260 :       delete i->second.top().second;
      90         260 :       i->second.pop();
      91             :     }
      92             :   }
      93      120953 :   for (auto& i : main_thread_idle_queue_) {
      94        3497 :     while (!i.second.empty()) {
      95          44 :       delete i.second.front();
      96             :       i.second.pop();
      97             :     }
      98             :   }
      99      117494 : }
     100             : 
     101             : 
     102       59495 : void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
     103       59495 :   base::LockGuard<base::Mutex> guard(&lock_);
     104             :   DCHECK(thread_pool_size >= 0);
     105       59495 :   if (thread_pool_size < 1) {
     106       59495 :     thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
     107             :   }
     108             :   thread_pool_size_ =
     109      118990 :       std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
     110       59495 : }
     111             : 
     112             : 
     113      692894 : void DefaultPlatform::EnsureInitialized() {
     114      692894 :   base::LockGuard<base::Mutex> guard(&lock_);
     115     1385788 :   if (initialized_) return;
     116       59495 :   initialized_ = true;
     117             : 
     118      475960 :   for (int i = 0; i < thread_pool_size_; ++i)
     119      832930 :     thread_pool_.push_back(new WorkerThread(&queue_));
     120             : }
     121             : 
     122             : 
     123      184055 : Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
     124             :   auto it = main_thread_queue_.find(isolate);
     125      195792 :   if (it == main_thread_queue_.end() || it->second.empty()) {
     126             :     return NULL;
     127             :   }
     128        9388 :   Task* task = it->second.front();
     129             :   it->second.pop();
     130        9388 :   return task;
     131             : }
     132             : 
     133             : 
     134      184068 : Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
     135             :   auto it = main_thread_delayed_queue_.find(isolate);
     136      187519 :   if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
     137             :     return NULL;
     138             :   }
     139        3427 :   double now = MonotonicallyIncreasingTime();
     140        3427 :   std::pair<double, Task*> deadline_and_task = it->second.top();
     141        3427 :   if (deadline_and_task.first > now) {
     142             :     return NULL;
     143             :   }
     144          13 :   it->second.pop();
     145          13 :   return deadline_and_task.second;
     146             : }
     147             : 
     148      155211 : IdleTask* DefaultPlatform::PopTaskInMainThreadIdleQueue(v8::Isolate* isolate) {
     149             :   auto it = main_thread_idle_queue_.find(isolate);
     150      185783 :   if (it == main_thread_idle_queue_.end() || it->second.empty()) {
     151             :     return nullptr;
     152             :   }
     153        9083 :   IdleTask* task = it->second.front();
     154             :   it->second.pop();
     155        9083 :   return task;
     156             : }
     157             : 
     158      184055 : bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
     159      184055 :   Task* task = NULL;
     160             :   {
     161      184055 :     base::LockGuard<base::Mutex> guard(&lock_);
     162             : 
     163             :     // Move delayed tasks that hit their deadline to the main queue.
     164      184055 :     task = PopTaskInMainThreadDelayedQueue(isolate);
     165      368123 :     while (task != NULL) {
     166          13 :       main_thread_queue_[isolate].push(task);
     167          13 :       task = PopTaskInMainThreadDelayedQueue(isolate);
     168             :     }
     169             : 
     170      184055 :     task = PopTaskInMainThreadQueue(isolate);
     171             : 
     172      184055 :     if (task == NULL) {
     173             :       return false;
     174             :     }
     175             :   }
     176        9388 :   task->Run();
     177        9388 :   delete task;
     178             :   return true;
     179             : }
     180             : 
     181      146142 : void DefaultPlatform::RunIdleTasks(v8::Isolate* isolate,
     182             :                                    double idle_time_in_seconds) {
     183             :   DCHECK(IdleTaskSupport::kEnabled == idle_task_support_);
     184             :   double deadline_in_seconds =
     185      146142 :       MonotonicallyIncreasingTime() + idle_time_in_seconds;
     186      301367 :   while (deadline_in_seconds > MonotonicallyIncreasingTime()) {
     187             :     {
     188             :       IdleTask* task;
     189             :       {
     190      155211 :         base::LockGuard<base::Mutex> guard(&lock_);
     191      155211 :         task = PopTaskInMainThreadIdleQueue(isolate);
     192             :       }
     193      301353 :       if (task == nullptr) return;
     194        9083 :       task->Run(deadline_in_seconds);
     195        9083 :       delete task;
     196             :     }
     197             :   }
     198             : }
     199             : 
     200      633399 : void DefaultPlatform::CallOnBackgroundThread(Task* task,
     201             :                                              ExpectedRuntime expected_runtime) {
     202      633399 :   EnsureInitialized();
     203      633399 :   queue_.Append(task);
     204      633399 : }
     205             : 
     206             : 
     207        9454 : void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
     208        9454 :   base::LockGuard<base::Mutex> guard(&lock_);
     209        9455 :   main_thread_queue_[isolate].push(task);
     210        9455 : }
     211             : 
     212             : 
     213         273 : void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
     214             :                                                     Task* task,
     215             :                                                     double delay_in_seconds) {
     216         273 :   base::LockGuard<base::Mutex> guard(&lock_);
     217         273 :   double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
     218         273 :   main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
     219         273 : }
     220             : 
     221        9127 : void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
     222             :                                                  IdleTask* task) {
     223        9127 :   base::LockGuard<base::Mutex> guard(&lock_);
     224        9127 :   main_thread_idle_queue_[isolate].push(task);
     225        9127 : }
     226             : 
     227       16471 : bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) {
     228       16471 :   return idle_task_support_ == IdleTaskSupport::kEnabled;
     229             : }
     230             : 
     231     7458360 : double DefaultPlatform::MonotonicallyIncreasingTime() {
     232    22375102 :   return base::TimeTicks::HighResolutionNow().ToInternalValue() /
     233    14916742 :          static_cast<double>(base::Time::kMicrosecondsPerSecond);
     234             : }
     235             : 
     236         188 : uint64_t DefaultPlatform::AddTraceEvent(
     237             :     char phase, const uint8_t* category_enabled_flag, const char* name,
     238             :     const char* scope, uint64_t id, uint64_t bind_id, int num_args,
     239             :     const char** arg_names, const uint8_t* arg_types,
     240             :     const uint64_t* arg_values,
     241             :     std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
     242             :     unsigned int flags) {
     243         188 :   if (tracing_controller_) {
     244             :     return tracing_controller_->AddTraceEvent(
     245             :         phase, category_enabled_flag, name, scope, id, bind_id, num_args,
     246         188 :         arg_names, arg_types, arg_values, arg_convertables, flags);
     247             :   }
     248             : 
     249             :   return 0;
     250             : }
     251             : 
     252           0 : void DefaultPlatform::UpdateTraceEventDuration(
     253             :     const uint8_t* category_enabled_flag, const char* name, uint64_t handle) {
     254           0 :   if (tracing_controller_) {
     255             :     tracing_controller_->UpdateTraceEventDuration(category_enabled_flag, name,
     256           0 :                                                   handle);
     257             :   }
     258           0 : }
     259             : 
     260     1346656 : const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
     261     1346656 :   if (tracing_controller_) {
     262         319 :     return tracing_controller_->GetCategoryGroupEnabled(name);
     263             :   }
     264             :   static uint8_t no = 0;
     265             :   return &no;
     266             : }
     267             : 
     268             : 
     269           0 : const char* DefaultPlatform::GetCategoryGroupName(
     270             :     const uint8_t* category_enabled_flag) {
     271             :   static const char dummy[] = "dummy";
     272           0 :   return dummy;
     273             : }
     274             : 
     275           0 : void DefaultPlatform::SetTracingController(
     276             :     tracing::TracingController* tracing_controller) {
     277             :   tracing_controller_.reset(tracing_controller);
     278           0 : }
     279             : 
     280      321890 : size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() {
     281      321890 :   return static_cast<size_t>(thread_pool_size_);
     282             : }
     283             : 
     284       59481 : void DefaultPlatform::AddTraceStateObserver(TraceStateObserver* observer) {
     285      118962 :   if (!tracing_controller_) return;
     286          20 :   tracing_controller_->AddTraceStateObserver(observer);
     287             : }
     288             : 
     289       58764 : void DefaultPlatform::RemoveTraceStateObserver(TraceStateObserver* observer) {
     290      117528 :   if (!tracing_controller_) return;
     291          20 :   tracing_controller_->RemoveTraceStateObserver(observer);
     292             : }
     293             : 
     294       59461 : Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
     295       59461 :   return PrintStackTrace;
     296             : }
     297             : 
     298             : }  // namespace platform
     299             : }  // namespace v8

Generated by: LCOV version 1.10