LCOV - code coverage report
Current view: top level - src/heap - item-parallel-job.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 36 38 94.7 %
Date: 2019-04-17 Functions: 6 7 85.7 %

          Line data    Source code
       1             : // Copyright 2018 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/heap/item-parallel-job.h"
       6             : 
       7             : #include "src/base/platform/semaphore.h"
       8             : #include "src/counters.h"
       9             : #include "src/v8.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14      521398 : ItemParallelJob::Task::Task(Isolate* isolate) : CancelableTask(isolate) {}
      15             : 
      16           0 : void ItemParallelJob::Task::SetupInternal(base::Semaphore* on_finish,
      17             :                                           std::vector<Item*>* items,
      18             :                                           size_t start_index) {
      19      521398 :   on_finish_ = on_finish;
      20      521398 :   items_ = items;
      21             : 
      22      521398 :   if (start_index < items->size()) {
      23      515152 :     cur_index_ = start_index;
      24             :   } else {
      25        6246 :     items_considered_ = items_->size();
      26             :   }
      27           0 : }
      28             : 
      29      439195 : void ItemParallelJob::Task::RunInternal() {
      30      439195 :   RunInParallel();
      31      439526 :   on_finish_->Signal();
      32      439403 : }
      33             : 
      34      234412 : ItemParallelJob::ItemParallelJob(CancelableTaskManager* cancelable_task_manager,
      35             :                                  base::Semaphore* pending_tasks)
      36             :     : cancelable_task_manager_(cancelable_task_manager),
      37      234412 :       pending_tasks_(pending_tasks) {}
      38             : 
      39      703236 : ItemParallelJob::~ItemParallelJob() {
      40     1847576 :   for (size_t i = 0; i < items_.size(); i++) {
      41      806582 :     Item* item = items_[i];
      42      806582 :     CHECK(item->IsFinished());
      43      806582 :     delete item;
      44             :   }
      45      234412 : }
      46             : 
      47      223538 : void ItemParallelJob::Run() {
      48             :   DCHECK_GT(tasks_.size(), 0);
      49             :   const size_t num_items = items_.size();
      50             :   const size_t num_tasks = tasks_.size();
      51             : 
      52      447076 :   TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("v8.gc"),
      53             :                        "ItemParallelJob::Run", TRACE_EVENT_SCOPE_THREAD,
      54             :                        "num_tasks", static_cast<int>(num_tasks), "num_items",
      55             :                        static_cast<int>(num_items));
      56             : 
      57             :   // Some jobs have more tasks than items (when the items are mere coarse
      58             :   // grain tasks that generate work dynamically for a second phase which all
      59             :   // tasks participate in). Some jobs even have 0 items to preprocess but
      60             :   // still have multiple tasks.
      61             :   // TODO(gab): Figure out a cleaner scheme for this.
      62             :   const size_t num_tasks_processing_items = Min(num_items, tasks_.size());
      63             : 
      64             :   // In the event of an uneven workload, distribute an extra item to the first
      65             :   // |items_remainder| tasks.
      66             :   const size_t items_remainder = num_tasks_processing_items > 0
      67             :                                      ? num_items % num_tasks_processing_items
      68      223538 :                                      : 0;
      69             :   // Base |items_per_task|, will be bumped by 1 for the first
      70             :   // |items_remainder| tasks.
      71             :   const size_t items_per_task = num_tasks_processing_items > 0
      72             :                                     ? num_items / num_tasks_processing_items
      73      223538 :                                     : 0;
      74             :   CancelableTaskManager::Id* task_ids =
      75      223538 :       new CancelableTaskManager::Id[num_tasks];
      76             :   std::unique_ptr<Task> main_task;
      77     1787732 :   for (size_t i = 0, start_index = 0; i < num_tasks;
      78      521398 :        i++, start_index += items_per_task + (i < items_remainder ? 1 : 0)) {
      79             :     auto task = std::move(tasks_[i]);
      80             :     DCHECK(task);
      81             : 
      82             :     // By definition there are less |items_remainder| to distribute then
      83             :     // there are tasks processing items so this cannot overflow while we are
      84             :     // assigning work items.
      85             :     DCHECK_IMPLIES(start_index >= num_items, i >= num_tasks_processing_items);
      86             : 
      87      521398 :     task->SetupInternal(pending_tasks_, &items_, start_index);
      88      521398 :     task_ids[i] = task->id();
      89      521398 :     if (i > 0) {
      90      893580 :       V8::GetCurrentPlatform()->CallBlockingTaskOnWorkerThread(std::move(task));
      91             :     } else {
      92             :       main_task = std::move(task);
      93             :     }
      94             :   }
      95             : 
      96             :   // Contribute on main thread.
      97             :   DCHECK(main_task);
      98      223538 :   main_task->Run();
      99             : 
     100             :   // Wait for background tasks.
     101     1266334 :   for (size_t i = 0; i < num_tasks; i++) {
     102      521398 :     if (cancelable_task_manager_->TryAbort(task_ids[i]) !=
     103             :         TryAbortResult::kTaskAborted) {
     104      439637 :       pending_tasks_->Wait();
     105             :     }
     106             :   }
     107      223538 :   delete[] task_ids;
     108      223538 : }
     109             : 
     110             : }  // namespace internal
     111      121996 : }  // namespace v8

Generated by: LCOV version 1.10