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" |
11 #include "src/ast/scopeinfo.h" | 11 #include "src/ast/scopeinfo.h" |
12 #include "src/ast/scopes.h" | 12 #include "src/ast/scopes.h" |
13 #include "src/bootstrapper.h" | 13 #include "src/bootstrapper.h" |
14 #include "src/codegen.h" | 14 #include "src/codegen.h" |
15 #include "src/compilation-cache.h" | 15 #include "src/compilation-cache.h" |
16 #include "src/compiler/pipeline.h" | 16 #include "src/compiler/pipeline.h" |
17 #include "src/crankshaft/hydrogen.h" | 17 #include "src/crankshaft/hydrogen.h" |
18 #include "src/debug/debug.h" | 18 #include "src/debug/debug.h" |
19 #include "src/debug/liveedit.h" | 19 #include "src/debug/liveedit.h" |
20 #include "src/deoptimizer.h" | 20 #include "src/deoptimizer.h" |
| 21 #include "src/frames-inl.h" |
21 #include "src/full-codegen/full-codegen.h" | 22 #include "src/full-codegen/full-codegen.h" |
22 #include "src/interpreter/interpreter.h" | 23 #include "src/interpreter/interpreter.h" |
23 #include "src/isolate-inl.h" | 24 #include "src/isolate-inl.h" |
24 #include "src/log-inl.h" | 25 #include "src/log-inl.h" |
25 #include "src/messages.h" | 26 #include "src/messages.h" |
26 #include "src/parsing/parser.h" | 27 #include "src/parsing/parser.h" |
27 #include "src/parsing/rewriter.h" | 28 #include "src/parsing/rewriter.h" |
28 #include "src/parsing/scanner-character-streams.h" | 29 #include "src/parsing/scanner-character-streams.h" |
29 #include "src/profiler/cpu-profiler.h" | 30 #include "src/profiler/cpu-profiler.h" |
30 #include "src/runtime-profiler.h" | 31 #include "src/runtime-profiler.h" |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 VMState<COMPILER> state(info->isolate()); | 584 VMState<COMPILER> state(info->isolate()); |
584 PostponeInterruptsScope postpone(info->isolate()); | 585 PostponeInterruptsScope postpone(info->isolate()); |
585 | 586 |
586 // Parse and update CompilationInfo with the results. | 587 // Parse and update CompilationInfo with the results. |
587 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); | 588 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); |
588 Handle<SharedFunctionInfo> shared = info->shared_info(); | 589 Handle<SharedFunctionInfo> shared = info->shared_info(); |
589 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode()); | 590 DCHECK_EQ(shared->language_mode(), info->literal()->language_mode()); |
590 | 591 |
591 // Compile either unoptimized code or bytecode for the interpreter. | 592 // Compile either unoptimized code or bytecode for the interpreter. |
592 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); | 593 if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); |
593 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info); | |
594 | 594 |
595 // Update the shared function info with the scope info. | 595 // Update the shared function info with the scope info. |
596 InstallSharedScopeInfo(info, shared); | 596 InstallSharedScopeInfo(info, shared); |
597 | 597 |
598 // Install compilation result on the shared function info | 598 // Install compilation result on the shared function info |
599 InstallSharedCompilationResult(info, shared); | 599 InstallSharedCompilationResult(info, shared); |
600 | 600 |
| 601 // Record the function compilation event. |
| 602 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info); |
| 603 |
601 return info->code(); | 604 return info->code(); |
602 } | 605 } |
603 | 606 |
604 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( | 607 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap( |
605 Handle<JSFunction> function, BailoutId osr_ast_id) { | 608 Handle<JSFunction> function, BailoutId osr_ast_id) { |
606 Handle<SharedFunctionInfo> shared(function->shared()); | 609 Handle<SharedFunctionInfo> shared(function->shared()); |
607 DisallowHeapAllocation no_gc; | 610 DisallowHeapAllocation no_gc; |
608 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( | 611 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( |
609 function->context()->native_context(), osr_ast_id); | 612 function->context()->native_context(), osr_ast_id); |
610 if (cached.code != nullptr) { | 613 if (cached.code != nullptr) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 PrintF("[found optimized code for "); | 801 PrintF("[found optimized code for "); |
799 function->ShortPrint(); | 802 function->ShortPrint(); |
800 if (!osr_ast_id.IsNone()) { | 803 if (!osr_ast_id.IsNone()) { |
801 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); | 804 PrintF(" at OSR AST id %d", osr_ast_id.ToInt()); |
802 } | 805 } |
803 PrintF("]\n"); | 806 PrintF("]\n"); |
804 } | 807 } |
805 return cached_code; | 808 return cached_code; |
806 } | 809 } |
807 | 810 |
808 DCHECK(AllowCompilation::IsAllowed(isolate)); | 811 // Reset profiler ticks, function is no longer considered hot. |
809 | |
810 if (shared->is_compiled()) { | 812 if (shared->is_compiled()) { |
811 shared->code()->set_profiler_ticks(0); | 813 shared->code()->set_profiler_ticks(0); |
812 } | 814 } |
813 | 815 |
814 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing | 816 // TODO(mstarzinger): We cannot properly deserialize a scope chain containing |
815 // an eval scope and hence would fail at parsing the eval source again. | 817 // an eval scope and hence would fail at parsing the eval source again. |
816 if (shared->disable_optimization_reason() == kEval) { | 818 if (shared->disable_optimization_reason() == kEval) { |
817 return MaybeHandle<Code>(); | 819 return MaybeHandle<Code>(); |
818 } | 820 } |
819 | 821 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 } | 855 } |
854 } else { | 856 } else { |
855 info->set_osr_frame(osr_frame); | 857 info->set_osr_frame(osr_frame); |
856 if (GetOptimizedCodeNow(info.get())) return info->code(); | 858 if (GetOptimizedCodeNow(info.get())) return info->code(); |
857 } | 859 } |
858 | 860 |
859 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 861 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
860 return MaybeHandle<Code>(); | 862 return MaybeHandle<Code>(); |
861 } | 863 } |
862 | 864 |
| 865 class InterpreterActivationsFinder : public ThreadVisitor { |
| 866 public: |
| 867 SharedFunctionInfo* shared_; |
| 868 bool has_activations_; |
| 869 |
| 870 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) |
| 871 : shared_(shared), has_activations_(false) {} |
| 872 |
| 873 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 874 JavaScriptFrameIterator it(isolate, top); |
| 875 for (; !it.done() && !has_activations_; it.Advance()) { |
| 876 JavaScriptFrame* frame = it.frame(); |
| 877 if (!frame->is_interpreted()) continue; |
| 878 if (frame->function()->shared() == shared_) has_activations_ = true; |
| 879 } |
| 880 } |
| 881 }; |
| 882 |
| 883 bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) { |
| 884 InterpreterActivationsFinder activations_finder(shared); |
| 885 activations_finder.VisitThread(isolate, isolate->thread_local_top()); |
| 886 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); |
| 887 return activations_finder.has_activations_; |
| 888 } |
| 889 |
| 890 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { |
| 891 Isolate* isolate = function->GetIsolate(); |
| 892 VMState<COMPILER> state(isolate); |
| 893 PostponeInterruptsScope postpone(isolate); |
| 894 CompilationInfoWithZone info(function); |
| 895 |
| 896 // Reset profiler ticks, function is no longer considered hot. |
| 897 if (function->shared()->HasBytecodeArray()) { |
| 898 function->shared()->set_profiler_ticks(0); |
| 899 } |
| 900 |
| 901 // We do not switch to baseline code when the debugger might have created a |
| 902 // copy of the bytecode with break slots to be able to set break points. |
| 903 if (function->shared()->HasDebugInfo()) { |
| 904 return MaybeHandle<Code>(); |
| 905 } |
| 906 |
| 907 // TODO(4280): For now we do not switch generators to baseline code because |
| 908 // there might be suspended activations stored in generator objects on the |
| 909 // heap. We could eventually go directly to TurboFan in this case. |
| 910 if (function->shared()->is_generator()) { |
| 911 return MaybeHandle<Code>(); |
| 912 } |
| 913 |
| 914 // TODO(4280): For now we disable switching to baseline code in the presence |
| 915 // of interpreter activations of the given function. The reasons are: |
| 916 // 1) The debugger assumes each function is either full-code or bytecode. |
| 917 // 2) The underlying bytecode is cleared below, breaking stack unwinding. |
| 918 if (HasInterpreterActivations(isolate, function->shared())) { |
| 919 if (FLAG_trace_opt) { |
| 920 OFStream os(stdout); |
| 921 os << "[unable to switch " << Brief(*function) << " due to activations]" |
| 922 << std::endl; |
| 923 } |
| 924 return MaybeHandle<Code>(); |
| 925 } |
| 926 |
| 927 if (FLAG_trace_opt) { |
| 928 OFStream os(stdout); |
| 929 os << "[switching method " << Brief(*function) << " to baseline code]" |
| 930 << std::endl; |
| 931 } |
| 932 |
| 933 // Parse and update CompilationInfo with the results. |
| 934 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>(); |
| 935 Handle<SharedFunctionInfo> shared = info.shared_info(); |
| 936 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); |
| 937 |
| 938 // Compile baseline code using the full code generator. |
| 939 if (!Compiler::Analyze(info.parse_info()) || |
| 940 !FullCodeGenerator::MakeCode(&info)) { |
| 941 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
| 942 return MaybeHandle<Code>(); |
| 943 } |
| 944 |
| 945 // TODO(4280): For now we play it safe and remove the bytecode array when we |
| 946 // switch to baseline code. We might consider keeping around the bytecode so |
| 947 // that it can be used as the "source of truth" eventually. |
| 948 shared->ClearBytecodeArray(); |
| 949 |
| 950 // Update the shared function info with the scope info. |
| 951 InstallSharedScopeInfo(&info, shared); |
| 952 |
| 953 // Install compilation result on the shared function info |
| 954 InstallSharedCompilationResult(&info, shared); |
| 955 |
| 956 // Record the function compilation event. |
| 957 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &info); |
| 958 |
| 959 return info.code(); |
| 960 } |
| 961 |
863 MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) { | 962 MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) { |
864 Isolate* isolate = function->GetIsolate(); | 963 Isolate* isolate = function->GetIsolate(); |
865 DCHECK(!isolate->has_pending_exception()); | 964 DCHECK(!isolate->has_pending_exception()); |
866 DCHECK(!function->is_compiled()); | 965 DCHECK(!function->is_compiled()); |
867 TimerEventScope<TimerEventCompileCode> compile_timer(isolate); | 966 TimerEventScope<TimerEventCompileCode> compile_timer(isolate); |
868 TRACE_EVENT0("v8", "V8.CompileCode"); | 967 TRACE_EVENT0("v8", "V8.CompileCode"); |
869 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy()); | 968 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy()); |
870 | 969 |
871 if (FLAG_turbo_cache_shared_code) { | 970 if (FLAG_turbo_cache_shared_code) { |
872 Handle<Code> cached_code; | 971 Handle<Code> cached_code; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 // Install code on closure. | 1181 // Install code on closure. |
1083 function->ReplaceCode(*code); | 1182 function->ReplaceCode(*code); |
1084 | 1183 |
1085 // Check postconditions on success. | 1184 // Check postconditions on success. |
1086 DCHECK(!isolate->has_pending_exception()); | 1185 DCHECK(!isolate->has_pending_exception()); |
1087 DCHECK(function->shared()->is_compiled()); | 1186 DCHECK(function->shared()->is_compiled()); |
1088 DCHECK(function->is_compiled()); | 1187 DCHECK(function->is_compiled()); |
1089 return true; | 1188 return true; |
1090 } | 1189 } |
1091 | 1190 |
| 1191 bool Compiler::CompileBaseline(Handle<JSFunction> function) { |
| 1192 Isolate* isolate = function->GetIsolate(); |
| 1193 DCHECK(AllowCompilation::IsAllowed(isolate)); |
| 1194 |
| 1195 // Start a compilation. |
| 1196 Handle<Code> code; |
| 1197 if (!GetBaselineCode(function).ToHandle(&code)) { |
| 1198 // Baseline generation failed, get unoptimized code. |
| 1199 DCHECK(function->shared()->is_compiled()); |
| 1200 code = handle(function->shared()->code()); |
| 1201 isolate->clear_pending_exception(); |
| 1202 } |
| 1203 |
| 1204 // Install code on closure. |
| 1205 function->ReplaceCode(*code); |
| 1206 |
| 1207 // Check postconditions on success. |
| 1208 DCHECK(!isolate->has_pending_exception()); |
| 1209 DCHECK(function->shared()->is_compiled()); |
| 1210 DCHECK(function->is_compiled()); |
| 1211 return true; |
| 1212 } |
| 1213 |
1092 bool Compiler::CompileOptimized(Handle<JSFunction> function, | 1214 bool Compiler::CompileOptimized(Handle<JSFunction> function, |
1093 ConcurrencyMode mode) { | 1215 ConcurrencyMode mode) { |
1094 if (function->IsOptimized()) return true; | 1216 if (function->IsOptimized()) return true; |
1095 Isolate* isolate = function->GetIsolate(); | 1217 Isolate* isolate = function->GetIsolate(); |
1096 DCHECK(AllowCompilation::IsAllowed(isolate)); | 1218 DCHECK(AllowCompilation::IsAllowed(isolate)); |
1097 | 1219 |
1098 // Start a compilation. | 1220 // Start a compilation. |
1099 Handle<Code> code; | 1221 Handle<Code> code; |
1100 if (!GetOptimizedCode(function, mode).ToHandle(&code)) { | 1222 if (!GetOptimizedCode(function, mode).ToHandle(&code)) { |
1101 // Optimization failed, get unoptimized code. | 1223 // Optimization failed, get unoptimized code. |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 MaybeHandle<Code> code; | 1799 MaybeHandle<Code> code; |
1678 if (cached.code != nullptr) code = handle(cached.code); | 1800 if (cached.code != nullptr) code = handle(cached.code); |
1679 Handle<Context> native_context(function->context()->native_context()); | 1801 Handle<Context> native_context(function->context()->native_context()); |
1680 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1802 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1681 literals, BailoutId::None()); | 1803 literals, BailoutId::None()); |
1682 } | 1804 } |
1683 } | 1805 } |
1684 | 1806 |
1685 } // namespace internal | 1807 } // namespace internal |
1686 } // namespace v8 | 1808 } // namespace v8 |
OLD | NEW |