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(); it.Advance()) { | |
rmcilroy
2016/04/22 10:02:57
Also done when "has_activations_" ?
Michael Starzinger
2016/04/22 10:47:45
Done.
| |
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 // TODO(4280): For now we do not switch to baseline code when the debugger | |
902 // might have created a copy of the bytecode with break slots. | |
rmcilroy
2016/04/22 10:02:57
Is this a TODO - I though we were planning to alwa
Michael Starzinger
2016/04/22 10:47:45
Done. I don't have a concrete answer on whether we
| |
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 unoptimized code using the full code generator. | |
rmcilroy
2016/04/22 10:02:57
/s/unoptimzed/baseline
Michael Starzinger
2016/04/22 10:47:45
Done.
| |
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 |