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/base/platform/mutex.h" 10 #include "src/base/platform/platform.h" 11 #include "src/base/platform/time.h" 12 #include "src/flags.h" 13 #include "src/list.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 base::Thread { 24 public: OptimizingCompilerThread(Isolate * isolate)25 explicit OptimizingCompilerThread(Isolate* isolate) 26 : Thread(Options("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 IsQueueAvailable()65 inline bool IsQueueAvailable() { 66 base::LockGuard<base::Mutex> access_input_queue(&input_queue_mutex_); 67 return input_queue_length_ < input_queue_capacity_; 68 } 69 AgeBufferedOsrJobs()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 Enabled(int max_available)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 InputQueueIndex(int i)99 inline int InputQueueIndex(int i) { 100 int result = (i + input_queue_shift_) % input_queue_capacity_; 101 DCHECK_LE(0, result); 102 DCHECK_LT(result, input_queue_capacity_); 103 return result; 104 } 105 106 #ifdef DEBUG 107 int thread_id_; 108 base::Mutex thread_id_mutex_; 109 #endif 110 111 Isolate* isolate_; 112 base::Semaphore stop_semaphore_; 113 base::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 base::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 base::TimeDelta time_spent_compiling_; 132 base::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