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_COMPILE_DISPATCHER_H_ 6 #define V8_OPTIMIZING_COMPILE_DISPATCHER_H_ 7 8 #include <queue> 9 10 #include "src/base/atomicops.h" 11 #include "src/base/platform/condition-variable.h" 12 #include "src/base/platform/mutex.h" 13 #include "src/base/platform/platform.h" 14 #include "src/flags.h" 15 #include "src/list.h" 16 17 namespace v8 { 18 namespace internal { 19 20 class HOptimizedGraphBuilder; 21 class OptimizedCompileJob; 22 class SharedFunctionInfo; 23 24 class OptimizingCompileDispatcher { 25 public: OptimizingCompileDispatcher(Isolate * isolate)26 explicit OptimizingCompileDispatcher(Isolate* isolate) 27 : isolate_(isolate), 28 input_queue_capacity_(FLAG_concurrent_recompilation_queue_length), 29 input_queue_length_(0), 30 input_queue_shift_(0), 31 osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4), 32 osr_buffer_cursor_(0), 33 osr_hits_(0), 34 osr_attempts_(0), 35 blocked_jobs_(0), 36 ref_count_(0), 37 recompilation_delay_(FLAG_concurrent_recompilation_delay) { 38 base::NoBarrier_Store(&mode_, static_cast<base::AtomicWord>(COMPILE)); 39 input_queue_ = NewArray<OptimizedCompileJob*>(input_queue_capacity_); 40 if (FLAG_concurrent_osr) { 41 // Allocate and mark OSR buffer slots as empty. 42 osr_buffer_ = NewArray<OptimizedCompileJob*>(osr_buffer_capacity_); 43 for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL; 44 } 45 } 46 47 ~OptimizingCompileDispatcher(); 48 49 void Run(); 50 void Stop(); 51 void Flush(); 52 void QueueForOptimization(OptimizedCompileJob* optimizing_compiler); 53 void Unblock(); 54 void InstallOptimizedFunctions(); 55 OptimizedCompileJob* FindReadyOSRCandidate(Handle<JSFunction> function, 56 BailoutId osr_ast_id); 57 bool IsQueuedForOSR(Handle<JSFunction> function, BailoutId osr_ast_id); 58 59 bool IsQueuedForOSR(JSFunction* function); 60 IsQueueAvailable()61 inline bool IsQueueAvailable() { 62 base::LockGuard<base::Mutex> access_input_queue(&input_queue_mutex_); 63 return input_queue_length_ < input_queue_capacity_; 64 } 65 AgeBufferedOsrJobs()66 inline void AgeBufferedOsrJobs() { 67 // Advance cursor of the cyclic buffer to next empty slot or stale OSR job. 68 // Dispose said OSR job in the latter case. Calling this on every GC 69 // should make sure that we do not hold onto stale jobs indefinitely. 70 AddToOsrBuffer(NULL); 71 } 72 Enabled()73 static bool Enabled() { return FLAG_concurrent_recompilation; } 74 75 private: 76 class CompileTask; 77 78 enum ModeFlag { COMPILE, FLUSH }; 79 80 void FlushOutputQueue(bool restore_function_code); 81 void FlushOsrBuffer(bool restore_function_code); 82 void CompileNext(OptimizedCompileJob* job); 83 OptimizedCompileJob* NextInput(bool check_if_flushing = false); 84 85 // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry. 86 // Tasks evicted from the cyclic buffer are discarded. 87 void AddToOsrBuffer(OptimizedCompileJob* compiler); 88 InputQueueIndex(int i)89 inline int InputQueueIndex(int i) { 90 int result = (i + input_queue_shift_) % input_queue_capacity_; 91 DCHECK_LE(0, result); 92 DCHECK_LT(result, input_queue_capacity_); 93 return result; 94 } 95 96 Isolate* isolate_; 97 98 // Circular queue of incoming recompilation tasks (including OSR). 99 OptimizedCompileJob** input_queue_; 100 int input_queue_capacity_; 101 int input_queue_length_; 102 int input_queue_shift_; 103 base::Mutex input_queue_mutex_; 104 105 // Queue of recompilation tasks ready to be installed (excluding OSR). 106 std::queue<OptimizedCompileJob*> output_queue_; 107 // Used for job based recompilation which has multiple producers on 108 // different threads. 109 base::Mutex output_queue_mutex_; 110 111 // Cyclic buffer of recompilation tasks for OSR. 112 OptimizedCompileJob** osr_buffer_; 113 int osr_buffer_capacity_; 114 int osr_buffer_cursor_; 115 116 volatile base::AtomicWord mode_; 117 118 int osr_hits_; 119 int osr_attempts_; 120 121 int blocked_jobs_; 122 123 int ref_count_; 124 base::Mutex ref_count_mutex_; 125 base::ConditionVariable ref_count_zero_; 126 127 // Copy of FLAG_concurrent_recompilation_delay that will be used from the 128 // background thread. 129 // 130 // Since flags might get modified while the background thread is running, it 131 // is not safe to access them directly. 132 int recompilation_delay_; 133 }; 134 } // namespace internal 135 } // namespace v8 136 137 #endif // V8_OPTIMIZING_COMPILE_DISPATCHER_H_ 138