| 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 |