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 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
852 } | 852 } |
853 } else { | 853 } else { |
854 info->set_osr_frame(osr_frame); | 854 info->set_osr_frame(osr_frame); |
855 if (GetOptimizedCodeNow(job.get())) return info->code(); | 855 if (GetOptimizedCodeNow(job.get())) return info->code(); |
856 } | 856 } |
857 | 857 |
858 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); | 858 if (isolate->has_pending_exception()) isolate->clear_pending_exception(); |
859 return MaybeHandle<Code>(); | 859 return MaybeHandle<Code>(); |
860 } | 860 } |
861 | 861 |
862 class InterpreterActivationsFinder : public ThreadVisitor { | 862 class InterpreterActivationsFinder : public ThreadVisitor, |
863 public OptimizedFunctionVisitor { | |
Yang
2016/04/29 10:19:49
Multiple inheritance. I hope that's fine with the
rmcilroy
2016/04/29 10:50:29
Both classes are pure virtual, which is allowed by
Michael Starzinger
2016/04/29 10:59:10
I don't have a strong opinion on this. Happy to se
| |
863 public: | 864 public: |
864 SharedFunctionInfo* shared_; | 865 SharedFunctionInfo* shared_; |
865 bool has_activations_; | 866 bool has_activations_; |
866 | 867 |
867 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) | 868 explicit InterpreterActivationsFinder(SharedFunctionInfo* shared) |
868 : shared_(shared), has_activations_(false) {} | 869 : shared_(shared), has_activations_(false) {} |
869 | 870 |
870 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 871 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
871 JavaScriptFrameIterator it(isolate, top); | 872 JavaScriptFrameIterator it(isolate, top); |
872 for (; !it.done() && !has_activations_; it.Advance()) { | 873 for (; !it.done() && !has_activations_; it.Advance()) { |
873 JavaScriptFrame* frame = it.frame(); | 874 JavaScriptFrame* frame = it.frame(); |
874 if (!frame->is_interpreted()) continue; | 875 if (!frame->is_interpreted()) continue; |
875 if (frame->function()->shared() == shared_) has_activations_ = true; | 876 if (frame->function()->shared() == shared_) has_activations_ = true; |
876 } | 877 } |
877 } | 878 } |
879 | |
880 void VisitFunction(JSFunction* function) { | |
881 if (function->Inlines(shared_)) has_activations_ = true; | |
Yang
2016/04/29 10:19:49
We could be more precise here and only mark has_ac
Michael Starzinger
2016/04/29 10:59:10
Not sure I understand entirely. The only way optim
| |
882 } | |
883 | |
884 void EnterContext(Context* context) {} | |
885 void LeaveContext(Context* context) {} | |
878 }; | 886 }; |
879 | 887 |
880 bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) { | 888 bool HasInterpreterActivations(Isolate* isolate, SharedFunctionInfo* shared) { |
881 InterpreterActivationsFinder activations_finder(shared); | 889 InterpreterActivationsFinder activations_finder(shared); |
882 activations_finder.VisitThread(isolate, isolate->thread_local_top()); | 890 activations_finder.VisitThread(isolate, isolate->thread_local_top()); |
883 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); | 891 isolate->thread_manager()->IterateArchivedThreads(&activations_finder); |
892 if (FLAG_turbo_from_bytecode) { | |
893 // If we are able to optimize functions directly from bytecode, then there | |
894 // might be optimized functions that rely on bytecode being around. We need | |
895 // to prevent switching the given function to baseline code in those cases. | |
896 Deoptimizer::VisitAllOptimizedFunctions(isolate, &activations_finder); | |
897 } | |
884 return activations_finder.has_activations_; | 898 return activations_finder.has_activations_; |
885 } | 899 } |
886 | 900 |
887 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { | 901 MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) { |
888 Isolate* isolate = function->GetIsolate(); | 902 Isolate* isolate = function->GetIsolate(); |
889 VMState<COMPILER> state(isolate); | 903 VMState<COMPILER> state(isolate); |
890 PostponeInterruptsScope postpone(isolate); | 904 PostponeInterruptsScope postpone(isolate); |
891 Zone zone(isolate->allocator()); | 905 Zone zone(isolate->allocator()); |
892 ParseInfo parse_info(&zone, function); | 906 ParseInfo parse_info(&zone, function); |
893 CompilationInfo info(&parse_info, function); | 907 CompilationInfo info(&parse_info, function); |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1320 DCHECK(!isolate->has_pending_exception()); | 1334 DCHECK(!isolate->has_pending_exception()); |
1321 return true; | 1335 return true; |
1322 } | 1336 } |
1323 | 1337 |
1324 // TODO(turbofan): In the future, unoptimized code with deopt support could | 1338 // TODO(turbofan): In the future, unoptimized code with deopt support could |
1325 // be generated lazily once deopt is triggered. | 1339 // be generated lazily once deopt is triggered. |
1326 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 1340 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
1327 DCHECK_NOT_NULL(info->literal()); | 1341 DCHECK_NOT_NULL(info->literal()); |
1328 DCHECK_NOT_NULL(info->scope()); | 1342 DCHECK_NOT_NULL(info->scope()); |
1329 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1343 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1330 if (shared->HasBytecodeArray() && | |
1331 HasInterpreterActivations(info->isolate(), *shared)) { | |
1332 // Do not tier up from here if we have bytecode on the stack. | |
1333 return false; | |
1334 } | |
1335 if (!shared->has_deoptimization_support()) { | 1344 if (!shared->has_deoptimization_support()) { |
1336 Zone zone(info->isolate()->allocator()); | 1345 Zone zone(info->isolate()->allocator()); |
1337 CompilationInfo unoptimized(info->parse_info(), info->closure()); | 1346 CompilationInfo unoptimized(info->parse_info(), info->closure()); |
1338 unoptimized.EnableDeoptimizationSupport(); | 1347 unoptimized.EnableDeoptimizationSupport(); |
1348 // TODO(4280): For now we disable switching to baseline code in the presence | |
1349 // of interpreter activations of the given function. The reasons are: | |
1350 // 1) The debugger assumes each function is either full-code or bytecode. | |
1351 // 2) The underlying bytecode is cleared below, breaking stack unwinding. | |
1352 // The expensive check for activations only needs to be done when the given | |
1353 // function has bytecode, otherwise we can be sure there are no activations. | |
1354 if (shared->HasBytecodeArray() && | |
1355 HasInterpreterActivations(info->isolate(), *shared)) { | |
1356 return false; | |
1357 } | |
1339 // If the current code has reloc info for serialization, also include | 1358 // If the current code has reloc info for serialization, also include |
1340 // reloc info for serialization for the new code, so that deopt support | 1359 // reloc info for serialization for the new code, so that deopt support |
1341 // can be added without losing IC state. | 1360 // can be added without losing IC state. |
1342 if (shared->code()->kind() == Code::FUNCTION && | 1361 if (shared->code()->kind() == Code::FUNCTION && |
1343 shared->code()->has_reloc_info_for_serialization()) { | 1362 shared->code()->has_reloc_info_for_serialization()) { |
1344 unoptimized.PrepareForSerializing(); | 1363 unoptimized.PrepareForSerializing(); |
1345 } | 1364 } |
1346 EnsureFeedbackVector(&unoptimized); | 1365 EnsureFeedbackVector(&unoptimized); |
1347 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; | 1366 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
1348 | 1367 |
1349 shared->EnableDeoptimizationSupport(*unoptimized.code()); | 1368 // TODO(4280): For now we play it safe and remove the bytecode array when we |
1369 // switch to baseline code. We might consider keeping around the bytecode so | |
1370 // that it can be used as the "source of truth" eventually. | |
1371 shared->ClearBytecodeArray(); | |
1350 | 1372 |
1351 // The scope info might not have been set if a lazily compiled | 1373 // The scope info might not have been set if a lazily compiled |
1352 // function is inlined before being called for the first time. | 1374 // function is inlined before being called for the first time. |
1353 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { | 1375 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
1354 InstallSharedScopeInfo(info, shared); | 1376 InstallSharedScopeInfo(info, shared); |
1355 } | 1377 } |
1356 | 1378 |
1379 // Install compilation result on the shared function info | |
1380 shared->EnableDeoptimizationSupport(*unoptimized.code()); | |
Yang
2016/04/29 10:19:49
Is there a reason this has been moved to after ins
Michael Starzinger
2016/04/29 10:59:10
No strong reason other than to bring the steps in
| |
1381 | |
1357 // The existing unoptimized code was replaced with the new one. | 1382 // The existing unoptimized code was replaced with the new one. |
1358 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized); | 1383 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized); |
1359 } | 1384 } |
1360 return true; | 1385 return true; |
1361 } | 1386 } |
1362 | 1387 |
1363 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( | 1388 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( |
1364 Handle<String> source, Handle<SharedFunctionInfo> outer_info, | 1389 Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
1365 Handle<Context> context, LanguageMode language_mode, | 1390 Handle<Context> context, LanguageMode language_mode, |
1366 ParseRestriction restriction, int eval_scope_position, int eval_position, | 1391 ParseRestriction restriction, int eval_scope_position, int eval_position, |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1814 MaybeHandle<Code> code; | 1839 MaybeHandle<Code> code; |
1815 if (cached.code != nullptr) code = handle(cached.code); | 1840 if (cached.code != nullptr) code = handle(cached.code); |
1816 Handle<Context> native_context(function->context()->native_context()); | 1841 Handle<Context> native_context(function->context()->native_context()); |
1817 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, | 1842 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, |
1818 literals, BailoutId::None()); | 1843 literals, BailoutId::None()); |
1819 } | 1844 } |
1820 } | 1845 } |
1821 | 1846 |
1822 } // namespace internal | 1847 } // namespace internal |
1823 } // namespace v8 | 1848 } // namespace v8 |
OLD | NEW |