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" |
11 #include "src/asmjs/asm-typer.h" | 11 #include "src/asmjs/asm-typer.h" |
12 #include "src/ast/ast-numbering.h" | 12 #include "src/ast/ast-numbering.h" |
13 #include "src/ast/prettyprinter.h" | 13 #include "src/ast/prettyprinter.h" |
14 #include "src/ast/scopes.h" | 14 #include "src/ast/scopes.h" |
15 #include "src/bootstrapper.h" | 15 #include "src/bootstrapper.h" |
16 #include "src/codegen.h" | 16 #include "src/codegen.h" |
17 #include "src/compilation-cache.h" | 17 #include "src/compilation-cache.h" |
18 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" | 18 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" |
19 #include "src/compiler/pipeline.h" | 19 #include "src/compiler/pipeline.h" |
20 #include "src/crankshaft/hydrogen.h" | 20 #include "src/crankshaft/hydrogen.h" |
21 #include "src/debug/debug.h" | 21 #include "src/debug/debug.h" |
22 #include "src/debug/liveedit.h" | 22 #include "src/debug/liveedit.h" |
23 #include "src/deoptimizer.h" | |
24 #include "src/frames-inl.h" | 23 #include "src/frames-inl.h" |
25 #include "src/full-codegen/full-codegen.h" | 24 #include "src/full-codegen/full-codegen.h" |
26 #include "src/globals.h" | 25 #include "src/globals.h" |
27 #include "src/heap/heap.h" | 26 #include "src/heap/heap.h" |
28 #include "src/interpreter/interpreter.h" | 27 #include "src/interpreter/interpreter.h" |
29 #include "src/isolate-inl.h" | 28 #include "src/isolate-inl.h" |
30 #include "src/log-inl.h" | 29 #include "src/log-inl.h" |
31 #include "src/messages.h" | 30 #include "src/messages.h" |
32 #include "src/parsing/parser.h" | 31 #include "src/parsing/parser.h" |
33 #include "src/parsing/rewriter.h" | 32 #include "src/parsing/rewriter.h" |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
771 DCHECK(job->state() == CompilationJob::State::kFailed); | 770 DCHECK(job->state() == CompilationJob::State::kFailed); |
772 if (FLAG_trace_opt) { | 771 if (FLAG_trace_opt) { |
773 PrintF("[aborted optimizing "); | 772 PrintF("[aborted optimizing "); |
774 info->closure()->ShortPrint(); | 773 info->closure()->ShortPrint(); |
775 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); | 774 PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); |
776 } | 775 } |
777 info->closure()->ReplaceCode(shared->code()); | 776 info->closure()->ReplaceCode(shared->code()); |
778 return CompilationJob::FAILED; | 777 return CompilationJob::FAILED; |
779 } | 778 } |
780 | 779 |
781 class InterpreterActivationsFinder : public ThreadVisitor, | |
782 public OptimizedFunctionVisitor { | |
783 public: | |
784 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) | |
785 : shared_(shared), has_activations_(false) {} | |
786 | |
787 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | |
788 Address* activation_pc_address = nullptr; | |
789 JavaScriptFrameIterator it(isolate, top); | |
790 for (; !it.done(); it.Advance()) { | |
791 JavaScriptFrame* frame = it.frame(); | |
792 if (FLAG_ignition_osr && frame->is_optimized() && | |
793 frame->function()->shared() == shared_) { | |
794 // There might be optimized OSR code active on the stack that is not | |
795 // reachable through a function. We count this as an activation. | |
796 has_activations_ = true; | |
797 } | |
798 if (frame->is_interpreted() && frame->function()->shared() == shared_) { | |
799 has_activations_ = true; | |
800 activation_pc_address = frame->pc_address(); | |
801 } | |
802 } | |
803 | |
804 if (activation_pc_address) { | |
805 activation_pc_addresses_.push_back(activation_pc_address); | |
806 } | |
807 } | |
808 | |
809 void VisitFunction(JSFunction* function) { | |
810 if (function->Inlines(shared_)) has_activations_ = true; | |
811 } | |
812 | |
813 void EnterContext(Context* context) {} | |
814 void LeaveContext(Context* context) {} | |
815 | |
816 bool MarkActivationsForBaselineOnReturn(Isolate* isolate) { | |
817 if (activation_pc_addresses_.empty()) return false; | |
818 | |
819 for (Address* activation_pc_address : activation_pc_addresses_) { | |
820 DCHECK(isolate->inner_pointer_to_code_cache() | |
821 ->GetCacheEntry(*activation_pc_address) | |
822 ->code->is_interpreter_trampoline_builtin()); | |
823 *activation_pc_address = | |
824 isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry(); | |
825 } | |
826 return true; | |
827 } | |
828 | |
829 bool has_activations() { return has_activations_; } | |
830 | |
831 private: | |
832 SharedFunctionInfo* shared_; | |
833 bool has_activations_; | |
834 std::vector<Address*> activation_pc_addresses_; | |
835 }; | |
836 | |
837 bool HasInterpreterActivations( | |
838 Isolate* isolate, InterpreterActivationsFinder* activations_finder) { | |
839 activations_finder->VisitThread(isolate, isolate->thread_local_top()); | |
840 isolate->thread_manager()->IterateArchivedThreads(activations_finder); | |
841 // There might be optimized functions that rely on bytecode being around. We | |
842 // need to prevent switching the given function to baseline code. | |
843 Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder); | |
844 return activations_finder->has_activations(); | |
845 } | |
846 | |
847 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { | 780 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { |
848 Isolate* isolate = function->GetIsolate(); | 781 Isolate* isolate = function->GetIsolate(); |
849 VMState<COMPILER> state(isolate); | 782 VMState<COMPILER> state(isolate); |
850 PostponeInterruptsScope postpone(isolate); | 783 PostponeInterruptsScope postpone(isolate); |
851 Zone zone(isolate->allocator(), ZONE_NAME); | 784 Zone zone(isolate->allocator(), ZONE_NAME); |
852 ParseInfo parse_info(&zone, handle(function->shared())); | 785 ParseInfo parse_info(&zone, handle(function->shared())); |
853 CompilationInfo info(&parse_info, function); | 786 CompilationInfo info(&parse_info, function); |
854 | 787 |
855 // Function no longer needs to be tiered up | 788 // Function no longer needs to be tiered up |
856 function->shared()->set_marked_for_tier_up(false); | 789 function->shared()->set_marked_for_tier_up(false); |
(...skipping 10 matching lines...) Expand all Loading... | |
867 | 800 |
868 // We do not switch to baseline code when the debugger might have created a | 801 // We do not switch to baseline code when the debugger might have created a |
869 // copy of the bytecode with break slots to be able to set break points. | 802 // copy of the bytecode with break slots to be able to set break points. |
870 if (function->shared()->HasDebugInfo()) { | 803 if (function->shared()->HasDebugInfo()) { |
871 return MaybeHandle<Code>(); | 804 return MaybeHandle<Code>(); |
872 } | 805 } |
873 | 806 |
874 // TODO(4280): For now we do not switch generators or async functions to | 807 // TODO(4280): For now we do not switch generators or async functions to |
875 // baseline code because there might be suspended activations stored in | 808 // baseline code because there might be suspended activations stored in |
876 // generator objects on the heap. We could eventually go directly to | 809 // generator objects on the heap. We could eventually go directly to |
877 // TurboFan in this case. | 810 // TurboFan in this case. |
rmcilroy
2016/11/04 14:23:34
Do we want to do anything about this? I don't thin
Michael Starzinger
2016/11/04 14:27:52
Acknowledged. At first glance I agree with you. Th
| |
878 if (IsResumableFunction(function->shared()->kind())) { | 811 if (IsResumableFunction(function->shared()->kind())) { |
879 return MaybeHandle<Code>(); | 812 return MaybeHandle<Code>(); |
880 } | 813 } |
881 | 814 |
882 // TODO(4280): For now we disable switching to baseline code in the presence | |
883 // of interpreter activations of the given function. The reasons is that the | |
884 // underlying bytecode is cleared below. Note that this only applies in case | |
885 // the --ignition-preserve-bytecode flag is not passed. | |
886 if (!FLAG_ignition_preserve_bytecode) { | |
887 InterpreterActivationsFinder activations_finder(function->shared()); | |
888 if (HasInterpreterActivations(isolate, &activations_finder)) { | |
889 if (FLAG_trace_opt) { | |
890 OFStream os(stdout); | |
891 os << "[unable to switch " << Brief(*function) << " due to activations]" | |
892 << std::endl; | |
893 } | |
894 | |
895 if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) { | |
896 if (FLAG_trace_opt) { | |
897 OFStream os(stdout); | |
898 os << "[marking " << Brief(function->shared()) | |
899 << " for baseline recompilation on return]" << std::endl; | |
900 } | |
901 } | |
902 | |
903 return MaybeHandle<Code>(); | |
904 } | |
905 } | |
906 | |
907 if (FLAG_trace_opt) { | 815 if (FLAG_trace_opt) { |
908 OFStream os(stdout); | 816 OFStream os(stdout); |
909 os << "[switching method " << Brief(*function) << " to baseline code]" | 817 os << "[switching method " << Brief(*function) << " to baseline code]" |
910 << std::endl; | 818 << std::endl; |
911 } | 819 } |
912 | 820 |
913 // Parse and update CompilationInfo with the results. | 821 // Parse and update CompilationInfo with the results. |
914 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>(); | 822 if (!Parser::ParseStatic(info.parse_info())) return MaybeHandle<Code>(); |
915 Handle<SharedFunctionInfo> shared = info.shared_info(); | 823 Handle<SharedFunctionInfo> shared = info.shared_info(); |
916 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); | 824 DCHECK_EQ(shared->language_mode(), info.literal()->language_mode()); |
917 | 825 |
918 // Compile baseline code using the full code generator. | 826 // Compile baseline code using the full code generator. |
919 if (!Compiler::Analyze(info.parse_info()) || | 827 if (!Compiler::Analyze(info.parse_info()) || |
920 !FullCodeGenerator::MakeCode(&info)) { | 828 !FullCodeGenerator::MakeCode(&info)) { |
921 if (!isolate->has_pending_exception()) isolate->StackOverflow(); | 829 if (!isolate->has_pending_exception()) isolate->StackOverflow(); |
922 return MaybeHandle<Code>(); | 830 return MaybeHandle<Code>(); |
923 } | 831 } |
924 | 832 |
925 // TODO(4280): For now we play it safe and remove the bytecode array when we | |
926 // switch to baseline code. We might consider keeping around the bytecode so | |
927 // that it can be used as the "source of truth" eventually. Note that this | |
928 // only applies in case the --ignition-preserve-bytecode flag is not passed. | |
929 if (!FLAG_ignition_preserve_bytecode) shared->ClearBytecodeArray(); | |
930 | |
931 // Update the shared function info with the scope info. | 833 // Update the shared function info with the scope info. |
932 InstallSharedScopeInfo(&info, shared); | 834 InstallSharedScopeInfo(&info, shared); |
933 | 835 |
934 // Install compilation result on the shared function info | 836 // Install compilation result on the shared function info |
935 InstallSharedCompilationResult(&info, shared); | 837 InstallSharedCompilationResult(&info, shared); |
936 | 838 |
937 // Record the function compilation event. | 839 // Record the function compilation event. |
938 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info); | 840 RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info); |
939 | 841 |
940 return info.code(); | 842 return info.code(); |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1305 Zone zone(info->isolate()->allocator(), ZONE_NAME); | 1207 Zone zone(info->isolate()->allocator(), ZONE_NAME); |
1306 CompilationInfo unoptimized(info->parse_info(), info->closure()); | 1208 CompilationInfo unoptimized(info->parse_info(), info->closure()); |
1307 unoptimized.EnableDeoptimizationSupport(); | 1209 unoptimized.EnableDeoptimizationSupport(); |
1308 | 1210 |
1309 // TODO(4280): For now we do not switch generators or async functions to | 1211 // TODO(4280): For now we do not switch generators or async functions to |
1310 // baseline code because there might be suspended activations stored in | 1212 // baseline code because there might be suspended activations stored in |
1311 // generator objects on the heap. We could eventually go directly to | 1213 // generator objects on the heap. We could eventually go directly to |
1312 // TurboFan in this case. | 1214 // TurboFan in this case. |
1313 if (IsResumableFunction(shared->kind())) return false; | 1215 if (IsResumableFunction(shared->kind())) return false; |
1314 | 1216 |
1315 // TODO(4280): For now we disable switching to baseline code in the presence | |
1316 // of interpreter activations of the given function. The reasons is that the | |
1317 // underlying bytecode is cleared below. The expensive check for activations | |
1318 // only needs to be done when the given function has bytecode, otherwise we | |
1319 // can be sure there are no activations. Note that this only applies in case | |
1320 // the --ignition-preserve-bytecode flag is not passed. | |
1321 if (!FLAG_ignition_preserve_bytecode && shared->HasBytecodeArray()) { | |
1322 InterpreterActivationsFinder activations_finder(*shared); | |
1323 if (HasInterpreterActivations(info->isolate(), &activations_finder)) { | |
1324 return false; | |
1325 } | |
1326 } | |
1327 | |
1328 // When we call PrepareForSerializing below, we will change the shared | 1217 // When we call PrepareForSerializing below, we will change the shared |
1329 // ParseInfo. Make sure to reset it. | 1218 // ParseInfo. Make sure to reset it. |
1330 bool old_will_serialize_value = info->parse_info()->will_serialize(); | 1219 bool old_will_serialize_value = info->parse_info()->will_serialize(); |
1331 | 1220 |
1332 // If the current code has reloc info for serialization, also include | 1221 // If the current code has reloc info for serialization, also include |
1333 // reloc info for serialization for the new code, so that deopt support | 1222 // reloc info for serialization for the new code, so that deopt support |
1334 // can be added without losing IC state. | 1223 // can be added without losing IC state. |
1335 if (shared->code()->kind() == Code::FUNCTION && | 1224 if (shared->code()->kind() == Code::FUNCTION && |
1336 shared->code()->has_reloc_info_for_serialization()) { | 1225 shared->code()->has_reloc_info_for_serialization()) { |
1337 unoptimized.PrepareForSerializing(); | 1226 unoptimized.PrepareForSerializing(); |
1338 } | 1227 } |
1339 EnsureFeedbackMetadata(&unoptimized); | 1228 EnsureFeedbackMetadata(&unoptimized); |
1340 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1229 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
1341 | 1230 |
1342 info->parse_info()->set_will_serialize(old_will_serialize_value); | 1231 info->parse_info()->set_will_serialize(old_will_serialize_value); |
1343 | 1232 |
1344 // TODO(4280): For now we play it safe and remove the bytecode array when we | |
1345 // switch to baseline code. We might consider keeping around the bytecode so | |
1346 // that it can be used as the "source of truth" eventually. Note that this | |
1347 // only applies in case the --ignition-preserve-bytecode flag is not passed. | |
1348 if (!FLAG_ignition_preserve_bytecode && shared->HasBytecodeArray()) { | |
1349 shared->ClearBytecodeArray(); | |
1350 } | |
1351 | |
1352 // The scope info might not have been set if a lazily compiled | 1233 // The scope info might not have been set if a lazily compiled |
1353 // function is inlined before being called for the first time. | 1234 // function is inlined before being called for the first time. |
1354 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1235 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
1355 InstallSharedScopeInfo(info, shared); | 1236 InstallSharedScopeInfo(info, shared); |
1356 } | 1237 } |
1357 | 1238 |
1358 // Install compilation result on the shared function info | 1239 // Install compilation result on the shared function info |
1359 shared->EnableDeoptimizationSupport(*unoptimized.code()); | 1240 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
1360 | 1241 |
1361 // The existing unoptimized code was replaced with the new one. | 1242 // The existing unoptimized code was replaced with the new one. |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1824 DCHECK(shared->is_compiled()); | 1705 DCHECK(shared->is_compiled()); |
1825 function->set_literals(cached.literals); | 1706 function->set_literals(cached.literals); |
1826 } else if (shared->is_compiled()) { | 1707 } else if (shared->is_compiled()) { |
1827 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. | 1708 // TODO(mvstanton): pass pretenure flag to EnsureLiterals. |
1828 JSFunction::EnsureLiterals(function); | 1709 JSFunction::EnsureLiterals(function); |
1829 } | 1710 } |
1830 } | 1711 } |
1831 | 1712 |
1832 } // namespace internal | 1713 } // namespace internal |
1833 } // namespace v8 | 1714 } // namespace v8 |
OLD | NEW |