Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: src/optimizing-compiler-thread.cc

Issue 24237009: Less aggressive polling when concurrently compiling for OSR. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: addressed comment. added TODO. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/optimizing-compiler-thread.h ('k') | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "optimizing-compiler-thread.h" 28 #include "optimizing-compiler-thread.h"
29 29
30 #include "v8.h" 30 #include "v8.h"
31 31
32 #include "full-codegen.h"
32 #include "hydrogen.h" 33 #include "hydrogen.h"
33 #include "isolate.h" 34 #include "isolate.h"
34 #include "v8threads.h" 35 #include "v8threads.h"
35 36
36 namespace v8 { 37 namespace v8 {
37 namespace internal { 38 namespace internal {
38 39
39 40
40 void OptimizingCompilerThread::Run() { 41 void OptimizingCompilerThread::Run() {
41 #ifdef DEBUG 42 #ifdef DEBUG
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1)); 101 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
101 102
102 // The function may have already been optimized by OSR. Simply continue. 103 // The function may have already been optimized by OSR. Simply continue.
103 OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph(); 104 OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph();
104 USE(status); // Prevent an unused-variable error in release mode. 105 USE(status); // Prevent an unused-variable error in release mode.
105 ASSERT(status != OptimizingCompiler::FAILED); 106 ASSERT(status != OptimizingCompiler::FAILED);
106 107
107 // The function may have already been optimized by OSR. Simply continue. 108 // The function may have already been optimized by OSR. Simply continue.
108 // Use a mutex to make sure that functions marked for install 109 // Use a mutex to make sure that functions marked for install
109 // are always also queued. 110 // are always also queued.
110 if (!optimizing_compiler->info()->osr_ast_id().IsNone()) { 111 LockGuard<Mutex> access_queue(&queue_mutex_);
111 ASSERT(FLAG_concurrent_osr); 112 output_queue_.Enqueue(optimizing_compiler);
112 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 113 isolate_->stack_guard()->RequestInstallCode();
113 osr_candidates_.RemoveElement(optimizing_compiler);
114 ready_for_osr_.Add(optimizing_compiler);
115 } else {
116 LockGuard<Mutex> access_queue(&queue_mutex_);
117 output_queue_.Enqueue(optimizing_compiler);
118 isolate_->stack_guard()->RequestInstallCode();
119 }
120 } 114 }
121 115
122 116
117 static void DisposeOptimizingCompiler(OptimizingCompiler* compiler,
118 bool restore_function_code) {
119 CompilationInfo* info = compiler->info();
120 if (restore_function_code) {
121 Handle<JSFunction> function = info->closure();
122 function->ReplaceCode(function->shared()->code());
123 }
124 delete info;
125 }
126
127
123 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) { 128 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) {
124 OptimizingCompiler* optimizing_compiler; 129 OptimizingCompiler* optimizing_compiler;
125 // The optimizing compiler is allocated in the CompilationInfo's zone. 130 // The optimizing compiler is allocated in the CompilationInfo's zone.
126 while (input_queue_.Dequeue(&optimizing_compiler)) { 131 while (input_queue_.Dequeue(&optimizing_compiler)) {
127 // This should not block, since we have one signal on the input queue 132 // This should not block, since we have one signal on the input queue
128 // semaphore corresponding to each element in the input queue. 133 // semaphore corresponding to each element in the input queue.
129 input_queue_semaphore_.Wait(); 134 input_queue_semaphore_.Wait();
130 CompilationInfo* info = optimizing_compiler->info(); 135 if (optimizing_compiler->info()->osr_ast_id().IsNone()) {
131 if (restore_function_code) { 136 // OSR jobs are dealt with separately.
132 Handle<JSFunction> function = info->closure(); 137 DisposeOptimizingCompiler(optimizing_compiler, restore_function_code);
133 function->ReplaceCode(function->shared()->code());
134 } 138 }
135 delete info;
136 } 139 }
137 Release_Store(&queue_length_, static_cast<AtomicWord>(0)); 140 Release_Store(&queue_length_, static_cast<AtomicWord>(0));
138
139 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
140 osr_candidates_.Clear();
141 } 141 }
142 142
143 143
144 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) { 144 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
145 OptimizingCompiler* optimizing_compiler; 145 OptimizingCompiler* optimizing_compiler;
146 // The optimizing compiler is allocated in the CompilationInfo's zone. 146 // The optimizing compiler is allocated in the CompilationInfo's zone.
147 while (true) { 147 while (true) {
148 { LockGuard<Mutex> access_queue(&queue_mutex_); 148 { LockGuard<Mutex> access_queue(&queue_mutex_);
149 if (!output_queue_.Dequeue(&optimizing_compiler)) break; 149 if (!output_queue_.Dequeue(&optimizing_compiler)) break;
150 } 150 }
151 CompilationInfo* info = optimizing_compiler->info(); 151 if (optimizing_compiler->info()->osr_ast_id().IsNone()) {
152 if (restore_function_code) { 152 // OSR jobs are dealt with separately.
153 Handle<JSFunction> function = info->closure(); 153 DisposeOptimizingCompiler(optimizing_compiler, restore_function_code);
154 function->ReplaceCode(function->shared()->code());
155 } 154 }
156 delete info;
157 } 155 }
158
159 RemoveStaleOSRCandidates(0);
160 } 156 }
161 157
162 158
159 void OptimizingCompilerThread::FlushOsrBuffer(bool restore_function_code) {
160 OptimizingCompiler* optimizing_compiler;
161 for (int i = 0; i < osr_buffer_size_; i++) {
162 optimizing_compiler = osr_buffer_[i];
163 if (optimizing_compiler != NULL) {
164 DisposeOptimizingCompiler(optimizing_compiler, restore_function_code);
165 }
166 }
167 osr_cursor_ = 0;
168 }
169
170
163 void OptimizingCompilerThread::Flush() { 171 void OptimizingCompilerThread::Flush() {
164 ASSERT(!IsOptimizerThread()); 172 ASSERT(!IsOptimizerThread());
165 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH)); 173 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
166 input_queue_semaphore_.Signal(); 174 input_queue_semaphore_.Signal();
167 stop_semaphore_.Wait(); 175 stop_semaphore_.Wait();
168 FlushOutputQueue(true); 176 FlushOutputQueue(true);
177 if (FLAG_concurrent_osr) FlushOsrBuffer(true);
169 } 178 }
170 179
171 180
172 void OptimizingCompilerThread::Stop() { 181 void OptimizingCompilerThread::Stop() {
173 ASSERT(!IsOptimizerThread()); 182 ASSERT(!IsOptimizerThread());
174 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP)); 183 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
175 input_queue_semaphore_.Signal(); 184 input_queue_semaphore_.Signal();
176 stop_semaphore_.Wait(); 185 stop_semaphore_.Wait();
177 186
178 if (FLAG_concurrent_recompilation_delay != 0) { 187 if (FLAG_concurrent_recompilation_delay != 0) {
179 // Barrier when loading queue length is not necessary since the write 188 // Barrier when loading queue length is not necessary since the write
180 // happens in CompileNext on the same thread. 189 // happens in CompileNext on the same thread.
181 // This is used only for testing. 190 // This is used only for testing.
182 while (NoBarrier_Load(&queue_length_) > 0) CompileNext(); 191 while (NoBarrier_Load(&queue_length_) > 0) CompileNext();
183 InstallOptimizedFunctions(); 192 InstallOptimizedFunctions();
184 } else { 193 } else {
185 FlushInputQueue(false); 194 FlushInputQueue(false);
186 FlushOutputQueue(false); 195 FlushOutputQueue(false);
187 } 196 }
188 197
198 if (FLAG_concurrent_osr) FlushOsrBuffer(false);
199
189 if (FLAG_trace_concurrent_recompilation) { 200 if (FLAG_trace_concurrent_recompilation) {
190 double percentage = time_spent_compiling_.PercentOf(time_spent_total_); 201 double percentage = time_spent_compiling_.PercentOf(time_spent_total_);
191 PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage); 202 PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage);
192 } 203 }
193 204
194 if (FLAG_trace_osr && FLAG_concurrent_osr) { 205 if ((FLAG_trace_osr || FLAG_trace_concurrent_recompilation) &&
206 FLAG_concurrent_osr) {
195 PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_); 207 PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_);
196 } 208 }
197 209
198 Join(); 210 Join();
199 } 211 }
200 212
201 213
202 void OptimizingCompilerThread::InstallOptimizedFunctions() { 214 void OptimizingCompilerThread::InstallOptimizedFunctions() {
203 ASSERT(!IsOptimizerThread()); 215 ASSERT(!IsOptimizerThread());
204 HandleScope handle_scope(isolate_); 216 HandleScope handle_scope(isolate_);
205 217
206 OptimizingCompiler* compiler; 218 OptimizingCompiler* compiler;
207 while (true) { 219 while (true) {
208 { LockGuard<Mutex> access_queue(&queue_mutex_); 220 { LockGuard<Mutex> access_queue(&queue_mutex_);
209 if (!output_queue_.Dequeue(&compiler)) break; 221 if (!output_queue_.Dequeue(&compiler)) break;
210 } 222 }
211 Compiler::InstallOptimizedCode(compiler); 223 CompilationInfo* info = compiler->info();
224 if (info->osr_ast_id().IsNone()) {
225 Compiler::InstallOptimizedCode(compiler);
226 } else {
227 if (FLAG_trace_osr) {
228 PrintF("[COSR - ");
229 info->closure()->PrintName();
230 PrintF(" is ready for install and entry at AST id %d]\n",
231 info->osr_ast_id().ToInt());
232 }
233 compiler->WaitForInstall();
234 BackEdgeTable::RemoveStackCheck(info);
235 }
212 } 236 }
213
214 // Remove the oldest OSR candidates that are ready so that we
215 // only have limited number of them waiting.
216 if (FLAG_concurrent_osr) RemoveStaleOSRCandidates();
217 } 237 }
218 238
219 239
220 void OptimizingCompilerThread::QueueForOptimization( 240 void OptimizingCompilerThread::QueueForOptimization(
221 OptimizingCompiler* optimizing_compiler) { 241 OptimizingCompiler* optimizing_compiler) {
222 ASSERT(IsQueueAvailable()); 242 ASSERT(IsQueueAvailable());
223 ASSERT(!IsOptimizerThread()); 243 ASSERT(!IsOptimizerThread());
224 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1)); 244 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
225 if (optimizing_compiler->info()->osr_ast_id().IsNone()) { 245 CompilationInfo* info = optimizing_compiler->info();
226 optimizing_compiler->info()->closure()->MarkInRecompileQueue(); 246 if (info->osr_ast_id().IsNone()) {
247 info->closure()->MarkInRecompileQueue();
227 } else { 248 } else {
228 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 249 if (FLAG_trace_concurrent_recompilation) {
229 osr_candidates_.Add(optimizing_compiler); 250 PrintF(" ** Queueing ");
251 info->closure()->PrintName();
252 PrintF(" for concurrent on-stack replacement.\n");
253 }
254 AddToOsrBuffer(optimizing_compiler);
230 osr_attempts_++; 255 osr_attempts_++;
256 BackEdgeTable::AddStackCheck(info);
231 } 257 }
232 input_queue_.Enqueue(optimizing_compiler); 258 input_queue_.Enqueue(optimizing_compiler);
233 input_queue_semaphore_.Signal(); 259 input_queue_semaphore_.Signal();
234 } 260 }
235 261
236 262
237 OptimizingCompiler* OptimizingCompilerThread::FindReadyOSRCandidate( 263 OptimizingCompiler* OptimizingCompilerThread::FindReadyOSRCandidate(
238 Handle<JSFunction> function, uint32_t osr_pc_offset) { 264 Handle<JSFunction> function, uint32_t osr_pc_offset) {
239 ASSERT(!IsOptimizerThread()); 265 ASSERT(!IsOptimizerThread());
240 OptimizingCompiler* result = NULL; 266 OptimizingCompiler* result = NULL;
241 { LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 267 for (int i = 0; i < osr_buffer_size_; i++) {
242 for (int i = 0; i < ready_for_osr_.length(); i++) { 268 result = osr_buffer_[i];
243 if (ready_for_osr_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { 269 if (result == NULL) continue;
244 osr_hits_++; 270 if (result->IsWaitingForInstall() &&
245 result = ready_for_osr_.Remove(i); 271 result->info()->HasSameOsrEntry(function, osr_pc_offset)) {
246 break; 272 osr_hits_++;
247 } 273 osr_buffer_[i] = NULL;
274 return result;
248 } 275 }
249 } 276 }
250 RemoveStaleOSRCandidates(); 277 return NULL;
251 return result;
252 } 278 }
253 279
254 280
255 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function, 281 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function,
256 uint32_t osr_pc_offset) { 282 uint32_t osr_pc_offset) {
257 ASSERT(!IsOptimizerThread()); 283 ASSERT(!IsOptimizerThread());
258 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 284 for (int i = 0; i < osr_buffer_size_; i++) {
259 for (int i = 0; i < osr_candidates_.length(); i++) { 285 if (osr_buffer_[i] != NULL &&
260 if (osr_candidates_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { 286 osr_buffer_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) {
261 return true; 287 return !osr_buffer_[i]->IsWaitingForInstall();
262 } 288 }
263 } 289 }
264 return false; 290 return false;
265 } 291 }
266 292
267 293
268 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) { 294 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) {
269 ASSERT(!IsOptimizerThread()); 295 ASSERT(!IsOptimizerThread());
270 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 296 for (int i = 0; i < osr_buffer_size_; i++) {
271 for (int i = 0; i < osr_candidates_.length(); i++) { 297 if (osr_buffer_[i] != NULL &&
272 if (*osr_candidates_[i]->info()->closure() == function) { 298 *osr_buffer_[i]->info()->closure() == function) {
273 return true; 299 return !osr_buffer_[i]->IsWaitingForInstall();
274 } 300 }
275 } 301 }
276 return false; 302 return false;
277 } 303 }
278 304
279 305
280 void OptimizingCompilerThread::RemoveStaleOSRCandidates(int limit) { 306 void OptimizingCompilerThread::AddToOsrBuffer(OptimizingCompiler* compiler) {
281 ASSERT(!IsOptimizerThread()); 307 ASSERT(!IsOptimizerThread());
282 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 308 // Store into next empty slot or replace next stale OSR job that's waiting
283 while (ready_for_osr_.length() > limit) { 309 // in vain. Dispose in the latter case.
284 OptimizingCompiler* compiler = ready_for_osr_.Remove(0); 310 OptimizingCompiler* stale;
285 CompilationInfo* throw_away = compiler->info(); 311 while (true) {
286 if (FLAG_trace_osr) { 312 stale = osr_buffer_[osr_cursor_];
287 PrintF("[COSR - Discarded "); 313 if (stale == NULL) break;
288 throw_away->closure()->PrintName(); 314 if (stale->IsWaitingForInstall()) {
289 PrintF(", AST id %d]\n", 315 CompilationInfo* info = stale->info();
290 throw_away->osr_ast_id().ToInt()); 316 if (FLAG_trace_osr) {
317 PrintF("[COSR - Discarded ");
318 info->closure()->PrintName();
319 PrintF(", AST id %d]\n", info->osr_ast_id().ToInt());
320 }
321 BackEdgeTable::RemoveStackCheck(info);
322 DisposeOptimizingCompiler(stale, false);
323 break;
291 } 324 }
292 delete throw_away; 325 AdvanceOsrCursor();
293 } 326 }
327
328 osr_buffer_[osr_cursor_] = compiler;
329 AdvanceOsrCursor();
294 } 330 }
295 331
296 332
297 #ifdef DEBUG 333 #ifdef DEBUG
298 bool OptimizingCompilerThread::IsOptimizerThread() { 334 bool OptimizingCompilerThread::IsOptimizerThread() {
299 if (!FLAG_concurrent_recompilation) return false; 335 if (!FLAG_concurrent_recompilation) return false;
300 LockGuard<Mutex> lock_guard(&thread_id_mutex_); 336 LockGuard<Mutex> lock_guard(&thread_id_mutex_);
301 return ThreadId::Current().ToInteger() == thread_id_; 337 return ThreadId::Current().ToInteger() == thread_id_;
302 } 338 }
303 #endif 339 #endif
304 340
305 341
306 } } // namespace v8::internal 342 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/optimizing-compiler-thread.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698