Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: src/compiler.cc

Issue 10807024: Optimize functions on a second thread. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 // going, not necessarily that we optimized the code. 200 // going, not necessarily that we optimized the code.
201 static bool MakeCrankshaftCode(CompilationInfo* info) { 201 static bool MakeCrankshaftCode(CompilationInfo* info) {
202 OptimizingCompiler compiler(info); 202 OptimizingCompiler compiler(info);
203 OptimizingCompiler::Status status = compiler.CreateGraph(); 203 OptimizingCompiler::Status status = compiler.CreateGraph();
204 204
205 if (status != OptimizingCompiler::SUCCEEDED) { 205 if (status != OptimizingCompiler::SUCCEEDED) {
206 return status != OptimizingCompiler::FAILED; 206 return status != OptimizingCompiler::FAILED;
207 } 207 }
208 status = compiler.OptimizeGraph(); 208 status = compiler.OptimizeGraph();
209 if (status != OptimizingCompiler::SUCCEEDED) { 209 if (status != OptimizingCompiler::SUCCEEDED) {
210 status = compiler.AbortOptimization();
210 return status != OptimizingCompiler::FAILED; 211 return status != OptimizingCompiler::FAILED;
211 } 212 }
212 status = compiler.GenerateAndInstallCode(); 213 status = compiler.GenerateAndInstallCode();
213 return status != OptimizingCompiler::FAILED; 214 return status != OptimizingCompiler::FAILED;
214 } 215 }
215 216
216 217
217 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { 218 OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
218 ASSERT(V8::UseCrankshaft()); 219 ASSERT(V8::UseCrankshaft());
219 ASSERT(info()->IsOptimizing()); 220 ASSERT(info()->IsOptimizing());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 return SetLastStatus(BAILED_OUT); 334 return SetLastStatus(BAILED_OUT);
334 } else { 335 } else {
335 return AbortOptimization(); 336 return AbortOptimization();
336 } 337 }
337 } 338 }
338 339
339 return SetLastStatus(SUCCEEDED); 340 return SetLastStatus(SUCCEEDED);
340 } 341 }
341 342
342 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() { 343 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
344 AssertNoAllocation no_gc;
345 NoHandleAllocation no_handles;
346
343 ASSERT(last_status() == SUCCEEDED); 347 ASSERT(last_status() == SUCCEEDED);
344 Timer t(this, &time_taken_to_optimize_); 348 Timer t(this, &time_taken_to_optimize_);
345 ASSERT(graph_ != NULL); 349 ASSERT(graph_ != NULL);
346 SmartArrayPointer<char> bailout_reason; 350 SmartArrayPointer<char> bailout_reason;
347 if (!graph_->Optimize(&bailout_reason)) { 351 if (!graph_->Optimize(&bailout_reason)) {
348 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason); 352 if (!bailout_reason.is_empty()) graph_builder_->Bailout(*bailout_reason);
349 return AbortOptimization(); 353 return SetLastStatus(BAILED_OUT);
350 } else { 354 } else {
351 chunk_ = LChunk::NewChunk(graph_); 355 chunk_ = LChunk::NewChunk(graph_);
352 if (chunk_ == NULL) { 356 if (chunk_ == NULL) {
353 return AbortOptimization(); 357 return SetLastStatus(BAILED_OUT);
Yang 2012/07/19 16:37:17 Do we handle BAILED_OUT when running this in the p
354 } 358 }
355 } 359 }
356 return SetLastStatus(SUCCEEDED); 360 return SetLastStatus(SUCCEEDED);
357 } 361 }
358 362
359 363
360 OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() { 364 OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
361 ASSERT(last_status() == SUCCEEDED); 365 ASSERT(last_status() == SUCCEEDED);
362 Timer timer(this, &time_taken_to_codegen_); 366 Timer timer(this, &time_taken_to_codegen_);
363 ASSERT(chunk_ != NULL); 367 ASSERT(chunk_ != NULL);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 } else { 655 } else {
652 if (result->ic_age() != HEAP->global_ic_age()) { 656 if (result->ic_age() != HEAP->global_ic_age()) {
653 result->ResetForNewContext(HEAP->global_ic_age()); 657 result->ResetForNewContext(HEAP->global_ic_age());
654 } 658 }
655 } 659 }
656 660
657 return result; 661 return result;
658 } 662 }
659 663
660 664
661 bool Compiler::CompileLazy(CompilationInfo* info) { 665 static bool InstallFullCode(CompilationInfo* info) {
662 Isolate* isolate = info->isolate(); 666 // Update the shared function info with the compiled code and the
667 // scope info. Please note, that the order of the shared function
668 // info initialization is important since set_scope_info might
669 // trigger a GC, causing the ASSERT below to be invalid if the code
670 // was flushed. By setting the code object last we avoid this.
671 Handle<SharedFunctionInfo> shared = info->shared_info();
672 Handle<Code> code = info->code();
673 Handle<JSFunction> function = info->closure();
674 Handle<ScopeInfo> scope_info =
675 ScopeInfo::Create(info->scope(), info->zone());
676 shared->set_scope_info(*scope_info);
677 shared->set_code(*code);
678 if (!function.is_null()) {
679 function->ReplaceCode(*code);
680 ASSERT(!function->IsOptimized());
681 }
663 682
664 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT); 683 // Set the expected number of properties for instances.
684 FunctionLiteral* lit = info->function();
685 int expected = lit->expected_property_count();
686 SetExpectedNofPropertiesFromEstimate(shared, expected);
665 687
666 // The VM is in the COMPILER state until exiting this function. 688 // Set the optimization hints after performing lazy compilation, as
667 VMState state(isolate, COMPILER); 689 // these are not set when the function is set up as a lazily
690 // compiled function.
691 shared->SetThisPropertyAssignmentsInfo(
692 lit->has_only_simple_this_property_assignments(),
693 *lit->this_property_assignments());
668 694
669 PostponeInterruptsScope postpone(isolate); 695 // Check the function has compiled code.
696 ASSERT(shared->is_compiled());
697 shared->set_code_age(0);
698 shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
699 shared->set_dont_inline(lit->flags()->Contains(kDontInline));
700 shared->set_ast_node_count(lit->ast_node_count());
670 701
702 if (V8::UseCrankshaft()&&
703 !function.is_null() &&
704 !shared->optimization_disabled()) {
705 // If we're asked to always optimize, we compile the optimized
706 // version of the function right away - unless the debugger is
707 // active as it makes no sense to compile optimized code then.
708 if (FLAG_always_opt &&
709 !Isolate::Current()->DebuggerHasBreakPoints()) {
710 CompilationInfoWithZone optimized(function);
711 optimized.SetOptimizing(AstNode::kNoNumber);
712 return Compiler::CompileLazy(&optimized);
713 }
714 }
715 return true;
716 }
717
718
719 static void InstallCodeCommon(CompilationInfo* info) {
671 Handle<SharedFunctionInfo> shared = info->shared_info(); 720 Handle<SharedFunctionInfo> shared = info->shared_info();
672 int compiled_size = shared->end_position() - shared->start_position(); 721 Handle<Code> code = info->code();
673 isolate->counters()->total_compile_size()->Increment(compiled_size); 722 ASSERT(!code.is_null());
674 723
724 // Set optimizable to false if this is disallowed by the shared
725 // function info, e.g., we might have flushed the code and must
726 // reset this bit when lazy compiling the code again.
727 if (shared->optimization_disabled()) code->set_optimizable(false);
728
729 Handle<JSFunction> function = info->closure();
730 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
731 }
732
733
734 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
735 Handle<Code> code = info->code();
736 Handle<JSFunction> function = info->closure();
737 if (FLAG_cache_optimized_code && code->kind() == Code::OPTIMIZED_FUNCTION) {
738 Handle<SharedFunctionInfo> shared(function->shared());
739 Handle<FixedArray> literals(function->literals());
740 Handle<Context> global_context(function->context()->global_context());
741 SharedFunctionInfo::AddToOptimizedCodeMap(
742 shared, global_context, code, literals);
743 }
744 }
745
746
747 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
675 if (FLAG_cache_optimized_code && info->IsOptimizing()) { 748 if (FLAG_cache_optimized_code && info->IsOptimizing()) {
749 Handle<SharedFunctionInfo> shared = info->shared_info();
676 Handle<JSFunction> function = info->closure(); 750 Handle<JSFunction> function = info->closure();
677 ASSERT(!function.is_null()); 751 ASSERT(!function.is_null());
678 Handle<Context> global_context(function->context()->global_context()); 752 Handle<Context> global_context(function->context()->global_context());
679 int index = shared->SearchOptimizedCodeMap(*global_context); 753 int index = shared->SearchOptimizedCodeMap(*global_context);
680 if (index > 0) { 754 if (index > 0) {
681 if (FLAG_trace_opt) { 755 if (FLAG_trace_opt) {
682 PrintF("[found optimized code for: "); 756 PrintF("[found optimized code for: ");
683 function->PrintName(); 757 function->PrintName();
684 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function)); 758 PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(*function));
685 } 759 }
686 // Caching of optimized code enabled and optimized code found. 760 // Caching of optimized code enabled and optimized code found.
687 shared->InstallFromOptimizedCodeMap(*function, index); 761 shared->InstallFromOptimizedCodeMap(*function, index);
688 return true; 762 return true;
689 } 763 }
690 } 764 }
765 return false;
766 }
767
768
769 bool Compiler::CompileLazy(CompilationInfo* info) {
770 Isolate* isolate = info->isolate();
771
772 ZoneScope zone_scope(info->zone(), DELETE_ON_EXIT);
773
774 // The VM is in the COMPILER state until exiting this function.
775 VMState state(isolate, COMPILER);
776
777 PostponeInterruptsScope postpone(isolate);
778
779 Handle<SharedFunctionInfo> shared = info->shared_info();
780 int compiled_size = shared->end_position() - shared->start_position();
781 isolate->counters()->total_compile_size()->Increment(compiled_size);
782
783 if (InstallCodeFromOptimizedCodeMap(info)) return true;
691 784
692 // Generate the AST for the lazily compiled function. 785 // Generate the AST for the lazily compiled function.
693 if (ParserApi::Parse(info, kNoParsingFlags)) { 786 if (ParserApi::Parse(info, kNoParsingFlags)) {
694 // Measure how long it takes to do the lazy compilation; only take the 787 // 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 788 // rest of the function into account to avoid overlap with the lazy
696 // parsing statistics. 789 // parsing statistics.
697 HistogramTimerScope timer(isolate->counters()->compile_lazy()); 790 HistogramTimerScope timer(isolate->counters()->compile_lazy());
698 791
699 // After parsing we know the function's language mode. Remember it. 792 // After parsing we know the function's language mode. Remember it.
700 LanguageMode language_mode = info->function()->language_mode(); 793 LanguageMode language_mode = info->function()->language_mode();
701 info->SetLanguageMode(language_mode); 794 info->SetLanguageMode(language_mode);
702 shared->set_language_mode(language_mode); 795 shared->set_language_mode(language_mode);
703 796
704 // Compile the code. 797 // Compile the code.
705 if (!MakeCode(info)) { 798 if (!MakeCode(info)) {
706 if (!isolate->has_pending_exception()) { 799 if (!isolate->has_pending_exception()) {
707 isolate->StackOverflow(); 800 isolate->StackOverflow();
708 } 801 }
709 } else { 802 } else {
710 ASSERT(!info->code().is_null()); 803 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 804
720 if (info->IsOptimizing()) { 805 if (info->IsOptimizing()) {
806 Handle<Code> code = info->code();
721 ASSERT(shared->scope_info() != ScopeInfo::Empty()); 807 ASSERT(shared->scope_info() != ScopeInfo::Empty());
722 function->ReplaceCode(*code); 808 info->closure()->ReplaceCode(*code);
723 if (FLAG_cache_optimized_code && 809 InsertCodeIntoOptimizedCodeMap(info);
724 code->kind() == Code::OPTIMIZED_FUNCTION) { 810 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 { 811 } else {
732 // Update the shared function info with the compiled code and the 812 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 } 813 }
780
781 return true;
782 } 814 }
783 } 815 }
784 816
785 ASSERT(info->code().is_null()); 817 ASSERT(info->code().is_null());
786 return false; 818 return false;
787 } 819 }
788 820
789 821
822 void Compiler::RecompileParallel(Handle<JSFunction> closure) {
823 CHECK(closure->IsMarkedForParallelRecompilation());
824 if (closure->IsInRecompileQueue()) return;
825
826 Isolate* isolate = closure->GetIsolate();
827 if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) {
828 if (FLAG_trace_parallel_recompilation) {
829 PrintF(" ** Compilation queue, will retry opting on next run.\n");
830 }
831 return;
832 }
833
834 SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(closure));
835 VMState state(isolate, PARALLEL_COMPILER_PROLOGUE);
836 PostponeInterruptsScope postpone(isolate);
837
838 Handle<SharedFunctionInfo> shared = info->shared_info();
839 int compiled_size = shared->end_position() - shared->start_position();
840 isolate->counters()->total_compile_size()->Increment(compiled_size);
841 info->SetOptimizing(AstNode::kNoNumber);
842
843 {
844 CompilationHandleScope handle_scope(*info);
845
846 if (InstallCodeFromOptimizedCodeMap(*info)) return;
847
848 if (ParserApi::Parse(*info, kNoParsingFlags)) {
849 LanguageMode language_mode = info->function()->language_mode();
850 info->SetLanguageMode(language_mode);
851 shared->set_language_mode(language_mode);
852 info->SaveHandles();
853
854 if (Rewriter::Rewrite(*info) && Scope::Analyze(*info)) {
855 OptimizingCompiler* compiler =
856 new(info->zone()) OptimizingCompiler(*info);
857 OptimizingCompiler::Status status = compiler->CreateGraph();
858 if (status == OptimizingCompiler::SUCCEEDED) {
859 isolate->optimizing_compiler_thread()->QueueForOptimization(compiler);
860 shared->code()->set_profiler_ticks(0);
861 closure->ReplaceCode(isolate->builtins()->builtin(
862 Builtins::kInRecompileQueue));
863 info.Detach();
864 } else if (status == OptimizingCompiler::BAILED_OUT) {
865 isolate->clear_pending_exception();
866 InstallFullCode(*info);
867 }
868 }
869 }
870 }
871
872 if (isolate->has_pending_exception()) {
873 isolate->clear_pending_exception();
874 }
875 }
876
877
878 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
879 SmartPointer<CompilationInfo> info(optimizing_compiler->info());
880 // If crankshaft succeeded, install the optimized code else install
881 // the unoptimized code.
882 OptimizingCompiler::Status status = optimizing_compiler->last_status();
883 if (status != OptimizingCompiler::SUCCEEDED) {
884 status = optimizing_compiler->AbortOptimization();
885 } else {
886 status = optimizing_compiler->GenerateAndInstallCode();
887 ASSERT(status == OptimizingCompiler::SUCCEEDED ||
888 status == OptimizingCompiler::BAILED_OUT);
889 }
890
891 InstallCodeCommon(*info);
892 if (status == OptimizingCompiler::SUCCEEDED) {
893 Handle<Code> code = info->code();
894 ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty());
895 info->closure()->ReplaceCode(*code);
896 if (info->shared_info()->SearchOptimizedCodeMap(
897 info->closure()->context()->global_context()) == -1) {
898 InsertCodeIntoOptimizedCodeMap(*info);
899 }
900 } else {
901 info->SetCode(Handle<Code>(info->shared_info()->code()));
902 InstallFullCode(*info);
903 }
904 }
905
906
790 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, 907 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
791 Handle<Script> script) { 908 Handle<Script> script) {
792 // Precondition: code has been parsed and scopes have been analyzed. 909 // Precondition: code has been parsed and scopes have been analyzed.
793 CompilationInfoWithZone info(script); 910 CompilationInfoWithZone info(script);
794 info.SetFunction(literal); 911 info.SetFunction(literal);
795 info.SetScope(literal->scope()); 912 info.SetScope(literal->scope());
796 info.SetLanguageMode(literal->scope()->language_mode()); 913 info.SetLanguageMode(literal->scope()->language_mode());
797 914
798 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal); 915 LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
799 // Determine if the function can be lazily compiled. This is necessary to 916 // Determine if the function can be lazily compiled. This is necessary to
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 } 1028 }
912 } 1029 }
913 1030
914 GDBJIT(AddCode(Handle<String>(shared->DebugName()), 1031 GDBJIT(AddCode(Handle<String>(shared->DebugName()),
915 Handle<Script>(info->script()), 1032 Handle<Script>(info->script()),
916 Handle<Code>(info->code()), 1033 Handle<Code>(info->code()),
917 info)); 1034 info));
918 } 1035 }
919 1036
920 } } // namespace v8::internal 1037 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/d8.h » ('j') | src/optimizing-compiler-thread.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698