Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "src/base/platform/semaphore.h" | 8 #include "src/base/platform/semaphore.h" |
| 9 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" | 9 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
| 10 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" | 10 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 static bool old_flag_; | 63 static bool old_flag_; |
| 64 DISALLOW_COPY_AND_ASSIGN(IgnitionCompilerDispatcherTest); | 64 DISALLOW_COPY_AND_ASSIGN(IgnitionCompilerDispatcherTest); |
| 65 }; | 65 }; |
| 66 | 66 |
| 67 bool IgnitionCompilerDispatcherTest::old_flag_; | 67 bool IgnitionCompilerDispatcherTest::old_flag_; |
| 68 | 68 |
| 69 namespace { | 69 namespace { |
| 70 | 70 |
| 71 class MockPlatform : public v8::Platform { | 71 class MockPlatform : public v8::Platform { |
| 72 public: | 72 public: |
| 73 MockPlatform() : idle_task_(nullptr), time_(0.0), time_step_(0.0), sem_(0) {} | 73 MockPlatform() : time_(0.0), time_step_(0.0), idle_task_(nullptr), sem_(0) {} |
| 74 ~MockPlatform() override { | 74 ~MockPlatform() override { |
| 75 EXPECT_TRUE(tasks_.empty()); | 75 base::LockGuard<base::Mutex> lock(&mutex_); |
| 76 EXPECT_TRUE(foreground_tasks_.empty()); | |
| 77 EXPECT_TRUE(background_tasks_.empty()); | |
| 76 EXPECT_TRUE(idle_task_ == nullptr); | 78 EXPECT_TRUE(idle_task_ == nullptr); |
| 77 } | 79 } |
| 78 | 80 |
| 79 size_t NumberOfAvailableBackgroundThreads() override { return 1; } | 81 size_t NumberOfAvailableBackgroundThreads() override { return 1; } |
| 80 | 82 |
| 81 void CallOnBackgroundThread(Task* task, | 83 void CallOnBackgroundThread(Task* task, |
| 82 ExpectedRuntime expected_runtime) override { | 84 ExpectedRuntime expected_runtime) override { |
| 83 tasks_.push_back(task); | 85 base::LockGuard<base::Mutex> lock(&mutex_); |
| 86 background_tasks_.push_back(task); | |
| 84 } | 87 } |
| 85 | 88 |
| 86 void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override { | 89 void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override { |
| 87 UNREACHABLE(); | 90 base::LockGuard<base::Mutex> lock(&mutex_); |
| 91 foreground_tasks_.push_back(task); | |
| 88 } | 92 } |
| 89 | 93 |
| 90 void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task, | 94 void CallDelayedOnForegroundThread(v8::Isolate* isolate, Task* task, |
| 91 double delay_in_seconds) override { | 95 double delay_in_seconds) override { |
| 92 UNREACHABLE(); | 96 UNREACHABLE(); |
| 93 } | 97 } |
| 94 | 98 |
| 95 void CallIdleOnForegroundThread(v8::Isolate* isolate, | 99 void CallIdleOnForegroundThread(v8::Isolate* isolate, |
| 96 IdleTask* task) override { | 100 IdleTask* task) override { |
| 101 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 97 ASSERT_TRUE(idle_task_ == nullptr); | 102 ASSERT_TRUE(idle_task_ == nullptr); |
| 98 idle_task_ = task; | 103 idle_task_ = task; |
| 99 } | 104 } |
| 100 | 105 |
| 101 bool IdleTasksEnabled(v8::Isolate* isolate) override { return true; } | 106 bool IdleTasksEnabled(v8::Isolate* isolate) override { return true; } |
| 102 | 107 |
| 103 double MonotonicallyIncreasingTime() override { | 108 double MonotonicallyIncreasingTime() override { |
| 104 time_ += time_step_; | 109 time_ += time_step_; |
| 105 return time_; | 110 return time_; |
| 106 } | 111 } |
| 107 | 112 |
| 108 void RunIdleTask(double deadline_in_seconds, double time_step) { | 113 void RunIdleTask(double deadline_in_seconds, double time_step) { |
| 109 ASSERT_TRUE(idle_task_ != nullptr); | |
| 110 time_step_ = time_step; | 114 time_step_ = time_step; |
| 111 IdleTask* task = idle_task_; | 115 IdleTask* task; |
| 112 idle_task_ = nullptr; | 116 { |
| 117 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 118 task = idle_task_; | |
| 119 ASSERT_TRUE(idle_task_ != nullptr); | |
| 120 idle_task_ = nullptr; | |
| 121 } | |
| 113 task->Run(deadline_in_seconds); | 122 task->Run(deadline_in_seconds); |
| 114 delete task; | 123 delete task; |
| 115 } | 124 } |
| 116 | 125 |
| 117 bool IdleTaskPending() const { return idle_task_; } | 126 bool IdleTaskPending() { |
| 127 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 128 return idle_task_; | |
| 129 } | |
| 118 | 130 |
| 119 bool BackgroundTasksPending() const { return !tasks_.empty(); } | 131 bool BackgroundTasksPending() { |
| 132 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 133 return !background_tasks_.empty(); | |
| 134 } | |
| 135 | |
| 136 bool ForegroundTasksPending() { | |
| 137 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 138 return !foreground_tasks_.empty(); | |
| 139 } | |
| 120 | 140 |
| 121 void RunBackgroundTasksAndBlock(Platform* platform) { | 141 void RunBackgroundTasksAndBlock(Platform* platform) { |
| 122 std::vector<Task*> tasks; | 142 std::vector<Task*> tasks; |
| 123 tasks.swap(tasks_); | 143 { |
| 144 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 145 tasks.swap(background_tasks_); | |
| 146 } | |
| 124 platform->CallOnBackgroundThread(new TaskWrapper(this, tasks, true), | 147 platform->CallOnBackgroundThread(new TaskWrapper(this, tasks, true), |
| 125 kShortRunningTask); | 148 kShortRunningTask); |
| 126 sem_.Wait(); | 149 sem_.Wait(); |
| 127 } | 150 } |
| 128 | 151 |
| 129 void RunBackgroundTasks(Platform* platform) { | 152 void RunBackgroundTasks(Platform* platform) { |
| 130 std::vector<Task*> tasks; | 153 std::vector<Task*> tasks; |
| 131 tasks.swap(tasks_); | 154 { |
| 155 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 156 tasks.swap(background_tasks_); | |
| 157 } | |
| 132 platform->CallOnBackgroundThread(new TaskWrapper(this, tasks, false), | 158 platform->CallOnBackgroundThread(new TaskWrapper(this, tasks, false), |
| 133 kShortRunningTask); | 159 kShortRunningTask); |
| 134 } | 160 } |
| 135 | 161 |
| 162 void RunForegroundTasks() { | |
| 163 std::vector<Task*> tasks; | |
| 164 { | |
| 165 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 166 tasks.swap(foreground_tasks_); | |
| 167 } | |
| 168 for (auto& task : tasks) { | |
| 169 task->Run(); | |
| 170 delete task; | |
| 171 } | |
| 172 } | |
| 173 | |
| 136 void ClearBackgroundTasks() { | 174 void ClearBackgroundTasks() { |
| 137 std::vector<Task*> tasks; | 175 std::vector<Task*> tasks; |
| 138 tasks.swap(tasks_); | 176 { |
| 177 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 178 tasks.swap(background_tasks_); | |
| 179 } | |
| 180 for (auto& task : tasks) { | |
| 181 delete task; | |
| 182 } | |
| 183 } | |
| 184 | |
| 185 void ClearForegroundTasks() { | |
| 186 std::vector<Task*> tasks; | |
| 187 { | |
| 188 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 189 tasks.swap(foreground_tasks_); | |
| 190 } | |
| 139 for (auto& task : tasks) { | 191 for (auto& task : tasks) { |
| 140 delete task; | 192 delete task; |
| 141 } | 193 } |
| 142 } | 194 } |
| 143 | 195 |
| 144 void ClearIdleTask() { | 196 void ClearIdleTask() { |
| 197 base::LockGuard<base::Mutex> lock(&mutex_); | |
| 145 ASSERT_TRUE(idle_task_ != nullptr); | 198 ASSERT_TRUE(idle_task_ != nullptr); |
| 146 delete idle_task_; | 199 delete idle_task_; |
| 147 idle_task_ = nullptr; | 200 idle_task_ = nullptr; |
| 148 } | 201 } |
| 149 | 202 |
| 150 private: | 203 private: |
| 151 class TaskWrapper : public Task { | 204 class TaskWrapper : public Task { |
| 152 public: | 205 public: |
| 153 TaskWrapper(MockPlatform* platform, const std::vector<Task*>& tasks, | 206 TaskWrapper(MockPlatform* platform, const std::vector<Task*>& tasks, |
| 154 bool signal) | 207 bool signal) |
| 155 : platform_(platform), tasks_(tasks), signal_(signal) {} | 208 : platform_(platform), tasks_(tasks), signal_(signal) {} |
| 156 ~TaskWrapper() = default; | 209 ~TaskWrapper() = default; |
| 157 | 210 |
| 158 void Run() override { | 211 void Run() override { |
| 159 for (auto& task : tasks_) { | 212 for (auto& task : tasks_) { |
| 160 task->Run(); | 213 task->Run(); |
| 161 delete task; | 214 delete task; |
| 162 } | 215 } |
| 163 if (signal_) platform_->sem_.Signal(); | 216 if (signal_) platform_->sem_.Signal(); |
| 164 } | 217 } |
| 165 | 218 |
| 166 private: | 219 private: |
| 167 MockPlatform* platform_; | 220 MockPlatform* platform_; |
| 168 std::vector<Task*> tasks_; | 221 std::vector<Task*> tasks_; |
| 169 bool signal_; | 222 bool signal_; |
| 170 | 223 |
| 171 DISALLOW_COPY_AND_ASSIGN(TaskWrapper); | 224 DISALLOW_COPY_AND_ASSIGN(TaskWrapper); |
| 172 }; | 225 }; |
| 173 | 226 |
| 174 IdleTask* idle_task_; | |
| 175 double time_; | 227 double time_; |
| 176 double time_step_; | 228 double time_step_; |
| 177 | 229 |
| 178 std::vector<Task*> tasks_; | 230 // Protects all *_tasks_. |
| 231 base::Mutex mutex_; | |
| 232 | |
| 233 IdleTask* idle_task_; | |
| 234 std::vector<Task*> background_tasks_; | |
| 235 std::vector<Task*> foreground_tasks_; | |
| 236 | |
| 179 base::Semaphore sem_; | 237 base::Semaphore sem_; |
| 180 | 238 |
| 181 DISALLOW_COPY_AND_ASSIGN(MockPlatform); | 239 DISALLOW_COPY_AND_ASSIGN(MockPlatform); |
| 182 }; | 240 }; |
| 183 | 241 |
| 184 } // namespace | 242 } // namespace |
| 185 | 243 |
| 186 TEST_F(CompilerDispatcherTest, Construct) { | 244 TEST_F(CompilerDispatcherTest, Construct) { |
| 187 MockPlatform platform; | 245 MockPlatform platform; |
| 188 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 246 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 ASSERT_FALSE(dispatcher.FinishNow(shared)); | 510 ASSERT_FALSE(dispatcher.FinishNow(shared)); |
| 453 | 511 |
| 454 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 512 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 455 ASSERT_FALSE(shared->is_compiled()); | 513 ASSERT_FALSE(shared->is_compiled()); |
| 456 ASSERT_TRUE(i_isolate()->has_pending_exception()); | 514 ASSERT_TRUE(i_isolate()->has_pending_exception()); |
| 457 | 515 |
| 458 i_isolate()->clear_pending_exception(); | 516 i_isolate()->clear_pending_exception(); |
| 459 platform.ClearIdleTask(); | 517 platform.ClearIdleTask(); |
| 460 } | 518 } |
| 461 | 519 |
| 520 TEST_F(IgnitionCompilerDispatcherTest, AsyncAbortAllPendingBackgroundTask) { | |
| 521 MockPlatform platform; | |
| 522 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | |
| 523 | |
| 524 const char script[] = | |
| 525 "function g() { var y = 1; function f11(x) { return x * y }; return f11; " | |
| 526 "} g();"; | |
| 527 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | |
| 528 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | |
| 529 | |
| 530 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 531 ASSERT_TRUE(dispatcher.Enqueue(shared)); | |
| 532 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 533 | |
| 534 ASSERT_EQ(dispatcher.jobs_.size(), 1u); | |
| 535 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 536 CompileJobStatus::kInitial); | |
| 537 | |
| 538 // Make compiling super expensive, and advance job as much as possible on the | |
| 539 // foreground thread. | |
| 540 dispatcher.tracer_->RecordCompile(50000.0, 1); | |
| 541 platform.RunIdleTask(10.0, 0.0); | |
| 542 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 543 CompileJobStatus::kReadyToCompile); | |
| 544 | |
| 545 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | |
| 546 ASSERT_FALSE(shared->is_compiled()); | |
| 547 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 548 ASSERT_TRUE(platform.BackgroundTasksPending()); | |
| 549 | |
| 550 // The background task hasn't yet started, so we can just cancel it. | |
| 551 dispatcher.AbortAll(CompilerDispatcher::BlockingBehavior::kDontBlock); | |
| 552 ASSERT_FALSE(platform.ForegroundTasksPending()); | |
| 553 | |
| 554 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | |
| 555 ASSERT_FALSE(shared->is_compiled()); | |
| 556 | |
| 557 platform.RunBackgroundTasksAndBlock(V8::GetCurrentPlatform()); | |
| 558 | |
| 559 if (platform.IdleTaskPending()) platform.ClearIdleTask(); | |
| 560 ASSERT_FALSE(platform.BackgroundTasksPending()); | |
| 561 ASSERT_FALSE(platform.ForegroundTasksPending()); | |
| 562 } | |
| 563 | |
| 564 TEST_F(IgnitionCompilerDispatcherTest, AsyncAbortAllRunningBackgroundTask) { | |
| 565 MockPlatform platform; | |
| 566 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | |
| 567 | |
| 568 const char script1[] = | |
| 569 "function g() { var y = 1; function f11(x) { return x * y }; return f11; " | |
| 570 "} g();"; | |
| 571 Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); | |
| 572 Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); | |
| 573 | |
| 574 const char script2[] = | |
| 575 "function g() { var y = 1; function f12(x) { return x * y }; return f12; " | |
| 576 "} g();"; | |
| 577 Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); | |
| 578 Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); | |
| 579 | |
| 580 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 581 ASSERT_TRUE(dispatcher.Enqueue(shared1)); | |
| 582 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 583 | |
| 584 ASSERT_EQ(dispatcher.jobs_.size(), 1u); | |
| 585 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 586 CompileJobStatus::kInitial); | |
| 587 | |
| 588 // Make compiling super expensive, and advance job as much as possible on the | |
| 589 // foreground thread. | |
| 590 dispatcher.tracer_->RecordCompile(50000.0, 1); | |
| 591 platform.RunIdleTask(10.0, 0.0); | |
| 592 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 593 CompileJobStatus::kReadyToCompile); | |
| 594 | |
| 595 ASSERT_TRUE(dispatcher.IsEnqueued(shared1)); | |
| 596 ASSERT_FALSE(shared1->is_compiled()); | |
| 597 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 598 ASSERT_TRUE(platform.BackgroundTasksPending()); | |
| 599 | |
| 600 // Kick off background tasks, racing with the AbortAll() call. | |
|
marja
2017/01/04 12:54:43
Instead of making your tests racy, you could use c
jochen (gone - plz use gerrit)
2017/01/04 13:18:31
ah, the comment is just wrong, it's no longer a ra
| |
| 601 dispatcher.block_for_testing_.SetValue(true); | |
| 602 platform.RunBackgroundTasks(V8::GetCurrentPlatform()); | |
| 603 | |
| 604 // Busy loop until the background task started running. | |
| 605 while (dispatcher.block_for_testing_.Value()) { | |
|
marja
2017/01/04 12:54:43
Here too you can wait on a condition variable.
jochen (gone - plz use gerrit)
2017/01/04 13:18:31
then I'd need even more members just for testing..
marja
2017/01/04 13:28:36
Ah, right, because you can't mock the task and jus
| |
| 606 } | |
| 607 dispatcher.AbortAll(CompilerDispatcher::BlockingBehavior::kDontBlock); | |
| 608 ASSERT_TRUE(platform.ForegroundTasksPending()); | |
| 609 | |
| 610 // We can't schedule new tasks while we're aborting. | |
| 611 ASSERT_FALSE(dispatcher.Enqueue(shared2)); | |
| 612 | |
| 613 // Run the first AbortTask. Since the background job is still pending, it | |
| 614 // can't do anything. | |
| 615 platform.RunForegroundTasks(); | |
| 616 { | |
| 617 base::LockGuard<base::Mutex> lock(&dispatcher.mutex_); | |
| 618 ASSERT_TRUE(dispatcher.abort_); | |
| 619 } | |
| 620 | |
| 621 // Release background task. | |
| 622 dispatcher.semaphore_for_testing_.Signal(); | |
| 623 | |
| 624 // Busy loop until the background task scheduled another AbortTask task. | |
|
marja
2017/01/04 12:54:43
Ditto
| |
| 625 while (!platform.ForegroundTasksPending()) { | |
| 626 } | |
| 627 | |
| 628 platform.RunForegroundTasks(); | |
| 629 ASSERT_TRUE(dispatcher.jobs_.empty()); | |
| 630 { | |
| 631 base::LockGuard<base::Mutex> lock(&dispatcher.mutex_); | |
| 632 ASSERT_FALSE(dispatcher.abort_); | |
| 633 } | |
| 634 | |
| 635 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 636 platform.RunIdleTask(5.0, 1.0); | |
| 637 ASSERT_FALSE(platform.BackgroundTasksPending()); | |
| 638 ASSERT_FALSE(platform.ForegroundTasksPending()); | |
| 639 | |
| 640 // Now it's possible to enqueue new functions again. | |
| 641 ASSERT_TRUE(dispatcher.Enqueue(shared2)); | |
| 642 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 643 ASSERT_FALSE(platform.BackgroundTasksPending()); | |
| 644 ASSERT_FALSE(platform.ForegroundTasksPending()); | |
| 645 platform.ClearIdleTask(); | |
| 646 } | |
| 647 | |
| 648 TEST_F(IgnitionCompilerDispatcherTest, FinishNowDuringAbortAll) { | |
| 649 MockPlatform platform; | |
| 650 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | |
| 651 | |
| 652 const char script[] = | |
| 653 "function g() { var y = 1; function f13(x) { return x * y }; return f13; " | |
| 654 "} g();"; | |
| 655 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | |
| 656 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | |
| 657 | |
| 658 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 659 ASSERT_TRUE(dispatcher.Enqueue(shared)); | |
| 660 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 661 | |
| 662 ASSERT_EQ(dispatcher.jobs_.size(), 1u); | |
| 663 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 664 CompileJobStatus::kInitial); | |
| 665 | |
| 666 // Make compiling super expensive, and advance job as much as possible on the | |
| 667 // foreground thread. | |
| 668 dispatcher.tracer_->RecordCompile(50000.0, 1); | |
| 669 platform.RunIdleTask(10.0, 0.0); | |
| 670 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | |
| 671 CompileJobStatus::kReadyToCompile); | |
| 672 | |
| 673 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | |
| 674 ASSERT_FALSE(shared->is_compiled()); | |
| 675 ASSERT_FALSE(platform.IdleTaskPending()); | |
| 676 ASSERT_TRUE(platform.BackgroundTasksPending()); | |
| 677 | |
| 678 // Kick off background tasks, racing with the AbortAll() call. | |
|
marja
2017/01/04 12:54:43
Ditto
| |
| 679 dispatcher.block_for_testing_.SetValue(true); | |
| 680 platform.RunBackgroundTasks(V8::GetCurrentPlatform()); | |
| 681 | |
| 682 // Busy loop until the background task started running. | |
| 683 while (dispatcher.block_for_testing_.Value()) { | |
| 684 } | |
| 685 dispatcher.AbortAll(CompilerDispatcher::BlockingBehavior::kDontBlock); | |
| 686 ASSERT_TRUE(platform.ForegroundTasksPending()); | |
| 687 | |
| 688 // Run the first AbortTask. Since the background job is still pending, it | |
| 689 // can't do anything. | |
| 690 platform.RunForegroundTasks(); | |
| 691 { | |
| 692 base::LockGuard<base::Mutex> lock(&dispatcher.mutex_); | |
| 693 ASSERT_TRUE(dispatcher.abort_); | |
| 694 } | |
| 695 | |
| 696 // While the background thread holds on to a job, it is still enqueud. | |
| 697 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | |
| 698 | |
| 699 // Release background task. | |
| 700 dispatcher.semaphore_for_testing_.Signal(); | |
| 701 | |
| 702 // Force the compilation to finish, even while aborting. | |
| 703 ASSERT_TRUE(dispatcher.FinishNow(shared)); | |
| 704 ASSERT_TRUE(dispatcher.jobs_.empty()); | |
| 705 { | |
| 706 base::LockGuard<base::Mutex> lock(&dispatcher.mutex_); | |
| 707 ASSERT_FALSE(dispatcher.abort_); | |
| 708 } | |
| 709 | |
| 710 ASSERT_TRUE(platform.ForegroundTasksPending()); | |
| 711 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 712 ASSERT_FALSE(platform.BackgroundTasksPending()); | |
| 713 platform.ClearForegroundTasks(); | |
| 714 platform.ClearIdleTask(); | |
| 715 } | |
| 716 | |
| 462 } // namespace internal | 717 } // namespace internal |
| 463 } // namespace v8 | 718 } // namespace v8 |
| OLD | NEW |