1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_OPTIMIZING_COMPILER_THREAD_H_ 29 #define V8_OPTIMIZING_COMPILER_THREAD_H_ 30 31 #include "atomicops.h" 32 #include "flags.h" 33 #include "list.h" 34 #include "platform.h" 35 #include "platform/mutex.h" 36 #include "platform/time.h" 37 #include "unbound-queue-inl.h" 38 39 namespace v8 { 40 namespace internal { 41 42 class HOptimizedGraphBuilder; 43 class RecompileJob; 44 class SharedFunctionInfo; 45 46 class OptimizingCompilerThread : public Thread { 47 public: OptimizingCompilerThread(Isolate * isolate)48 explicit OptimizingCompilerThread(Isolate *isolate) : 49 Thread("OptimizingCompilerThread"), 50 #ifdef DEBUG 51 thread_id_(0), 52 #endif 53 isolate_(isolate), 54 stop_semaphore_(0), 55 input_queue_semaphore_(0), 56 input_queue_capacity_(FLAG_concurrent_recompilation_queue_length), 57 input_queue_length_(0), 58 input_queue_shift_(0), 59 osr_buffer_capacity_(FLAG_concurrent_recompilation_queue_length + 4), 60 osr_buffer_cursor_(0), 61 osr_hits_(0), 62 osr_attempts_(0), 63 blocked_jobs_(0) { 64 NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(CONTINUE)); 65 input_queue_ = NewArray<RecompileJob*>(input_queue_capacity_); 66 if (FLAG_concurrent_osr) { 67 // Allocate and mark OSR buffer slots as empty. 68 osr_buffer_ = NewArray<RecompileJob*>(osr_buffer_capacity_); 69 for (int i = 0; i < osr_buffer_capacity_; i++) osr_buffer_[i] = NULL; 70 } 71 } 72 73 ~OptimizingCompilerThread(); 74 75 void Run(); 76 void Stop(); 77 void Flush(); 78 void QueueForOptimization(RecompileJob* optimizing_compiler); 79 void Unblock(); 80 void InstallOptimizedFunctions(); 81 RecompileJob* FindReadyOSRCandidate(Handle<JSFunction> function, 82 uint32_t osr_pc_offset); 83 bool IsQueuedForOSR(Handle<JSFunction> function, uint32_t osr_pc_offset); 84 85 bool IsQueuedForOSR(JSFunction* function); 86 IsQueueAvailable()87 inline bool IsQueueAvailable() { 88 LockGuard<Mutex> access_input_queue(&input_queue_mutex_); 89 return input_queue_length_ < input_queue_capacity_; 90 } 91 AgeBufferedOsrJobs()92 inline void AgeBufferedOsrJobs() { 93 // Advance cursor of the cyclic buffer to next empty slot or stale OSR job. 94 // Dispose said OSR job in the latter case. Calling this on every GC 95 // should make sure that we do not hold onto stale jobs indefinitely. 96 AddToOsrBuffer(NULL); 97 } 98 Enabled(int max_available)99 static bool Enabled(int max_available) { 100 return (FLAG_concurrent_recompilation && max_available > 1); 101 } 102 103 #ifdef DEBUG 104 static bool IsOptimizerThread(Isolate* isolate); 105 bool IsOptimizerThread(); 106 #endif 107 108 private: 109 enum StopFlag { CONTINUE, STOP, FLUSH }; 110 111 void FlushInputQueue(bool restore_function_code); 112 void FlushOutputQueue(bool restore_function_code); 113 void FlushOsrBuffer(bool restore_function_code); 114 void CompileNext(); 115 RecompileJob* NextInput(); 116 117 // Add a recompilation task for OSR to the cyclic buffer, awaiting OSR entry. 118 // Tasks evicted from the cyclic buffer are discarded. 119 void AddToOsrBuffer(RecompileJob* compiler); 120 InputQueueIndex(int i)121 inline int InputQueueIndex(int i) { 122 int result = (i + input_queue_shift_) % input_queue_capacity_; 123 ASSERT_LE(0, result); 124 ASSERT_LT(result, input_queue_capacity_); 125 return result; 126 } 127 128 #ifdef DEBUG 129 int thread_id_; 130 Mutex thread_id_mutex_; 131 #endif 132 133 Isolate* isolate_; 134 Semaphore stop_semaphore_; 135 Semaphore input_queue_semaphore_; 136 137 // Circular queue of incoming recompilation tasks (including OSR). 138 RecompileJob** input_queue_; 139 int input_queue_capacity_; 140 int input_queue_length_; 141 int input_queue_shift_; 142 Mutex input_queue_mutex_; 143 144 // Queue of recompilation tasks ready to be installed (excluding OSR). 145 UnboundQueue<RecompileJob*> output_queue_; 146 147 // Cyclic buffer of recompilation tasks for OSR. 148 RecompileJob** osr_buffer_; 149 int osr_buffer_capacity_; 150 int osr_buffer_cursor_; 151 152 volatile AtomicWord stop_thread_; 153 TimeDelta time_spent_compiling_; 154 TimeDelta time_spent_total_; 155 156 int osr_hits_; 157 int osr_attempts_; 158 159 int blocked_jobs_; 160 }; 161 162 } } // namespace v8::internal 163 164 #endif // V8_OPTIMIZING_COMPILER_THREAD_H_ 165