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

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

Issue 2615533005: Revert of Implement async AbortAll for the compiler dispatcher (Closed)
Patch Set: 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"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 case CompileJobStatus::kCompiled: 46 case CompileJobStatus::kCompiled:
47 job->FinalizeCompilingOnMainThread(); 47 job->FinalizeCompilingOnMainThread();
48 break; 48 break;
49 49
50 case CompileJobStatus::kFailed: 50 case CompileJobStatus::kFailed:
51 case CompileJobStatus::kDone: 51 case CompileJobStatus::kDone:
52 break; 52 break;
53 } 53 }
54 54
55 DCHECK_EQ(job->status() == CompileJobStatus::kFailed, 55 if (job->status() == CompileJobStatus::kFailed) {
56 isolate->has_pending_exception()); 56 DCHECK(isolate->has_pending_exception());
57 if (job->status() == CompileJobStatus::kFailed && 57 if (exception_handling == ExceptionHandling::kSwallow) {
58 exception_handling == ExceptionHandling::kSwallow) { 58 isolate->clear_pending_exception();
59 isolate->clear_pending_exception(); 59 }
60 } else {
61 DCHECK(!isolate->has_pending_exception());
60 } 62 }
61 return job->status() != CompileJobStatus::kFailed; 63 return job->status() != CompileJobStatus::kFailed;
62 } 64 }
63 65
64 bool IsFinished(CompilerDispatcherJob* job) { 66 bool IsFinished(CompilerDispatcherJob* job) {
65 return job->status() == CompileJobStatus::kDone || 67 return job->status() == CompileJobStatus::kDone ||
66 job->status() == CompileJobStatus::kFailed; 68 job->status() == CompileJobStatus::kFailed;
67 } 69 }
68 70
69 bool CanRunOnAnyThread(CompilerDispatcherJob* job) { 71 bool CanRunOnAnyThread(CompilerDispatcherJob* job) {
(...skipping 18 matching lines...) Expand all
88 UNREACHABLE(); 90 UNREACHABLE();
89 } 91 }
90 } 92 }
91 93
92 // Theoretically we get 50ms of idle time max, however it's unlikely that 94 // Theoretically we get 50ms of idle time max, however it's unlikely that
93 // we'll get all of it so try to be a conservative. 95 // we'll get all of it so try to be a conservative.
94 const double kMaxIdleTimeToExpectInMs = 40; 96 const double kMaxIdleTimeToExpectInMs = 40;
95 97
96 } // namespace 98 } // namespace
97 99
98 class CompilerDispatcher::AbortTask : public CancelableTask {
99 public:
100 AbortTask(Isolate* isolate, CancelableTaskManager* task_manager,
101 CompilerDispatcher* dispatcher);
102 ~AbortTask() override;
103
104 // CancelableTask implementation.
105 void RunInternal() override;
106
107 private:
108 CompilerDispatcher* dispatcher_;
109
110 DISALLOW_COPY_AND_ASSIGN(AbortTask);
111 };
112
113 CompilerDispatcher::AbortTask::AbortTask(Isolate* isolate,
114 CancelableTaskManager* task_manager,
115 CompilerDispatcher* dispatcher)
116 : CancelableTask(isolate, task_manager), dispatcher_(dispatcher) {}
117
118 CompilerDispatcher::AbortTask::~AbortTask() {}
119
120 void CompilerDispatcher::AbortTask::RunInternal() {
121 dispatcher_->AbortInactiveJobs();
122 }
123
124 class CompilerDispatcher::BackgroundTask : public CancelableTask { 100 class CompilerDispatcher::BackgroundTask : public CancelableTask {
125 public: 101 public:
126 BackgroundTask(Isolate* isolate, CancelableTaskManager* task_manager, 102 BackgroundTask(Isolate* isolate, CancelableTaskManager* task_manager,
127 CompilerDispatcher* dispatcher); 103 CompilerDispatcher* dispatcher);
128 ~BackgroundTask() override; 104 ~BackgroundTask() override;
129 105
130 // CancelableTask implementation. 106 // CancelableTask implementation.
131 void RunInternal() override; 107 void RunInternal() override;
132 108
133 private: 109 private:
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 dispatcher_->DoIdleWork(deadline_in_seconds); 149 dispatcher_->DoIdleWork(deadline_in_seconds);
174 } 150 }
175 151
176 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform, 152 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform,
177 size_t max_stack_size) 153 size_t max_stack_size)
178 : isolate_(isolate), 154 : isolate_(isolate),
179 platform_(platform), 155 platform_(platform),
180 max_stack_size_(max_stack_size), 156 max_stack_size_(max_stack_size),
181 tracer_(new CompilerDispatcherTracer(isolate_)), 157 tracer_(new CompilerDispatcherTracer(isolate_)),
182 task_manager_(new CancelableTaskManager()), 158 task_manager_(new CancelableTaskManager()),
183 abort_(false),
184 idle_task_scheduled_(false), 159 idle_task_scheduled_(false),
185 num_scheduled_background_tasks_(0), 160 num_scheduled_background_tasks_(0),
186 main_thread_blocking_on_job_(nullptr), 161 main_thread_blocking_on_job_(nullptr) {}
187 block_for_testing_(false),
188 semaphore_for_testing_(0) {}
189 162
190 CompilerDispatcher::~CompilerDispatcher() { 163 CompilerDispatcher::~CompilerDispatcher() {
191 // To avoid crashing in unit tests due to unfished jobs. 164 // To avoid crashing in unit tests due to unfished jobs.
192 AbortAll(BlockingBehavior::kBlock); 165 AbortAll(BlockingBehavior::kBlock);
193 task_manager_->CancelAndWait(); 166 task_manager_->CancelAndWait();
194 } 167 }
195 168
196 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { 169 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
197 if (!IsEnabled()) return false; 170 if (!IsEnabled()) return false;
198 171
199 {
200 base::LockGuard<base::Mutex> lock(&mutex_);
201 if (abort_) return false;
202 }
203
204 // We only handle functions (no eval / top-level code / wasm) that are 172 // We only handle functions (no eval / top-level code / wasm) that are
205 // attached to a script. 173 // attached to a script.
206 if (!function->script()->IsScript() || !function->is_function() || 174 if (!function->script()->IsScript() || !function->is_function() ||
207 function->asm_function() || function->native()) { 175 function->asm_function() || function->native()) {
208 return false; 176 return false;
209 } 177 }
210 178
211 if (IsEnqueued(function)) return true; 179 if (IsEnqueued(function)) return true;
212 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( 180 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
213 isolate_, tracer_.get(), function, max_stack_size_)); 181 isolate_, tracer_.get(), function, max_stack_size_));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 CHECK(job != jobs_.end()); 216 CHECK(job != jobs_.end());
249 217
250 WaitForJobIfRunningOnBackground(job->second.get()); 218 WaitForJobIfRunningOnBackground(job->second.get());
251 while (!IsFinished(job->second.get())) { 219 while (!IsFinished(job->second.get())) {
252 DoNextStepOnMainThread(isolate_, job->second.get(), 220 DoNextStepOnMainThread(isolate_, job->second.get(),
253 ExceptionHandling::kThrow); 221 ExceptionHandling::kThrow);
254 } 222 }
255 bool result = job->second->status() != CompileJobStatus::kFailed; 223 bool result = job->second->status() != CompileJobStatus::kFailed;
256 job->second->ResetOnMainThread(); 224 job->second->ResetOnMainThread();
257 jobs_.erase(job); 225 jobs_.erase(job);
258 if (jobs_.empty()) {
259 base::LockGuard<base::Mutex> lock(&mutex_);
260 abort_ = false;
261 }
262 return result; 226 return result;
263 } 227 }
264 228
265 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) { 229 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
266 bool background_tasks_running = 230 // TODO(jochen): Implement support for non-blocking abort.
267 task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning; 231 DCHECK(blocking == BlockingBehavior::kBlock);
268 if (!background_tasks_running || blocking == BlockingBehavior::kBlock) { 232 for (auto& kv : jobs_) {
269 for (auto& it : jobs_) { 233 WaitForJobIfRunningOnBackground(kv.second.get());
270 WaitForJobIfRunningOnBackground(it.second.get()); 234 kv.second->ResetOnMainThread();
271 it.second->ResetOnMainThread();
272 }
273 jobs_.clear();
274 {
275 base::LockGuard<base::Mutex> lock(&mutex_);
276 DCHECK(pending_background_jobs_.empty());
277 DCHECK(running_background_jobs_.empty());
278 abort_ = false;
279 }
280 return;
281 } 235 }
282 236 jobs_.clear();
283 {
284 base::LockGuard<base::Mutex> lock(&mutex_);
285 abort_ = true;
286 pending_background_jobs_.clear();
287 }
288 AbortInactiveJobs();
289
290 // All running background jobs might already have scheduled idle tasks instead
291 // of abort tasks. Schedule a single abort task here to make sure they get
292 // processed as soon as possible (and not first when we have idle time).
293 ScheduleAbortTask();
294 }
295
296 void CompilerDispatcher::AbortInactiveJobs() {
297 {
298 base::LockGuard<base::Mutex> lock(&mutex_);
299 // Since we schedule two abort tasks per async abort, we might end up
300 // here with nothing left to do.
301 if (!abort_) return;
302 }
303 for (auto it = jobs_.begin(); it != jobs_.end();) {
304 auto job = it;
305 ++it;
306 {
307 base::LockGuard<base::Mutex> lock(&mutex_);
308 if (running_background_jobs_.find(job->second.get()) !=
309 running_background_jobs_.end()) {
310 continue;
311 }
312 }
313 job->second->ResetOnMainThread();
314 jobs_.erase(job);
315 }
316 if (jobs_.empty()) {
317 base::LockGuard<base::Mutex> lock(&mutex_);
318 abort_ = false;
319 }
320 } 237 }
321 238
322 CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor( 239 CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor(
323 Handle<SharedFunctionInfo> shared) const { 240 Handle<SharedFunctionInfo> shared) const {
324 if (!shared->script()->IsScript()) return jobs_.end(); 241 if (!shared->script()->IsScript()) return jobs_.end();
325 std::pair<int, int> key(Script::cast(shared->script())->id(), 242 std::pair<int, int> key(Script::cast(shared->script())->id(),
326 shared->function_literal_id()); 243 shared->function_literal_id());
327 auto range = jobs_.equal_range(key); 244 auto range = jobs_.equal_range(key);
328 for (auto job = range.first; job != range.second; ++job) { 245 for (auto job = range.first; job != range.second; ++job) {
329 if (job->second->IsAssociatedWith(shared)) return job; 246 if (job->second->IsAssociatedWith(shared)) return job;
(...skipping 11 matching lines...) Expand all
341 } 258 }
342 platform_->CallIdleOnForegroundThread( 259 platform_->CallIdleOnForegroundThread(
343 v8_isolate, new IdleTask(isolate_, task_manager_.get(), this)); 260 v8_isolate, new IdleTask(isolate_, task_manager_.get(), this));
344 } 261 }
345 262
346 void CompilerDispatcher::ScheduleIdleTaskIfNeeded() { 263 void CompilerDispatcher::ScheduleIdleTaskIfNeeded() {
347 if (jobs_.empty()) return; 264 if (jobs_.empty()) return;
348 ScheduleIdleTaskFromAnyThread(); 265 ScheduleIdleTaskFromAnyThread();
349 } 266 }
350 267
351 void CompilerDispatcher::ScheduleAbortTask() {
352 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
353 platform_->CallOnForegroundThread(
354 v8_isolate, new AbortTask(isolate_, task_manager_.get(), this));
355 }
356
357 void CompilerDispatcher::ConsiderJobForBackgroundProcessing( 268 void CompilerDispatcher::ConsiderJobForBackgroundProcessing(
358 CompilerDispatcherJob* job) { 269 CompilerDispatcherJob* job) {
359 if (!CanRunOnAnyThread(job)) return; 270 if (!CanRunOnAnyThread(job)) return;
360 { 271 {
361 base::LockGuard<base::Mutex> lock(&mutex_); 272 base::LockGuard<base::Mutex> lock(&mutex_);
362 pending_background_jobs_.insert(job); 273 pending_background_jobs_.insert(job);
363 } 274 }
364 ScheduleMoreBackgroundTasksIfNeeded(); 275 ScheduleMoreBackgroundTasksIfNeeded();
365 } 276 }
366 277
(...skipping 19 matching lines...) Expand all
386 base::LockGuard<base::Mutex> lock(&mutex_); 297 base::LockGuard<base::Mutex> lock(&mutex_);
387 --num_scheduled_background_tasks_; 298 --num_scheduled_background_tasks_;
388 if (!pending_background_jobs_.empty()) { 299 if (!pending_background_jobs_.empty()) {
389 auto it = pending_background_jobs_.begin(); 300 auto it = pending_background_jobs_.begin();
390 job = *it; 301 job = *it;
391 pending_background_jobs_.erase(it); 302 pending_background_jobs_.erase(it);
392 running_background_jobs_.insert(job); 303 running_background_jobs_.insert(job);
393 } 304 }
394 } 305 }
395 if (job == nullptr) return; 306 if (job == nullptr) return;
396
397 if (V8_UNLIKELY(block_for_testing_.Value())) {
398 block_for_testing_.SetValue(false);
399 semaphore_for_testing_.Wait();
400 }
401
402 DoNextStepOnBackgroundThread(job); 307 DoNextStepOnBackgroundThread(job);
403 308
404 ScheduleMoreBackgroundTasksIfNeeded(); 309 ScheduleMoreBackgroundTasksIfNeeded();
405 // Unconditionally schedule an idle task, as all background steps have to be 310 // Unconditionally schedule an idle task, as all background steps have to be
406 // followed by a main thread step. 311 // followed by a main thread step.
407 ScheduleIdleTaskFromAnyThread(); 312 ScheduleIdleTaskFromAnyThread();
408 313
409 { 314 {
410 base::LockGuard<base::Mutex> lock(&mutex_); 315 base::LockGuard<base::Mutex> lock(&mutex_);
411 running_background_jobs_.erase(job); 316 running_background_jobs_.erase(job);
412 317
413 if (running_background_jobs_.empty() && abort_) {
414 // This is the last background job that finished. The abort task
415 // scheduled by AbortAll might already have ran, so schedule another
416 // one to be on the safe side.
417 ScheduleAbortTask();
418 }
419
420 if (main_thread_blocking_on_job_ == job) { 318 if (main_thread_blocking_on_job_ == job) {
421 main_thread_blocking_on_job_ = nullptr; 319 main_thread_blocking_on_job_ = nullptr;
422 main_thread_blocking_signal_.NotifyOne(); 320 main_thread_blocking_signal_.NotifyOne();
423 } 321 }
424 } 322 }
425 // Don't touch |this| anymore after this point, as it might have been 323 // Don't touch |this| anymore after this point, as it might have been
426 // deleted. 324 // deleted.
427 } 325 }
428 326
429 void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) { 327 void CompilerDispatcher::DoIdleWork(double deadline_in_seconds) {
430 bool aborted = false;
431 { 328 {
432 base::LockGuard<base::Mutex> lock(&mutex_); 329 base::LockGuard<base::Mutex> lock(&mutex_);
433 idle_task_scheduled_ = false; 330 idle_task_scheduled_ = false;
434 aborted = abort_;
435 }
436
437 if (aborted) {
438 AbortInactiveJobs();
439 return;
440 } 331 }
441 332
442 // Number of jobs that are unlikely to make progress during any idle callback 333 // Number of jobs that are unlikely to make progress during any idle callback
443 // due to their estimated duration. 334 // due to their estimated duration.
444 size_t too_long_jobs = 0; 335 size_t too_long_jobs = 0;
445 336
446 // Iterate over all available jobs & remaining time. For each job, decide 337 // Iterate over all available jobs & remaining time. For each job, decide
447 // whether to 1) skip it (if it would take too long), 2) erase it (if it's 338 // whether to 1) skip it (if it would take too long), 2) erase it (if it's
448 // finished), or 3) make progress on it. 339 // finished), or 3) make progress on it.
449 double idle_time_in_seconds = 340 double idle_time_in_seconds =
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 lock.reset(); 381 lock.reset();
491 DoNextStepOnMainThread(isolate_, job->second.get(), 382 DoNextStepOnMainThread(isolate_, job->second.get(),
492 ExceptionHandling::kSwallow); 383 ExceptionHandling::kSwallow);
493 } 384 }
494 } 385 }
495 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); 386 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded();
496 } 387 }
497 388
498 } // namespace internal 389 } // namespace internal
499 } // namespace v8 390 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler-dispatcher/compiler-dispatcher.h ('k') | test/unittests/cancelable-tasks-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698