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

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

Issue 2611313002: [complier] Enable parallel eager inner function compilation with compiler dispatcher. (Closed)
Patch Set: Move flag 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/compilation-info.h"
11 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" 12 #include "src/compiler-dispatcher/compiler-dispatcher-job.h"
12 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" 13 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
13 #include "src/flags.h" 14 #include "src/flags.h"
14 #include "src/objects-inl.h" 15 #include "src/objects-inl.h"
15 16
16 namespace v8 { 17 namespace v8 {
17 namespace internal { 18 namespace internal {
18 19
19 namespace { 20 namespace {
20 21
21 enum class ExceptionHandling { kSwallow, kThrow }; 22 enum class ExceptionHandling { kSwallow, kThrow };
22 23
23 bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job, 24 bool DoNextStepOnMainThread(Isolate* isolate, CompilerDispatcherJob* job,
24 ExceptionHandling exception_handling) { 25 ExceptionHandling exception_handling) {
25 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); 26 DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
26 switch (job->status()) { 27 switch (job->status()) {
27 case CompileJobStatus::kInitial: 28 case CompileJobStatus::kInitial:
28 job->PrepareToParseOnMainThread(); 29 job->PrepareToParseOnMainThread();
29 break; 30 break;
30 31
31 case CompileJobStatus::kReadyToParse: 32 case CompileJobStatus::kReadyToParse:
32 job->Parse(); 33 job->Parse();
33 break; 34 break;
34 35
35 case CompileJobStatus::kParsed: 36 case CompileJobStatus::kParsed:
36 job->FinalizeParsingOnMainThread(); 37 job->FinalizeParsingOnMainThread();
37 break; 38 break;
38 39
39 case CompileJobStatus::kReadyToAnalyse: 40 case CompileJobStatus::kReadyToAnalyze:
41 job->AnalyzeOnMainThread();
42 break;
43
44 case CompileJobStatus::kAnalyzed:
40 job->PrepareToCompileOnMainThread(); 45 job->PrepareToCompileOnMainThread();
41 break; 46 break;
42 47
43 case CompileJobStatus::kReadyToCompile: 48 case CompileJobStatus::kReadyToCompile:
44 job->Compile(); 49 job->Compile();
45 break; 50 break;
46 51
47 case CompileJobStatus::kCompiled: 52 case CompileJobStatus::kCompiled:
48 job->FinalizeCompilingOnMainThread(); 53 job->FinalizeCompilingOnMainThread();
49 break; 54 break;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 PrintF("CompilerDispatcher: dispatcher is disabled\n"); 224 PrintF("CompilerDispatcher: dispatcher is disabled\n");
220 } 225 }
221 } 226 }
222 227
223 CompilerDispatcher::~CompilerDispatcher() { 228 CompilerDispatcher::~CompilerDispatcher() {
224 // To avoid crashing in unit tests due to unfished jobs. 229 // To avoid crashing in unit tests due to unfished jobs.
225 AbortAll(BlockingBehavior::kBlock); 230 AbortAll(BlockingBehavior::kBlock);
226 task_manager_->CancelAndWait(); 231 task_manager_->CancelAndWait();
227 } 232 }
228 233
229 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) { 234 bool CompilerDispatcher::CanEnqueue(Handle<SharedFunctionInfo> function) {
230 if (!IsEnabled()) return false; 235 if (!IsEnabled()) return false;
231 236
232 if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) { 237 if (memory_pressure_level_.Value() != MemoryPressureLevel::kNone) {
233 return false; 238 return false;
234 } 239 }
235 240
236 { 241 {
237 base::LockGuard<base::Mutex> lock(&mutex_); 242 base::LockGuard<base::Mutex> lock(&mutex_);
238 if (abort_) return false; 243 if (abort_) return false;
239 } 244 }
240 245
241 // We only handle functions (no eval / top-level code / wasm) that are 246 // We only handle functions (no eval / top-level code / wasm) that are
242 // attached to a script. 247 // attached to a script.
243 if (!function->script()->IsScript() || !function->is_function() || 248 if (!function->script()->IsScript() || !function->is_function() ||
244 function->asm_function() || function->native()) { 249 function->asm_function() || function->native()) {
245 return false; 250 return false;
246 } 251 }
247 252
253 return true;
254 }
255
256 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function) {
257 if (!CanEnqueue(function)) return false;
248 if (IsEnqueued(function)) return true; 258 if (IsEnqueued(function)) return true;
249 259
250 if (trace_compiler_dispatcher_) { 260 if (trace_compiler_dispatcher_) {
251 PrintF("CompilerDispatcher: enqueuing "); 261 PrintF("CompilerDispatcher: enqueuing ");
252 function->ShortPrint(); 262 function->ShortPrint();
253 PrintF("\n"); 263 PrintF(" for parse and compile\n");
254 } 264 }
255 265
256 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob( 266 std::unique_ptr<CompilerDispatcherJob> job(new CompilerDispatcherJob(
257 isolate_, tracer_.get(), function, max_stack_size_)); 267 isolate_, tracer_.get(), function, max_stack_size_));
258 std::pair<int, int> key(Script::cast(function->script())->id(), 268 std::pair<int, int> key(Script::cast(function->script())->id(),
259 function->function_literal_id()); 269 function->function_literal_id());
260 jobs_.insert(std::make_pair(key, std::move(job))); 270 jobs_.insert(std::make_pair(key, std::move(job)));
261 ScheduleIdleTaskIfNeeded(); 271 ScheduleIdleTaskIfNeeded();
262 return true; 272 return true;
263 } 273 }
264 274
265 bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) { 275 bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function) {
266 if (!Enqueue(function)) return false; 276 if (!Enqueue(function)) return false;
267 277
268 if (trace_compiler_dispatcher_) { 278 if (trace_compiler_dispatcher_) {
269 PrintF("CompilerDispatcher: stepping "); 279 PrintF("CompilerDispatcher: stepping ");
270 function->ShortPrint(); 280 function->ShortPrint();
271 PrintF("\n"); 281 PrintF("\n");
272 } 282 }
273 JobMap::const_iterator job = GetJobFor(function); 283 JobMap::const_iterator job = GetJobFor(function);
274 DoNextStepOnMainThread(isolate_, job->second.get(), 284 DoNextStepOnMainThread(isolate_, job->second.get(),
275 ExceptionHandling::kSwallow); 285 ExceptionHandling::kSwallow);
276 ConsiderJobForBackgroundProcessing(job->second.get()); 286 ConsiderJobForBackgroundProcessing(job->second.get());
277 return true; 287 return true;
278 } 288 }
279 289
280 bool CompilerDispatcher::IsEnabled() const { 290 bool CompilerDispatcher::Enqueue(Handle<SharedFunctionInfo> function,
281 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); 291 FunctionLiteral* literal,
282 return FLAG_compiler_dispatcher && platform_->IdleTasksEnabled(v8_isolate); 292 AstValueFactory* ast_value_factory) {
marja 2017/01/12 16:07:33 So now we might access this AstValueFactory from a
rmcilroy 2017/01/13 11:28:02 Yes this is a valid concern. Right now it isn't a
rmcilroy 2017/01/16 14:18:25 Removed need for ast-value-factory, does this work
293 if (!CanEnqueue(function)) return false;
294 if (IsEnqueued(function)) return true;
295
296 if (trace_compiler_dispatcher_) {
297 PrintF("CompilerDispatcher: enqueuing ");
298 function->ShortPrint();
299 PrintF(" for compile\n");
300 }
301
302 std::unique_ptr<CompilerDispatcherJob> job(
303 new CompilerDispatcherJob(isolate_, tracer_.get(), function, literal,
304 ast_value_factory, max_stack_size_));
305 std::pair<int, int> key(Script::cast(function->script())->id(),
306 function->function_literal_id());
307 jobs_.insert(std::make_pair(key, std::move(job)));
308 ScheduleIdleTaskIfNeeded();
309 return true;
283 } 310 }
284 311
312 bool CompilerDispatcher::EnqueueAndStep(Handle<SharedFunctionInfo> function,
313 FunctionLiteral* literal,
314 AstValueFactory* ast_value_factory) {
315 if (!Enqueue(function, literal, ast_value_factory)) return false;
316
317 if (trace_compiler_dispatcher_) {
318 PrintF("CompilerDispatcher: stepping ");
319 function->ShortPrint();
320 PrintF("\n");
321 }
322 JobMap::const_iterator job = GetJobFor(function);
323 DoNextStepOnMainThread(isolate_, job->second.get(),
324 ExceptionHandling::kSwallow);
325 ConsiderJobForBackgroundProcessing(job->second.get());
326 return true;
327 }
328
329 bool CompilerDispatcher::IsEnabled() const { return FLAG_compiler_dispatcher; }
330
285 bool CompilerDispatcher::IsEnqueued(Handle<SharedFunctionInfo> function) const { 331 bool CompilerDispatcher::IsEnqueued(Handle<SharedFunctionInfo> function) const {
286 return GetJobFor(function) != jobs_.end(); 332 return GetJobFor(function) != jobs_.end();
287 } 333 }
288 334
289 void CompilerDispatcher::WaitForJobIfRunningOnBackground( 335 void CompilerDispatcher::WaitForJobIfRunningOnBackground(
290 CompilerDispatcherJob* job) { 336 CompilerDispatcherJob* job) {
291 base::LockGuard<base::Mutex> lock(&mutex_); 337 base::LockGuard<base::Mutex> lock(&mutex_);
292 if (running_background_jobs_.find(job) == running_background_jobs_.end()) { 338 if (running_background_jobs_.find(job) == running_background_jobs_.end()) {
293 pending_background_jobs_.erase(job); 339 pending_background_jobs_.erase(job);
294 return; 340 return;
295 } 341 }
296 DCHECK_NULL(main_thread_blocking_on_job_); 342 DCHECK_NULL(main_thread_blocking_on_job_);
297 main_thread_blocking_on_job_ = job; 343 main_thread_blocking_on_job_ = job;
298 while (main_thread_blocking_on_job_ != nullptr) { 344 while (main_thread_blocking_on_job_ != nullptr) {
299 main_thread_blocking_signal_.Wait(&mutex_); 345 main_thread_blocking_signal_.Wait(&mutex_);
300 } 346 }
301 DCHECK(pending_background_jobs_.find(job) == pending_background_jobs_.end()); 347 DCHECK(pending_background_jobs_.find(job) == pending_background_jobs_.end());
302 DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end()); 348 DCHECK(running_background_jobs_.find(job) == running_background_jobs_.end());
303 } 349 }
304 350
351 bool CompilerDispatcher::FinishNow(CompilerDispatcherJob* job) {
352 WaitForJobIfRunningOnBackground(job);
353 while (!IsFinished(job)) {
354 DoNextStepOnMainThread(isolate_, job, ExceptionHandling::kThrow);
355 }
356 bool result = job->status() != CompileJobStatus::kFailed;
357 job->ResetOnMainThread();
358 return result;
359 }
360
305 bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) { 361 bool CompilerDispatcher::FinishNow(Handle<SharedFunctionInfo> function) {
306 JobMap::const_iterator job = GetJobFor(function); 362 JobMap::const_iterator job = GetJobFor(function);
307 CHECK(job != jobs_.end()); 363 CHECK(job != jobs_.end());
308 364
309 if (trace_compiler_dispatcher_) { 365 if (trace_compiler_dispatcher_) {
310 PrintF("CompilerDispatcher: finishing "); 366 PrintF("CompilerDispatcher: finishing ");
311 function->ShortPrint(); 367 function->ShortPrint();
312 PrintF(" now\n"); 368 PrintF(" now\n");
313 } 369 }
314 370
315 WaitForJobIfRunningOnBackground(job->second.get()); 371 bool result = FinishNow(job->second.get());
316 while (!IsFinished(job->second.get())) {
317 DoNextStepOnMainThread(isolate_, job->second.get(),
318 ExceptionHandling::kThrow);
319 }
320 bool result = job->second->status() != CompileJobStatus::kFailed;
321 372
322 if (trace_compiler_dispatcher_) { 373 if (trace_compiler_dispatcher_) {
323 PrintF("CompilerDispatcher: finished working on "); 374 PrintF("CompilerDispatcher: finished working on ");
324 function->ShortPrint(); 375 function->ShortPrint();
325 PrintF(": %s\n", result ? "success" : "failure"); 376 PrintF(": %s\n", result ? "success" : "failure");
326 tracer_->DumpStatistics(); 377 tracer_->DumpStatistics();
327 } 378 }
328 379
329 job->second->ResetOnMainThread();
330 jobs_.erase(job); 380 jobs_.erase(job);
331 if (jobs_.empty()) { 381 if (jobs_.empty()) {
332 base::LockGuard<base::Mutex> lock(&mutex_); 382 base::LockGuard<base::Mutex> lock(&mutex_);
333 abort_ = false; 383 abort_ = false;
334 } 384 }
335 return result; 385 return result;
336 } 386 }
337 387
388 bool CompilerDispatcher::FinishAllNow() {
389 if (trace_compiler_dispatcher_) {
390 PrintF("CompilerDispatcher: finishing all jobs now\n");
391 }
392
393 bool result = true;
394 for (auto& it : jobs_) {
395 result &= FinishNow(it.second.get());
jochen (gone - plz use gerrit) 2017/01/12 13:13:36 does that work? FinishNow() should delete it from
rmcilroy 2017/01/12 13:59:47 This is calling the new FinishNowwith a Job argume
396 }
397
398 if (trace_compiler_dispatcher_) {
399 PrintF("CompilerDispatcher: finished all jobs\n");
400 }
401
402 jobs_.clear();
jochen (gone - plz use gerrit) 2017/01/12 13:13:36 jobs_ should already be empty here, no?
rmcilroy 2017/01/12 13:59:47 As above, the jobs are not deleted by the FinishNo
403 {
404 base::LockGuard<base::Mutex> lock(&mutex_);
405 DCHECK(pending_background_jobs_.empty());
406 DCHECK(running_background_jobs_.empty());
407 abort_ = false;
408 }
409 return result;
410 }
411
338 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) { 412 void CompilerDispatcher::AbortAll(BlockingBehavior blocking) {
339 bool background_tasks_running = 413 bool background_tasks_running =
340 task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning; 414 task_manager_->TryAbortAll() == CancelableTaskManager::kTaskRunning;
341 if (!background_tasks_running || blocking == BlockingBehavior::kBlock) { 415 if (!background_tasks_running || blocking == BlockingBehavior::kBlock) {
342 for (auto& it : jobs_) { 416 for (auto& it : jobs_) {
343 WaitForJobIfRunningOnBackground(it.second.get()); 417 WaitForJobIfRunningOnBackground(it.second.get());
344 if (trace_compiler_dispatcher_) { 418 if (trace_compiler_dispatcher_) {
345 PrintF("CompilerDispatcher: aborted "); 419 PrintF("CompilerDispatcher: aborted ");
346 it.second->ShortPrint(); 420 it.second->ShortPrint();
347 PrintF("\n"); 421 PrintF("\n");
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 lock.reset(); 696 lock.reset();
623 DoNextStepOnMainThread(isolate_, job->second.get(), 697 DoNextStepOnMainThread(isolate_, job->second.get(),
624 ExceptionHandling::kSwallow); 698 ExceptionHandling::kSwallow);
625 } 699 }
626 } 700 }
627 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded(); 701 if (jobs_.size() > too_long_jobs) ScheduleIdleTaskIfNeeded();
628 } 702 }
629 703
630 } // namespace internal 704 } // namespace internal
631 } // namespace v8 705 } // 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