| 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 "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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 86 |
| 87 default: | 87 default: |
| 88 UNREACHABLE(); | 88 UNREACHABLE(); |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Theoretically we get 50ms of idle time max, however it's unlikely that | 92 // 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. | 93 // we'll get all of it so try to be a conservative. |
| 94 const double kMaxIdleTimeToExpectInMs = 40; | 94 const double kMaxIdleTimeToExpectInMs = 40; |
| 95 | 95 |
| 96 class MemoryPressureTask : public CancelableTask { |
| 97 public: |
| 98 MemoryPressureTask(Isolate* isolate, CancelableTaskManager* task_manager, |
| 99 CompilerDispatcher* dispatcher); |
| 100 ~MemoryPressureTask() override; |
| 101 |
| 102 // CancelableTask implementation. |
| 103 void RunInternal() override; |
| 104 |
| 105 private: |
| 106 CompilerDispatcher* dispatcher_; |
| 107 |
| 108 DISALLOW_COPY_AND_ASSIGN(MemoryPressureTask); |
| 109 }; |
| 110 |
| 111 MemoryPressureTask::MemoryPressureTask(Isolate* isolate, |
| 112 CancelableTaskManager* task_manager, |
| 113 CompilerDispatcher* dispatcher) |
| 114 : CancelableTask(isolate, task_manager), dispatcher_(dispatcher) {} |
| 115 |
| 116 MemoryPressureTask::~MemoryPressureTask() {} |
| 117 |
| 118 void MemoryPressureTask::RunInternal() { |
| 119 dispatcher_->AbortAll(CompilerDispatcher::BlockingBehavior::kDontBlock); |
| 120 } |
| 121 |
| 96 } // namespace | 122 } // namespace |
| 97 | 123 |
| 98 class CompilerDispatcher::AbortTask : public CancelableTask { | 124 class CompilerDispatcher::AbortTask : public CancelableTask { |
| 99 public: | 125 public: |
| 100 AbortTask(Isolate* isolate, CancelableTaskManager* task_manager, | 126 AbortTask(Isolate* isolate, CancelableTaskManager* task_manager, |
| 101 CompilerDispatcher* dispatcher); | 127 CompilerDispatcher* dispatcher); |
| 102 ~AbortTask() override; | 128 ~AbortTask() override; |
| 103 | 129 |
| 104 // CancelableTask implementation. | 130 // CancelableTask implementation. |
| 105 void RunInternal() override; | 131 void RunInternal() override; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 dispatcher_->DoIdleWork(deadline_in_seconds); | 199 dispatcher_->DoIdleWork(deadline_in_seconds); |
| 174 } | 200 } |
| 175 | 201 |
| 176 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform, | 202 CompilerDispatcher::CompilerDispatcher(Isolate* isolate, Platform* platform, |
| 177 size_t max_stack_size) | 203 size_t max_stack_size) |
| 178 : isolate_(isolate), | 204 : isolate_(isolate), |
| 179 platform_(platform), | 205 platform_(platform), |
| 180 max_stack_size_(max_stack_size), | 206 max_stack_size_(max_stack_size), |
| 181 tracer_(new CompilerDispatcherTracer(isolate_)), | 207 tracer_(new CompilerDispatcherTracer(isolate_)), |
| 182 task_manager_(new CancelableTaskManager()), | 208 task_manager_(new CancelableTaskManager()), |
| 209 memory_pressure_level_(MemoryPressureLevel::kNone), |
| 183 abort_(false), | 210 abort_(false), |
| 184 idle_task_scheduled_(false), | 211 idle_task_scheduled_(false), |
| 185 num_scheduled_background_tasks_(0), | 212 num_scheduled_background_tasks_(0), |
| 186 main_thread_blocking_on_job_(nullptr), | 213 main_thread_blocking_on_job_(nullptr), |
| 187 block_for_testing_(false), | 214 block_for_testing_(false), |
| 188 semaphore_for_testing_(0) {} | 215 semaphore_for_testing_(0) {} |
| 189 | 216 |
| 190 CompilerDispatcher::~CompilerDispatcher() { | 217 CompilerDispatcher::~CompilerDispatcher() { |
| 191 // To avoid crashing in unit tests due to unfished jobs. | 218 // To avoid crashing in unit tests due to unfished jobs. |
| 192 AbortAll(BlockingBehavior::kBlock); | 219 AbortAll(BlockingBehavior::kBlock); |
| 193 task_manager_->CancelAndWait(); | 220 task_manager_->CancelAndWait(); |
| 194 } | 221 } |
| 195 | 222 |
| 196 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { | 223 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { |
| 197 if (!IsEnabled()) return false; | 224 if (!IsEnabled()) return false; |
| 198 | 225 |
| 226 if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) { |
| 227 return false; |
| 228 } |
| 229 |
| 199 { | 230 { |
| 200 base::LockGuard<base::Mutex> lock(&mutex_); | 231 base::LockGuard<base::Mutex> lock(&mutex_); |
| 201 if (abort_) return false; | 232 if (abort_) return false; |
| 202 } | 233 } |
| 203 | 234 |
| 204 // We only handle functions (no eval / top-level code / wasm) that are | 235 // We only handle functions (no eval / top-level code / wasm) that are |
| 205 // attached to a script. | 236 // attached to a script. |
| 206 if (!function->script()->IsScript() || !function->is_function() || | 237 if (!function->script()->IsScript() || !function->is_function() || |
| 207 function->asm_function() || function->native()) { | 238 function->asm_function() || function->native()) { |
| 208 return false; | 239 return false; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 } | 343 } |
| 313 job->second->ResetOnMainThread(); | 344 job->second->ResetOnMainThread(); |
| 314 jobs_.erase(job); | 345 jobs_.erase(job); |
| 315 } | 346 } |
| 316 if (jobs_.empty()) { | 347 if (jobs_.empty()) { |
| 317 base::LockGuard<base::Mutex> lock(&mutex_); | 348 base::LockGuard<base::Mutex> lock(&mutex_); |
| 318 abort_ = false; | 349 abort_ = false; |
| 319 } | 350 } |
| 320 } | 351 } |
| 321 | 352 |
| 353 void CompilerDispatcher::MemoryPressureNotification( |
| 354 v8::MemoryPressureLevel level, bool is_isolate_locked) { |
| 355 MemoryPressureLevel previous = memory_pressure_level_.Value(); |
| 356 memory_pressure_level_.SetValue(level); |
| 357 // 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. |
| 359 if (previous != MemoryPressureLevel::kNone || |
| 360 level == MemoryPressureLevel::kNone) { |
| 361 return; |
| 362 } |
| 363 if (is_isolate_locked) { |
| 364 AbortAll(BlockingBehavior::kDontBlock); |
| 365 } else { |
| 366 { |
| 367 base::LockGuard<base::Mutex> lock(&mutex_); |
| 368 if (abort_) return; |
| 369 // By going into abort mode here, and clearing the |
| 370 // pending_background_jobs_, we at keep existing background jobs from |
| 371 // picking up more work before the MemoryPressureTask gets executed. |
| 372 abort_ = true; |
| 373 pending_background_jobs_.clear(); |
| 374 } |
| 375 platform_->CallOnForegroundThread( |
| 376 reinterpret_cast<v8::Isolate*>(isolate_), |
| 377 new MemoryPressureTask(isolate_, task_manager_.get(), this)); |
| 378 } |
| 379 } |
| 380 |
| 322 CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor( | 381 CompilerDispatcher::JobMap::const_iterator CompilerDispatcher::GetJobFor( |
| 323 Handle<SharedFunctionInfo> shared) const { | 382 Handle<SharedFunctionInfo> shared) const { |
| 324 if (!shared->script()->IsScript()) return jobs_.end(); | 383 if (!shared->script()->IsScript()) return jobs_.end(); |
| 325 std::pair<int, int> key(Script::cast(shared->script())->id(), | 384 std::pair<int, int> key(Script::cast(shared->script())->id(), |
| 326 shared->function_literal_id()); | 385 shared->function_literal_id()); |
| 327 auto range = jobs_.equal_range(key); | 386 auto range = jobs_.equal_range(key); |
| 328 for (auto job = range.first; job != range.second; ++job) { | 387 for (auto job = range.first; job != range.second; ++job) { |
| 329 if (job->second->IsAssociatedWith(shared)) return job; | 388 if (job->second->IsAssociatedWith(shared)) return job; |
| 330 } | 389 } |
| 331 return jobs_.end(); | 390 return jobs_.end(); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 lock.reset(); | 549 lock.reset(); |
| 491 DoNextStepOnMainThread(isolate_, job->second.get(), | 550 DoNextStepOnMainThread(isolate_, job->second.get(), |
| 492 ExceptionHandling::kSwallow); | 551 ExceptionHandling::kSwallow); |
| 493 } | 552 } |
| 494 } | 553 } |
| 495 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); | 554 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); |
| 496 } | 555 } |
| 497 | 556 |
| 498 } // namespace internal | 557 } // namespace internal |
| 499 } // namespace v8 | 558 } // namespace v8 |
| OLD | NEW |