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

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

Issue 153953005: A64: Synchronize with r16993. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/platform.h » ('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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 CompileNext(); 87 CompileNext();
87 88
88 if (FLAG_trace_concurrent_recompilation) { 89 if (FLAG_trace_concurrent_recompilation) {
89 time_spent_compiling_ += compiling_timer.Elapsed(); 90 time_spent_compiling_ += compiling_timer.Elapsed();
90 } 91 }
91 } 92 }
92 } 93 }
93 94
94 95
95 void OptimizingCompilerThread::CompileNext() { 96 void OptimizingCompilerThread::CompileNext() {
96 OptimizingCompiler* optimizing_compiler = NULL; 97 RecompileJob* job = NULL;
97 bool result = input_queue_.Dequeue(&optimizing_compiler); 98 bool result = input_queue_.Dequeue(&job);
98 USE(result); 99 USE(result);
99 ASSERT(result); 100 ASSERT(result);
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 RecompileJob::Status status = job->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 != RecompileJob::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(job);
112 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 113 isolate_->stack_guard()->RequestInstallCode();
113 osr_candidates_.RemoveElement(optimizing_compiler); 114 }
114 ready_for_osr_.Add(optimizing_compiler); 115
115 } else { 116
116 LockGuard<Mutex> access_queue(&queue_mutex_); 117 static void DisposeRecompileJob(RecompileJob* job,
117 output_queue_.Enqueue(optimizing_compiler); 118 bool restore_function_code) {
118 isolate_->stack_guard()->RequestInstallCode(); 119 // The recompile job is allocated in the CompilationInfo's zone.
120 CompilationInfo* info = job->info();
121 if (restore_function_code) {
122 if (info->is_osr()) {
123 if (!job->IsWaitingForInstall()) BackEdgeTable::RemoveStackCheck(info);
124 } else {
125 Handle<JSFunction> function = info->closure();
126 function->ReplaceCode(function->shared()->code());
127 }
128 }
129 delete info;
130 }
131
132
133 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) {
134 RecompileJob* job;
135 while (input_queue_.Dequeue(&job)) {
136 // This should not block, since we have one signal on the input queue
137 // semaphore corresponding to each element in the input queue.
138 input_queue_semaphore_.Wait();
139 // OSR jobs are dealt with separately.
140 if (!job->info()->is_osr()) {
141 DisposeRecompileJob(job, restore_function_code);
142 }
143 }
144 Release_Store(&queue_length_, static_cast<AtomicWord>(0));
145 }
146
147
148 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
149 RecompileJob* job;
150 while (true) {
151 { LockGuard<Mutex> access_queue(&queue_mutex_);
152 if (!output_queue_.Dequeue(&job)) break;
153 }
154 // OSR jobs are dealt with separately.
155 if (!job->info()->is_osr()) {
156 DisposeRecompileJob(job, restore_function_code);
157 }
119 } 158 }
120 } 159 }
121 160
122 161
123 void OptimizingCompilerThread::FlushInputQueue(bool restore_function_code) { 162 void OptimizingCompilerThread::FlushOsrBuffer(bool restore_function_code) {
124 OptimizingCompiler* optimizing_compiler; 163 RecompileJob* job;
125 // The optimizing compiler is allocated in the CompilationInfo's zone. 164 for (int i = 0; i < osr_buffer_size_; i++) {
126 while (input_queue_.Dequeue(&optimizing_compiler)) { 165 job = osr_buffer_[i];
127 // This should not block, since we have one signal on the input queue 166 if (job != NULL) DisposeRecompileJob(job, restore_function_code);
128 // semaphore corresponding to each element in the input queue.
129 input_queue_semaphore_.Wait();
130 CompilationInfo* info = optimizing_compiler->info();
131 if (restore_function_code) {
132 Handle<JSFunction> function = info->closure();
133 function->ReplaceCode(function->shared()->code());
134 }
135 delete info;
136 } 167 }
137 Release_Store(&queue_length_, static_cast<AtomicWord>(0)); 168 osr_cursor_ = 0;
138
139 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_);
140 osr_candidates_.Clear();
141 } 169 }
142 170
143 171
144 void OptimizingCompilerThread::FlushOutputQueue(bool restore_function_code) {
145 OptimizingCompiler* optimizing_compiler;
146 // The optimizing compiler is allocated in the CompilationInfo's zone.
147 while (true) {
148 { LockGuard<Mutex> access_queue(&queue_mutex_);
149 if (!output_queue_.Dequeue(&optimizing_compiler)) break;
150 }
151 CompilationInfo* info = optimizing_compiler->info();
152 if (restore_function_code) {
153 Handle<JSFunction> function = info->closure();
154 function->ReplaceCode(function->shared()->code());
155 }
156 delete info;
157 }
158
159 RemoveStaleOSRCandidates(0);
160 }
161
162
163 void OptimizingCompilerThread::Flush() { 172 void OptimizingCompilerThread::Flush() {
164 ASSERT(!IsOptimizerThread()); 173 ASSERT(!IsOptimizerThread());
165 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH)); 174 Release_Store(&stop_thread_, static_cast<AtomicWord>(FLUSH));
166 input_queue_semaphore_.Signal(); 175 input_queue_semaphore_.Signal();
167 stop_semaphore_.Wait(); 176 stop_semaphore_.Wait();
168 FlushOutputQueue(true); 177 FlushOutputQueue(true);
178 if (FLAG_concurrent_osr) FlushOsrBuffer(true);
179 if (FLAG_trace_concurrent_recompilation) {
180 PrintF(" ** Flushed concurrent recompilation queues.\n");
181 }
169 } 182 }
170 183
171 184
172 void OptimizingCompilerThread::Stop() { 185 void OptimizingCompilerThread::Stop() {
173 ASSERT(!IsOptimizerThread()); 186 ASSERT(!IsOptimizerThread());
174 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP)); 187 Release_Store(&stop_thread_, static_cast<AtomicWord>(STOP));
175 input_queue_semaphore_.Signal(); 188 input_queue_semaphore_.Signal();
176 stop_semaphore_.Wait(); 189 stop_semaphore_.Wait();
177 190
178 if (FLAG_concurrent_recompilation_delay != 0) { 191 if (FLAG_concurrent_recompilation_delay != 0) {
179 // Barrier when loading queue length is not necessary since the write 192 // Barrier when loading queue length is not necessary since the write
180 // happens in CompileNext on the same thread. 193 // happens in CompileNext on the same thread.
181 // This is used only for testing. 194 // This is used only for testing.
182 while (NoBarrier_Load(&queue_length_) > 0) CompileNext(); 195 while (NoBarrier_Load(&queue_length_) > 0) CompileNext();
183 InstallOptimizedFunctions(); 196 InstallOptimizedFunctions();
184 } else { 197 } else {
185 FlushInputQueue(false); 198 FlushInputQueue(false);
186 FlushOutputQueue(false); 199 FlushOutputQueue(false);
187 } 200 }
188 201
202 if (FLAG_concurrent_osr) FlushOsrBuffer(false);
203
189 if (FLAG_trace_concurrent_recompilation) { 204 if (FLAG_trace_concurrent_recompilation) {
190 double percentage = time_spent_compiling_.PercentOf(time_spent_total_); 205 double percentage = time_spent_compiling_.PercentOf(time_spent_total_);
191 PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage); 206 PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage);
192 } 207 }
193 208
194 if (FLAG_trace_osr && FLAG_concurrent_osr) { 209 if ((FLAG_trace_osr || FLAG_trace_concurrent_recompilation) &&
210 FLAG_concurrent_osr) {
195 PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_); 211 PrintF("[COSR hit rate %d / %d]\n", osr_hits_, osr_attempts_);
196 } 212 }
197 213
198 Join(); 214 Join();
199 } 215 }
200 216
201 217
202 void OptimizingCompilerThread::InstallOptimizedFunctions() { 218 void OptimizingCompilerThread::InstallOptimizedFunctions() {
203 ASSERT(!IsOptimizerThread()); 219 ASSERT(!IsOptimizerThread());
204 HandleScope handle_scope(isolate_); 220 HandleScope handle_scope(isolate_);
205 221
206 OptimizingCompiler* compiler; 222 RecompileJob* job;
207 while (true) { 223 while (true) {
208 { LockGuard<Mutex> access_queue(&queue_mutex_); 224 { LockGuard<Mutex> access_queue(&queue_mutex_);
209 if (!output_queue_.Dequeue(&compiler)) break; 225 if (!output_queue_.Dequeue(&job)) break;
210 } 226 }
211 Compiler::InstallOptimizedCode(compiler); 227 CompilationInfo* info = job->info();
228 if (info->is_osr()) {
229 if (FLAG_trace_osr) {
230 PrintF("[COSR - ");
231 info->closure()->PrintName();
232 PrintF(" is ready for install and entry at AST id %d]\n",
233 info->osr_ast_id().ToInt());
234 }
235 job->WaitForInstall();
236 BackEdgeTable::RemoveStackCheck(info);
237 } else {
238 Compiler::InstallOptimizedCode(job);
239 }
212 } 240 }
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 } 241 }
218 242
219 243
220 void OptimizingCompilerThread::QueueForOptimization( 244 void OptimizingCompilerThread::QueueForOptimization(RecompileJob* job) {
221 OptimizingCompiler* optimizing_compiler) {
222 ASSERT(IsQueueAvailable()); 245 ASSERT(IsQueueAvailable());
223 ASSERT(!IsOptimizerThread()); 246 ASSERT(!IsOptimizerThread());
224 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1)); 247 Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(1));
225 if (optimizing_compiler->info()->osr_ast_id().IsNone()) { 248 CompilationInfo* info = job->info();
226 optimizing_compiler->info()->closure()->MarkInRecompileQueue(); 249 if (info->is_osr()) {
250 if (FLAG_trace_concurrent_recompilation) {
251 PrintF(" ** Queueing ");
252 info->closure()->PrintName();
253 PrintF(" for concurrent on-stack replacement.\n");
254 }
255 AddToOsrBuffer(job);
256 osr_attempts_++;
257 BackEdgeTable::AddStackCheck(info);
227 } else { 258 } else {
228 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 259 info->closure()->MarkInRecompileQueue();
229 osr_candidates_.Add(optimizing_compiler);
230 osr_attempts_++;
231 } 260 }
232 input_queue_.Enqueue(optimizing_compiler); 261 input_queue_.Enqueue(job);
233 input_queue_semaphore_.Signal(); 262 input_queue_semaphore_.Signal();
234 } 263 }
235 264
236 265
237 OptimizingCompiler* OptimizingCompilerThread::FindReadyOSRCandidate( 266 RecompileJob* OptimizingCompilerThread::FindReadyOSRCandidate(
238 Handle<JSFunction> function, uint32_t osr_pc_offset) { 267 Handle<JSFunction> function, uint32_t osr_pc_offset) {
239 ASSERT(!IsOptimizerThread()); 268 ASSERT(!IsOptimizerThread());
240 OptimizingCompiler* result = NULL; 269 RecompileJob* result = NULL;
241 { LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 270 for (int i = 0; i < osr_buffer_size_; i++) {
242 for (int i = 0; i < ready_for_osr_.length(); i++) { 271 result = osr_buffer_[i];
243 if (ready_for_osr_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { 272 if (result == NULL) continue;
244 osr_hits_++; 273 if (result->IsWaitingForInstall() &&
245 result = ready_for_osr_.Remove(i); 274 result->info()->HasSameOsrEntry(function, osr_pc_offset)) {
246 break; 275 osr_hits_++;
247 } 276 osr_buffer_[i] = NULL;
277 return result;
248 } 278 }
249 } 279 }
250 RemoveStaleOSRCandidates(); 280 return NULL;
251 return result;
252 } 281 }
253 282
254 283
255 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function, 284 bool OptimizingCompilerThread::IsQueuedForOSR(Handle<JSFunction> function,
256 uint32_t osr_pc_offset) { 285 uint32_t osr_pc_offset) {
257 ASSERT(!IsOptimizerThread()); 286 ASSERT(!IsOptimizerThread());
258 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 287 for (int i = 0; i < osr_buffer_size_; i++) {
259 for (int i = 0; i < osr_candidates_.length(); i++) { 288 if (osr_buffer_[i] != NULL &&
260 if (osr_candidates_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) { 289 osr_buffer_[i]->info()->HasSameOsrEntry(function, osr_pc_offset)) {
261 return true; 290 return !osr_buffer_[i]->IsWaitingForInstall();
262 } 291 }
263 } 292 }
264 return false; 293 return false;
265 } 294 }
266 295
267 296
268 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) { 297 bool OptimizingCompilerThread::IsQueuedForOSR(JSFunction* function) {
269 ASSERT(!IsOptimizerThread()); 298 ASSERT(!IsOptimizerThread());
270 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 299 for (int i = 0; i < osr_buffer_size_; i++) {
271 for (int i = 0; i < osr_candidates_.length(); i++) { 300 if (osr_buffer_[i] != NULL &&
272 if (*osr_candidates_[i]->info()->closure() == function) { 301 *osr_buffer_[i]->info()->closure() == function) {
273 return true; 302 return !osr_buffer_[i]->IsWaitingForInstall();
274 } 303 }
275 } 304 }
276 return false; 305 return false;
277 } 306 }
278 307
279 308
280 void OptimizingCompilerThread::RemoveStaleOSRCandidates(int limit) { 309 void OptimizingCompilerThread::AddToOsrBuffer(RecompileJob* job) {
281 ASSERT(!IsOptimizerThread()); 310 ASSERT(!IsOptimizerThread());
282 LockGuard<Mutex> access_osr_lists(&osr_list_mutex_); 311 // Store into next empty slot or replace next stale OSR job that's waiting
283 while (ready_for_osr_.length() > limit) { 312 // in vain. Dispose in the latter case.
284 OptimizingCompiler* compiler = ready_for_osr_.Remove(0); 313 RecompileJob* stale;
285 CompilationInfo* throw_away = compiler->info(); 314 while (true) {
286 if (FLAG_trace_osr) { 315 stale = osr_buffer_[osr_cursor_];
287 PrintF("[COSR - Discarded "); 316 if (stale == NULL) break;
288 throw_away->closure()->PrintName(); 317 if (stale->IsWaitingForInstall()) {
289 PrintF(", AST id %d]\n", 318 CompilationInfo* info = stale->info();
290 throw_away->osr_ast_id().ToInt()); 319 if (FLAG_trace_osr) {
320 PrintF("[COSR - Discarded ");
321 info->closure()->PrintName();
322 PrintF(", AST id %d]\n", info->osr_ast_id().ToInt());
323 }
324 DisposeRecompileJob(stale, false);
325 break;
291 } 326 }
292 delete throw_away; 327 AdvanceOsrCursor();
293 } 328 }
329
330 osr_buffer_[osr_cursor_] = job;
331 AdvanceOsrCursor();
294 } 332 }
295 333
296 334
297 #ifdef DEBUG 335 #ifdef DEBUG
298 bool OptimizingCompilerThread::IsOptimizerThread() { 336 bool OptimizingCompilerThread::IsOptimizerThread() {
299 if (!FLAG_concurrent_recompilation) return false; 337 if (!FLAG_concurrent_recompilation) return false;
300 LockGuard<Mutex> lock_guard(&thread_id_mutex_); 338 LockGuard<Mutex> lock_guard(&thread_id_mutex_);
301 return ThreadId::Current().ToInteger() == thread_id_; 339 return ThreadId::Current().ToInteger() == thread_id_;
302 } 340 }
303 #endif 341 #endif
304 342
305 343
306 } } // namespace v8::internal 344 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/optimizing-compiler-thread.h ('k') | src/platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698