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 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 651 } else { | 651 } else { |
| 652 if (result->ic_age() != HEAP->global_ic_age()) { | 652 if (result->ic_age() != HEAP->global_ic_age()) { |
| 653 result->ResetForNewContext(HEAP->global_ic_age()); | 653 result->ResetForNewContext(HEAP->global_ic_age()); |
| 654 } | 654 } |
| 655 } | 655 } |
| 656 | 656 |
| 657 return result; | 657 return result; |
| 658 } | 658 } |
| 659 | 659 |
| 660 | 660 |
| 661 bool Compiler::CompileLazy(CompilationInfo* info) { | 661 static bool InstallFullCode(CompilationInfo* info) { |
| 662 Isolate* isolate = info->isolate(); | 662 // Update the shared function info with the compiled code and the |
| 663 // scope info. Please note, that the order of the shared function | |
| 664 // info initialization is important since set_scope_info might | |
| 665 // trigger a GC, causing the ASSERT below to be invalid if the code | |
| 666 // was flushed. By setting the code object last we avoid this. | |
| 667 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 668 Handle<Code> code = info->code(); | |
| 669 Handle<JSFunction> function = info->closure(); | |
| 670 Handle<ScopeInfo> scope_info = | |
| 671 ScopeInfo::Create(info->scope(), info->zone()); | |
| 672 shared->set_scope_info(*scope_info); | |
| 673 shared->set_code(*code); | |
| 674 if (!function.is_null()) { | |
| 675 function->ReplaceCode(*code); | |
| 676 ASSERT(!function->IsOptimized()); | |
| 677 } | |
| 663 | 678 |
| 664 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT); | 679 // Set the expected number of properties for instances. |
| 680 FunctionLiteral* lit = info->function(); | |
| 681 int expected = lit->expected_property_count(); | |
| 682 SetExpectedNofPropertiesFromEstimate(shared, expected); | |
| 665 | 683 |
| 666 // The VM is in the COMPILER state until exiting this function. | 684 // Set the optimization hints after performing lazy compilation, as |
| 667 VMState state(isolate, COMPILER); | 685 // these are not set when the function is set up as a lazily |
| 686 // compiled function. | |
| 687 shared->SetThisPropertyAssignmentsInfo( | |
| 688 lit->has_only_simple_this_property_assignments(), | |
| 689 *lit->this_property_assignments()); | |
| 668 | 690 |
| 669 PostponeInterruptsScope postpone(isolate); | 691 // Check the function has compiled code. |
| 692 ASSERT(shared->is_compiled()); | |
| 693 shared->set_code_age(0); | |
| 694 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize)); | |
| 695 shared->set_dont_inline(lit->flags()->Contains(kDontInline)); | |
| 696 shared->set_ast_node_count(lit->ast_node_count()); | |
| 670 | 697 |
| 698 if (V8::UseCrankshaft()&& | |
| 699 !function.is_null() && | |
| 700 !shared->optimization_disabled()) { | |
| 701 // If we're asked to always optimize, we compile the optimized | |
| 702 // version of the function right away - unless the debugger is | |
| 703 // active as it makes no sense to compile optimized code then. | |
| 704 if (FLAG_always_opt && | |
| 705 !Isolate::Current()->DebuggerHasBreakPoints()) { | |
| 706 CompilationInfoWithZone optimized(function); | |
| 707 optimized.SetOptimizing(AstNode::kNoNumber); | |
| 708 return Compiler::CompileLazy(&optimized); | |
| 709 } | |
| 710 } | |
| 711 return true; | |
| 712 } | |
| 713 | |
| 714 | |
| 715 static void InstallCodeCommon(CompilationInfo* info) { | |
| 671 Handle<SharedFunctionInfo> shared = info->shared_info(); | 716 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 672 int compiled_size = shared->end_position() - shared->start_position(); | 717 Handle<Code> code = info->code(); |
| 673 isolate->counters()->total_compile_size()->Increment(compiled_size); | 718 ASSERT(!code.is_null()); |
| 674 | 719 |
| 720 // Set optimizable to false if this is disallowed by the shared | |
| 721 // function info, e.g., we might have flushed the code and must | |
| 722 // reset this bit when lazy compiling the code again. | |
| 723 if (shared->optimization_disabled()) code->set_optimizable(false); | |
| 724 | |
| 725 Handle<JSFunction> function = info->closure(); | |
| 726 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | |
| 727 } | |
| 728 | |
| 729 | |
| 730 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) { | |
| 731 Handle<Code> code = info->code(); | |
| 732 Handle<JSFunction> function = info->closure(); | |
| 733 if (FLAG_cache_optimized_code && code->kind() == Code::OPTIMIZED_FUNCTION) { | |
| 734 Handle<SharedFunctionInfo> shared(function->shared()); | |
| 735 Handle<FixedArray> literals(function->literals()); | |
| 736 Handle<Context> global_context(function->context()->global_context()); | |
| 737 SharedFunctionInfo::AddToOptimizedCodeMap( | |
| 738 shared, global_context, code, literals); | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 | |
| 743 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) { | |
| 675 if (FLAG_cache_optimized_code && info->IsOptimizing()) { | 744 if (FLAG_cache_optimized_code && info->IsOptimizing()) { |
| 745 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 676 Handle<JSFunction> function = info->closure(); | 746 Handle<JSFunction> function = info->closure(); |
| 677 ASSERT(!function.is_null()); | 747 ASSERT(!function.is_null()); |
| 678 Handle<Context> global_context(function->context()->global_context()); | 748 Handle<Context> global_context(function->context()->global_context()); |
| 679 int index = shared->SearchOptimizedCodeMap(*global_context); | 749 int index = shared->SearchOptimizedCodeMap(*global_context); |
| 680 if (index > 0) { | 750 if (index > 0) { |
| 681 if (FLAG_trace_opt) { | 751 if (FLAG_trace_opt) { |
| 682 PrintF("[found optimized code for: "); | 752 PrintF("[found optimized code for: "); |
| 683 function->PrintName(); | 753 function->PrintName(); |
| 684 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function)); | 754 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function)); |
| 685 } | 755 } |
| 686 // Caching of optimized code enabled and optimized code found. | 756 // Caching of optimized code enabled and optimized code found. |
| 687 shared->InstallFromOptimizedCodeMap(*function, index); | 757 shared->InstallFromOptimizedCodeMap(*function, index); |
| 688 return true; | 758 return true; |
| 689 } | 759 } |
| 690 } | 760 } |
| 761 return false; | |
| 762 } | |
| 763 | |
| 764 | |
| 765 bool Compiler::CompileLazy(CompilationInfo* info) { | |
| 766 Isolate* isolate = info->isolate(); | |
| 767 | |
| 768 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT); | |
| 769 | |
| 770 // The VM is in the COMPILER state until exiting this function. | |
| 771 VMState state(isolate, COMPILER); | |
| 772 | |
| 773 PostponeInterruptsScope postpone(isolate); | |
| 774 | |
| 775 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 776 int compiled_size = shared->end_position() - shared->start_position(); | |
| 777 isolate->counters()->total_compile_size()->Increment(compiled_size); | |
| 778 | |
| 779 if (InstallCodeFromOptimizedCodeMap(info)) return true; | |
| 691 | 780 |
| 692 // Generate the AST for the lazily compiled function. | 781 // Generate the AST for the lazily compiled function. |
| 693 if (ParserApi::Parse(info, kNoParsingFlags)) { | 782 if (ParserApi::Parse(info, kNoParsingFlags)) { |
| 694 // Measure how long it takes to do the lazy compilation; only take the | 783 // Measure how long it takes to do the lazy compilation; only take the |
| 695 // rest of the function into account to avoid overlap with the lazy | 784 // rest of the function into account to avoid overlap with the lazy |
| 696 // parsing statistics. | 785 // parsing statistics. |
| 697 HistogramTimerScope timer(isolate->counters()->compile_lazy()); | 786 HistogramTimerScope timer(isolate->counters()->compile_lazy()); |
| 698 | 787 |
| 699 // After parsing we know the function's language mode. Remember it. | 788 // After parsing we know the function's language mode. Remember it. |
| 700 LanguageMode language_mode = info->function()->language_mode(); | 789 LanguageMode language_mode = info->function()->language_mode(); |
| 701 info->SetLanguageMode(language_mode); | 790 info->SetLanguageMode(language_mode); |
| 702 shared->set_language_mode(language_mode); | 791 shared->set_language_mode(language_mode); |
| 703 | 792 |
| 704 // Compile the code. | 793 // Compile the code. |
| 705 if (!MakeCode(info)) { | 794 if (!MakeCode(info)) { |
| 706 if (!isolate->has_pending_exception()) { | 795 if (!isolate->has_pending_exception()) { |
| 707 isolate->StackOverflow(); | 796 isolate->StackOverflow(); |
| 708 } | 797 } |
| 709 } else { | 798 } else { |
| 710 ASSERT(!info->code().is_null()); | 799 InstallCodeCommon(info); |
| 711 Handle<Code> code = info->code(); | |
| 712 // Set optimizable to false if this is disallowed by the shared | |
| 713 // function info, e.g., we might have flushed the code and must | |
| 714 // reset this bit when lazy compiling the code again. | |
| 715 if (shared->optimization_disabled()) code->set_optimizable(false); | |
| 716 | |
| 717 Handle<JSFunction> function = info->closure(); | |
| 718 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); | |
| 719 | 800 |
| 720 if (info->IsOptimizing()) { | 801 if (info->IsOptimizing()) { |
| 802 Handle<Code> code = info->code(); | |
| 721 ASSERT(shared->scope_info() != ScopeInfo::Empty()); | 803 ASSERT(shared->scope_info() != ScopeInfo::Empty()); |
| 722 function->ReplaceCode(*code); | 804 info->closure()->ReplaceCode(*code); |
| 723 if (FLAG_cache_optimized_code && | 805 InsertCodeIntoOptimizedCodeMap(info); |
| 724 code->kind() == Code::OPTIMIZED_FUNCTION) { | 806 return true; |
| 725 Handle<SharedFunctionInfo> shared(function->shared()); | |
| 726 Handle<FixedArray> literals(function->literals()); | |
| 727 Handle<Context> global_context(function->context()->global_context()); | |
| 728 SharedFunctionInfo::AddToOptimizedCodeMap( | |
| 729 shared, global_context, code, literals); | |
| 730 } | |
| 731 } else { | 807 } else { |
| 732 // Update the shared function info with the compiled code and the | 808 return InstallFullCode(info); |
| 733 // scope info. Please note, that the order of the shared function | |
| 734 // info initialization is important since set_scope_info might | |
| 735 // trigger a GC, causing the ASSERT below to be invalid if the code | |
| 736 // was flushed. By setting the code object last we avoid this. | |
| 737 Handle<ScopeInfo> scope_info = | |
| 738 ScopeInfo::Create(info->scope(), info->zone()); | |
| 739 shared->set_scope_info(*scope_info); | |
| 740 shared->set_code(*code); | |
| 741 if (!function.is_null()) { | |
| 742 function->ReplaceCode(*code); | |
| 743 ASSERT(!function->IsOptimized()); | |
| 744 } | |
| 745 | |
| 746 // Set the expected number of properties for instances. | |
| 747 FunctionLiteral* lit = info->function(); | |
| 748 int expected = lit->expected_property_count(); | |
| 749 SetExpectedNofPropertiesFromEstimate(shared, expected); | |
| 750 | |
| 751 // Set the optimization hints after performing lazy compilation, as | |
| 752 // these are not set when the function is set up as a lazily | |
| 753 // compiled function. | |
| 754 shared->SetThisPropertyAssignmentsInfo( | |
| 755 lit->has_only_simple_this_property_assignments(), | |
| 756 *lit->this_property_assignments()); | |
| 757 | |
| 758 // Check the function has compiled code. | |
| 759 ASSERT(shared->is_compiled()); | |
| 760 shared->set_code_age(0); | |
| 761 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize)); | |
| 762 shared->set_dont_inline(lit->flags()->Contains(kDontInline)); | |
| 763 shared->set_dont_cache(lit->flags()->Contains(kDontCache)); | |
| 764 shared->set_ast_node_count(lit->ast_node_count()); | |
| 765 | |
| 766 if (V8::UseCrankshaft()&& | |
| 767 !function.is_null() && | |
| 768 !shared->optimization_disabled()) { | |
| 769 // If we're asked to always optimize, we compile the optimized | |
| 770 // version of the function right away - unless the debugger is | |
| 771 // active as it makes no sense to compile optimized code then. | |
| 772 if (FLAG_always_opt && | |
| 773 !Isolate::Current()->DebuggerHasBreakPoints()) { | |
| 774 CompilationInfoWithZone optimized(function); | |
| 775 optimized.SetOptimizing(AstNode::kNoNumber); | |
| 776 return CompileLazy(&optimized); | |
| 777 } | |
| 778 } | |
| 779 } | 809 } |
| 780 | |
| 781 return true; | |
| 782 } | 810 } |
| 783 } | 811 } |
| 784 | 812 |
| 785 ASSERT(info->code().is_null()); | 813 ASSERT(info->code().is_null()); |
| 786 return false; | 814 return false; |
| 787 } | 815 } |
| 788 | 816 |
| 789 | 817 |
| 818 void Compiler::RecompileParallel(Handle<JSFunction> closure) { | |
| 819 ASSERT(!closure->IsInRecompileQueue()); | |
| 820 | |
| 821 Isolate* isolate = closure->GetIsolate(); | |
| 822 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { | |
| 823 if (FLAG_trace_parallel_recompilation) { | |
| 824 PrintF(" ** Compilation queue, will retry opting on next run.\n"); | |
| 825 } | |
| 826 return; | |
| 827 } | |
| 828 | |
| 829 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure)); | |
| 830 VMState state(isolate, PARALLEL_COMPILER_PROLOGUE); | |
| 831 PostponeInterruptsScope postpone(isolate); | |
| 832 | |
| 833 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 834 int compiled_size = shared->end_position() - shared->start_position(); | |
| 835 isolate->counters()->total_compile_size()->Increment(compiled_size); | |
| 836 info->SetOptimizing(AstNode::kNoNumber); | |
| 837 | |
| 838 { | |
| 839 CompilationHandleScope handle_scope(*info); | |
| 840 | |
| 841 if (InstallCodeFromOptimizedCodeMap(*info)) return; | |
| 842 | |
| 843 if (ParserApi::Parse(*info, kNoParsingFlags)) { | |
| 844 LanguageMode language_mode = info->function()->language_mode(); | |
| 845 info->SetLanguageMode(language_mode); | |
| 846 shared->set_language_mode(language_mode); | |
| 847 info->SaveHandles(); | |
| 848 | |
| 849 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) { | |
| 850 OptimizingCompiler* compiler = | |
| 851 new(info->zone()) OptimizingCompiler(*info); | |
| 852 OptimizingCompiler::Status status = compiler->CreateGraph(); | |
| 853 if (status == OptimizingCompiler::SUCCEEDED) { | |
| 854 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler); | |
| 855 shared->code()->set_profiler_ticks(0); | |
| 856 closure->ReplaceCode(isolate->builtins()->builtin( | |
| 857 Builtins::kInRecompileQueue)); | |
| 858 info.Detach(); | |
| 859 } else if (status == OptimizingCompiler::BAILED_OUT) { | |
| 860 isolate->clear_pending_exception(); | |
| 861 InstallFullCode(*info); | |
| 862 } | |
| 863 } | |
| 864 } | |
| 865 } | |
| 866 | |
| 867 if (isolate->has_pending_exception()) { | |
| 868 isolate->clear_pending_exception(); | |
| 869 } | |
| 870 } | |
| 871 | |
| 872 | |
| 873 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) { | |
| 874 SmartPointer<CompilationInfo> info(optimizing_compiler->info()); | |
| 875 // If crankshaft succeeded, install the optimized code else install | |
|
Yang
2012/07/19 12:47:30
"If crankshaft succeeded, install the optimized co
sanjoy
2012/07/19 15:06:09
Done.
| |
| 876 // the full code. | |
| 877 OptimizingCompiler::Status status = optimizing_compiler->last_status(); | |
| 878 if (status == OptimizingCompiler::SUCCEEDED) { | |
| 879 status = optimizing_compiler->GenerateAndInstallCode(); | |
| 880 ASSERT(status == OptimizingCompiler::SUCCEEDED || | |
| 881 status == OptimizingCompiler::BAILED_OUT); | |
| 882 } | |
| 883 | |
| 884 InstallCodeCommon(*info); | |
| 885 if (status == OptimizingCompiler::SUCCEEDED) { | |
| 886 Handle<Code> code = info->code(); | |
| 887 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty()); | |
| 888 info->closure()->ReplaceCode(*code); | |
| 889 if (info->shared_info()->SearchOptimizedCodeMap( | |
| 890 info->closure()->context()->global_context()) == -1) { | |
| 891 InsertCodeIntoOptimizedCodeMap(*info); | |
| 892 } | |
| 893 } else { | |
| 894 info->SetCode(Handle<Code>(info->shared_info()->code())); | |
| 895 InstallFullCode(*info); | |
| 896 } | |
| 897 } | |
| 898 | |
| 899 | |
| 790 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 900 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 791 Handle<Script> script) { | 901 Handle<Script> script) { |
| 792 // Precondition: code has been parsed and scopes have been analyzed. | 902 // Precondition: code has been parsed and scopes have been analyzed. |
| 793 CompilationInfoWithZone info(script); | 903 CompilationInfoWithZone info(script); |
| 794 info.SetFunction(literal); | 904 info.SetFunction(literal); |
| 795 info.SetScope(literal->scope()); | 905 info.SetScope(literal->scope()); |
| 796 info.SetLanguageMode(literal->scope()->language_mode()); | 906 info.SetLanguageMode(literal->scope()->language_mode()); |
| 797 | 907 |
| 798 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal); | 908 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal); |
| 799 // Determine if the function can be lazily compiled. This is necessary to | 909 // Determine if the function can be lazily compiled. This is necessary to |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 911 } | 1021 } |
| 912 } | 1022 } |
| 913 | 1023 |
| 914 GDBJIT(AddCode(Handle<String>(shared->DebugName()), | 1024 GDBJIT(AddCode(Handle<String>(shared->DebugName()), |
| 915 Handle<Script>(info->script()), | 1025 Handle<Script>(info->script()), |
| 916 Handle<Code>(info->code()), | 1026 Handle<Code>(info->code()), |
| 917 info)); | 1027 info)); |
| 918 } | 1028 } |
| 919 | 1029 |
| 920 } } // namespace v8::internal | 1030 } } // namespace v8::internal |
| OLD | NEW |