OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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.h" | 5 #include "src/compiler.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/asmjs/asm-js.h" | 10 #include "src/asmjs/asm-js.h" |
11 #include "src/asmjs/asm-typer.h" | 11 #include "src/asmjs/asm-typer.h" |
12 #include "src/ast/ast-numbering.h" | 12 #include "src/ast/ast-numbering.h" |
13 #include "src/ast/prettyprinter.h" | 13 #include "src/ast/prettyprinter.h" |
14 #include "src/ast/scopes.h" | 14 #include "src/ast/scopes.h" |
15 #include "src/bootstrapper.h" | 15 #include "src/bootstrapper.h" |
16 #include "src/codegen.h" | 16 #include "src/codegen.h" |
17 #include "src/compilation-cache.h" | 17 #include "src/compilation-cache.h" |
| 18 #include "src/compiler-dispatcher/compiler-dispatcher.h" |
18 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" | 19 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" |
19 #include "src/compiler/pipeline.h" | 20 #include "src/compiler/pipeline.h" |
20 #include "src/crankshaft/hydrogen.h" | 21 #include "src/crankshaft/hydrogen.h" |
21 #include "src/debug/debug.h" | 22 #include "src/debug/debug.h" |
22 #include "src/debug/liveedit.h" | 23 #include "src/debug/liveedit.h" |
23 #include "src/frames-inl.h" | 24 #include "src/frames-inl.h" |
24 #include "src/full-codegen/full-codegen.h" | 25 #include "src/full-codegen/full-codegen.h" |
25 #include "src/globals.h" | 26 #include "src/globals.h" |
26 #include "src/heap/heap.h" | 27 #include "src/heap/heap.h" |
27 #include "src/interpreter/interpreter.h" | 28 #include "src/interpreter/interpreter.h" |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 // Checks whether top level functions should be passed by the filter. | 369 // Checks whether top level functions should be passed by the filter. |
369 if (shared->is_toplevel()) { | 370 if (shared->is_toplevel()) { |
370 Vector<const char> filter = CStrVector(FLAG_ignition_filter); | 371 Vector<const char> filter = CStrVector(FLAG_ignition_filter); |
371 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); | 372 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); |
372 } | 373 } |
373 | 374 |
374 // Finally respect the filter. | 375 // Finally respect the filter. |
375 return shared->PassesFilter(FLAG_ignition_filter); | 376 return shared->PassesFilter(FLAG_ignition_filter); |
376 } | 377 } |
377 | 378 |
| 379 bool UseAsmWasm(DeclarationScope* scope, Handle<SharedFunctionInfo> shared_info, |
| 380 bool is_debug) { |
| 381 return FLAG_validate_asm && scope->asm_module() && |
| 382 !shared_info->is_asm_wasm_broken() && !is_debug; |
| 383 } |
| 384 |
| 385 bool UseCompilerDispatcher(CompilerDispatcher* dispatcher, |
| 386 DeclarationScope* scope, |
| 387 Handle<SharedFunctionInfo> shared_info, |
| 388 bool is_debug, bool will_serialize) { |
| 389 return dispatcher->IsEnabled() && !is_debug && !will_serialize && |
| 390 !UseAsmWasm(scope, shared_info, is_debug); |
| 391 } |
| 392 |
378 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { | 393 CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) { |
379 // Function should have been parsed and analyzed before creating a compilation | 394 // Function should have been parsed and analyzed before creating a compilation |
380 // job. | 395 // job. |
381 DCHECK_NOT_NULL(info->literal()); | 396 DCHECK_NOT_NULL(info->literal()); |
382 DCHECK_NOT_NULL(info->scope()); | 397 DCHECK_NOT_NULL(info->scope()); |
383 | 398 |
384 EnsureFeedbackMetadata(info); | 399 EnsureFeedbackMetadata(info); |
385 if (ShouldUseIgnition(info)) { | 400 if (ShouldUseIgnition(info)) { |
386 return interpreter::Interpreter::NewCompilationJob(info); | 401 return interpreter::Interpreter::NewCompilationJob(info); |
387 } else { | 402 } else { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 // Update the shared function info with the scope info. | 436 // Update the shared function info with the scope info. |
422 InstallSharedScopeInfo(info, shared); | 437 InstallSharedScopeInfo(info, shared); |
423 | 438 |
424 // Install compilation result on the shared function info | 439 // Install compilation result on the shared function info |
425 InstallSharedCompilationResult(info, shared); | 440 InstallSharedCompilationResult(info, shared); |
426 } | 441 } |
427 | 442 |
428 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { | 443 CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) { |
429 CompilationJob::Status status = job->FinalizeJob(); | 444 CompilationJob::Status status = job->FinalizeJob(); |
430 if (status == CompilationJob::SUCCEEDED) { | 445 if (status == CompilationJob::SUCCEEDED) { |
431 InstallUnoptimizedCode(job->info()); | 446 CompilationInfo* info = job->info(); |
| 447 DCHECK(!info->code().is_null()); |
| 448 if (info->parse_info()->literal()->should_be_used_once_hint()) { |
| 449 info->code()->MarkToBeExecutedOnce(info->isolate()); |
| 450 } |
| 451 InstallUnoptimizedCode(info); |
432 job->RecordUnoptimizedCompilationStats(); | 452 job->RecordUnoptimizedCompilationStats(); |
433 } | 453 } |
434 return status; | 454 return status; |
435 } | 455 } |
436 | 456 |
437 bool Renumber(ParseInfo* parse_info, | 457 bool Renumber(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
| 458 Handle<SharedFunctionInfo> shared_info, |
438 Compiler::EagerInnerFunctionLiterals* eager_literals) { | 459 Compiler::EagerInnerFunctionLiterals* eager_literals) { |
439 RuntimeCallTimerScope runtimeTimer(parse_info->isolate(), | 460 RuntimeCallTimerScope runtimeTimer(isolate, |
440 &RuntimeCallStats::CompileRenumber); | 461 &RuntimeCallStats::CompileRenumber); |
441 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), | 462 if (!AstNumbering::Renumber(isolate, zone, literal, eager_literals)) { |
442 parse_info->literal(), eager_literals)) { | |
443 return false; | 463 return false; |
444 } | 464 } |
445 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); | |
446 if (!shared_info.is_null()) { | 465 if (!shared_info.is_null()) { |
447 FunctionLiteral* lit = parse_info->literal(); | 466 shared_info->set_ast_node_count(literal->ast_node_count()); |
448 shared_info->set_ast_node_count(lit->ast_node_count()); | 467 if (literal->dont_optimize_reason() != kNoReason) { |
449 if (lit->dont_optimize_reason() != kNoReason) { | 468 shared_info->DisableOptimization(literal->dont_optimize_reason()); |
450 shared_info->DisableOptimization(lit->dont_optimize_reason()); | |
451 } | 469 } |
452 if (lit->flags() & AstProperties::kMustUseIgnitionTurbo) { | 470 if (literal->flags() & AstProperties::kMustUseIgnitionTurbo) { |
453 shared_info->set_must_use_ignition_turbo(true); | 471 shared_info->set_must_use_ignition_turbo(true); |
454 } | 472 } |
455 } | 473 } |
456 return true; | 474 return true; |
457 } | 475 } |
458 | 476 |
459 bool GenerateUnoptimizedCode(CompilationInfo* info) { | 477 bool GenerateUnoptimizedCode(CompilationInfo* info) { |
460 if (FLAG_validate_asm && info->scope()->asm_module() && | 478 if (UseAsmWasm(info->scope(), info->shared_info(), info->is_debug())) { |
461 !info->shared_info()->is_asm_wasm_broken() && !info->is_debug()) { | |
462 EnsureFeedbackMetadata(info); | 479 EnsureFeedbackMetadata(info); |
463 MaybeHandle<FixedArray> wasm_data; | 480 MaybeHandle<FixedArray> wasm_data; |
464 wasm_data = AsmJs::CompileAsmViaWasm(info); | 481 wasm_data = AsmJs::CompileAsmViaWasm(info); |
465 if (!wasm_data.is_null()) { | 482 if (!wasm_data.is_null()) { |
466 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); | 483 info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked()); |
467 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); | 484 info->SetCode(info->isolate()->builtins()->InstantiateAsmJs()); |
468 InstallUnoptimizedCode(info); | 485 InstallUnoptimizedCode(info); |
469 return true; | 486 return true; |
470 } | 487 } |
471 } | 488 } |
472 | 489 |
473 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); | 490 std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info)); |
474 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; | 491 if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; |
475 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; | 492 if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false; |
476 if (FinalizeUnoptimizedCompilationJob(job.get()) != | 493 if (FinalizeUnoptimizedCompilationJob(job.get()) != |
477 CompilationJob::SUCCEEDED) { | 494 CompilationJob::SUCCEEDED) { |
478 return false; | 495 return false; |
479 } | 496 } |
480 return true; | 497 return true; |
481 } | 498 } |
482 | 499 |
483 bool CompileUnoptimizedInnerFunctionsRecursively( | 500 bool CompileUnoptimizedInnerFunctionsRecursively( |
484 ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals, | 501 ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals, |
485 CompilationInfo* outer_info) { | 502 CompilationInfo* outer_info) { |
486 Isolate* isolate = outer_info->isolate(); | 503 Isolate* isolate = outer_info->isolate(); |
487 Handle<Script> script = outer_info->script(); | 504 Handle<Script> script = outer_info->script(); |
| 505 bool is_debug = outer_info->is_debug(); |
| 506 bool will_serialize = outer_info->will_serialize(); |
488 RuntimeCallTimerScope runtimeTimer(isolate, | 507 RuntimeCallTimerScope runtimeTimer(isolate, |
489 &RuntimeCallStats::CompileInnerFunction); | 508 &RuntimeCallStats::CompileInnerFunction); |
490 | 509 |
491 for (auto it : *literals) { | 510 for (auto it : *literals) { |
492 FunctionLiteral* literal = it->value(); | 511 FunctionLiteral* literal = it->value(); |
493 | 512 Handle<SharedFunctionInfo> shared = |
494 // Find any previously allocated shared function info for the given literal. | 513 Compiler::GetSharedFunctionInfo(literal, script, outer_info); |
495 Handle<SharedFunctionInfo> shared; | |
496 MaybeHandle<SharedFunctionInfo> maybe_existing = | |
497 script->FindSharedFunctionInfo(isolate, literal); | |
498 if (maybe_existing.ToHandle(&shared)) { | |
499 DCHECK(!shared->is_toplevel()); | |
500 // If we found an existing shared function info with compiled code, | |
501 // we are done. | |
502 if (shared->is_compiled()) continue; | |
503 } else { | |
504 shared = | |
505 isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script); | |
506 shared->set_is_toplevel(false); | |
507 } | |
508 | |
509 Zone zone(isolate->allocator(), ZONE_NAME); | |
510 ParseInfo parse_info(&zone, script); | |
511 parse_info.set_literal(literal); | |
512 parse_info.set_shared_info(shared); | |
513 parse_info.set_function_literal_id(shared->function_literal_id()); | |
514 parse_info.set_language_mode(literal->scope()->language_mode()); | |
515 parse_info.set_ast_value_factory( | |
516 outer_info->parse_info()->ast_value_factory()); | |
517 parse_info.set_ast_value_factory_owned(false); | |
518 | |
519 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); | |
520 if (outer_info->will_serialize()) info.PrepareForSerializing(); | |
521 if (outer_info->is_debug()) info.MarkAsDebug(); | |
522 | |
523 Compiler::EagerInnerFunctionLiterals inner_literals; | 514 Compiler::EagerInnerFunctionLiterals inner_literals; |
524 if (!Renumber(&parse_info, &inner_literals) || | 515 if (!Renumber(isolate, outer_info->zone(), literal, shared, |
| 516 &inner_literals) || |
525 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, | 517 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, |
526 outer_info) || | 518 outer_info)) { |
527 !GenerateUnoptimizedCode(&info)) { | |
528 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 519 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
529 return false; | 520 return false; |
530 } | 521 } |
531 | 522 |
532 DCHECK(!info.code().is_null()); | 523 // Try to enqueue the eager function on the compiler dispatcher. |
533 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info); | 524 CompilerDispatcher* dispatcher = isolate->compiler_dispatcher(); |
534 if (literal->should_be_used_once_hint()) { | 525 if (UseCompilerDispatcher(dispatcher, literal->scope(), shared, is_debug, |
535 info.code()->MarkToBeExecutedOnce(isolate); | 526 will_serialize) && |
| 527 dispatcher->EnqueueAndStep( |
| 528 shared, literal, outer_info->parse_info()->ast_value_factory())) { |
| 529 // If we have successfully queued up the function for compilation on the |
| 530 // compiler dispatcher then we are done. |
| 531 continue; |
| 532 } else { |
| 533 // Otherwise generate unoptimized code now. |
| 534 Zone zone(isolate->allocator(), ZONE_NAME); |
| 535 ParseInfo parse_info(&zone, script); |
| 536 CompilationInfo info(&parse_info, Handle<JSFunction>::null()); |
| 537 |
| 538 parse_info.set_literal(literal); |
| 539 parse_info.set_shared_info(shared); |
| 540 parse_info.set_function_literal_id(shared->function_literal_id()); |
| 541 parse_info.set_language_mode(literal->scope()->language_mode()); |
| 542 parse_info.set_ast_value_factory( |
| 543 outer_info->parse_info()->ast_value_factory()); |
| 544 parse_info.set_ast_value_factory_owned(false); |
| 545 |
| 546 if (will_serialize) info.PrepareForSerializing(); |
| 547 if (is_debug) info.MarkAsDebug(); |
| 548 |
| 549 if (!GenerateUnoptimizedCode(&info)) { |
| 550 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 551 return false; |
| 552 } |
536 } | 553 } |
537 } | 554 } |
538 return true; | 555 return true; |
539 } | 556 } |
540 | 557 |
541 bool CompileUnoptimizedCode(CompilationInfo* info) { | 558 bool CompileUnoptimizedCode(CompilationInfo* info) { |
542 Isolate* isolate = info->isolate(); | 559 Isolate* isolate = info->isolate(); |
543 DCHECK(AllowCompilation::IsAllowed(isolate)); | 560 DCHECK(AllowCompilation::IsAllowed(isolate)); |
544 | 561 |
545 Compiler::EagerInnerFunctionLiterals inner_literals; | 562 Compiler::EagerInnerFunctionLiterals inner_literals; |
546 if (!Compiler::Analyze(info->parse_info(), &inner_literals) || | 563 if (!Compiler::Analyze(info->parse_info(), &inner_literals) || |
547 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, info) || | 564 !CompileUnoptimizedInnerFunctionsRecursively(&inner_literals, info) || |
548 !GenerateUnoptimizedCode(info)) { | 565 !GenerateUnoptimizedCode(info)) { |
549 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 566 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
550 return false; | 567 return false; |
551 } | 568 } |
552 | 569 |
| 570 // TODO(rmcilroy): Remove this once the enqueued tasks can keep the parsed |
| 571 // zone and handles alive and replace with a check in CompileLazy to finish |
| 572 // the task itself. |
| 573 if (isolate->compiler_dispatcher()->IsEnabled() && |
| 574 !isolate->compiler_dispatcher()->FinishAllNow()) { |
| 575 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 576 return false; |
| 577 } |
| 578 |
553 return true; | 579 return true; |
554 } | 580 } |
555 | 581 |
556 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { | 582 void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) { |
557 DCHECK(info->is_toplevel()); | 583 DCHECK(info->is_toplevel()); |
558 DCHECK(!info->script().is_null()); | 584 DCHECK(!info->script().is_null()); |
559 if (info->script()->shared_function_infos()->length() > 0) { | 585 if (info->script()->shared_function_infos()->length() > 0) { |
560 DCHECK_EQ(info->script()->shared_function_infos()->length(), | 586 DCHECK_EQ(info->script()->shared_function_infos()->length(), |
561 info->max_function_literal_id() + 1); | 587 info->max_function_literal_id() + 1); |
562 return; | 588 return; |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // ---------------------------------------------------------------------------- | 1144 // ---------------------------------------------------------------------------- |
1119 // Implementation of Compiler | 1145 // Implementation of Compiler |
1120 | 1146 |
1121 bool Compiler::Analyze(ParseInfo* info, | 1147 bool Compiler::Analyze(ParseInfo* info, |
1122 EagerInnerFunctionLiterals* eager_literals) { | 1148 EagerInnerFunctionLiterals* eager_literals) { |
1123 DCHECK_NOT_NULL(info->literal()); | 1149 DCHECK_NOT_NULL(info->literal()); |
1124 RuntimeCallTimerScope runtimeTimer(info->isolate(), | 1150 RuntimeCallTimerScope runtimeTimer(info->isolate(), |
1125 &RuntimeCallStats::CompileAnalyse); | 1151 &RuntimeCallStats::CompileAnalyse); |
1126 if (!Rewriter::Rewrite(info)) return false; | 1152 if (!Rewriter::Rewrite(info)) return false; |
1127 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); | 1153 DeclarationScope::Analyze(info, AnalyzeMode::kRegular); |
1128 if (!Renumber(info, eager_literals)) return false; | 1154 if (!Renumber(info->isolate(), info->zone(), info->literal(), |
| 1155 info->shared_info(), eager_literals)) { |
| 1156 return false; |
| 1157 } |
1129 DCHECK_NOT_NULL(info->scope()); | 1158 DCHECK_NOT_NULL(info->scope()); |
1130 return true; | 1159 return true; |
1131 } | 1160 } |
1132 | 1161 |
1133 bool Compiler::ParseAndAnalyze(ParseInfo* info) { | 1162 bool Compiler::ParseAndAnalyze(ParseInfo* info) { |
1134 if (!parsing::ParseAny(info)) return false; | 1163 if (!parsing::ParseAny(info)) return false; |
1135 if (info->is_toplevel()) EnsureSharedFunctionInfosArrayOnScript(info); | 1164 if (info->is_toplevel()) EnsureSharedFunctionInfosArrayOnScript(info); |
1136 if (!Compiler::Analyze(info)) return false; | 1165 if (!Compiler::Analyze(info)) return false; |
1137 DCHECK_NOT_NULL(info->literal()); | 1166 DCHECK_NOT_NULL(info->literal()); |
1138 DCHECK_NOT_NULL(info->scope()); | 1167 DCHECK_NOT_NULL(info->scope()); |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 } | 1791 } |
1763 | 1792 |
1764 if (shared->is_compiled()) { | 1793 if (shared->is_compiled()) { |
1765 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1794 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1766 JSFunction::EnsureLiterals(function); | 1795 JSFunction::EnsureLiterals(function); |
1767 } | 1796 } |
1768 } | 1797 } |
1769 | 1798 |
1770 } // namespace internal | 1799 } // namespace internal |
1771 } // namespace v8 | 1800 } // namespace v8 |
OLD | NEW |