| 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 | 8 |
| 9 #include "src/ast/ast-numbering.h" | 9 #include "src/ast/ast-numbering.h" |
| 10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 public: | 70 public: |
| 71 explicit CompilationHandleScope(CompilationInfo* info) | 71 explicit CompilationHandleScope(CompilationInfo* info) |
| 72 : deferred_(info->isolate()), info_(info) {} | 72 : deferred_(info->isolate()), info_(info) {} |
| 73 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } | 73 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
| 74 | 74 |
| 75 private: | 75 private: |
| 76 DeferredHandleScope deferred_; | 76 DeferredHandleScope deferred_; |
| 77 CompilationInfo* info_; | 77 CompilationInfo* info_; |
| 78 }; | 78 }; |
| 79 | 79 |
| 80 // Exactly like a CompilationInfo, except being allocated via {new} and it also | |
| 81 // creates and enters a Zone on construction and deallocates it on destruction. | |
| 82 class CompilationInfoWithZone : public CompilationInfo { | |
| 83 public: | |
| 84 explicit CompilationInfoWithZone(Handle<JSFunction> function) | |
| 85 : CompilationInfo(new ParseInfo(&zone_, function), function), | |
| 86 zone_(function->GetIsolate()->allocator()) {} | |
| 87 | |
| 88 // Virtual destructor because a CompilationInfoWithZone has to exit the | |
| 89 // zone scope and get rid of dependent maps even when the destructor is | |
| 90 // called when cast as a CompilationInfo. | |
| 91 virtual ~CompilationInfoWithZone() { | |
| 92 DisableFutureOptimization(); | |
| 93 dependencies()->Rollback(); | |
| 94 delete parse_info_; | |
| 95 parse_info_ = nullptr; | |
| 96 } | |
| 97 | |
| 98 private: | |
| 99 Zone zone_; | |
| 100 }; | |
| 101 | |
| 102 // Helper that times a scoped region and records the elapsed time. | 80 // Helper that times a scoped region and records the elapsed time. |
| 103 struct ScopedTimer { | 81 struct ScopedTimer { |
| 104 explicit ScopedTimer(base::TimeDelta* location) : location_(location) { | 82 explicit ScopedTimer(base::TimeDelta* location) : location_(location) { |
| 105 DCHECK(location_ != NULL); | 83 DCHECK(location_ != NULL); |
| 106 timer_.Start(); | 84 timer_.Start(); |
| 107 } | 85 } |
| 108 | 86 |
| 109 ~ScopedTimer() { *location_ += timer_.Elapsed(); } | 87 ~ScopedTimer() { *location_ += timer_.Elapsed(); } |
| 110 | 88 |
| 111 base::ElapsedTimer timer_; | 89 base::ElapsedTimer timer_; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 prologue_offset_(Code::kPrologueOffsetNotSet), | 139 prologue_offset_(Code::kPrologueOffsetNotSet), |
| 162 track_positions_(FLAG_hydrogen_track_positions || | 140 track_positions_(FLAG_hydrogen_track_positions || |
| 163 isolate->cpu_profiler()->is_profiling()), | 141 isolate->cpu_profiler()->is_profiling()), |
| 164 parameter_count_(0), | 142 parameter_count_(0), |
| 165 optimization_id_(-1), | 143 optimization_id_(-1), |
| 166 osr_expr_stack_height_(0), | 144 osr_expr_stack_height_(0), |
| 167 debug_name_(debug_name) {} | 145 debug_name_(debug_name) {} |
| 168 | 146 |
| 169 CompilationInfo::~CompilationInfo() { | 147 CompilationInfo::~CompilationInfo() { |
| 170 DisableFutureOptimization(); | 148 DisableFutureOptimization(); |
| 149 dependencies()->Rollback(); |
| 171 delete deferred_handles_; | 150 delete deferred_handles_; |
| 172 #ifdef DEBUG | |
| 173 // Check that no dependent maps have been added or added dependent maps have | |
| 174 // been rolled back or committed. | |
| 175 DCHECK(dependencies()->IsEmpty()); | |
| 176 #endif // DEBUG | |
| 177 } | 151 } |
| 178 | 152 |
| 179 | 153 |
| 180 int CompilationInfo::num_parameters() const { | 154 int CompilationInfo::num_parameters() const { |
| 181 return !IsStub() ? scope()->num_parameters() : parameter_count_; | 155 return !IsStub() ? scope()->num_parameters() : parameter_count_; |
| 182 } | 156 } |
| 183 | 157 |
| 184 | 158 |
| 185 int CompilationInfo::num_parameters_including_this() const { | 159 int CompilationInfo::num_parameters_including_this() const { |
| 186 return num_parameters() + (is_this_defined() ? 1 : 0); | 160 return num_parameters() + (is_this_defined() ? 1 : 0); |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 if (lit->dont_optimize_reason() != kNoReason) { | 636 if (lit->dont_optimize_reason() != kNoReason) { |
| 663 shared_info->DisableOptimization(lit->dont_optimize_reason()); | 637 shared_info->DisableOptimization(lit->dont_optimize_reason()); |
| 664 } | 638 } |
| 665 shared_info->set_dont_crankshaft( | 639 shared_info->set_dont_crankshaft( |
| 666 shared_info->dont_crankshaft() || | 640 shared_info->dont_crankshaft() || |
| 667 (lit->flags() & AstProperties::kDontCrankshaft)); | 641 (lit->flags() & AstProperties::kDontCrankshaft)); |
| 668 } | 642 } |
| 669 return true; | 643 return true; |
| 670 } | 644 } |
| 671 | 645 |
| 672 bool UseTurboFan(CompilationInfo* info) { | 646 bool UseTurboFan(Handle<SharedFunctionInfo> shared, BailoutId osr_ast_id) { |
| 673 bool optimization_disabled = info->shared_info()->optimization_disabled(); | 647 bool optimization_disabled = shared->optimization_disabled(); |
| 674 bool dont_crankshaft = info->shared_info()->dont_crankshaft(); | 648 bool dont_crankshaft = shared->dont_crankshaft(); |
| 675 | 649 |
| 676 // Check the enabling conditions for Turbofan. | 650 // Check the enabling conditions for Turbofan. |
| 677 // 1. "use asm" code. | 651 // 1. "use asm" code. |
| 678 bool is_turbofanable_asm = FLAG_turbo_asm && | 652 bool is_turbofanable_asm = |
| 679 info->shared_info()->asm_function() && | 653 FLAG_turbo_asm && shared->asm_function() && !optimization_disabled; |
| 680 !optimization_disabled; | |
| 681 | 654 |
| 682 // 2. Fallback for features unsupported by Crankshaft. | 655 // 2. Fallback for features unsupported by Crankshaft. |
| 683 bool is_unsupported_by_crankshaft_but_turbofanable = | 656 bool is_unsupported_by_crankshaft_but_turbofanable = |
| 684 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && | 657 dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && |
| 685 !optimization_disabled; | 658 !optimization_disabled; |
| 686 | 659 |
| 687 // 3. Explicitly enabled by the command-line filter. | 660 // 3. Explicitly enabled by the command-line filter. |
| 688 bool passes_turbo_filter = | 661 bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter); |
| 689 info->shared_info()->PassesFilter(FLAG_turbo_filter); | |
| 690 | 662 |
| 691 // If this is OSR request, OSR must be enabled by Turbofan. | 663 // If this is OSR request, OSR must be enabled by Turbofan. |
| 692 bool passes_osr_test = FLAG_turbo_osr || !info->is_osr(); | 664 bool passes_osr_test = FLAG_turbo_osr || osr_ast_id.IsNone(); |
| 693 | 665 |
| 694 return (is_turbofanable_asm || | 666 return (is_turbofanable_asm || |
| 695 is_unsupported_by_crankshaft_but_turbofanable || | 667 is_unsupported_by_crankshaft_but_turbofanable || |
| 696 passes_turbo_filter) && | 668 passes_turbo_filter) && |
| 697 passes_osr_test; | 669 passes_osr_test; |
| 698 } | 670 } |
| 699 | 671 |
| 700 bool GetOptimizedCodeNow(CompilationJob* job) { | 672 bool GetOptimizedCodeNow(CompilationJob* job) { |
| 701 CompilationInfo* info = job->info(); | 673 CompilationInfo* info = job->info(); |
| 702 Isolate* isolate = info->isolate(); | 674 Isolate* isolate = info->isolate(); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 if (shared->is_compiled()) { | 765 if (shared->is_compiled()) { |
| 794 shared->code()->set_profiler_ticks(0); | 766 shared->code()->set_profiler_ticks(0); |
| 795 } | 767 } |
| 796 | 768 |
| 797 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing | 769 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing |
| 798 // an eval scope and hence would fail at parsing the eval source again. | 770 // an eval scope and hence would fail at parsing the eval source again. |
| 799 if (shared->disable_optimization_reason() == kEval) { | 771 if (shared->disable_optimization_reason() == kEval) { |
| 800 return MaybeHandle<Code>(); | 772 return MaybeHandle<Code>(); |
| 801 } | 773 } |
| 802 | 774 |
| 803 base::SmartPointer<CompilationInfo> info( | |
| 804 new CompilationInfoWithZone(function)); | |
| 805 VMState<COMPILER> state(isolate); | 775 VMState<COMPILER> state(isolate); |
| 806 DCHECK(!isolate->has_pending_exception()); | 776 DCHECK(!isolate->has_pending_exception()); |
| 807 PostponeInterruptsScope postpone(isolate); | 777 PostponeInterruptsScope postpone(isolate); |
| 778 bool use_turbofan = UseTurboFan(shared, osr_ast_id); |
| 779 base::SmartPointer<CompilationJob> job( |
| 780 use_turbofan ? compiler::Pipeline::NewCompilationJob(function) |
| 781 : new HCompilationJob(function)); |
| 782 CompilationInfo* info = job->info(); |
| 808 | 783 |
| 809 info->SetOptimizingForOsr(osr_ast_id); | 784 info->SetOptimizingForOsr(osr_ast_id); |
| 810 | 785 |
| 811 // Do not use Crankshaft/TurboFan if we need to be able to set break points. | 786 // Do not use Crankshaft/TurboFan if we need to be able to set break points. |
| 812 if (info->shared_info()->HasDebugInfo()) { | 787 if (info->shared_info()->HasDebugInfo()) { |
| 813 info->AbortOptimization(kFunctionBeingDebugged); | 788 info->AbortOptimization(kFunctionBeingDebugged); |
| 814 return MaybeHandle<Code>(); | 789 return MaybeHandle<Code>(); |
| 815 } | 790 } |
| 816 | 791 |
| 817 // Do not use Crankshaft/TurboFan on a generator function. | 792 // Do not use Crankshaft/TurboFan on a generator function. |
| 818 // TODO(neis): Eventually enable for Turbofan. | 793 // TODO(neis): Eventually enable for Turbofan. |
| 819 if (IsGeneratorFunction(info->shared_info()->kind())) { | 794 if (IsGeneratorFunction(info->shared_info()->kind())) { |
| 820 info->AbortOptimization(kGenerator); | 795 info->AbortOptimization(kGenerator); |
| 821 return MaybeHandle<Code>(); | 796 return MaybeHandle<Code>(); |
| 822 } | 797 } |
| 823 | 798 |
| 824 // Limit the number of times we try to optimize functions. | 799 // Limit the number of times we try to optimize functions. |
| 825 const int kMaxOptCount = | 800 const int kMaxOptCount = |
| 826 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; | 801 FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000; |
| 827 if (info->shared_info()->opt_count() > kMaxOptCount) { | 802 if (info->shared_info()->opt_count() > kMaxOptCount) { |
| 828 info->AbortOptimization(kOptimizedTooManyTimes); | 803 info->AbortOptimization(kOptimizedTooManyTimes); |
| 829 return MaybeHandle<Code>(); | 804 return MaybeHandle<Code>(); |
| 830 } | 805 } |
| 831 | 806 |
| 832 CanonicalHandleScope canonical(isolate); | 807 CanonicalHandleScope canonical(isolate); |
| 833 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 808 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
| 834 TRACE_EVENT0("v8", "V8.OptimizeCode"); | 809 TRACE_EVENT0("v8", "V8.OptimizeCode"); |
| 835 | 810 |
| 836 bool use_turbofan = UseTurboFan(info.get()); | |
| 837 base::SmartPointer<CompilationJob> job( | |
| 838 use_turbofan ? compiler::Pipeline::NewCompilationJob(info.get()) | |
| 839 : new HCompilationJob(info.get())); | |
| 840 | |
| 841 // TruboFan can optimize directly from existing bytecode. | 811 // TruboFan can optimize directly from existing bytecode. |
| 842 if (use_turbofan && info->shared_info()->HasBytecodeArray()) { | 812 if (use_turbofan && info->shared_info()->HasBytecodeArray()) { |
| 843 info->MarkAsOptimizeFromBytecode(); | 813 info->MarkAsOptimizeFromBytecode(); |
| 844 } | 814 } |
| 845 | 815 |
| 846 if (mode == Compiler::CONCURRENT) { | 816 if (mode == Compiler::CONCURRENT) { |
| 847 if (GetOptimizedCodeLater(job.get())) { | 817 if (GetOptimizedCodeLater(job.get())) { |
| 848 info.Detach(); // The background recompile job owns this now. | |
| 849 job.Detach(); // The background recompile job owns this now. | 818 job.Detach(); // The background recompile job owns this now. |
| 850 return isolate->builtins()->InOptimizationQueue(); | 819 return isolate->builtins()->InOptimizationQueue(); |
| 851 } | 820 } |
| 852 } else { | 821 } else { |
| 853 info->set_osr_frame(osr_frame); | 822 info->set_osr_frame(osr_frame); |
| 854 if (GetOptimizedCodeNow(job.get())) return info->code(); | 823 if (GetOptimizedCodeNow(job.get())) return info->code(); |
| 855 } | 824 } |
| 856 | 825 |
| 857 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 826 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
| 858 return MaybeHandle<Code>(); | 827 return MaybeHandle<Code>(); |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1722 } | 1691 } |
| 1723 | 1692 |
| 1724 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, | 1693 MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, |
| 1725 BailoutId osr_ast_id, | 1694 BailoutId osr_ast_id, |
| 1726 JavaScriptFrame* osr_frame) { | 1695 JavaScriptFrame* osr_frame) { |
| 1727 DCHECK(!osr_ast_id.IsNone()); | 1696 DCHECK(!osr_ast_id.IsNone()); |
| 1728 DCHECK_NOT_NULL(osr_frame); | 1697 DCHECK_NOT_NULL(osr_frame); |
| 1729 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); | 1698 return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame); |
| 1730 } | 1699 } |
| 1731 | 1700 |
| 1732 void Compiler::FinalizeCompilationJob(CompilationJob* job) { | 1701 void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { |
| 1733 // Take ownership of compilation info. Deleting compilation info | 1702 // Take ownership of compilation job. Deleting job also tears down the zone. |
| 1734 // also tears down the zone. | 1703 base::SmartPointer<CompilationJob> job(raw_job); |
| 1735 base::SmartPointer<CompilationInfo> info(job->info()); | 1704 CompilationInfo* info = job->info(); |
| 1736 Isolate* isolate = info->isolate(); | 1705 Isolate* isolate = info->isolate(); |
| 1737 | 1706 |
| 1738 VMState<COMPILER> state(isolate); | 1707 VMState<COMPILER> state(isolate); |
| 1739 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 1708 TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); |
| 1740 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 1709 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
| 1741 | 1710 |
| 1742 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1711 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 1743 shared->code()->set_profiler_ticks(0); | 1712 shared->code()->set_profiler_ticks(0); |
| 1744 | 1713 |
| 1745 DCHECK(!shared->HasDebugInfo()); | 1714 DCHECK(!shared->HasDebugInfo()); |
| 1746 | 1715 |
| 1747 // 1) Optimization on the concurrent thread may have failed. | 1716 // 1) Optimization on the concurrent thread may have failed. |
| 1748 // 2) The function may have already been optimized by OSR. Simply continue. | 1717 // 2) The function may have already been optimized by OSR. Simply continue. |
| 1749 // Except when OSR already disabled optimization for some reason. | 1718 // Except when OSR already disabled optimization for some reason. |
| 1750 // 3) The code may have already been invalidated due to dependency change. | 1719 // 3) The code may have already been invalidated due to dependency change. |
| 1751 // 4) Code generation may have failed. | 1720 // 4) Code generation may have failed. |
| 1752 if (job->last_status() == CompilationJob::SUCCEEDED) { | 1721 if (job->last_status() == CompilationJob::SUCCEEDED) { |
| 1753 if (shared->optimization_disabled()) { | 1722 if (shared->optimization_disabled()) { |
| 1754 job->RetryOptimization(kOptimizationDisabled); | 1723 job->RetryOptimization(kOptimizationDisabled); |
| 1755 } else if (info->dependencies()->HasAborted()) { | 1724 } else if (info->dependencies()->HasAborted()) { |
| 1756 job->RetryOptimization(kBailedOutDueToDependencyChange); | 1725 job->RetryOptimization(kBailedOutDueToDependencyChange); |
| 1757 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) { | 1726 } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) { |
| 1758 job->RecordOptimizationStats(); | 1727 job->RecordOptimizationStats(); |
| 1759 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get()); | 1728 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info); |
| 1760 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | 1729 if (shared->SearchOptimizedCodeMap(info->context()->native_context(), |
| 1761 info->osr_ast_id()).code == nullptr) { | 1730 info->osr_ast_id()).code == nullptr) { |
| 1762 InsertCodeIntoOptimizedCodeMap(info.get()); | 1731 InsertCodeIntoOptimizedCodeMap(info); |
| 1763 } | 1732 } |
| 1764 if (FLAG_trace_opt) { | 1733 if (FLAG_trace_opt) { |
| 1765 PrintF("[completed optimizing "); | 1734 PrintF("[completed optimizing "); |
| 1766 info->closure()->ShortPrint(); | 1735 info->closure()->ShortPrint(); |
| 1767 PrintF("]\n"); | 1736 PrintF("]\n"); |
| 1768 } | 1737 } |
| 1769 info->closure()->ReplaceCode(*info->code()); | 1738 info->closure()->ReplaceCode(*info->code()); |
| 1770 delete job; | |
| 1771 return; | 1739 return; |
| 1772 } | 1740 } |
| 1773 } | 1741 } |
| 1774 | 1742 |
| 1775 DCHECK(job->last_status() != CompilationJob::SUCCEEDED); | 1743 DCHECK(job->last_status() != CompilationJob::SUCCEEDED); |
| 1776 if (FLAG_trace_opt) { | 1744 if (FLAG_trace_opt) { |
| 1777 PrintF("[aborted optimizing "); | 1745 PrintF("[aborted optimizing "); |
| 1778 info->closure()->ShortPrint(); | 1746 info->closure()->ShortPrint(); |
| 1779 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 1747 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
| 1780 } | 1748 } |
| 1781 info->closure()->ReplaceCode(shared->code()); | 1749 info->closure()->ReplaceCode(shared->code()); |
| 1782 delete job; | |
| 1783 } | 1750 } |
| 1784 | 1751 |
| 1785 void Compiler::PostInstantiation(Handle<JSFunction> function, | 1752 void Compiler::PostInstantiation(Handle<JSFunction> function, |
| 1786 PretenureFlag pretenure) { | 1753 PretenureFlag pretenure) { |
| 1787 Handle<SharedFunctionInfo> shared(function->shared()); | 1754 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1788 | 1755 |
| 1789 if (FLAG_always_opt && shared->allows_lazy_compilation()) { | 1756 if (FLAG_always_opt && shared->allows_lazy_compilation()) { |
| 1790 function->MarkForOptimization(); | 1757 function->MarkForOptimization(); |
| 1791 } | 1758 } |
| 1792 | 1759 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1813 MaybeHandle<Code> code; | 1780 MaybeHandle<Code> code; |
| 1814 if (cached.code != nullptr) code = handle(cached.code); | 1781 if (cached.code != nullptr) code = handle(cached.code); |
| 1815 Handle<Context> native_context(function->context()->native_context()); | 1782 Handle<Context> native_context(function->context()->native_context()); |
| 1816 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1783 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
| 1817 literals, BailoutId::None()); | 1784 literals, BailoutId::None()); |
| 1818 } | 1785 } |
| 1819 } | 1786 } |
| 1820 | 1787 |
| 1821 } // namespace internal | 1788 } // namespace internal |
| 1822 } // namespace v8 | 1789 } // namespace v8 |
| OLD | NEW |