| 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 |