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

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

Issue 2608163006: Abort running compiler dispatcher tasks under memory pressure (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"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler-dispatcher/compiler-dispatcher.h ('k') | test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698