Chromium Code Reviews| 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 |