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 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 if (GetOptimizedCodeNow(job.get())) return info->code(); | 782 if (GetOptimizedCodeNow(job.get())) return info->code(); |
783 } | 783 } |
784 | 784 |
785 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 785 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
786 return MaybeHandle<Code>(); | 786 return MaybeHandle<Code>(); |
787 } | 787 } |
788 | 788 |
789 class InterpreterActivationsFinder : public ThreadVisitor, | 789 class InterpreterActivationsFinder : public ThreadVisitor, |
790 public OptimizedFunctionVisitor { | 790 public OptimizedFunctionVisitor { |
791 public: | 791 public: |
792 SharedFunctionInfo* shared_; | |
793 bool has_activations_; | |
794 | |
795 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) | 792 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) |
796 : shared_(shared), has_activations_(false) {} | 793 : shared_(shared), has_activations_(false) {} |
797 | 794 |
798 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 795 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 796 Address* activation_pc_address = nullptr; |
799 JavaScriptFrameIterator it(isolate, top); | 797 JavaScriptFrameIterator it(isolate, top); |
800 for (; !it.done() && !has_activations_; it.Advance()) { | 798 for (; !it.done(); it.Advance()) { |
801 JavaScriptFrame* frame = it.frame(); | 799 JavaScriptFrame* frame = it.frame(); |
802 if (!frame->is_interpreted()) continue; | 800 if (!frame->is_interpreted()) continue; |
803 if (frame->function()->shared() == shared_) has_activations_ = true; | 801 if (frame->function()->shared() == shared_) { |
| 802 has_activations_ = true; |
| 803 activation_pc_address = frame->pc_address(); |
| 804 } |
| 805 } |
| 806 |
| 807 if (activation_pc_address) { |
| 808 activation_pc_addresses_.push_back(activation_pc_address); |
804 } | 809 } |
805 } | 810 } |
806 | 811 |
807 void VisitFunction(JSFunction* function) { | 812 void VisitFunction(JSFunction* function) { |
808 if (function->Inlines(shared_)) has_activations_ = true; | 813 if (function->Inlines(shared_)) has_activations_ = true; |
809 } | 814 } |
810 | 815 |
811 void EnterContext(Context* context) {} | 816 void EnterContext(Context* context) {} |
812 void LeaveContext(Context* context) {} | 817 void LeaveContext(Context* context) {} |
| 818 |
| 819 bool MarkActivationsForBaselineOnReturn(Isolate* isolate) { |
| 820 if (activation_pc_addresses_.empty()) return false; |
| 821 |
| 822 for (Address* activation_pc_address : activation_pc_addresses_) { |
| 823 DCHECK(isolate->inner_pointer_to_code_cache() |
| 824 ->GetCacheEntry(*activation_pc_address) |
| 825 ->code->is_interpreter_trampoline_builtin()); |
| 826 *activation_pc_address = |
| 827 isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry(); |
| 828 } |
| 829 return true; |
| 830 } |
| 831 |
| 832 bool has_activations() { return has_activations_; } |
| 833 |
| 834 private: |
| 835 SharedFunctionInfo* shared_; |
| 836 bool has_activations_; |
| 837 std::vector<Address*> activation_pc_addresses_; |
813 }; | 838 }; |
814 | 839 |
815 bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) { | 840 bool HasInterpreterActivations( |
816 InterpreterActivationsFinder activations_finder(shared); | 841 Isolate* isolate, InterpreterActivationsFinder* activations_finder) { |
817 activations_finder.VisitThread(isolate, isolate->thread_local_top()); | 842 activations_finder->VisitThread(isolate, isolate->thread_local_top()); |
818 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); | 843 isolate->thread_manager()->IterateArchivedThreads(activations_finder); |
819 if (FLAG_turbo_from_bytecode) { | 844 if (FLAG_turbo_from_bytecode) { |
820 // If we are able to optimize functions directly from bytecode, then there | 845 // If we are able to optimize functions directly from bytecode, then there |
821 // might be optimized functions that rely on bytecode being around. We need | 846 // might be optimized functions that rely on bytecode being around. We need |
822 // to prevent switching the given function to baseline code in those cases. | 847 // to prevent switching the given function to baseline code in those cases. |
823 Deoptimizer::VisitAllOptimizedFunctions(isolate, &activations_finder); | 848 Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder); |
824 } | 849 } |
825 return activations_finder.has_activations_; | 850 return activations_finder->has_activations(); |
826 } | 851 } |
827 | 852 |
828 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { | 853 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { |
829 Isolate* isolate = function->GetIsolate(); | 854 Isolate* isolate = function->GetIsolate(); |
830 VMState<COMPILER> state(isolate); | 855 VMState<COMPILER> state(isolate); |
831 PostponeInterruptsScope postpone(isolate); | 856 PostponeInterruptsScope postpone(isolate); |
832 Zone zone(isolate->allocator()); | 857 Zone zone(isolate->allocator()); |
833 ParseInfo parse_info(&zone, function); | 858 ParseInfo parse_info(&zone, function); |
834 CompilationInfo info(&parse_info, function); | 859 CompilationInfo info(&parse_info, function); |
835 | 860 |
(...skipping 17 matching lines...) Expand all Loading... |
853 // there might be suspended activations stored in generator objects on the | 878 // there might be suspended activations stored in generator objects on the |
854 // heap. We could eventually go directly to TurboFan in this case. | 879 // heap. We could eventually go directly to TurboFan in this case. |
855 if (function->shared()->is_generator()) { | 880 if (function->shared()->is_generator()) { |
856 return MaybeHandle<Code>(); | 881 return MaybeHandle<Code>(); |
857 } | 882 } |
858 | 883 |
859 // TODO(4280): For now we disable switching to baseline code in the presence | 884 // TODO(4280): For now we disable switching to baseline code in the presence |
860 // of interpreter activations of the given function. The reasons are: | 885 // of interpreter activations of the given function. The reasons are: |
861 // 1) The debugger assumes each function is either full-code or bytecode. | 886 // 1) The debugger assumes each function is either full-code or bytecode. |
862 // 2) The underlying bytecode is cleared below, breaking stack unwinding. | 887 // 2) The underlying bytecode is cleared below, breaking stack unwinding. |
863 if (HasInterpreterActivations(isolate, function->shared())) { | 888 InterpreterActivationsFinder activations_finder(function->shared()); |
| 889 if (HasInterpreterActivations(isolate, &activations_finder)) { |
864 if (FLAG_trace_opt) { | 890 if (FLAG_trace_opt) { |
865 OFStream os(stdout); | 891 OFStream os(stdout); |
866 os << "[unable to switch " << Brief(*function) << " due to activations]" | 892 os << "[unable to switch " << Brief(*function) << " due to activations]" |
867 << std::endl; | 893 << std::endl; |
868 } | 894 } |
| 895 |
| 896 if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) { |
| 897 if (FLAG_trace_opt) { |
| 898 OFStream os(stdout); |
| 899 os << "[marking " << Brief(function->shared()) |
| 900 << " for baseline recompilation on return]" << std::endl; |
| 901 } |
| 902 } |
| 903 |
869 return MaybeHandle<Code>(); | 904 return MaybeHandle<Code>(); |
870 } | 905 } |
871 | 906 |
872 if (FLAG_trace_opt) { | 907 if (FLAG_trace_opt) { |
873 OFStream os(stdout); | 908 OFStream os(stdout); |
874 os << "[switching method " << Brief(*function) << " to baseline code]" | 909 os << "[switching method " << Brief(*function) << " to baseline code]" |
875 << std::endl; | 910 << std::endl; |
876 } | 911 } |
877 | 912 |
878 // Parse and update CompilationInfo with the results. | 913 // Parse and update CompilationInfo with the results. |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 // there might be suspended activations stored in generator objects on the | 1310 // there might be suspended activations stored in generator objects on the |
1276 // heap. We could eventually go directly to TurboFan in this case. | 1311 // heap. We could eventually go directly to TurboFan in this case. |
1277 if (shared->is_generator()) return false; | 1312 if (shared->is_generator()) return false; |
1278 | 1313 |
1279 // TODO(4280): For now we disable switching to baseline code in the presence | 1314 // TODO(4280): For now we disable switching to baseline code in the presence |
1280 // of interpreter activations of the given function. The reasons are: | 1315 // of interpreter activations of the given function. The reasons are: |
1281 // 1) The debugger assumes each function is either full-code or bytecode. | 1316 // 1) The debugger assumes each function is either full-code or bytecode. |
1282 // 2) The underlying bytecode is cleared below, breaking stack unwinding. | 1317 // 2) The underlying bytecode is cleared below, breaking stack unwinding. |
1283 // The expensive check for activations only needs to be done when the given | 1318 // The expensive check for activations only needs to be done when the given |
1284 // function has bytecode, otherwise we can be sure there are no activations. | 1319 // function has bytecode, otherwise we can be sure there are no activations. |
1285 if (shared->HasBytecodeArray() && | 1320 if (shared->HasBytecodeArray()) { |
1286 HasInterpreterActivations(info->isolate(), *shared)) { | 1321 InterpreterActivationsFinder activations_finder(*shared); |
1287 return false; | 1322 if (HasInterpreterActivations(info->isolate(), &activations_finder)) { |
| 1323 return false; |
| 1324 } |
1288 } | 1325 } |
1289 | 1326 |
1290 // If the current code has reloc info for serialization, also include | 1327 // If the current code has reloc info for serialization, also include |
1291 // reloc info for serialization for the new code, so that deopt support | 1328 // reloc info for serialization for the new code, so that deopt support |
1292 // can be added without losing IC state. | 1329 // can be added without losing IC state. |
1293 if (shared->code()->kind() == Code::FUNCTION && | 1330 if (shared->code()->kind() == Code::FUNCTION && |
1294 shared->code()->has_reloc_info_for_serialization()) { | 1331 shared->code()->has_reloc_info_for_serialization()) { |
1295 unoptimized.PrepareForSerializing(); | 1332 unoptimized.PrepareForSerializing(); |
1296 } | 1333 } |
1297 EnsureFeedbackVector(&unoptimized); | 1334 EnsureFeedbackVector(&unoptimized); |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1756 MaybeHandle<Code> code; | 1793 MaybeHandle<Code> code; |
1757 if (cached.code != nullptr) code = handle(cached.code); | 1794 if (cached.code != nullptr) code = handle(cached.code); |
1758 Handle<Context> native_context(function->context()->native_context()); | 1795 Handle<Context> native_context(function->context()->native_context()); |
1759 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1796 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1760 literals, BailoutId::None()); | 1797 literals, BailoutId::None()); |
1761 } | 1798 } |
1762 } | 1799 } |
1763 | 1800 |
1764 } // namespace internal | 1801 } // namespace internal |
1765 } // namespace v8 | 1802 } // namespace v8 |
OLD | NEW |