Home | History | Annotate | Download | only in src
      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 #ifndef V8_OPTIMIZING_COMPILER_THREAD_H_
      6 #define V8_OPTIMIZING_COMPILER_THREAD_H_
      7 
      8 #include "src/base/atomicops.h"
      9 #include "src/flags.h"
     10 #include "src/list.h"
     11 #include "src/platform.h"
     12 #include "src/platform/mutex.h"
     13 #include "src/platform/time.h"
     14 #include "src/unbound-queue-inl.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 class HOptimizedGraphBuilder;
     20 class OptimizedCompileJob;
     21 class SharedFunctionInfo;
     22 
     23 class OptimizingCompilerThread : public Thread {
     24  public:
     25   explicit OptimizingCompilerThread(Isolate *isolate) :
     26       Thread("OptimizingCompilerThread"),
     27 #ifdef DEBUG
     28       thread_id_(0),
     29 #endif
     30       isolate_(isolate),
     31       stop_semaphore_(0),
     32       input_queue_semaphore_(0),
     33       input_queue_capacity_(FLAG_concurrent_recompilation_queue_length),
     34       input_queue_length_(0),
     35       input_queue_shift_(0),
     36       osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4),
     37       osr_buffer_cursor_(0),
     38       osr_hits_(0),
     39       osr_attempts_(0),
     40       blocked_jobs_(0) {
     41     base::NoBarrier_Store(&stop_thread_,
     42                           static_cast<base::AtomicWord>(CONTINUE));
     43     input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_);
     44     if (FLAG_concurrent_osr) {
     45       // Allocate and mark OSR buffer slots as empty.
     46       osr_buffer_ = NewArray<OptimizedCompileJob*>(osr_buffer_capacity_);
     47       for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL;
     48     }
     49   }
     50 
     51   ~OptimizingCompilerThread();
     52 
     53   void Run();
     54   void Stop();
     55   void Flush();
     56   void QueueForOptimization(OptimizedCompileJob* optimizing_compiler);
     57   void Unblock();
     58   void InstallOptimizedFunctions();
     59   OptimizedCompileJob* FindReadyOSRCandidate(Handle<JSFunction> function,
     60                                              BailoutId osr_ast_id);
     61   bool IsQueuedForOSR(Handle<JSFunction> function, BailoutId osr_ast_id);
     62 
     63   bool IsQueuedForOSR(JSFunction* function);
     64 
     65   inline bool IsQueueAvailable() {
     66     LockGuard<Mutex> access_input_queue(&input_queue_mutex_);
     67     return input_queue_length_ < input_queue_capacity_;
     68   }
     69 
     70   inline void AgeBufferedOsrJobs() {
     71     // Advance cursor of the cyclic buffer to next empty slot or stale OSR job.
     72     // Dispose said OSR job in the latter case.  Calling this on every GC
     73     // should make sure that we do not hold onto stale jobs indefinitely.
     74     AddToOsrBuffer(NULL);
     75   }
     76 
     77   static bool Enabled(int max_available) {
     78     return (FLAG_concurrent_recompilation && max_available > 1);
     79   }
     80 
     81 #ifdef DEBUG
     82   static bool IsOptimizerThread(Isolate* isolate);
     83   bool IsOptimizerThread();
     84 #endif
     85 
     86  private:
     87   enum StopFlag { CONTINUE, STOP, FLUSH };
     88 
     89   void FlushInputQueue(bool restore_function_code);
     90   void FlushOutputQueue(bool restore_function_code);
     91   void FlushOsrBuffer(bool restore_function_code);
     92   void CompileNext();
     93   OptimizedCompileJob* NextInput();
     94 
     95   // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry.
     96   // Tasks evicted from the cyclic buffer are discarded.
     97   void AddToOsrBuffer(OptimizedCompileJob* compiler);
     98 
     99   inline int InputQueueIndex(int i) {
    100     int result = (i + input_queue_shift_) % input_queue_capacity_;
    101     ASSERT_LE(0, result);
    102     ASSERT_LT(result, input_queue_capacity_);
    103     return result;
    104   }
    105 
    106 #ifdef DEBUG
    107   int thread_id_;
    108   Mutex thread_id_mutex_;
    109 #endif
    110 
    111   Isolate* isolate_;
    112   Semaphore stop_semaphore_;
    113   Semaphore input_queue_semaphore_;
    114 
    115   // Circular queue of incoming recompilation tasks (including OSR).
    116   OptimizedCompileJob** input_queue_;
    117   int input_queue_capacity_;
    118   int input_queue_length_;
    119   int input_queue_shift_;
    120   Mutex input_queue_mutex_;
    121 
    122   // Queue of recompilation tasks ready to be installed (excluding OSR).
    123   UnboundQueue<OptimizedCompileJob*> output_queue_;
    124 
    125   // Cyclic buffer of recompilation tasks for OSR.
    126   OptimizedCompileJob** osr_buffer_;
    127   int osr_buffer_capacity_;
    128   int osr_buffer_cursor_;
    129 
    130   volatile base::AtomicWord stop_thread_;
    131   TimeDelta time_spent_compiling_;
    132   TimeDelta time_spent_total_;
    133 
    134   int osr_hits_;
    135   int osr_attempts_;
    136 
    137   int blocked_jobs_;
    138 };
    139 
    140 } }  // namespace v8::internal
    141 
    142 #endif  // V8_OPTIMIZING_COMPILER_THREAD_H_
    143