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" |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "src/parsing/parsing.h" | 32 #include "src/parsing/parsing.h" |
33 #include "src/parsing/rewriter.h" | 33 #include "src/parsing/rewriter.h" |
34 #include "src/parsing/scanner-character-streams.h" | 34 #include "src/parsing/scanner-character-streams.h" |
35 #include "src/runtime-profiler.h" | 35 #include "src/runtime-profiler.h" |
36 #include "src/snapshot/code-serializer.h" | 36 #include "src/snapshot/code-serializer.h" |
37 #include "src/vm-state-inl.h" | 37 #include "src/vm-state-inl.h" |
38 | 38 |
39 namespace v8 { | 39 namespace v8 { |
40 namespace internal { | 40 namespace internal { |
41 | 41 |
| 42 // A wrapper around a ParseInfo that detaches the parser handles from the |
| 43 // underlying DeferredHandleScope and stores them in info_ on destruction. |
| 44 class ParseHandleScope final { |
| 45 public: |
| 46 explicit ParseHandleScope(ParseInfo* info) |
| 47 : deferred_(info->isolate()), info_(info) {} |
| 48 ~ParseHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
| 49 |
| 50 private: |
| 51 DeferredHandleScope deferred_; |
| 52 ParseInfo* info_; |
| 53 }; |
| 54 |
42 // A wrapper around a CompilationInfo that detaches the Handles from | 55 // A wrapper around a CompilationInfo that detaches the Handles from |
43 // the underlying DeferredHandleScope and stores them in info_ on | 56 // the underlying DeferredHandleScope and stores them in info_ on |
44 // destruction. | 57 // destruction. |
45 class CompilationHandleScope final { | 58 class CompilationHandleScope final { |
46 public: | 59 public: |
47 explicit CompilationHandleScope(CompilationInfo* info) | 60 explicit CompilationHandleScope(CompilationInfo* info) |
48 : deferred_(info->isolate()), info_(info) {} | 61 : deferred_(info->isolate()), info_(info) {} |
49 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } | 62 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
50 | 63 |
51 private: | 64 private: |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
505 if (FinalizeUnoptimizedCompilationJob(job.get()) != | 518 if (FinalizeUnoptimizedCompilationJob(job.get()) != |
506 CompilationJob::SUCCEEDED) { | 519 CompilationJob::SUCCEEDED) { |
507 return false; | 520 return false; |
508 } | 521 } |
509 return true; | 522 return true; |
510 } | 523 } |
511 | 524 |
512 bool CompileUnoptimizedInnerFunctions( | 525 bool CompileUnoptimizedInnerFunctions( |
513 Compiler::EagerInnerFunctionLiterals* literals, | 526 Compiler::EagerInnerFunctionLiterals* literals, |
514 Compiler::ConcurrencyMode inner_function_mode, | 527 Compiler::ConcurrencyMode inner_function_mode, |
515 CompilationInfo* outer_info) { | 528 std::shared_ptr<Zone> parse_zone, CompilationInfo* outer_info) { |
516 Isolate* isolate = outer_info->isolate(); | 529 Isolate* isolate = outer_info->isolate(); |
517 Handle<Script> script = outer_info->script(); | 530 Handle<Script> script = outer_info->script(); |
518 bool is_debug = outer_info->is_debug(); | 531 bool is_debug = outer_info->is_debug(); |
519 bool will_serialize = outer_info->will_serialize(); | 532 bool will_serialize = outer_info->will_serialize(); |
520 RuntimeCallTimerScope runtimeTimer(isolate, | 533 RuntimeCallTimerScope runtimeTimer(isolate, |
521 &RuntimeCallStats::CompileInnerFunction); | 534 &RuntimeCallStats::CompileInnerFunction); |
522 | 535 |
523 for (auto it : *literals) { | 536 for (auto it : *literals) { |
524 FunctionLiteral* literal = it->value(); | 537 FunctionLiteral* literal = it->value(); |
525 Handle<SharedFunctionInfo> shared = | 538 Handle<SharedFunctionInfo> shared = |
526 Compiler::GetSharedFunctionInfo(literal, script, outer_info); | 539 Compiler::GetSharedFunctionInfo(literal, script, outer_info); |
527 if (shared->is_compiled()) continue; | 540 if (shared->is_compiled()) continue; |
528 | 541 |
529 // The {literal} has already been numbered because AstNumbering decends into | 542 // The {literal} has already been numbered because AstNumbering decends into |
530 // eagerly compiled function literals. | 543 // eagerly compiled function literals. |
531 SetSharedFunctionFlagsFromLiteral(literal, shared); | 544 SetSharedFunctionFlagsFromLiteral(literal, shared); |
532 | 545 |
533 // Try to enqueue the eager function on the compiler dispatcher. | 546 // Try to enqueue the eager function on the compiler dispatcher. |
534 CompilerDispatcher* dispatcher = isolate->compiler_dispatcher(); | 547 CompilerDispatcher* dispatcher = isolate->compiler_dispatcher(); |
535 if (UseCompilerDispatcher(inner_function_mode, dispatcher, literal->scope(), | 548 if (UseCompilerDispatcher(inner_function_mode, dispatcher, literal->scope(), |
536 shared, is_debug, will_serialize) && | 549 shared, is_debug, will_serialize) && |
537 dispatcher->EnqueueAndStep(shared, literal)) { | 550 dispatcher->EnqueueAndStep(shared, literal, parse_zone, |
| 551 outer_info->parse_info()->deferred_handles(), |
| 552 outer_info->deferred_handles())) { |
538 // If we have successfully queued up the function for compilation on the | 553 // If we have successfully queued up the function for compilation on the |
539 // compiler dispatcher then we are done. | 554 // compiler dispatcher then we are done. |
540 continue; | 555 continue; |
541 } else { | 556 } else { |
542 // Otherwise generate unoptimized code now. | 557 // Otherwise generate unoptimized code now. |
543 ParseInfo parse_info(script); | 558 ParseInfo parse_info(script); |
544 CompilationInfo info(parse_info.zone(), &parse_info, | 559 CompilationInfo info(parse_info.zone(), &parse_info, |
545 Handle<JSFunction>::null()); | 560 Handle<JSFunction>::null()); |
546 | 561 |
547 parse_info.set_literal(literal); | 562 parse_info.set_literal(literal); |
(...skipping 24 matching lines...) Expand all Loading... |
572 } | 587 } |
573 return false; | 588 return false; |
574 } | 589 } |
575 | 590 |
576 bool CompileUnoptimizedCode(CompilationInfo* info, | 591 bool CompileUnoptimizedCode(CompilationInfo* info, |
577 Compiler::ConcurrencyMode inner_function_mode) { | 592 Compiler::ConcurrencyMode inner_function_mode) { |
578 Isolate* isolate = info->isolate(); | 593 Isolate* isolate = info->isolate(); |
579 DCHECK(AllowCompilation::IsAllowed(isolate)); | 594 DCHECK(AllowCompilation::IsAllowed(isolate)); |
580 | 595 |
581 Compiler::EagerInnerFunctionLiterals inner_literals; | 596 Compiler::EagerInnerFunctionLiterals inner_literals; |
582 if (!Compiler::Analyze(info->parse_info(), &inner_literals)) { | 597 { |
583 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 598 std::unique_ptr<CompilationHandleScope> compilation_handle_scope; |
584 return false; | 599 if (inner_function_mode == Compiler::CONCURRENT) { |
| 600 compilation_handle_scope.reset(new CompilationHandleScope(info)); |
| 601 } |
| 602 if (!Compiler::Analyze(info->parse_info(), &inner_literals)) { |
| 603 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 604 return false; |
| 605 } |
585 } | 606 } |
586 | 607 |
587 // Disable concurrent inner compilation for asm-wasm code. | 608 // Disable concurrent inner compilation for asm-wasm code. |
588 // TODO(rmcilroy,bradnelson): Remove this AsmWasm check once the asm-wasm | 609 // TODO(rmcilroy,bradnelson): Remove this AsmWasm check once the asm-wasm |
589 // builder doesn't do parsing when visiting function declarations. | 610 // builder doesn't do parsing when visiting function declarations. |
590 if (info->scope()->IsAsmModule() || | 611 if (info->scope()->IsAsmModule() || |
591 InnerFunctionIsAsmModule(&inner_literals)) { | 612 InnerFunctionIsAsmModule(&inner_literals)) { |
592 inner_function_mode = Compiler::NOT_CONCURRENT; | 613 inner_function_mode = Compiler::NOT_CONCURRENT; |
593 } | 614 } |
594 | 615 |
| 616 std::shared_ptr<Zone> parse_zone; |
595 if (inner_function_mode == Compiler::CONCURRENT) { | 617 if (inner_function_mode == Compiler::CONCURRENT) { |
596 // Seal the parse zone so that it can be shared by parallel inner function | 618 // Seal the parse zone so that it can be shared by parallel inner function |
597 // compilation jobs. | 619 // compilation jobs. |
598 DCHECK_NE(info->parse_info()->zone(), info->zone()); | 620 DCHECK_NE(info->parse_info()->zone(), info->zone()); |
599 info->parse_info()->zone()->Seal(); | 621 parse_zone = info->parse_info()->zone_shared(); |
| 622 parse_zone->Seal(); |
600 } | 623 } |
601 | 624 |
602 if (!CompileUnoptimizedInnerFunctions(&inner_literals, inner_function_mode, | 625 if (!CompileUnoptimizedInnerFunctions(&inner_literals, inner_function_mode, |
603 info) || | 626 parse_zone, info) || |
604 !GenerateUnoptimizedCode(info)) { | 627 !GenerateUnoptimizedCode(info)) { |
605 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 628 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
606 return false; | 629 return false; |
607 } | 630 } |
608 | 631 |
609 // TODO(rmcilroy): Remove this once the enqueued tasks can keep the parsed | 632 // TODO(rmcilroy): Remove this once the enqueued tasks can keep the parsed |
610 // zone and handles alive and replace with a check in CompileLazy to finish | 633 // zone and handles alive and replace with a check in CompileLazy to finish |
611 // the task itself. | 634 // the task itself. |
612 RuntimeCallTimerScope runtimeTimer( | 635 RuntimeCallTimerScope runtimeTimer( |
613 isolate, &RuntimeCallStats::CompileWaitForDispatcher); | 636 isolate, &RuntimeCallStats::CompileWaitForDispatcher); |
(...skipping 20 matching lines...) Expand all Loading... |
634 info->script()->set_shared_function_infos(*infos); | 657 info->script()->set_shared_function_infos(*infos); |
635 } | 658 } |
636 | 659 |
637 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode( | 660 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode( |
638 CompilationInfo* info, Compiler::ConcurrencyMode inner_function_mode) { | 661 CompilationInfo* info, Compiler::ConcurrencyMode inner_function_mode) { |
639 RuntimeCallTimerScope runtimeTimer( | 662 RuntimeCallTimerScope runtimeTimer( |
640 info->isolate(), &RuntimeCallStats::CompileGetUnoptimizedCode); | 663 info->isolate(), &RuntimeCallStats::CompileGetUnoptimizedCode); |
641 VMState<COMPILER> state(info->isolate()); | 664 VMState<COMPILER> state(info->isolate()); |
642 PostponeInterruptsScope postpone(info->isolate()); | 665 PostponeInterruptsScope postpone(info->isolate()); |
643 | 666 |
644 // Parse and update CompilationInfo with the results. | 667 // Parse and update ParseInfo with the results. |
645 if (!parsing::ParseAny(info->parse_info())) return MaybeHandle<Code>(); | 668 { |
| 669 if (!parsing::ParseAny(info->parse_info(), |
| 670 inner_function_mode != Compiler::CONCURRENT)) { |
| 671 return MaybeHandle<Code>(); |
| 672 } |
| 673 |
| 674 if (inner_function_mode == Compiler::CONCURRENT) { |
| 675 ParseHandleScope parse_handles(info->parse_info()); |
| 676 info->parse_info()->ReopenHandlesInNewHandleScope(); |
| 677 info->parse_info()->ast_value_factory()->Internalize(info->isolate()); |
| 678 } |
| 679 } |
| 680 |
646 if (info->parse_info()->is_toplevel()) { | 681 if (info->parse_info()->is_toplevel()) { |
647 EnsureSharedFunctionInfosArrayOnScript(info->parse_info()); | 682 EnsureSharedFunctionInfosArrayOnScript(info->parse_info()); |
648 } | 683 } |
649 DCHECK_EQ(info->shared_info()->language_mode(), | 684 DCHECK_EQ(info->shared_info()->language_mode(), |
650 info->literal()->language_mode()); | 685 info->literal()->language_mode()); |
651 | 686 |
652 // Compile either unoptimized code or bytecode for the interpreter. | 687 // Compile either unoptimized code or bytecode for the interpreter. |
653 if (!CompileUnoptimizedCode(info, inner_function_mode)) { | 688 if (!CompileUnoptimizedCode(info, inner_function_mode)) { |
654 return MaybeHandle<Code>(); | 689 return MaybeHandle<Code>(); |
655 } | 690 } |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 | 1162 |
1128 Handle<Script> script = parse_info->script(); | 1163 Handle<Script> script = parse_info->script(); |
1129 | 1164 |
1130 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? | 1165 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? |
1131 FixedArray* array = isolate->native_context()->embedder_data(); | 1166 FixedArray* array = isolate->native_context()->embedder_data(); |
1132 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); | 1167 script->set_context_data(array->get(v8::Context::kDebugIdIndex)); |
1133 | 1168 |
1134 Handle<SharedFunctionInfo> result; | 1169 Handle<SharedFunctionInfo> result; |
1135 | 1170 |
1136 { VMState<COMPILER> state(info->isolate()); | 1171 { VMState<COMPILER> state(info->isolate()); |
1137 if (parse_info->literal() == nullptr && | 1172 if (parse_info->literal() == nullptr) { |
1138 !parsing::ParseProgram(parse_info)) { | 1173 if (!parsing::ParseProgram(parse_info, false)) { |
1139 return Handle<SharedFunctionInfo>::null(); | 1174 return Handle<SharedFunctionInfo>::null(); |
| 1175 } |
| 1176 |
| 1177 { |
| 1178 ParseHandleScope parse_handles(parse_info); |
| 1179 parse_info->ReopenHandlesInNewHandleScope(); |
| 1180 parse_info->ast_value_factory()->Internalize(info->isolate()); |
| 1181 } |
1140 } | 1182 } |
1141 | 1183 |
1142 EnsureSharedFunctionInfosArrayOnScript(parse_info); | 1184 EnsureSharedFunctionInfosArrayOnScript(parse_info); |
1143 | 1185 |
1144 // Measure how long it takes to do the compilation; only take the | 1186 // Measure how long it takes to do the compilation; only take the |
1145 // rest of the function into account to avoid overlap with the | 1187 // rest of the function into account to avoid overlap with the |
1146 // parsing statistics. | 1188 // parsing statistics. |
1147 HistogramTimer* rate = parse_info->is_eval() | 1189 HistogramTimer* rate = parse_info->is_eval() |
1148 ? info->isolate()->counters()->compile_eval() | 1190 ? info->isolate()->counters()->compile_eval() |
1149 : info->isolate()->counters()->compile(); | 1191 : info->isolate()->counters()->compile(); |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1869 } | 1911 } |
1870 | 1912 |
1871 if (shared->is_compiled()) { | 1913 if (shared->is_compiled()) { |
1872 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1914 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1873 JSFunction::EnsureLiterals(function); | 1915 JSFunction::EnsureLiterals(function); |
1874 } | 1916 } |
1875 } | 1917 } |
1876 | 1918 |
1877 } // namespace internal | 1919 } // namespace internal |
1878 } // namespace v8 | 1920 } // namespace v8 |
OLD | NEW |