LCOV - code coverage report
Current view: top level - src/compiler-dispatcher - optimizing-compile-dispatcher.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 95 104 91.3 %
Date: 2019-04-17 Functions: 14 15 93.3 %

          Line data    Source code
       1             : // Copyright 2012 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/compiler-dispatcher/optimizing-compile-dispatcher.h"
       6             : 
       7             : #include "src/base/atomicops.h"
       8             : #include "src/base/template-utils.h"
       9             : #include "src/cancelable-task.h"
      10             : #include "src/compiler.h"
      11             : #include "src/counters.h"
      12             : #include "src/isolate.h"
      13             : #include "src/log.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/optimized-compilation-info.h"
      16             : #include "src/tracing/trace-event.h"
      17             : #include "src/v8.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : namespace {
      23             : 
      24         194 : void DisposeCompilationJob(OptimizedCompilationJob* job,
      25             :                            bool restore_function_code) {
      26         194 :   if (restore_function_code) {
      27             :     Handle<JSFunction> function = job->compilation_info()->closure();
      28         168 :     function->set_code(function->shared()->GetCode());
      29          84 :     if (function->IsInOptimizationQueue()) {
      30             :       function->ClearOptimizationMarker();
      31             :     }
      32             :     // TODO(mvstanton): We can't call EnsureFeedbackVector here due to
      33             :     // allocation, but we probably shouldn't call set_code either, as this
      34             :     // sometimes runs on the worker thread!
      35             :     // JSFunction::EnsureFeedbackVector(function);
      36             :   }
      37         194 :   delete job;
      38         194 : }
      39             : 
      40             : }  // namespace
      41             : 
      42             : class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
      43             :  public:
      44        6852 :   explicit CompileTask(Isolate* isolate,
      45             :                        OptimizingCompileDispatcher* dispatcher)
      46             :       : CancelableTask(isolate),
      47             :         isolate_(isolate),
      48             :         worker_thread_runtime_call_stats_(
      49             :             isolate->counters()->worker_thread_runtime_call_stats()),
      50       13704 :         dispatcher_(dispatcher) {
      51        6852 :     base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
      52        6852 :     ++dispatcher_->ref_count_;
      53        6852 :   }
      54             : 
      55       13702 :   ~CompileTask() override = default;
      56             : 
      57             :  private:
      58             :   // v8::Task overrides.
      59        6852 :   void RunInternal() override {
      60             :     DisallowHeapAllocation no_allocation;
      61             :     DisallowHandleAllocation no_handles;
      62             :     DisallowHandleDereference no_deref;
      63             : 
      64             :     {
      65             :       WorkerThreadRuntimeCallStatsScope runtime_call_stats_scope(
      66       13702 :           worker_thread_runtime_call_stats_);
      67             :       RuntimeCallTimerScope runtimeTimer(
      68             :           runtime_call_stats_scope.Get(),
      69        6852 :           RuntimeCallCounterId::kRecompileConcurrent);
      70             : 
      71        6852 :       TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
      72       20554 :       TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
      73             :                    "V8.RecompileConcurrent");
      74             : 
      75        6851 :       if (dispatcher_->recompilation_delay_ != 0) {
      76           0 :         base::OS::Sleep(base::TimeDelta::FromMilliseconds(
      77           0 :             dispatcher_->recompilation_delay_));
      78             :       }
      79             : 
      80        6851 :       dispatcher_->CompileNext(dispatcher_->NextInput(true));
      81             :     }
      82             :     {
      83        6850 :       base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
      84        6852 :       if (--dispatcher_->ref_count_ == 0) {
      85        4932 :         dispatcher_->ref_count_zero_.NotifyOne();
      86             :       }
      87             :     }
      88        6852 :   }
      89             : 
      90             :   Isolate* isolate_;
      91             :   WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
      92             :   OptimizingCompileDispatcher* dispatcher_;
      93             : 
      94             :   DISALLOW_COPY_AND_ASSIGN(CompileTask);
      95             : };
      96             : 
      97      186912 : OptimizingCompileDispatcher::~OptimizingCompileDispatcher() {
      98             : #ifdef DEBUG
      99             :   {
     100             :     base::MutexGuard lock_guard(&ref_count_mutex_);
     101             :     DCHECK_EQ(0, ref_count_);
     102             :   }
     103             : #endif
     104             :   DCHECK_EQ(0, input_queue_length_);
     105       62303 :   DeleteArray(input_queue_);
     106       62303 : }
     107             : 
     108        6851 : OptimizedCompilationJob* OptimizingCompileDispatcher::NextInput(
     109             :     bool check_if_flushing) {
     110        6851 :   base::MutexGuard access_input_queue_(&input_queue_mutex_);
     111        6852 :   if (input_queue_length_ == 0) return nullptr;
     112       13692 :   OptimizedCompilationJob* job = input_queue_[InputQueueIndex(0)];
     113             :   DCHECK_NOT_NULL(job);
     114        6846 :   input_queue_shift_ = InputQueueIndex(1);
     115        6846 :   input_queue_length_--;
     116        6846 :   if (check_if_flushing) {
     117        6846 :     if (mode_ == FLUSH) {
     118             :       AllowHandleDereference allow_handle_dereference;
     119          25 :       DisposeCompilationJob(job, true);
     120             :       return nullptr;
     121             :     }
     122             :   }
     123             :   return job;
     124             : }
     125             : 
     126        6852 : void OptimizingCompileDispatcher::CompileNext(OptimizedCompilationJob* job) {
     127        6852 :   if (!job) return;
     128             : 
     129             :   // The function may have already been optimized by OSR.  Simply continue.
     130        6821 :   CompilationJob::Status status = job->ExecuteJob();
     131             :   USE(status);  // Prevent an unused-variable error.
     132             : 
     133             :   {
     134             :     // The function may have already been optimized by OSR.  Simply continue.
     135             :     // Use a mutex to make sure that functions marked for install
     136             :     // are always also queued.
     137        6816 :     base::MutexGuard access_output_queue_(&output_queue_mutex_);
     138             :     output_queue_.push(job);
     139             :   }
     140             : 
     141        6821 :   isolate_->stack_guard()->RequestInstallCode();
     142             : }
     143             : 
     144       85996 : void OptimizingCompileDispatcher::FlushOutputQueue(bool restore_function_code) {
     145         155 :   for (;;) {
     146             :     OptimizedCompilationJob* job = nullptr;
     147             :     {
     148       86151 :       base::MutexGuard access_output_queue_(&output_queue_mutex_);
     149      172148 :       if (output_queue_.empty()) return;
     150         155 :       job = output_queue_.front();
     151             :       output_queue_.pop();
     152             :     }
     153             : 
     154         155 :     DisposeCompilationJob(job, restore_function_code);
     155             :   }
     156             : }
     157             : 
     158       23693 : void OptimizingCompileDispatcher::Flush(BlockingBehavior blocking_behavior) {
     159       23693 :   if (blocking_behavior == BlockingBehavior::kDontBlock) {
     160        4375 :     if (FLAG_block_concurrent_recompilation) Unblock();
     161        4375 :     base::MutexGuard access_input_queue_(&input_queue_mutex_);
     162        4387 :     while (input_queue_length_ > 0) {
     163          12 :       OptimizedCompilationJob* job = input_queue_[InputQueueIndex(0)];
     164             :       DCHECK_NOT_NULL(job);
     165           6 :       input_queue_shift_ = InputQueueIndex(1);
     166           6 :       input_queue_length_--;
     167           6 :       DisposeCompilationJob(job, true);
     168             :     }
     169        4375 :     FlushOutputQueue(true);
     170        4375 :     if (FLAG_trace_concurrent_recompilation) {
     171           0 :       PrintF("  ** Flushed concurrent recompilation queues (not blocking).\n");
     172             :     }
     173             :     return;
     174             :   }
     175             :   mode_ = FLUSH;
     176       19318 :   if (FLAG_block_concurrent_recompilation) Unblock();
     177             :   {
     178       19318 :     base::MutexGuard lock_guard(&ref_count_mutex_);
     179       19373 :     while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
     180             :     mode_ = COMPILE;
     181             :   }
     182       19318 :   FlushOutputQueue(true);
     183       19318 :   if (FLAG_trace_concurrent_recompilation) {
     184           0 :     PrintF("  ** Flushed concurrent recompilation queues.\n");
     185             :   }
     186             : }
     187             : 
     188       62303 : void OptimizingCompileDispatcher::Stop() {
     189             :   mode_ = FLUSH;
     190       62303 :   if (FLAG_block_concurrent_recompilation) Unblock();
     191             :   {
     192       62303 :     base::MutexGuard lock_guard(&ref_count_mutex_);
     193       62356 :     while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
     194             :     mode_ = COMPILE;
     195             :   }
     196             : 
     197       62304 :   if (recompilation_delay_ != 0) {
     198             :     // At this point the optimizing compiler thread's event loop has stopped.
     199             :     // There is no need for a mutex when reading input_queue_length_.
     200           0 :     while (input_queue_length_ > 0) CompileNext(NextInput());
     201           0 :     InstallOptimizedFunctions();
     202             :   } else {
     203       62304 :     FlushOutputQueue(false);
     204             :   }
     205       62303 : }
     206             : 
     207        6121 : void OptimizingCompileDispatcher::InstallOptimizedFunctions() {
     208        6121 :   HandleScope handle_scope(isolate_);
     209             : 
     210             :   for (;;) {
     211             :     OptimizedCompilationJob* job = nullptr;
     212             :     {
     213       12787 :       base::MutexGuard access_output_queue_(&output_queue_mutex_);
     214       18908 :       if (output_queue_.empty()) return;
     215        6666 :       job = output_queue_.front();
     216             :       output_queue_.pop();
     217             :     }
     218             :     OptimizedCompilationInfo* info = job->compilation_info();
     219        6666 :     Handle<JSFunction> function(*info->closure(), isolate_);
     220        6666 :     if (function->HasOptimizedCode()) {
     221           8 :       if (FLAG_trace_concurrent_recompilation) {
     222           0 :         PrintF("  ** Aborting compilation for ");
     223           0 :         function->ShortPrint();
     224           0 :         PrintF(" as it has already been optimized.\n");
     225             :       }
     226           8 :       DisposeCompilationJob(job, false);
     227             :     } else {
     228        6658 :       Compiler::FinalizeOptimizedCompilationJob(job, isolate_);
     229             :     }
     230             :   }
     231             : }
     232             : 
     233        6852 : void OptimizingCompileDispatcher::QueueForOptimization(
     234             :     OptimizedCompilationJob* job) {
     235             :   DCHECK(IsQueueAvailable());
     236             :   {
     237             :     // Add job to the back of the input queue.
     238        6852 :     base::MutexGuard access_input_queue(&input_queue_mutex_);
     239             :     DCHECK_LT(input_queue_length_, input_queue_capacity_);
     240       13704 :     input_queue_[InputQueueIndex(input_queue_length_)] = job;
     241        6852 :     input_queue_length_++;
     242             :   }
     243        6852 :   if (FLAG_block_concurrent_recompilation) {
     244          76 :     blocked_jobs_++;
     245             :   } else {
     246       13552 :     V8::GetCurrentPlatform()->CallOnWorkerThread(
     247       20328 :         base::make_unique<CompileTask>(isolate_, this));
     248             :   }
     249        6852 : }
     250             : 
     251         211 : void OptimizingCompileDispatcher::Unblock() {
     252         363 :   while (blocked_jobs_ > 0) {
     253         152 :     V8::GetCurrentPlatform()->CallOnWorkerThread(
     254         228 :         base::make_unique<CompileTask>(isolate_, this));
     255          76 :     blocked_jobs_--;
     256             :   }
     257         211 : }
     258             : 
     259             : }  // namespace internal
     260      121996 : }  // namespace v8

Generated by: LCOV version 1.10