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

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

Issue 950323002: Use mutex/condition variables to synchronize threads (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: updates Created 5 years, 9 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
« no previous file with comments | « src/optimizing-compiler-thread.h ('k') | no next file » | 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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/optimizing-compiler-thread.h" 5 #include "src/optimizing-compiler-thread.h"
6 6
7 #include "src/v8.h" 7 #include "src/v8.h"
8 8
9 #include "src/base/atomicops.h" 9 #include "src/base/atomicops.h"
10 #include "src/full-codegen.h" 10 #include "src/full-codegen.h"
(...skipping 25 matching lines...) Expand all
36 } 36 }
37 delete info; 37 delete info;
38 } 38 }
39 39
40 } // namespace 40 } // namespace
41 41
42 42
43 class OptimizingCompilerThread::CompileTask : public v8::Task { 43 class OptimizingCompilerThread::CompileTask : public v8::Task {
44 public: 44 public:
45 explicit CompileTask(Isolate* isolate) : isolate_(isolate) { 45 explicit CompileTask(Isolate* isolate) : isolate_(isolate) {
46 base::NoBarrier_AtomicIncrement( 46 OptimizingCompilerThread* thread = isolate_->optimizing_compiler_thread();
47 &isolate_->optimizing_compiler_thread()->ref_count_, 1); 47 base::LockGuard<base::Mutex> lock_guard(&thread->ref_count_mutex_);
48 ++thread->ref_count_;
48 } 49 }
49 50
50 virtual ~CompileTask() {} 51 virtual ~CompileTask() {}
51 52
52 private: 53 private:
53 // v8::Task overrides. 54 // v8::Task overrides.
54 void Run() OVERRIDE { 55 void Run() OVERRIDE {
55 DisallowHeapAllocation no_allocation; 56 DisallowHeapAllocation no_allocation;
56 DisallowHandleAllocation no_handles; 57 DisallowHandleAllocation no_handles;
57 DisallowHandleDereference no_deref; 58 DisallowHandleDereference no_deref;
58 59
59 OptimizingCompilerThread* thread = isolate_->optimizing_compiler_thread(); 60 OptimizingCompilerThread* thread = isolate_->optimizing_compiler_thread();
60 StopFlag flag = CONTINUE;
61
62 { 61 {
63 TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_); 62 TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
64 63
65 if (thread->recompilation_delay_ != 0) { 64 if (thread->recompilation_delay_ != 0) {
66 base::OS::Sleep(thread->recompilation_delay_); 65 base::OS::Sleep(thread->recompilation_delay_);
67 } 66 }
68 67
69 OptimizedCompileJob* job = thread->NextInput(&flag); 68 thread->CompileNext(thread->NextInput(true));
70 69 }
71 switch (flag) { 70 {
72 case CONTINUE: 71 base::LockGuard<base::Mutex> lock_guard(&thread->ref_count_mutex_);
73 thread->CompileNext(job); 72 if (--thread->ref_count_ == 0) {
74 break; 73 thread->ref_count_zero_.NotifyOne();
75
76 case STOP:
77 case FLUSH: {
78 AllowHandleDereference allow_handle_dereference;
79 if (!job->info()->is_osr()) {
80 DisposeOptimizedCompileJob(job, true);
81 }
82 break;
83 }
84 } 74 }
85 } 75 }
86 if (flag == STOP) {
87 base::Release_Store(&thread->stop_thread_,
88 static_cast<base::AtomicWord>(CONTINUE));
89 thread->stop_semaphore_.Signal();
90 }
91
92 if (base::NoBarrier_AtomicIncrement(&thread->ref_count_, -1) == 0) {
93 thread->stop_semaphore_.Signal();
94 }
95 } 76 }
96 77
97 Isolate* isolate_; 78 Isolate* isolate_;
98 79
99 DISALLOW_COPY_AND_ASSIGN(CompileTask); 80 DISALLOW_COPY_AND_ASSIGN(CompileTask);
100 }; 81 };
101 82
102 83
103 OptimizingCompilerThread::~OptimizingCompilerThread() { 84 OptimizingCompilerThread::~OptimizingCompilerThread() {
104 if (base::NoBarrier_AtomicIncrement(&ref_count_, -1) > 0) { 85 #ifdef DEBUG
105 stop_semaphore_.Wait(); 86 {
87 base::LockGuard<base::Mutex> lock_guard(&ref_count_mutex_);
88 DCHECK_EQ(0, ref_count_);
106 } 89 }
90 #endif
107 DCHECK_EQ(0, input_queue_length_); 91 DCHECK_EQ(0, input_queue_length_);
108 DeleteArray(input_queue_); 92 DeleteArray(input_queue_);
109 if (FLAG_concurrent_osr) { 93 if (FLAG_concurrent_osr) {
110 #ifdef DEBUG 94 #ifdef DEBUG
111 for (int i = 0; i < osr_buffer_capacity_; i++) { 95 for (int i = 0; i < osr_buffer_capacity_; i++) {
112 CHECK_NULL(osr_buffer_[i]); 96 CHECK_NULL(osr_buffer_[i]);
113 } 97 }
114 #endif 98 #endif
115 DeleteArray(osr_buffer_); 99 DeleteArray(osr_buffer_);
116 } 100 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 152
169 CompileNext(NextInput()); 153 CompileNext(NextInput());
170 154
171 if (tracing_enabled_) { 155 if (tracing_enabled_) {
172 time_spent_compiling_ += compiling_timer.Elapsed(); 156 time_spent_compiling_ += compiling_timer.Elapsed();
173 } 157 }
174 } 158 }
175 } 159 }
176 160
177 161
178 OptimizedCompileJob* OptimizingCompilerThread::NextInput(StopFlag* flag) { 162 OptimizedCompileJob* OptimizingCompilerThread::NextInput(
163 bool check_if_flushing) {
179 base::LockGuard<base::Mutex> access_input_queue_(&input_queue_mutex_); 164 base::LockGuard<base::Mutex> access_input_queue_(&input_queue_mutex_);
180 if (input_queue_length_ == 0) { 165 if (input_queue_length_ == 0) return NULL;
181 if (flag) {
182 UNREACHABLE();
183 *flag = CONTINUE;
184 }
185 return NULL;
186 }
187 OptimizedCompileJob* job = input_queue_[InputQueueIndex(0)]; 166 OptimizedCompileJob* job = input_queue_[InputQueueIndex(0)];
188 DCHECK_NOT_NULL(job); 167 DCHECK_NOT_NULL(job);
189 input_queue_shift_ = InputQueueIndex(1); 168 input_queue_shift_ = InputQueueIndex(1);
190 input_queue_length_--; 169 input_queue_length_--;
191 if (flag) { 170 if (check_if_flushing) {
192 switch (static_cast<StopFlag>(base::Acquire_Load(&stop_thread_))) { 171 if (static_cast<StopFlag>(base::Acquire_Load(&stop_thread_)) != CONTINUE) {
193 case CONTINUE: 172 if (!job->info()->is_osr()) DisposeOptimizedCompileJob(job, true);
194 *flag = CONTINUE; 173 return NULL;
195 break;
196
197 case FLUSH:
198 if (input_queue_length_ == 0) {
199 *flag = STOP;
200 } else {
201 *flag = FLUSH;
202 }
203 break;
204
205 case STOP:
206 UNREACHABLE();
207 *flag = CONTINUE;
208 break;
209 } 174 }
210 } 175 }
211 return job; 176 return job;
212 } 177 }
213 178
214 179
215 void OptimizingCompilerThread::CompileNext(OptimizedCompileJob* job) { 180 void OptimizingCompilerThread::CompileNext(OptimizedCompileJob* job) {
216 DCHECK_NOT_NULL(job); 181 if (!job) return;
217 182
218 // The function may have already been optimized by OSR. Simply continue. 183 // The function may have already been optimized by OSR. Simply continue.
219 OptimizedCompileJob::Status status = job->OptimizeGraph(); 184 OptimizedCompileJob::Status status = job->OptimizeGraph();
220 USE(status); // Prevent an unused-variable error in release mode. 185 USE(status); // Prevent an unused-variable error in release mode.
221 DCHECK(status != OptimizedCompileJob::FAILED); 186 DCHECK(status != OptimizedCompileJob::FAILED);
222 187
223 // The function may have already been optimized by OSR. Simply continue. 188 // The function may have already been optimized by OSR. Simply continue.
224 // Use a mutex to make sure that functions marked for install 189 // Use a mutex to make sure that functions marked for install
225 // are always also queued. 190 // are always also queued.
226 if (job_based_recompilation_) output_queue_mutex_.Lock(); 191 if (job_based_recompilation_) output_queue_mutex_.Lock();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 if (osr_buffer_[i] != NULL) { 227 if (osr_buffer_[i] != NULL) {
263 DisposeOptimizedCompileJob(osr_buffer_[i], restore_function_code); 228 DisposeOptimizedCompileJob(osr_buffer_[i], restore_function_code);
264 osr_buffer_[i] = NULL; 229 osr_buffer_[i] = NULL;
265 } 230 }
266 } 231 }
267 } 232 }
268 233
269 234
270 void OptimizingCompilerThread::Flush() { 235 void OptimizingCompilerThread::Flush() {
271 DCHECK(!IsOptimizerThread()); 236 DCHECK(!IsOptimizerThread());
272 bool block = true; 237 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(FLUSH));
273 if (job_based_recompilation_) { 238 if (FLAG_block_concurrent_recompilation) Unblock();
274 if (FLAG_block_concurrent_recompilation) Unblock(); 239 if (!job_based_recompilation_) {
275 { 240 input_queue_semaphore_.Signal();
276 base::LockGuard<base::Mutex> lock(&input_queue_mutex_); 241 stop_semaphore_.Wait();
277 block = input_queue_length_ > 0;
278 if (block) {
279 base::Release_Store(&stop_thread_,
280 static_cast<base::AtomicWord>(FLUSH));
281 }
282 }
283 } else { 242 } else {
284 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(FLUSH)); 243 base::LockGuard<base::Mutex> lock_guard(&ref_count_mutex_);
285 if (FLAG_block_concurrent_recompilation) Unblock(); 244 while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
245 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(CONTINUE));
286 } 246 }
287 if (!job_based_recompilation_) input_queue_semaphore_.Signal();
288 if (block) stop_semaphore_.Wait();
289 FlushOutputQueue(true); 247 FlushOutputQueue(true);
290 if (FLAG_concurrent_osr) FlushOsrBuffer(true); 248 if (FLAG_concurrent_osr) FlushOsrBuffer(true);
291 if (tracing_enabled_) { 249 if (tracing_enabled_) {
292 PrintF(" ** Flushed concurrent recompilation queues.\n"); 250 PrintF(" ** Flushed concurrent recompilation queues.\n");
293 } 251 }
294 } 252 }
295 253
296 254
297 void OptimizingCompilerThread::Stop() { 255 void OptimizingCompilerThread::Stop() {
298 DCHECK(!IsOptimizerThread()); 256 DCHECK(!IsOptimizerThread());
299 bool block = true; 257 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(STOP));
300 if (job_based_recompilation_) { 258 if (FLAG_block_concurrent_recompilation) Unblock();
301 if (FLAG_block_concurrent_recompilation) Unblock(); 259 if (!job_based_recompilation_) {
302 { 260 input_queue_semaphore_.Signal();
303 base::LockGuard<base::Mutex> lock(&input_queue_mutex_); 261 stop_semaphore_.Wait();
304 block = input_queue_length_ > 0;
305 if (block) {
306 base::Release_Store(&stop_thread_,
307 static_cast<base::AtomicWord>(FLUSH));
308 }
309 }
310 } else { 262 } else {
311 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(STOP)); 263 base::LockGuard<base::Mutex> lock_guard(&ref_count_mutex_);
312 if (FLAG_block_concurrent_recompilation) Unblock(); 264 while (ref_count_ > 0) ref_count_zero_.Wait(&ref_count_mutex_);
265 base::Release_Store(&stop_thread_, static_cast<base::AtomicWord>(CONTINUE));
313 } 266 }
314 if (!job_based_recompilation_) input_queue_semaphore_.Signal();
315 if (block) stop_semaphore_.Wait();
316 267
317 if (recompilation_delay_ != 0) { 268 if (recompilation_delay_ != 0) {
318 // At this point the optimizing compiler thread's event loop has stopped. 269 // At this point the optimizing compiler thread's event loop has stopped.
319 // There is no need for a mutex when reading input_queue_length_. 270 // There is no need for a mutex when reading input_queue_length_.
320 while (input_queue_length_ > 0) CompileNext(NextInput()); 271 while (input_queue_length_ > 0) CompileNext(NextInput());
321 InstallOptimizedFunctions(); 272 InstallOptimizedFunctions();
322 } else { 273 } else {
323 FlushInputQueue(false); 274 FlushInputQueue(false);
324 FlushOutputQueue(false); 275 FlushOutputQueue(false);
325 } 276 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 452
502 453
503 bool OptimizingCompilerThread::IsOptimizerThread() { 454 bool OptimizingCompilerThread::IsOptimizerThread() {
504 base::LockGuard<base::Mutex> lock_guard(&thread_id_mutex_); 455 base::LockGuard<base::Mutex> lock_guard(&thread_id_mutex_);
505 return ThreadId::Current().ToInteger() == thread_id_; 456 return ThreadId::Current().ToInteger() == thread_id_;
506 } 457 }
507 #endif 458 #endif
508 459
509 460
510 } } // namespace v8::internal 461 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/optimizing-compiler-thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698