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