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

Side by Side Diff: src/compiler-dispatcher/compiler-dispatcher.cc

Issue 2618503002: Add a flag for printf debugging the compiler dispatcher (Closed)
Patch Set: updates Created 3 years, 11 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
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/compiler-dispatcher/compiler-dispatcher.h" 5 #include "src/compiler-dispatcher/compiler-dispatcher.h"
6 6
7 #include "include/v8-platform.h" 7 #include "include/v8-platform.h"
8 #include "include/v8.h" 8 #include "include/v8.h"
9 #include "src/base/platform/time.h" 9 #include "src/base/platform/time.h"
10 #include "src/cancelable-task.h" 10 #include "src/cancelable-task.h"
11 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" 11 #include "src/compiler-dispatcher/compiler-dispatcher-job.h"
12 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" 12 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
13 #include "src/flags.h"
13 #include "src/objects-inl.h" 14 #include "src/objects-inl.h"
14 15
15 namespace v8 { 16 namespace v8 {
16 namespace internal { 17 namespace internal {
17 18
18 namespace { 19 namespace {
19 20
20 enum class ExceptionHandling { kSwallow, kThrow }; 21 enum class ExceptionHandling { kSwallow, kThrow };
21 22
22 bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job, 23 bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 198
198 void CompilerDispatcher::IdleTask::RunInternal(double deadline_in_seconds) { 199 void CompilerDispatcher::IdleTask::RunInternal(double deadline_in_seconds) {
199 dispatcher_->DoIdleWork(deadline_in_seconds); 200 dispatcher_->DoIdleWork(deadline_in_seconds);
200 } 201 }
201 202
202 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform, 203 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
203 size_t max_stack_size) 204 size_t max_stack_size)
204 : isolate_(isolate), 205 : isolate_(isolate),
205 platform_(platform), 206 platform_(platform),
206 max_stack_size_(max_stack_size), 207 max_stack_size_(max_stack_size),
208 trace_compiler_dispatcher_(FLAG_trace_compiler_dispatcher),
207 tracer_(new CompilerDispatcherTracer(isolate_)), 209 tracer_(new CompilerDispatcherTracer(isolate_)),
208 task_manager_(new CancelableTaskManager()), 210 task_manager_(new CancelableTaskManager()),
209 memory_pressure_level_(MemoryPressureLevel::kNone), 211 memory_pressure_level_(MemoryPressureLevel::kNone),
210 abort_(false), 212 abort_(false),
211 idle_task_scheduled_(false), 213 idle_task_scheduled_(false),
212 num_scheduled_background_tasks_(0), 214 num_scheduled_background_tasks_(0),
213 main_thread_blocking_on_job_(nullptr), 215 main_thread_blocking_on_job_(nullptr),
214 block_for_testing_(false), 216 block_for_testing_(false),
215 semaphore_for_testing_(0) {} 217 semaphore_for_testing_(0) {
218 if (trace_compiler_dispatcher_ && !IsEnabled()) {
219 PrintF("CompilerDispatcher: dispatcher is disabled\n");
220 }
221 }
216 222
217 CompilerDispatcher::~CompilerDispatcher() { 223 CompilerDispatcher::~CompilerDispatcher() {
218 // To avoid crashing in unit tests due to unfished jobs. 224 // To avoid crashing in unit tests due to unfished jobs.
219 AbortAll(BlockingBehavior::kBlock); 225 AbortAll(BlockingBehavior::kBlock);
220 task_manager_->CancelAndWait(); 226 task_manager_->CancelAndWait();
221 } 227 }
222 228
223 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { 229 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
224 if (!IsEnabled()) return false; 230 if (!IsEnabled()) return false;
225 231
226 if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) { 232 if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) {
227 return false; 233 return false;
228 } 234 }
229 235
230 { 236 {
231 base::LockGuard<base::Mutex> lock(&mutex_); 237 base::LockGuard<base::Mutex> lock(&mutex_);
232 if (abort_) return false; 238 if (abort_) return false;
233 } 239 }
234 240
235 // We only handle functions (no eval / top-level code / wasm) that are 241 // We only handle functions (no eval / top-level code / wasm) that are
236 // attached to a script. 242 // attached to a script.
237 if (!function->script()->IsScript() || !function->is_function() || 243 if (!function->script()->IsScript() || !function->is_function() ||
238 function->asm_function() || function->native()) { 244 function->asm_function() || function->native()) {
239 return false; 245 return false;
240 } 246 }
241 247
242 if (IsEnqueued(function)) return true; 248 if (IsEnqueued(function)) return true;
249
250 if (trace_compiler_dispatcher_) {
251 PrintF("CompilerDispatcher: enqueuing ");
252 function->ShortPrint();
253 PrintF("\n");
254 }
255
243 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( 256 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
244 isolate_, tracer_.get(), function, max_stack_size_)); 257 isolate_, tracer_.get(), function, max_stack_size_));
245 std::pair<int, int> key(Script::cast(function->script())->id(), 258 std::pair<int, int> key(Script::cast(function->script())->id(),
246 function->function_literal_id()); 259 function->function_literal_id());
247 jobs_.insert(std::make_pair(key, std::move(job))); 260 jobs_.insert(std::make_pair(key, std::move(job)));
248 ScheduleIdleTaskIfNeeded(); 261 ScheduleIdleTaskIfNeeded();
249 return true; 262 return true;
250 } 263 }
251 264
252 bool CompilerDispatcher::IsEnabled() const { 265 bool CompilerDispatcher::IsEnabled() const {
(...skipping 18 matching lines...) Expand all
271 main_thread_blocking_signal_.Wait(&mutex_); 284 main_thread_blocking_signal_.Wait(&mutex_);
272 } 285 }
273 DCHECK(pending_background_jobs_.find(job) == pending_background_jobs_.end()); 286 DCHECK(pending_background_jobs_.find(job) == pending_background_jobs_.end());
274 DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end()); 287 DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end());
275 } 288 }
276 289
277 bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) { 290 bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
278 JobMap::const_iterator job = GetJobFor(function); 291 JobMap::const_iterator job = GetJobFor(function);
279 CHECK(job != jobs_.end()); 292 CHECK(job != jobs_.end());
280 293
294 if (trace_compiler_dispatcher_) {
295 PrintF("CompilerDispatcher: finishing ");
296 function->ShortPrint();
297 PrintF(" now\n");
298 }
299
281 WaitForJobIfRunningOnBackground(job->second.get()); 300 WaitForJobIfRunningOnBackground(job->second.get());
282 while (!IsFinished(job->second.get())) { 301 while (!IsFinished(job->second.get())) {
283 DoNextStepOnMainThread(isolate_, job->second.get(), 302 DoNextStepOnMainThread(isolate_, job->second.get(),
284 ExceptionHandling::kThrow); 303 ExceptionHandling::kThrow);
285 } 304 }
286 bool result = job->second->status() != CompileJobStatus::kFailed; 305 bool result = job->second->status() != CompileJobStatus::kFailed;
306
307 if (trace_compiler_dispatcher_) {
308 PrintF("CompilerDispatcher: finished working on ");
309 function->ShortPrint();
310 PrintF(": %s\n", result ? "success" : "failure");
311 tracer_->DumpStatistics();
312 }
313
287 job->second->ResetOnMainThread(); 314 job->second->ResetOnMainThread();
288 jobs_.erase(job); 315 jobs_.erase(job);
289 if (jobs_.empty()) { 316 if (jobs_.empty()) {
290 base::LockGuard<base::Mutex> lock(&mutex_); 317 base::LockGuard<base::Mutex> lock(&mutex_);
291 abort_ = false; 318 abort_ = false;
292 } 319 }
293 return result; 320 return result;
294 } 321 }
295 322
296 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) { 323 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
297 bool background_tasks_running = 324 bool background_tasks_running =
298 task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning; 325 task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning;
299 if (!background_tasks_running || blocking == BlockingBehavior::kBlock) { 326 if (!background_tasks_running || blocking == BlockingBehavior::kBlock) {
300 for (auto& it : jobs_) { 327 for (auto& it : jobs_) {
301 WaitForJobIfRunningOnBackground(it.second.get()); 328 WaitForJobIfRunningOnBackground(it.second.get());
329 if (trace_compiler_dispatcher_) {
330 PrintF("CompilerDispatcher: aborted ");
331 it.second->ShortPrint();
332 PrintF("\n");
333 }
302 it.second->ResetOnMainThread(); 334 it.second->ResetOnMainThread();
303 } 335 }
304 jobs_.clear(); 336 jobs_.clear();
305 { 337 {
306 base::LockGuard<base::Mutex> lock(&mutex_); 338 base::LockGuard<base::Mutex> lock(&mutex_);
307 DCHECK(pending_background_jobs_.empty()); 339 DCHECK(pending_background_jobs_.empty());
308 DCHECK(running_background_jobs_.empty()); 340 DCHECK(running_background_jobs_.empty());
309 abort_ = false; 341 abort_ = false;
310 } 342 }
311 return; 343 return;
(...skipping 22 matching lines...) Expand all
334 for (auto it = jobs_.begin(); it != jobs_.end();) { 366 for (auto it = jobs_.begin(); it != jobs_.end();) {
335 auto job = it; 367 auto job = it;
336 ++it; 368 ++it;
337 { 369 {
338 base::LockGuard<base::Mutex> lock(&mutex_); 370 base::LockGuard<base::Mutex> lock(&mutex_);
339 if (running_background_jobs_.find(job->second.get()) != 371 if (running_background_jobs_.find(job->second.get()) !=
340 running_background_jobs_.end()) { 372 running_background_jobs_.end()) {
341 continue; 373 continue;
342 } 374 }
343 } 375 }
376 if (trace_compiler_dispatcher_) {
377 PrintF("CompilerDispatcher: aborted ");
378 job->second->ShortPrint();
379 PrintF("\n");
380 }
344 job->second->ResetOnMainThread(); 381 job->second->ResetOnMainThread();
345 jobs_.erase(job); 382 jobs_.erase(job);
346 } 383 }
347 if (jobs_.empty()) { 384 if (jobs_.empty()) {
348 base::LockGuard<base::Mutex> lock(&mutex_); 385 base::LockGuard<base::Mutex> lock(&mutex_);
349 abort_ = false; 386 abort_ = false;
350 } 387 }
351 } 388 }
352 389
353 void CompilerDispatcher::MemoryPressureNotification( 390 void CompilerDispatcher::MemoryPressureNotification(
354 v8::MemoryPressureLevel level, bool is_isolate_locked) { 391 v8::MemoryPressureLevel level, bool is_isolate_locked) {
355 MemoryPressureLevel previous = memory_pressure_level_.Value(); 392 MemoryPressureLevel previous = memory_pressure_level_.Value();
356 memory_pressure_level_.SetValue(level); 393 memory_pressure_level_.SetValue(level);
357 // If we're already under pressure, we haven't accepted new tasks meanwhile 394 // If we're already under pressure, we haven't accepted new tasks meanwhile
358 // and can just return. If we're no longer under pressure, we're also done. 395 // and can just return. If we're no longer under pressure, we're also done.
359 if (previous != MemoryPressureLevel::kNone || 396 if (previous != MemoryPressureLevel::kNone ||
360 level == MemoryPressureLevel::kNone) { 397 level == MemoryPressureLevel::kNone) {
361 return; 398 return;
362 } 399 }
400 if (trace_compiler_dispatcher_) {
401 PrintF("CompilerDispatcher: received memory pressure notification\n");
402 }
363 if (is_isolate_locked) { 403 if (is_isolate_locked) {
364 AbortAll(BlockingBehavior::kDontBlock); 404 AbortAll(BlockingBehavior::kDontBlock);
365 } else { 405 } else {
366 { 406 {
367 base::LockGuard<base::Mutex> lock(&mutex_); 407 base::LockGuard<base::Mutex> lock(&mutex_);
368 if (abort_) return; 408 if (abort_) return;
369 // By going into abort mode here, and clearing the 409 // By going into abort mode here, and clearing the
370 // pending_background_jobs_, we at keep existing background jobs from 410 // pending_background_jobs_, we at keep existing background jobs from
371 // picking up more work before the MemoryPressureTask gets executed. 411 // picking up more work before the MemoryPressureTask gets executed.
372 abort_ = true; 412 abort_ = true;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 running_background_jobs_.insert(job); 491 running_background_jobs_.insert(job);
452 } 492 }
453 } 493 }
454 if (job == nullptr) return; 494 if (job == nullptr) return;
455 495
456 if (V8_UNLIKELY(block_for_testing_.Value())) { 496 if (V8_UNLIKELY(block_for_testing_.Value())) {
457 block_for_testing_.SetValue(false); 497 block_for_testing_.SetValue(false);
458 semaphore_for_testing_.Wait(); 498 semaphore_for_testing_.Wait();
459 } 499 }
460 500
501 if (trace_compiler_dispatcher_) {
502 PrintF("CompilerDispatcher: doing background work\n");
503 }
504
461 DoNextStepOnBackgroundThread(job); 505 DoNextStepOnBackgroundThread(job);
462 506
463 ScheduleMoreBackgroundTasksIfNeeded(); 507 ScheduleMoreBackgroundTasksIfNeeded();
464 // Unconditionally schedule an idle task, as all background steps have to be 508 // Unconditionally schedule an idle task, as all background steps have to be
465 // followed by a main thread step. 509 // followed by a main thread step.
466 ScheduleIdleTaskFromAnyThread(); 510 ScheduleIdleTaskFromAnyThread();
467 511
468 { 512 {
469 base::LockGuard<base::Mutex> lock(&mutex_); 513 base::LockGuard<base::Mutex> lock(&mutex_);
470 running_background_jobs_.erase(job); 514 running_background_jobs_.erase(job);
(...skipping 29 matching lines...) Expand all
500 544
501 // Number of jobs that are unlikely to make progress during any idle callback 545 // Number of jobs that are unlikely to make progress during any idle callback
502 // due to their estimated duration. 546 // due to their estimated duration.
503 size_t too_long_jobs = 0; 547 size_t too_long_jobs = 0;
504 548
505 // Iterate over all available jobs & remaining time. For each job, decide 549 // Iterate over all available jobs & remaining time. For each job, decide
506 // whether to 1) skip it (if it would take too long), 2) erase it (if it's 550 // whether to 1) skip it (if it would take too long), 2) erase it (if it's
507 // finished), or 3) make progress on it. 551 // finished), or 3) make progress on it.
508 double idle_time_in_seconds = 552 double idle_time_in_seconds =
509 deadline_in_seconds - platform_->MonotonicallyIncreasingTime(); 553 deadline_in_seconds - platform_->MonotonicallyIncreasingTime();
554
555 if (trace_compiler_dispatcher_) {
556 PrintF("CompilerDispatcher: received %0.1lfms of idle time\n",
557 idle_time_in_seconds *
558 static_cast<double>(base::Time::kMillisecondsPerSecond));
559 }
510 for (auto job = jobs_.begin(); 560 for (auto job = jobs_.begin();
511 job != jobs_.end() && idle_time_in_seconds > 0.0; 561 job != jobs_.end() && idle_time_in_seconds > 0.0;
512 idle_time_in_seconds = 562 idle_time_in_seconds =
513 deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) { 563 deadline_in_seconds - platform_->MonotonicallyIncreasingTime()) {
514 // Don't work on jobs that are being worked on by background tasks. 564 // Don't work on jobs that are being worked on by background tasks.
515 // Similarly, remove jobs we work on from the set of available background 565 // Similarly, remove jobs we work on from the set of available background
516 // jobs. 566 // jobs.
517 std::unique_ptr<base::LockGuard<base::Mutex>> lock( 567 std::unique_ptr<base::LockGuard<base::Mutex>> lock(
518 new base::LockGuard<base::Mutex>(&mutex_)); 568 new base::LockGuard<base::Mutex>(&mutex_));
519 if (running_background_jobs_.find(job->second.get()) != 569 if (running_background_jobs_.find(job->second.get()) !=
(...skipping 10 matching lines...) Expand all
530 // have managed to finish the job in a large idle task to assess 580 // have managed to finish the job in a large idle task to assess
531 // whether we should ask for another idle callback. 581 // whether we should ask for another idle callback.
532 if (estimate_in_ms > kMaxIdleTimeToExpectInMs) ++too_long_jobs; 582 if (estimate_in_ms > kMaxIdleTimeToExpectInMs) ++too_long_jobs;
533 if (it == pending_background_jobs_.end()) { 583 if (it == pending_background_jobs_.end()) {
534 lock.reset(); 584 lock.reset();
535 ConsiderJobForBackgroundProcessing(job->second.get()); 585 ConsiderJobForBackgroundProcessing(job->second.get());
536 } 586 }
537 ++job; 587 ++job;
538 } else if (IsFinished(job->second.get())) { 588 } else if (IsFinished(job->second.get())) {
539 DCHECK(it == pending_background_jobs_.end()); 589 DCHECK(it == pending_background_jobs_.end());
590 if (trace_compiler_dispatcher_) {
591 PrintF("CompilerDispatcher: finished working on ");
592 job->second->ShortPrint();
593 PrintF(": %s\n", job->second->status() == CompileJobStatus::kDone
594 ? "success"
595 : "failure");
596 tracer_->DumpStatistics();
597 }
540 job->second->ResetOnMainThread(); 598 job->second->ResetOnMainThread();
541 job = jobs_.erase(job); 599 job = jobs_.erase(job);
542 continue; 600 continue;
543 } else { 601 } else {
544 // Do one step, and keep processing the job (as we don't advance the 602 // Do one step, and keep processing the job (as we don't advance the
545 // iterator). 603 // iterator).
546 if (it != pending_background_jobs_.end()) { 604 if (it != pending_background_jobs_.end()) {
547 pending_background_jobs_.erase(it); 605 pending_background_jobs_.erase(it);
548 } 606 }
549 lock.reset(); 607 lock.reset();
550 DoNextStepOnMainThread(isolate_, job->second.get(), 608 DoNextStepOnMainThread(isolate_, job->second.get(),
551 ExceptionHandling::kSwallow); 609 ExceptionHandling::kSwallow);
552 } 610 }
553 } 611 }
554 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); 612 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded();
555 } 613 }
556 614
557 } // namespace internal 615 } // namespace internal
558 } // namespace v8 616 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler-dispatcher/compiler-dispatcher.h ('k') | src/compiler-dispatcher/compiler-dispatcher-job.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698