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

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

Issue 25505002: Improve queuing for concurrent OSR. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 88
89 if (FLAG_trace_concurrent_recompilation) { 89 if (FLAG_trace_concurrent_recompilation) {
90 time_spent_compiling_ += compiling_timer.Elapsed(); 90 time_spent_compiling_ += compiling_timer.Elapsed();
91 } 91 }
92 } 92 }
93 } 93 }
94 94
95 95
96 void OptimizingCompilerThread::CompileNext() { 96 void OptimizingCompilerThread::CompileNext() {
97 RecompileJob* job = NULL; 97 RecompileJob* job = NULL;
98 bool result = input_queue_.Dequeue(&job); 98 { LockGuard<Mutex> access_input(&input_mutex_);
99 USE(result); 99 job = input_queue_.Dequeue();
100 ASSERT(result); 100 }
101 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
102 101
103 // The function may have already been optimized by OSR. Simply continue. 102 // The function may have already been optimized by OSR. Simply continue.
104 RecompileJob::Status status = job->OptimizeGraph(); 103 RecompileJob::Status status = job->OptimizeGraph();
105 USE(status); // Prevent an unused-variable error in release mode. 104 USE(status); // Prevent an unused-variable error in release mode.
106 ASSERT(status != RecompileJob::FAILED); 105 ASSERT(status != RecompileJob::FAILED);
107 106
108 // The function may have already been optimized by OSR. Simply continue. 107 // The function may have already been optimized by OSR. Simply continue.
109 // Use a mutex to make sure that functions marked for install 108 // Use a mutex to make sure that functions marked for install
110 // are always also queued. 109 // are always also queued.
111 output_queue_.Enqueue(job); 110 output_queue_.Enqueue(job);
(...skipping 12 matching lines...) Expand all
124 Handle<JSFunction> function = info->closure(); 123 Handle<JSFunction> function = info->closure();
125 function->ReplaceCode(function->shared()->code()); 124 function->ReplaceCode(function->shared()->code());
126 } 125 }
127 } 126 }
128 delete info; 127 delete info;
129 } 128 }
130 129
131 130
132 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) { 131 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) {
133 RecompileJob* job; 132 RecompileJob* job;
134 while (input_queue_.Dequeue(&job)) { 133 while (true) {
134 { LockGuard<Mutex> access_input(&input_mutex_);
135 if (input_queue_.length() == 0) break;
136 job = input_queue_.Dequeue();
137 }
135 // This should not block, since we have one signal on the input queue 138 // This should not block, since we have one signal on the input queue
136 // semaphore corresponding to each element in the input queue. 139 // semaphore corresponding to each element in the input queue.
137 input_queue_semaphore_.Wait(); 140 input_queue_semaphore_.Wait();
138 // OSR jobs are dealt with separately. 141 // OSR jobs are dealt with separately.
139 if (!job->info()->is_osr()) { 142 if (!job->info()->is_osr()) {
140 DisposeRecompileJob(job, restore_function_code); 143 DisposeRecompileJob(job, restore_function_code);
141 } 144 }
142 } 145 }
143 Release_Store(&queue_length_, static_cast<AtomicWord>(0));
144 } 146 }
145 147
146 148
147 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) { 149 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
148 RecompileJob* job; 150 RecompileJob* job;
149 while (output_queue_.Dequeue(&job)) { 151 while (output_queue_.Dequeue(&job)) {
150 // OSR jobs are dealt with separately. 152 // OSR jobs are dealt with separately.
151 if (!job->info()->is_osr()) { 153 if (!job->info()->is_osr()) {
152 DisposeRecompileJob(job, restore_function_code); 154 DisposeRecompileJob(job, restore_function_code);
153 } 155 }
154 } 156 }
155 } 157 }
156 158
157 159
158 void OptimizingCompilerThread::FlushOsrBuffer(bool restore_function_code) { 160 void OptimizingCompilerThread::FlushOsrBuffer(bool restore_function_code) {
159 RecompileJob* job; 161 RecompileJob* job;
160 for (int i = 0; i < osr_buffer_size_; i++) { 162 for (int i = 0; i < osr_buffer_.capacity(); i++) {
161 job = osr_buffer_[i]; 163 job = osr_buffer_.Remove(i);
162 if (job != NULL) DisposeRecompileJob(job, restore_function_code); 164 if (job != NULL) DisposeRecompileJob(job, restore_function_code);
163 } 165 }
164 osr_cursor_ = 0;
165 } 166 }
166 167
167 168
168 void OptimizingCompilerThread::Flush() { 169 void OptimizingCompilerThread::Flush() {
169 ASSERT(!IsOptimizerThread()); 170 ASSERT(!IsOptimizerThread());
170 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH)); 171 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
171 input_queue_semaphore_.Signal(); 172 input_queue_semaphore_.Signal();
172 stop_semaphore_.Wait(); 173 stop_semaphore_.Wait();
173 FlushOutputQueue(true); 174 FlushOutputQueue(true);
174 if (FLAG_concurrent_osr) FlushOsrBuffer(true); 175 if (FLAG_concurrent_osr) FlushOsrBuffer(true);
175 if (FLAG_trace_concurrent_recompilation) { 176 if (FLAG_trace_concurrent_recompilation) {
176 PrintF(" ** Flushed concurrent recompilation queues.\n"); 177 PrintF(" ** Flushed concurrent recompilation queues.\n");
177 } 178 }
178 } 179 }
179 180
180 181
181 void OptimizingCompilerThread::Stop() { 182 void OptimizingCompilerThread::Stop() {
182 ASSERT(!IsOptimizerThread()); 183 ASSERT(!IsOptimizerThread());
183 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP)); 184 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
184 input_queue_semaphore_.Signal(); 185 input_queue_semaphore_.Signal();
185 stop_semaphore_.Wait(); 186 stop_semaphore_.Wait();
186 187
187 if (FLAG_concurrent_recompilation_delay != 0) { 188 if (FLAG_concurrent_recompilation_delay != 0) {
188 // Barrier when loading queue length is not necessary since the write 189 // At this point the optimizing compiler threa's event loop has stopped.
189 // happens in CompileNext on the same thread. 190 // There is no need for a mutex when reading input_queue_.
190 // This is used only for testing. 191 while (input_queue_.length() > 0) CompileNext();
191 while (NoBarrier_Load(&queue_length_) > 0) CompileNext();
192 InstallOptimizedFunctions(); 192 InstallOptimizedFunctions();
193 } else { 193 } else {
194 FlushInputQueue(false); 194 FlushInputQueue(false);
195 FlushOutputQueue(false); 195 FlushOutputQueue(false);
196 } 196 }
197 197
198 if (FLAG_concurrent_osr) FlushOsrBuffer(false); 198 if (FLAG_concurrent_osr) FlushOsrBuffer(false);
199 199
200 if (FLAG_trace_concurrent_recompilation) { 200 if (FLAG_trace_concurrent_recompilation) {
201 double percentage = time_spent_compiling_.PercentOf(time_spent_total_); 201 double percentage = time_spent_compiling_.PercentOf(time_spent_total_);
(...skipping 28 matching lines...) Expand all
230 } else { 230 } else {
231 Compiler::InstallOptimizedCode(job); 231 Compiler::InstallOptimizedCode(job);
232 } 232 }
233 } 233 }
234 } 234 }
235 235
236 236
237 void OptimizingCompilerThread::QueueForOptimization(RecompileJob* job) { 237 void OptimizingCompilerThread::QueueForOptimization(RecompileJob* job) {
238 ASSERT(IsQueueAvailable()); 238 ASSERT(IsQueueAvailable());
239 ASSERT(!IsOptimizerThread()); 239 ASSERT(!IsOptimizerThread());
240 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
241 CompilationInfo* info = job->info(); 240 CompilationInfo* info = job->info();
242 if (info->is_osr()) { 241 if (info->is_osr()) {
243 if (FLAG_trace_concurrent_recompilation) { 242 if (FLAG_trace_concurrent_recompilation) {
244 PrintF(" ** Queueing "); 243 PrintF(" ** Queueing ");
245 info->closure()->PrintName(); 244 info->closure()->PrintName();
246 PrintF(" for concurrent on-stack replacement.\n"); 245 PrintF(" for concurrent on-stack replacement.\n");
247 } 246 }
248 AddToOsrBuffer(job);
249 osr_attempts_++; 247 osr_attempts_++;
250 BackEdgeTable::AddStackCheck(info); 248 BackEdgeTable::AddStackCheck(info);
249 AddToOsrBuffer(job);
250 { LockGuard<Mutex> access_input(&input_mutex_);
251 input_queue_.Prepend(job);
252 }
251 } else { 253 } else {
252 info->closure()->MarkInRecompileQueue(); 254 info->closure()->MarkInRecompileQueue();
255 { LockGuard<Mutex> access_input(&input_mutex_);
256 input_queue_.Enqueue(job);
257 }
253 } 258 }
254 input_queue_.Enqueue(job);
255 input_queue_semaphore_.Signal(); 259 input_queue_semaphore_.Signal();
256 } 260 }
257 261
258 262
259 RecompileJob* OptimizingCompilerThread::FindReadyOSRCandidate( 263 RecompileJob* OptimizingCompilerThread::FindReadyOSRCandidate(
260 Handle<JSFunction> function, uint32_t osr_pc_offset) { 264 Handle<JSFunction> function, uint32_t osr_pc_offset) {
261 ASSERT(!IsOptimizerThread()); 265 ASSERT(!IsOptimizerThread());
262 RecompileJob* result = NULL; 266 for (int i = 0; i < osr_buffer_.capacity(); i++) {
263 for (int i = 0; i < osr_buffer_size_; i++) { 267 RecompileJob* result = osr_buffer_.Get(i);
264 result = osr_buffer_[i];
265 if (result == NULL) continue; 268 if (result == NULL) continue;
266 if (result->IsWaitingForInstall() && 269 if (result->IsWaitingForInstall() &&
267 result->info()->HasSameOsrEntry(function, osr_pc_offset)) { 270 result->info()->HasSameOsrEntry(function, osr_pc_offset)) {
268 osr_hits_++; 271 osr_hits_++;
269 osr_buffer_[i] = NULL; 272 osr_buffer_.Remove(i);
270 return result; 273 return result;
271 } 274 }
272 } 275 }
273 return NULL; 276 return NULL;
274 } 277 }
275 278
276 279
277 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function, 280 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function,
278 uint32_t osr_pc_offset) { 281 uint32_t osr_pc_offset) {
279 ASSERT(!IsOptimizerThread()); 282 ASSERT(!IsOptimizerThread());
280 for (int i = 0; i < osr_buffer_size_; i++) { 283 for (int i = 0; i < osr_buffer_.capacity(); i++) {
281 if (osr_buffer_[i] != NULL && 284 RecompileJob* result = osr_buffer_.Get(i);
282 osr_buffer_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { 285 if (result != NULL &&
283 return !osr_buffer_[i]->IsWaitingForInstall(); 286 result->info()->HasSameOsrEntry(function, osr_pc_offset)) {
287 return !result->IsWaitingForInstall();
284 } 288 }
285 } 289 }
286 return false; 290 return false;
287 } 291 }
288 292
289 293
290 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) { 294 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) {
291 ASSERT(!IsOptimizerThread()); 295 ASSERT(!IsOptimizerThread());
292 for (int i = 0; i < osr_buffer_size_; i++) { 296 for (int i = 0; i < osr_buffer_.capacity(); i++) {
293 if (osr_buffer_[i] != NULL && 297 RecompileJob* result = osr_buffer_.Get(i);
294 *osr_buffer_[i]->info()->closure() == function) { 298 if (result != NULL && *result->info()->closure() == function) {
295 return !osr_buffer_[i]->IsWaitingForInstall(); 299 return !result->IsWaitingForInstall();
296 } 300 }
297 } 301 }
298 return false; 302 return false;
299 } 303 }
300 304
301 305
302 void OptimizingCompilerThread::AddToOsrBuffer(RecompileJob* job) { 306 void OptimizingCompilerThread::AddToOsrBuffer(RecompileJob* job) {
303 ASSERT(!IsOptimizerThread()); 307 ASSERT(!IsOptimizerThread());
304 // Store into next empty slot or replace next stale OSR job that's waiting 308 // Find the next slot that is empty or has a stale job.
305 // in vain. Dispose in the latter case.
306 RecompileJob* stale;
307 while (true) { 309 while (true) {
308 stale = osr_buffer_[osr_cursor_]; 310 RecompileJob* stale = osr_buffer_.Current();
309 if (stale == NULL) break; 311 if (stale == NULL || stale->IsWaitingForInstall()) break;
310 if (stale->IsWaitingForInstall()) { 312 osr_buffer_.AdvanceCursor();
311 CompilationInfo* info = stale->info();
312 if (FLAG_trace_osr) {
313 PrintF("[COSR - Discarded ");
314 info->closure()->PrintName();
315 PrintF(", AST id %d]\n", info->osr_ast_id().ToInt());
316 }
317 DisposeRecompileJob(stale, false);
318 break;
319 }
320 AdvanceOsrCursor();
321 } 313 }
322 314
323 osr_buffer_[osr_cursor_] = job; 315 // Add to found slot and dispose the evicted job.
324 AdvanceOsrCursor(); 316 RecompileJob* evicted = osr_buffer_.Add(job);
317 if (evicted != NULL) {
318 ASSERT(evicted->IsWaitingForInstall());
319 CompilationInfo* info = evicted->info();
320 if (FLAG_trace_osr) {
321 PrintF("[COSR - Discarded ");
322 info->closure()->PrintName();
323 PrintF(", AST id %d]\n", info->osr_ast_id().ToInt());
324 }
325 DisposeRecompileJob(evicted, false);
326 }
325 } 327 }
326 328
327 329
328 #ifdef DEBUG 330 #ifdef DEBUG
329 bool OptimizingCompilerThread::IsOptimizerThread() { 331 bool OptimizingCompilerThread::IsOptimizerThread() {
330 if (!FLAG_concurrent_recompilation) return false; 332 if (!FLAG_concurrent_recompilation) return false;
331 LockGuard<Mutex> lock_guard(&thread_id_mutex_); 333 LockGuard<Mutex> lock_guard(&thread_id_mutex_);
332 return ThreadId::Current().ToInteger() == thread_id_; 334 return ThreadId::Current().ToInteger() == thread_id_;
333 } 335 }
334 #endif 336 #endif
335 337
336 338
337 } } // namespace v8::internal 339 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698