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 |