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 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 if (GetOptimizedCodeNow(job.get())) return info->code(); | 778 if (GetOptimizedCodeNow(job.get())) return info->code(); |
779 } | 779 } |
780 | 780 |
781 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 781 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
782 return MaybeHandle<Code>(); | 782 return MaybeHandle<Code>(); |
783 } | 783 } |
784 | 784 |
785 class InterpreterActivationsFinder : public ThreadVisitor, | 785 class InterpreterActivationsFinder : public ThreadVisitor, |
786 public OptimizedFunctionVisitor { | 786 public OptimizedFunctionVisitor { |
787 public: | 787 public: |
788 SharedFunctionInfo* shared_; | |
789 bool has_activations_; | |
790 | |
791 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) | 788 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) |
792 : shared_(shared), has_activations_(false) {} | 789 : shared_(shared), has_activations_(false) {} |
793 | 790 |
794 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 791 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
792 Address* activation_pc_address = nullptr; | |
795 JavaScriptFrameIterator it(isolate, top); | 793 JavaScriptFrameIterator it(isolate, top); |
796 for (; !it.done() && !has_activations_; it.Advance()) { | 794 for (; !it.done(); it.Advance()) { |
797 JavaScriptFrame* frame = it.frame(); | 795 JavaScriptFrame* frame = it.frame(); |
798 if (!frame->is_interpreted()) continue; | 796 if (!frame->is_interpreted()) continue; |
799 if (frame->function()->shared() == shared_) has_activations_ = true; | 797 if (frame->function()->shared() == shared_) { |
798 has_activations_ = true; | |
799 activation_pc_address = frame->pc_address(); | |
800 } | |
801 } | |
802 | |
803 if (activation_pc_address) { | |
804 activation_pc_addresses_.push_back(activation_pc_address); | |
800 } | 805 } |
801 } | 806 } |
802 | 807 |
803 void VisitFunction(JSFunction* function) { | 808 void VisitFunction(JSFunction* function) { |
804 if (function->Inlines(shared_)) has_activations_ = true; | 809 if (function->Inlines(shared_)) has_activations_ = true; |
805 } | 810 } |
806 | 811 |
807 void EnterContext(Context* context) {} | 812 void EnterContext(Context* context) {} |
808 void LeaveContext(Context* context) {} | 813 void LeaveContext(Context* context) {} |
814 | |
815 bool MarkActivationsForBaselineOnReturn(Isolate* isolate) { | |
816 if (activation_pc_addresses_.empty()) return false; | |
817 | |
818 for (Address* activation_pc_address : activation_pc_addresses_) { | |
819 DCHECK(isolate->inner_pointer_to_code_cache() | |
820 ->GetCacheEntry(*activation_pc_address) | |
821 ->code->is_interpreter_trampoline_builtin()); | |
822 *activation_pc_address = | |
823 isolate->builtins()->InterpreterMarkBaselineOnReturn()->entry(); | |
824 } | |
825 return true; | |
826 } | |
827 | |
828 bool has_activations() { return has_activations_; } | |
829 | |
830 private: | |
831 SharedFunctionInfo* shared_; | |
832 bool has_activations_; | |
833 std::vector<Address*> activation_pc_addresses_; | |
809 }; | 834 }; |
810 | 835 |
811 bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) { | 836 bool HasInterpreterActivations( |
812 InterpreterActivationsFinder activations_finder(shared); | 837 Isolate* isolate, InterpreterActivationsFinder* activations_finder) { |
813 activations_finder.VisitThread(isolate, isolate->thread_local_top()); | 838 activations_finder->VisitThread(isolate, isolate->thread_local_top()); |
814 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); | 839 isolate->thread_manager()->IterateArchivedThreads(activations_finder); |
815 if (FLAG_turbo_from_bytecode) { | 840 if (FLAG_turbo_from_bytecode) { |
816 // If we are able to optimize functions directly from bytecode, then there | 841 // If we are able to optimize functions directly from bytecode, then there |
817 // might be optimized functions that rely on bytecode being around. We need | 842 // might be optimized functions that rely on bytecode being around. We need |
818 // to prevent switching the given function to baseline code in those cases. | 843 // to prevent switching the given function to baseline code in those cases. |
819 Deoptimizer::VisitAllOptimizedFunctions(isolate, &activations_finder); | 844 Deoptimizer::VisitAllOptimizedFunctions(isolate, activations_finder); |
820 } | 845 } |
821 return activations_finder.has_activations_; | 846 return activations_finder->has_activations(); |
822 } | 847 } |
823 | 848 |
824 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { | 849 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { |
825 Isolate* isolate = function->GetIsolate(); | 850 Isolate* isolate = function->GetIsolate(); |
826 VMState<COMPILER> state(isolate); | 851 VMState<COMPILER> state(isolate); |
827 PostponeInterruptsScope postpone(isolate); | 852 PostponeInterruptsScope postpone(isolate); |
828 Zone zone(isolate->allocator()); | 853 Zone zone(isolate->allocator()); |
829 ParseInfo parse_info(&zone, function); | 854 ParseInfo parse_info(&zone, function); |
830 CompilationInfo info(&parse_info, function); | 855 CompilationInfo info(&parse_info, function); |
831 | 856 |
(...skipping 17 matching lines...) Expand all Loading... | |
849 // there might be suspended activations stored in generator objects on the | 874 // there might be suspended activations stored in generator objects on the |
850 // heap. We could eventually go directly to TurboFan in this case. | 875 // heap. We could eventually go directly to TurboFan in this case. |
851 if (function->shared()->is_generator()) { | 876 if (function->shared()->is_generator()) { |
852 return MaybeHandle<Code>(); | 877 return MaybeHandle<Code>(); |
853 } | 878 } |
854 | 879 |
855 // TODO(4280): For now we disable switching to baseline code in the presence | 880 // TODO(4280): For now we disable switching to baseline code in the presence |
856 // of interpreter activations of the given function. The reasons are: | 881 // of interpreter activations of the given function. The reasons are: |
857 // 1) The debugger assumes each function is either full-code or bytecode. | 882 // 1) The debugger assumes each function is either full-code or bytecode. |
858 // 2) The underlying bytecode is cleared below, breaking stack unwinding. | 883 // 2) The underlying bytecode is cleared below, breaking stack unwinding. |
859 if (HasInterpreterActivations(isolate, function->shared())) { | 884 InterpreterActivationsFinder activations_finder(function->shared()); |
885 if (HasInterpreterActivations(isolate, &activations_finder)) { | |
860 if (FLAG_trace_opt) { | 886 if (FLAG_trace_opt) { |
861 OFStream os(stdout); | 887 OFStream os(stdout); |
862 os << "[unable to switch " << Brief(*function) << " due to activations]" | 888 os << "[unable to switch " << Brief(*function) << " due to activations]" |
863 << std::endl; | 889 << std::endl; |
864 } | 890 } |
891 | |
892 if (activations_finder.MarkActivationsForBaselineOnReturn(isolate)) { | |
893 if (FLAG_trace_opt) { | |
894 OFStream os(stdout); | |
895 os << "[marking " << Brief(*function) << " for baseline recompilation " | |
Michael Starzinger
2016/05/11 13:04:27
nit: Let's print s/*function/function->shared()/ h
rmcilroy
2016/05/12 13:11:47
Done. This brings up the point of whether we shoul
Michael Starzinger
2016/05/13 09:01:39
Hmm. Interesting idea. I suppose it would be possi
rmcilroy
2016/05/17 11:28:30
Yes absolutely, only in a separate CL and if it's
| |
896 << "on return]" << std::endl; | |
897 } | |
898 } | |
899 | |
865 return MaybeHandle<Code>(); | 900 return MaybeHandle<Code>(); |
866 } | 901 } |
867 | 902 |
868 if (FLAG_trace_opt) { | 903 if (FLAG_trace_opt) { |
869 OFStream os(stdout); | 904 OFStream os(stdout); |
870 os << "[switching method " << Brief(*function) << " to baseline code]" | 905 os << "[switching method " << Brief(*function) << " to baseline code]" |
871 << std::endl; | 906 << std::endl; |
872 } | 907 } |
873 | 908 |
874 // Parse and update CompilationInfo with the results. | 909 // Parse and update CompilationInfo with the results. |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1244 // TODO(turbofan): In the future, unoptimized code with deopt support could | 1279 // TODO(turbofan): In the future, unoptimized code with deopt support could |
1245 // be generated lazily once deopt is triggered. | 1280 // be generated lazily once deopt is triggered. |
1246 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 1281 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
1247 DCHECK_NOT_NULL(info->literal()); | 1282 DCHECK_NOT_NULL(info->literal()); |
1248 DCHECK_NOT_NULL(info->scope()); | 1283 DCHECK_NOT_NULL(info->scope()); |
1249 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1284 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1250 if (!shared->has_deoptimization_support()) { | 1285 if (!shared->has_deoptimization_support()) { |
1251 Zone zone(info->isolate()->allocator()); | 1286 Zone zone(info->isolate()->allocator()); |
1252 CompilationInfo unoptimized(info->parse_info(), info->closure()); | 1287 CompilationInfo unoptimized(info->parse_info(), info->closure()); |
1253 unoptimized.EnableDeoptimizationSupport(); | 1288 unoptimized.EnableDeoptimizationSupport(); |
1289 | |
1254 // TODO(4280): For now we disable switching to baseline code in the presence | 1290 // TODO(4280): For now we disable switching to baseline code in the presence |
1255 // of interpreter activations of the given function. The reasons are: | 1291 // of interpreter activations of the given function. The reasons are: |
1256 // 1) The debugger assumes each function is either full-code or bytecode. | 1292 // 1) The debugger assumes each function is either full-code or bytecode. |
1257 // 2) The underlying bytecode is cleared below, breaking stack unwinding. | 1293 // 2) The underlying bytecode is cleared below, breaking stack unwinding. |
1258 // The expensive check for activations only needs to be done when the given | 1294 // The expensive check for activations only needs to be done when the given |
1259 // function has bytecode, otherwise we can be sure there are no activations. | 1295 // function has bytecode, otherwise we can be sure there are no activations. |
1260 if (shared->HasBytecodeArray() && | 1296 if (shared->HasBytecodeArray()) { |
1261 HasInterpreterActivations(info->isolate(), *shared)) { | 1297 InterpreterActivationsFinder activations_finder(*shared); |
1262 return false; | 1298 if (HasInterpreterActivations(info->isolate(), &activations_finder)) { |
1299 return false; | |
1300 } | |
1263 } | 1301 } |
1264 // If the current code has reloc info for serialization, also include | 1302 // If the current code has reloc info for serialization, also include |
1265 // reloc info for serialization for the new code, so that deopt support | 1303 // reloc info for serialization for the new code, so that deopt support |
1266 // can be added without losing IC state. | 1304 // can be added without losing IC state. |
1267 if (shared->code()->kind() == Code::FUNCTION && | 1305 if (shared->code()->kind() == Code::FUNCTION && |
1268 shared->code()->has_reloc_info_for_serialization()) { | 1306 shared->code()->has_reloc_info_for_serialization()) { |
1269 unoptimized.PrepareForSerializing(); | 1307 unoptimized.PrepareForSerializing(); |
1270 } | 1308 } |
1271 EnsureFeedbackVector(&unoptimized); | 1309 EnsureFeedbackVector(&unoptimized); |
1272 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1310 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1743 MaybeHandle<Code> code; | 1781 MaybeHandle<Code> code; |
1744 if (cached.code != nullptr) code = handle(cached.code); | 1782 if (cached.code != nullptr) code = handle(cached.code); |
1745 Handle<Context> native_context(function->context()->native_context()); | 1783 Handle<Context> native_context(function->context()->native_context()); |
1746 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1784 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1747 literals, BailoutId::None()); | 1785 literals, BailoutId::None()); |
1748 } | 1786 } |
1749 } | 1787 } |
1750 | 1788 |
1751 } // namespace internal | 1789 } // namespace internal |
1752 } // namespace v8 | 1790 } // namespace v8 |
OLD | NEW |