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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 // Recompile the unoptimized version of the code if the current version | 390 // Recompile the unoptimized version of the code if the current version |
391 // doesn't have deoptimization support already. | 391 // doesn't have deoptimization support already. |
392 // Otherwise, if we are gathering compilation time and space statistics | 392 // Otherwise, if we are gathering compilation time and space statistics |
393 // for hydrogen, gather baseline statistics for a fullcode compilation. | 393 // for hydrogen, gather baseline statistics for a fullcode compilation. |
394 bool should_recompile = !info()->shared_info()->has_deoptimization_support(); | 394 bool should_recompile = !info()->shared_info()->has_deoptimization_support(); |
395 if (should_recompile || FLAG_hydrogen_stats) { | 395 if (should_recompile || FLAG_hydrogen_stats) { |
396 base::ElapsedTimer timer; | 396 base::ElapsedTimer timer; |
397 if (FLAG_hydrogen_stats) { | 397 if (FLAG_hydrogen_stats) { |
398 timer.Start(); | 398 timer.Start(); |
399 } | 399 } |
400 CompilationInfoWithZone unoptimized(info()->shared_info()); | 400 if (!Compiler::EnsureDeoptimizationSupport(info())) { |
401 // Note that we use the same AST that we will use for generating the | 401 return SetLastStatus(FAILED); |
402 // optimized code. | |
403 unoptimized.SetFunction(info()->function()); | |
404 unoptimized.PrepareForCompilation(info()->scope()); | |
405 unoptimized.SetContext(info()->context()); | |
406 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); | |
407 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); | |
408 if (should_recompile) { | |
409 if (!succeeded) return SetLastStatus(FAILED); | |
410 Handle<SharedFunctionInfo> shared = info()->shared_info(); | |
411 shared->EnableDeoptimizationSupport(*unoptimized.code()); | |
412 // The existing unoptimized code was replaced with the new one. | |
413 Compiler::RecordFunctionCompilation( | |
414 Logger::LAZY_COMPILE_TAG, &unoptimized, shared); | |
415 } | 402 } |
416 if (FLAG_hydrogen_stats) { | 403 if (FLAG_hydrogen_stats) { |
417 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); | 404 isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed()); |
418 } | 405 } |
419 } | 406 } |
420 | 407 |
421 DCHECK(info()->shared_info()->has_deoptimization_support()); | 408 DCHECK(info()->shared_info()->has_deoptimization_support()); |
422 | 409 |
423 // Check the whitelist for TurboFan. | 410 // Check the whitelist for TurboFan. |
424 if (info()->closure()->PassesFilter(FLAG_turbo_filter) && | 411 if (info()->closure()->PassesFilter(FLAG_turbo_filter) && |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 function->GetIsolate()->clear_pending_exception(); | 738 function->GetIsolate()->clear_pending_exception(); |
752 } | 739 } |
753 return false; | 740 return false; |
754 } | 741 } |
755 function->ReplaceCode(*code); | 742 function->ReplaceCode(*code); |
756 DCHECK(function->is_compiled()); | 743 DCHECK(function->is_compiled()); |
757 return true; | 744 return true; |
758 } | 745 } |
759 | 746 |
760 | 747 |
| 748 // TODO(turbofan): In the future, unoptimized code with deopt support could |
| 749 // be generated lazily once deopt is triggered. |
| 750 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
| 751 if (!info->shared_info()->has_deoptimization_support()) { |
| 752 CompilationInfoWithZone unoptimized(info->shared_info()); |
| 753 // Note that we use the same AST that we will use for generating the |
| 754 // optimized code. |
| 755 unoptimized.SetFunction(info->function()); |
| 756 unoptimized.PrepareForCompilation(info->scope()); |
| 757 unoptimized.SetContext(info->context()); |
| 758 unoptimized.EnableDeoptimizationSupport(); |
| 759 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; |
| 760 |
| 761 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 762 shared->EnableDeoptimizationSupport(*unoptimized.code()); |
| 763 shared->set_feedback_vector(*unoptimized.feedback_vector()); |
| 764 |
| 765 // The scope info might not have been set if a lazily compiled |
| 766 // function is inlined before being called for the first time. |
| 767 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) { |
| 768 Handle<ScopeInfo> target_scope_info = |
| 769 ScopeInfo::Create(info->scope(), info->zone()); |
| 770 shared->set_scope_info(*target_scope_info); |
| 771 } |
| 772 |
| 773 // The existing unoptimized code was replaced with the new one. |
| 774 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared); |
| 775 } |
| 776 return true; |
| 777 } |
| 778 |
| 779 |
761 // Compile full code for debugging. This code will have debug break slots | 780 // Compile full code for debugging. This code will have debug break slots |
762 // and deoptimization information. Deoptimization information is required | 781 // and deoptimization information. Deoptimization information is required |
763 // in case that an optimized version of this function is still activated on | 782 // in case that an optimized version of this function is still activated on |
764 // the stack. It will also make sure that the full code is compiled with | 783 // the stack. It will also make sure that the full code is compiled with |
765 // the same flags as the previous version, that is flags which can change | 784 // the same flags as the previous version, that is flags which can change |
766 // the code generated. The current method of mapping from already compiled | 785 // the code generated. The current method of mapping from already compiled |
767 // full code without debug break slots to full code with debug break slots | 786 // full code without debug break slots to full code with debug break slots |
768 // depends on the generated code is otherwise exactly the same. | 787 // depends on the generated code is otherwise exactly the same. |
769 // If compilation fails, just keep the existing code. | 788 // If compilation fails, just keep the existing code. |
770 MaybeHandle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) { | 789 MaybeHandle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) { |
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 AllowHandleDereference allow_deref; | 1426 AllowHandleDereference allow_deref; |
1408 bool tracing_on = info()->IsStub() | 1427 bool tracing_on = info()->IsStub() |
1409 ? FLAG_trace_hydrogen_stubs | 1428 ? FLAG_trace_hydrogen_stubs |
1410 : (FLAG_trace_hydrogen && | 1429 : (FLAG_trace_hydrogen && |
1411 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); | 1430 info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter)); |
1412 return (tracing_on && | 1431 return (tracing_on && |
1413 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); | 1432 base::OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL); |
1414 } | 1433 } |
1415 | 1434 |
1416 } } // namespace v8::internal | 1435 } } // namespace v8::internal |
OLD | NEW |