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

Side by Side Diff: src/compiler.cc

Issue 1809403002: [compiler] Readability refactor of comilation pipeline. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 DisableFutureOptimization(); 94 DisableFutureOptimization();
95 dependencies()->Rollback(); 95 dependencies()->Rollback();
96 delete parse_info_; 96 delete parse_info_;
97 parse_info_ = nullptr; 97 parse_info_ = nullptr;
98 } 98 }
99 99
100 private: 100 private:
101 Zone zone_; 101 Zone zone_;
102 }; 102 };
103 103
104 // ----------------------------------------------------------------------------
105 // Implementation of CompilationInfo
104 106
105 bool CompilationInfo::has_shared_info() const { 107 bool CompilationInfo::has_shared_info() const {
106 return parse_info_ && !parse_info_->shared_info().is_null(); 108 return parse_info_ && !parse_info_->shared_info().is_null();
107 } 109 }
108 110
109 111
110 bool CompilationInfo::has_context() const { 112 bool CompilationInfo::has_context() const {
111 return parse_info_ && !parse_info_->context().is_null(); 113 return parse_info_ && !parse_info_->context().is_null();
112 } 114 }
113 115
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 default: 324 default:
323 UNIMPLEMENTED(); 325 UNIMPLEMENTED();
324 return StackFrame::NONE; 326 return StackFrame::NONE;
325 } 327 }
326 } 328 }
327 329
328 bool CompilationInfo::ExpectsJSReceiverAsReceiver() { 330 bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
329 return is_sloppy(language_mode()) && !is_native(); 331 return is_sloppy(language_mode()) && !is_native();
330 } 332 }
331 333
334 #if DEBUG
335 void CompilationInfo::PrintAstForTesting() {
336 PrintF("--- Source from AST ---\n%s\n",
337 PrettyPrinter(isolate()).PrintProgram(literal()));
338 }
339 #endif
340
341 // ----------------------------------------------------------------------------
342 // Implementation of OptimizedCompileJob
332 343
333 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { 344 class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
334 public: 345 public:
335 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) 346 explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
336 : HOptimizedGraphBuilder(info) { 347 : HOptimizedGraphBuilder(info) {
337 } 348 }
338 349
339 #define DEF_VISIT(type) \ 350 #define DEF_VISIT(type) \
340 void Visit##type(type* node) override { \ 351 void Visit##type(type* node) override { \
341 SourcePosition old_position = SourcePosition::Unknown(); \ 352 SourcePosition old_position = SourcePosition::Unknown(); \
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 code_size, 717 code_size,
707 compilation_time); 718 compilation_time);
708 } 719 }
709 if (FLAG_hydrogen_stats) { 720 if (FLAG_hydrogen_stats) {
710 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, 721 isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
711 time_taken_to_optimize_, 722 time_taken_to_optimize_,
712 time_taken_to_codegen_); 723 time_taken_to_codegen_);
713 } 724 }
714 } 725 }
715 726
727 // ----------------------------------------------------------------------------
728 // Local helper methods that make up the compilation pipeline.
729
730 namespace {
716 731
717 // Sets the expected number of properties based on estimate from compiler. 732 // Sets the expected number of properties based on estimate from compiler.
718 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, 733 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
719 int estimate) { 734 int estimate) {
720 // If no properties are added in the constructor, they are more likely 735 // If no properties are added in the constructor, they are more likely
721 // to be added later. 736 // to be added later.
722 if (estimate == 0) estimate = 2; 737 if (estimate == 0) estimate = 2;
723 738
724 // TODO(yangguo): check whether those heuristics are still up-to-date. 739 // TODO(yangguo): check whether those heuristics are still up-to-date.
725 // We do not shrink objects that go into a snapshot (yet), so we adjust 740 // We do not shrink objects that go into a snapshot (yet), so we adjust
726 // the estimate conservatively. 741 // the estimate conservatively.
727 if (shared->GetIsolate()->serializer_enabled()) { 742 if (shared->GetIsolate()->serializer_enabled()) {
728 estimate += 2; 743 estimate += 2;
729 } else { 744 } else {
730 // Inobject slack tracking will reclaim redundant inobject space later, 745 // Inobject slack tracking will reclaim redundant inobject space later,
731 // so we can afford to adjust the estimate generously. 746 // so we can afford to adjust the estimate generously.
732 estimate += 8; 747 estimate += 8;
733 } 748 }
734 749
735 shared->set_expected_nof_properties(estimate); 750 shared->set_expected_nof_properties(estimate);
736 } 751 }
737 752
738 753 void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info,
739 static void MaybeDisableOptimization(Handle<SharedFunctionInfo> shared_info, 754 BailoutReason bailout_reason) {
740 BailoutReason bailout_reason) {
741 if (bailout_reason != kNoReason) { 755 if (bailout_reason != kNoReason) {
742 shared_info->DisableOptimization(bailout_reason); 756 shared_info->DisableOptimization(bailout_reason);
743 } 757 }
744 } 758 }
745 759
746 760 void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
747 static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, 761 CompilationInfo* info,
748 CompilationInfo* info, 762 Handle<SharedFunctionInfo> shared) {
749 Handle<SharedFunctionInfo> shared) {
750 // SharedFunctionInfo is passed separately, because if CompilationInfo 763 // SharedFunctionInfo is passed separately, because if CompilationInfo
751 // was created using Script object, it will not have it. 764 // was created using Script object, it will not have it.
752 765
753 // Log the code generation. If source information is available include 766 // Log the code generation. If source information is available include
754 // script name and line number. Check explicitly whether logging is 767 // script name and line number. Check explicitly whether logging is
755 // enabled as finding the line number is not free. 768 // enabled as finding the line number is not free.
756 if (info->isolate()->logger()->is_logging_code_events() || 769 if (info->isolate()->logger()->is_logging_code_events() ||
757 info->isolate()->cpu_profiler()->is_profiling()) { 770 info->isolate()->cpu_profiler()->is_profiling()) {
758 Handle<Script> script = info->parse_info()->script(); 771 Handle<Script> script = info->parse_info()->script();
759 Handle<AbstractCode> abstract_code = info->abstract_code(); 772 Handle<AbstractCode> abstract_code = info->abstract_code();
760 if (abstract_code.is_identical_to( 773 if (abstract_code.is_identical_to(
761 info->isolate()->builtins()->CompileLazy())) { 774 info->isolate()->builtins()->CompileLazy())) {
762 return; 775 return;
763 } 776 }
764 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1; 777 int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
765 int column_num = 778 int column_num =
766 Script::GetColumnNumber(script, shared->start_position()) + 1; 779 Script::GetColumnNumber(script, shared->start_position()) + 1;
767 String* script_name = script->name()->IsString() 780 String* script_name = script->name()->IsString()
768 ? String::cast(script->name()) 781 ? String::cast(script->name())
769 : info->isolate()->heap()->empty_string(); 782 : info->isolate()->heap()->empty_string();
770 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script); 783 Logger::LogEventsAndTags log_tag = Logger::ToNativeByScript(tag, *script);
771 PROFILE(info->isolate(), 784 PROFILE(info->isolate(),
772 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name, 785 CodeCreateEvent(log_tag, *abstract_code, *shared, info, script_name,
773 line_num, column_num)); 786 line_num, column_num));
774 } 787 }
775 } 788 }
776 789
777 static bool CompileUnoptimizedCode(CompilationInfo* info) { 790 bool CompileUnoptimizedCode(CompilationInfo* info) {
778 DCHECK(AllowCompilation::IsAllowed(info->isolate())); 791 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
779 if (!Compiler::Analyze(info->parse_info()) || 792 if (!Compiler::Analyze(info->parse_info()) ||
780 !FullCodeGenerator::MakeCode(info)) { 793 !FullCodeGenerator::MakeCode(info)) {
781 Isolate* isolate = info->isolate(); 794 Isolate* isolate = info->isolate();
782 if (!isolate->has_pending_exception()) isolate->StackOverflow(); 795 if (!isolate->has_pending_exception()) isolate->StackOverflow();
783 return false; 796 return false;
784 } 797 }
785 return true; 798 return true;
786 } 799 }
787 800
788 static bool UseIgnition(CompilationInfo* info) { 801 bool UseIgnition(CompilationInfo* info) {
789 // TODO(4681): Generator functions are not yet supported. 802 // TODO(4681): Generator functions are not yet supported.
790 if ((info->has_shared_info() && info->shared_info()->is_generator()) || 803 if ((info->has_shared_info() && info->shared_info()->is_generator()) ||
791 (info->has_literal() && IsGeneratorFunction(info->literal()->kind()))) { 804 (info->has_literal() && IsGeneratorFunction(info->literal()->kind()))) {
792 return false; 805 return false;
793 } 806 }
794 807
795 // TODO(4681): Resuming a suspended frame is not supported. 808 // TODO(4681): Resuming a suspended frame is not supported.
796 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId() && 809 if (info->has_shared_info() && info->shared_info()->HasBuiltinFunctionId() &&
797 (info->shared_info()->builtin_function_id() == kGeneratorObjectNext || 810 (info->shared_info()->builtin_function_id() == kGeneratorObjectNext ||
798 info->shared_info()->builtin_function_id() == kGeneratorObjectReturn || 811 info->shared_info()->builtin_function_id() == kGeneratorObjectReturn ||
799 info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) { 812 info->shared_info()->builtin_function_id() == kGeneratorObjectThrow)) {
800 return false; 813 return false;
801 } 814 }
802 815
803 // Checks whether top level functions should be passed by the filter. 816 // Checks whether top level functions should be passed by the filter.
804 if (info->closure().is_null()) { 817 if (info->closure().is_null()) {
805 Vector<const char> filter = CStrVector(FLAG_ignition_filter); 818 Vector<const char> filter = CStrVector(FLAG_ignition_filter);
806 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*'); 819 return (filter.length() == 0) || (filter.length() == 1 && filter[0] == '*');
807 } 820 }
808 821
809 // Finally respect the filter. 822 // Finally respect the filter.
810 return info->closure()->PassesFilter(FLAG_ignition_filter); 823 return info->closure()->PassesFilter(FLAG_ignition_filter);
811 } 824 }
812 825
813 static int CodeAndMetadataSize(CompilationInfo* info) { 826 int CodeAndMetadataSize(CompilationInfo* info) {
814 int size = 0; 827 int size = 0;
815 if (info->has_bytecode_array()) { 828 if (info->has_bytecode_array()) {
816 Handle<BytecodeArray> bytecode_array = info->bytecode_array(); 829 Handle<BytecodeArray> bytecode_array = info->bytecode_array();
817 size += bytecode_array->BytecodeArraySize(); 830 size += bytecode_array->BytecodeArraySize();
818 size += bytecode_array->constant_pool()->Size(); 831 size += bytecode_array->constant_pool()->Size();
819 size += bytecode_array->handler_table()->Size(); 832 size += bytecode_array->handler_table()->Size();
820 size += bytecode_array->source_position_table()->Size(); 833 size += bytecode_array->source_position_table()->Size();
821 } else { 834 } else {
822 Handle<Code> code = info->code(); 835 Handle<Code> code = info->code();
823 size += code->CodeSize(); 836 size += code->CodeSize();
824 size += code->relocation_info()->Size(); 837 size += code->relocation_info()->Size();
825 size += code->deoptimization_data()->Size(); 838 size += code->deoptimization_data()->Size();
826 size += code->handler_table()->Size(); 839 size += code->handler_table()->Size();
827 } 840 }
828 return size; 841 return size;
829 } 842 }
830 843
831 844 bool GenerateBaselineCode(CompilationInfo* info) {
832 static bool GenerateBaselineCode(CompilationInfo* info) {
833 bool success; 845 bool success;
834 if (FLAG_ignition && UseIgnition(info)) { 846 if (FLAG_ignition && UseIgnition(info)) {
835 success = interpreter::Interpreter::MakeBytecode(info); 847 success = interpreter::Interpreter::MakeBytecode(info);
836 } else { 848 } else {
837 success = FullCodeGenerator::MakeCode(info); 849 success = FullCodeGenerator::MakeCode(info);
838 } 850 }
839 if (success) { 851 if (success) {
840 Isolate* isolate = info->isolate(); 852 Isolate* isolate = info->isolate();
841 Counters* counters = isolate->counters(); 853 Counters* counters = isolate->counters();
842 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info)); 854 counters->total_baseline_code_size()->Increment(CodeAndMetadataSize(info));
843 counters->total_baseline_compile_count()->Increment(1); 855 counters->total_baseline_compile_count()->Increment(1);
844 } 856 }
845 return success; 857 return success;
846 } 858 }
847 859
848 860 bool CompileBaselineCode(CompilationInfo* info) {
849 static bool CompileBaselineCode(CompilationInfo* info) {
850 DCHECK(AllowCompilation::IsAllowed(info->isolate())); 861 DCHECK(AllowCompilation::IsAllowed(info->isolate()));
851 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) { 862 if (!Compiler::Analyze(info->parse_info()) || !GenerateBaselineCode(info)) {
852 Isolate* isolate = info->isolate(); 863 Isolate* isolate = info->isolate();
853 if (!isolate->has_pending_exception()) isolate->StackOverflow(); 864 if (!isolate->has_pending_exception()) isolate->StackOverflow();
854 return false; 865 return false;
855 } 866 }
856 return true; 867 return true;
857 } 868 }
858 869
859 static void InstallBaselineCompilationResult(CompilationInfo* info, 870 void InstallBaselineCompilationResult(CompilationInfo* info,
860 Handle<SharedFunctionInfo> shared, 871 Handle<SharedFunctionInfo> shared,
861 Handle<ScopeInfo> scope_info) { 872 Handle<ScopeInfo> scope_info) {
862 // Assert that we are not overwriting (possibly patched) debug code. 873 // Assert that we are not overwriting (possibly patched) debug code.
863 DCHECK(!shared->HasDebugCode()); 874 DCHECK(!shared->HasDebugCode());
864 DCHECK(!info->code().is_null()); 875 DCHECK(!info->code().is_null());
865 shared->ReplaceCode(*info->code()); 876 shared->ReplaceCode(*info->code());
866 shared->set_scope_info(*scope_info); 877 shared->set_scope_info(*scope_info);
867 shared->set_feedback_vector(*info->feedback_vector()); 878 shared->set_feedback_vector(*info->feedback_vector());
868 if (info->has_bytecode_array()) { 879 if (info->has_bytecode_array()) {
869 DCHECK(!shared->HasBytecodeArray()); // Only compiled once. 880 DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
870 shared->set_bytecode_array(*info->bytecode_array()); 881 shared->set_bytecode_array(*info->bytecode_array());
871 } 882 }
872 } 883 }
873 884
874 MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( 885 MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCodeCommon(
875 CompilationInfo* info) { 886 CompilationInfo* info) {
876 VMState<COMPILER> state(info->isolate()); 887 VMState<COMPILER> state(info->isolate());
877 PostponeInterruptsScope postpone(info->isolate()); 888 PostponeInterruptsScope postpone(info->isolate());
878 889
879 // Parse and update CompilationInfo with the results. 890 // Parse and update CompilationInfo with the results.
880 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>(); 891 if (!Parser::ParseStatic(info->parse_info())) return MaybeHandle<Code>();
881 Handle<SharedFunctionInfo> shared = info->shared_info(); 892 Handle<SharedFunctionInfo> shared = info->shared_info();
882 FunctionLiteral* lit = info->literal(); 893 FunctionLiteral* lit = info->literal();
883 DCHECK_EQ(shared->language_mode(), lit->language_mode()); 894 DCHECK_EQ(shared->language_mode(), lit->language_mode());
884 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); 895 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
885 MaybeDisableOptimization(shared, lit->dont_optimize_reason()); 896 MaybeDisableOptimization(shared, lit->dont_optimize_reason());
886 897
887 // Compile either unoptimized code or bytecode for the interpreter. 898 // Compile either unoptimized code or bytecode for the interpreter.
888 if (!CompileBaselineCode(info)) return MaybeHandle<Code>(); 899 if (!CompileBaselineCode(info)) return MaybeHandle<Code>();
889 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared); 900 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
890 901
891 // Update the shared function info with the scope info. Allocating the 902 // Update the shared function info with the scope info. Allocating the
892 // ScopeInfo object may cause a GC. 903 // ScopeInfo object may cause a GC.
893 Handle<ScopeInfo> scope_info = 904 Handle<ScopeInfo> scope_info =
894 ScopeInfo::Create(info->isolate(), info->zone(), info->scope()); 905 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
895 906
896 // Install compilation result on the shared function info 907 // Install compilation result on the shared function info
897 InstallBaselineCompilationResult(info, shared, scope_info); 908 InstallBaselineCompilationResult(info, shared, scope_info);
898 909
899 return info->code(); 910 return info->code();
900 } 911 }
901 912
902 913 MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
903 MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
904 Handle<JSFunction> function, BailoutId osr_ast_id) { 914 Handle<JSFunction> function, BailoutId osr_ast_id) {
905 Handle<SharedFunctionInfo> shared(function->shared()); 915 Handle<SharedFunctionInfo> shared(function->shared());
906 DisallowHeapAllocation no_gc; 916 DisallowHeapAllocation no_gc;
907 CodeAndLiterals cached = shared->SearchOptimizedCodeMap( 917 CodeAndLiterals cached = shared->SearchOptimizedCodeMap(
908 function->context()->native_context(), osr_ast_id); 918 function->context()->native_context(), osr_ast_id);
909 if (cached.code != nullptr) { 919 if (cached.code != nullptr) {
910 // Caching of optimized code enabled and optimized code found. 920 // Caching of optimized code enabled and optimized code found.
911 if (cached.literals != nullptr) function->set_literals(cached.literals); 921 if (cached.literals != nullptr) function->set_literals(cached.literals);
912 DCHECK(!cached.code->marked_for_deoptimization()); 922 DCHECK(!cached.code->marked_for_deoptimization());
913 DCHECK(function->shared()->is_compiled()); 923 DCHECK(function->shared()->is_compiled());
914 return Handle<Code>(cached.code); 924 return Handle<Code>(cached.code);
915 } 925 }
916 return MaybeHandle<Code>(); 926 return MaybeHandle<Code>();
917 } 927 }
918 928
919 929 void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
920 static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
921 Handle<Code> code = info->code(); 930 Handle<Code> code = info->code();
922 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do. 931 if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
923 932
924 // Function context specialization folds-in the function context, 933 // Function context specialization folds-in the function context,
925 // so no sharing can occur. 934 // so no sharing can occur.
926 if (info->is_function_context_specializing()) return; 935 if (info->is_function_context_specializing()) return;
927 // Frame specialization implies function context specialization. 936 // Frame specialization implies function context specialization.
928 DCHECK(!info->is_frame_specializing()); 937 DCHECK(!info->is_frame_specializing());
929 938
930 // Cache optimized context-specific code. 939 // Cache optimized context-specific code.
(...skipping 10 matching lines...) Expand all
941 // Cache optimized (native) context-independent code. 950 // Cache optimized (native) context-independent code.
942 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() && 951 if (FLAG_turbo_cache_shared_code && code->is_turbofanned() &&
943 !info->is_native_context_specializing()) { 952 !info->is_native_context_specializing()) {
944 DCHECK(!info->is_function_context_specializing()); 953 DCHECK(!info->is_function_context_specializing());
945 DCHECK(info->osr_ast_id().IsNone()); 954 DCHECK(info->osr_ast_id().IsNone());
946 Handle<SharedFunctionInfo> shared(function->shared()); 955 Handle<SharedFunctionInfo> shared(function->shared());
947 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code); 956 SharedFunctionInfo::AddSharedCodeToOptimizedCodeMap(shared, code);
948 } 957 }
949 } 958 }
950 959
951 960 bool Renumber(ParseInfo* parse_info) {
952 static bool Renumber(ParseInfo* parse_info) {
953 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(), 961 if (!AstNumbering::Renumber(parse_info->isolate(), parse_info->zone(),
954 parse_info->literal())) { 962 parse_info->literal())) {
955 return false; 963 return false;
956 } 964 }
957 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info(); 965 Handle<SharedFunctionInfo> shared_info = parse_info->shared_info();
958 if (!shared_info.is_null()) { 966 if (!shared_info.is_null()) {
959 FunctionLiteral* lit = parse_info->literal(); 967 FunctionLiteral* lit = parse_info->literal();
960 shared_info->set_ast_node_count(lit->ast_node_count()); 968 shared_info->set_ast_node_count(lit->ast_node_count());
961 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason()); 969 MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
962 shared_info->set_dont_crankshaft( 970 shared_info->set_dont_crankshaft(
963 shared_info->dont_crankshaft() || 971 shared_info->dont_crankshaft() ||
964 (lit->flags() & AstProperties::kDontCrankshaft)); 972 (lit->flags() & AstProperties::kDontCrankshaft));
965 } 973 }
966 return true; 974 return true;
967 } 975 }
968 976
969
970 bool Compiler::Analyze(ParseInfo* info) {
971 DCHECK_NOT_NULL(info->literal());
972 if (!Rewriter::Rewrite(info)) return false;
973 if (!Scope::Analyze(info)) return false;
974 if (!Renumber(info)) return false;
975 DCHECK_NOT_NULL(info->scope());
976 return true;
977 }
978
979
980 bool Compiler::ParseAndAnalyze(ParseInfo* info) {
981 if (!Parser::ParseStatic(info)) return false;
982 return Compiler::Analyze(info);
983 }
984
985 namespace {
986
987 bool GetOptimizedCodeNow(CompilationInfo* info) { 977 bool GetOptimizedCodeNow(CompilationInfo* info) {
988 Isolate* isolate = info->isolate(); 978 Isolate* isolate = info->isolate();
989 CanonicalHandleScope canonical(isolate); 979 CanonicalHandleScope canonical(isolate);
990 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); 980 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
991 TRACE_EVENT0("v8", "V8.OptimizeCode"); 981 TRACE_EVENT0("v8", "V8.OptimizeCode");
992 982
993 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; 983 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
994 984
995 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); 985 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
996 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); 986 TRACE_EVENT0("v8", "V8.RecompileSynchronous");
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 Handle<Code> opt_code; 1165 Handle<Code> opt_code;
1176 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT) 1166 if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
1177 .ToHandle(&opt_code)) { 1167 .ToHandle(&opt_code)) {
1178 result = opt_code; 1168 result = opt_code;
1179 } 1169 }
1180 } 1170 }
1181 1171
1182 return result; 1172 return result;
1183 } 1173 }
1184 1174
1185 } // namespace
1186
1187 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1188 if (function->is_compiled()) return true;
1189 MaybeHandle<Code> maybe_code = GetLazyCode(function);
1190 Handle<Code> code;
1191 if (!maybe_code.ToHandle(&code)) {
1192 if (flag == CLEAR_EXCEPTION) {
1193 function->GetIsolate()->clear_pending_exception();
1194 }
1195 return false;
1196 }
1197 DCHECK(code->IsJavaScriptCode());
1198 function->ReplaceCode(*code);
1199 DCHECK(function->is_compiled());
1200 return true;
1201 }
1202
1203 bool Compiler::CompileOptimized(Handle<JSFunction> function,
1204 ConcurrencyMode mode) {
1205 Handle<Code> code;
1206 if (GetOptimizedCode(function, mode).ToHandle(&code)) {
1207 // Optimization succeeded, return optimized code.
1208 function->ReplaceCode(*code);
1209 } else {
1210 // Optimization failed, get unoptimized code.
1211 Isolate* isolate = function->GetIsolate();
1212 if (isolate->has_pending_exception()) { // Possible stack overflow.
1213 return false;
1214 }
1215 code = Handle<Code>(function->shared()->code(), isolate);
1216 if (code->kind() != Code::FUNCTION &&
1217 code->kind() != Code::OPTIMIZED_FUNCTION) {
1218 if (!GetUnoptimizedCode(function).ToHandle(&code)) {
1219 return false;
1220 }
1221 }
1222 function->ReplaceCode(*code);
1223 }
1224
1225 DCHECK(function->code()->kind() == Code::FUNCTION ||
1226 function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
1227 (function->code()->is_interpreter_entry_trampoline() &&
1228 function->shared()->HasBytecodeArray()) ||
1229 function->IsInOptimizationQueue());
1230 return true;
1231 }
1232
1233 // TODO(turbofan): In the future, unoptimized code with deopt support could
1234 // be generated lazily once deopt is triggered.
1235 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1236 DCHECK_NOT_NULL(info->literal());
1237 DCHECK(info->has_scope());
1238 Handle<SharedFunctionInfo> shared = info->shared_info();
1239 if (!shared->has_deoptimization_support()) {
1240 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
1241 CompilationInfoWithZone unoptimized(info->closure());
1242 // Note that we use the same AST that we will use for generating the
1243 // optimized code.
1244 ParseInfo* parse_info = unoptimized.parse_info();
1245 parse_info->set_literal(info->literal());
1246 parse_info->set_scope(info->scope());
1247 parse_info->set_context(info->context());
1248 unoptimized.EnableDeoptimizationSupport();
1249 // If the current code has reloc info for serialization, also include
1250 // reloc info for serialization for the new code, so that deopt support
1251 // can be added without losing IC state.
1252 if (shared->code()->kind() == Code::FUNCTION &&
1253 shared->code()->has_reloc_info_for_serialization()) {
1254 unoptimized.PrepareForSerializing();
1255 }
1256 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1257
1258 shared->EnableDeoptimizationSupport(*unoptimized.code());
1259 shared->set_feedback_vector(*unoptimized.feedback_vector());
1260
1261 info->MarkAsCompiled();
1262
1263 // The scope info might not have been set if a lazily compiled
1264 // function is inlined before being called for the first time.
1265 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1266 Handle<ScopeInfo> target_scope_info =
1267 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
1268 shared->set_scope_info(*target_scope_info);
1269 }
1270
1271 // The existing unoptimized code was replaced with the new one.
1272 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1273 }
1274 return true;
1275 }
1276
1277 1175
1278 bool CompileEvalForDebugging(Handle<JSFunction> function, 1176 bool CompileEvalForDebugging(Handle<JSFunction> function,
1279 Handle<SharedFunctionInfo> shared) { 1177 Handle<SharedFunctionInfo> shared) {
1280 Handle<Script> script(Script::cast(shared->script())); 1178 Handle<Script> script(Script::cast(shared->script()));
1281 Handle<Context> context(function->context()); 1179 Handle<Context> context(function->context());
1282 1180
1283 Zone zone; 1181 Zone zone;
1284 ParseInfo parse_info(&zone, script); 1182 ParseInfo parse_info(&zone, script);
1285 CompilationInfo info(&parse_info); 1183 CompilationInfo info(&parse_info);
1286 Isolate* isolate = info.isolate(); 1184 Isolate* isolate = info.isolate();
(...skipping 28 matching lines...) Expand all
1315 1213
1316 bool CompileForDebugging(CompilationInfo* info) { 1214 bool CompileForDebugging(CompilationInfo* info) {
1317 info->MarkAsDebug(); 1215 info->MarkAsDebug();
1318 if (GetUnoptimizedCodeCommon(info).is_null()) { 1216 if (GetUnoptimizedCodeCommon(info).is_null()) {
1319 info->isolate()->clear_pending_exception(); 1217 info->isolate()->clear_pending_exception();
1320 return false; 1218 return false;
1321 } 1219 }
1322 return true; 1220 return true;
1323 } 1221 }
1324 1222
1325 1223 inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
1326 static inline bool IsEvalToplevel(Handle<SharedFunctionInfo> shared) {
1327 return shared->is_toplevel() && shared->script()->IsScript() && 1224 return shared->is_toplevel() && shared->script()->IsScript() &&
1328 Script::cast(shared->script())->compilation_type() == 1225 Script::cast(shared->script())->compilation_type() ==
1329 Script::COMPILATION_TYPE_EVAL; 1226 Script::COMPILATION_TYPE_EVAL;
1330 } 1227 }
1331 1228
1332 1229 Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
1333 bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
1334 Handle<SharedFunctionInfo> shared(function->shared());
1335 if (IsEvalToplevel(shared)) {
1336 return CompileEvalForDebugging(function, shared);
1337 } else {
1338 CompilationInfoWithZone info(function);
1339 return CompileForDebugging(&info);
1340 }
1341 }
1342
1343
1344 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1345 DCHECK(shared->allows_lazy_compilation_without_context());
1346 DCHECK(!IsEvalToplevel(shared));
1347 Zone zone;
1348 ParseInfo parse_info(&zone, shared);
1349 CompilationInfo info(&parse_info);
1350 return CompileForDebugging(&info);
1351 }
1352
1353
1354 void Compiler::CompileForLiveEdit(Handle<Script> script) {
1355 // TODO(635): support extensions.
1356 Zone zone;
1357 ParseInfo parse_info(&zone, script);
1358 CompilationInfo info(&parse_info);
1359 PostponeInterruptsScope postpone(info.isolate());
1360 VMState<COMPILER> state(info.isolate());
1361
1362 // Get rid of old list of shared function infos.
1363 info.MarkAsFirstCompile();
1364 info.MarkAsDebug();
1365 info.parse_info()->set_global();
1366 if (!Parser::ParseStatic(info.parse_info())) return;
1367
1368 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
1369 if (!CompileUnoptimizedCode(&info)) return;
1370 if (info.has_shared_info()) {
1371 Handle<ScopeInfo> scope_info =
1372 ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
1373 info.shared_info()->set_scope_info(*scope_info);
1374 }
1375 tracker.RecordRootFunctionInfo(info.code());
1376 }
1377
1378 static Handle<SharedFunctionInfo> NewSharedFunctionInfoForLiteral(
1379 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) { 1230 Isolate* isolate, FunctionLiteral* literal, Handle<Script> script) {
1380 Handle<Code> code = isolate->builtins()->CompileLazy(); 1231 Handle<Code> code = isolate->builtins()->CompileLazy();
1381 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate)); 1232 Handle<ScopeInfo> scope_info = handle(ScopeInfo::Empty(isolate));
1382 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo( 1233 Handle<SharedFunctionInfo> result = isolate->factory()->NewSharedFunctionInfo(
1383 literal->name(), literal->materialized_literal_count(), literal->kind(), 1234 literal->name(), literal->materialized_literal_count(), literal->kind(),
1384 code, scope_info); 1235 code, scope_info);
1385 SharedFunctionInfo::InitFromFunctionLiteral(result, literal); 1236 SharedFunctionInfo::InitFromFunctionLiteral(result, literal);
1386 SharedFunctionInfo::SetScript(result, script); 1237 SharedFunctionInfo::SetScript(result, script);
1387 return result; 1238 return result;
1388 } 1239 }
1389 1240
1390 static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { 1241 Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1391 Isolate* isolate = info->isolate(); 1242 Isolate* isolate = info->isolate();
1392 TimerEventScope<TimerEventCompileCode> timer(isolate); 1243 TimerEventScope<TimerEventCompileCode> timer(isolate);
1393 TRACE_EVENT0("v8", "V8.CompileCode"); 1244 TRACE_EVENT0("v8", "V8.CompileCode");
1394 PostponeInterruptsScope postpone(isolate); 1245 PostponeInterruptsScope postpone(isolate);
1395 DCHECK(!isolate->native_context().is_null()); 1246 DCHECK(!isolate->native_context().is_null());
1396 ParseInfo* parse_info = info->parse_info(); 1247 ParseInfo* parse_info = info->parse_info();
1397 Handle<Script> script = parse_info->script(); 1248 Handle<Script> script = parse_info->script();
1398 1249
1399 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile? 1250 // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
1400 FixedArray* array = isolate->native_context()->embedder_data(); 1251 FixedArray* array = isolate->native_context()->embedder_data();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1493 1344
1494 if (!script.is_null()) 1345 if (!script.is_null())
1495 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED); 1346 script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1496 1347
1497 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); 1348 live_edit_tracker.RecordFunctionInfo(result, lit, info->zone());
1498 } 1349 }
1499 1350
1500 return result; 1351 return result;
1501 } 1352 }
1502 1353
1354 } // namespace
1355
1356 // ----------------------------------------------------------------------------
1357 // Implementation of Compiler
1358
1359 bool Compiler::Analyze(ParseInfo* info) {
1360 DCHECK_NOT_NULL(info->literal());
1361 if (!Rewriter::Rewrite(info)) return false;
1362 if (!Scope::Analyze(info)) return false;
1363 if (!Renumber(info)) return false;
1364 DCHECK_NOT_NULL(info->scope());
1365 return true;
1366 }
1367
1368 bool Compiler::ParseAndAnalyze(ParseInfo* info) {
1369 if (!Parser::ParseStatic(info)) return false;
1370 return Compiler::Analyze(info);
1371 }
1372
1373 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1374 if (function->is_compiled()) return true;
1375 MaybeHandle<Code> maybe_code = GetLazyCode(function);
1376 Handle<Code> code;
1377 if (!maybe_code.ToHandle(&code)) {
1378 if (flag == CLEAR_EXCEPTION) {
1379 function->GetIsolate()->clear_pending_exception();
1380 }
1381 return false;
1382 }
1383 DCHECK(code->IsJavaScriptCode());
1384 function->ReplaceCode(*code);
1385 DCHECK(function->is_compiled());
1386 return true;
1387 }
1388
1389 bool Compiler::CompileOptimized(Handle<JSFunction> function,
1390 ConcurrencyMode mode) {
1391 Handle<Code> code;
1392 if (GetOptimizedCode(function, mode).ToHandle(&code)) {
1393 // Optimization succeeded, return optimized code.
1394 function->ReplaceCode(*code);
1395 } else {
1396 // Optimization failed, get unoptimized code.
1397 Isolate* isolate = function->GetIsolate();
1398 if (isolate->has_pending_exception()) { // Possible stack overflow.
1399 return false;
1400 }
1401 code = Handle<Code>(function->shared()->code(), isolate);
1402 if (code->kind() != Code::FUNCTION &&
1403 code->kind() != Code::OPTIMIZED_FUNCTION) {
1404 if (!GetUnoptimizedCode(function).ToHandle(&code)) {
1405 return false;
1406 }
1407 }
1408 function->ReplaceCode(*code);
1409 }
1410
1411 DCHECK(function->code()->kind() == Code::FUNCTION ||
1412 function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
1413 (function->code()->is_interpreter_entry_trampoline() &&
1414 function->shared()->HasBytecodeArray()) ||
1415 function->IsInOptimizationQueue());
1416 return true;
1417 }
1418
1419 bool Compiler::CompileDebugCode(Handle<JSFunction> function) {
1420 Handle<SharedFunctionInfo> shared(function->shared());
1421 if (IsEvalToplevel(shared)) {
1422 return CompileEvalForDebugging(function, shared);
1423 } else {
1424 CompilationInfoWithZone info(function);
1425 return CompileForDebugging(&info);
1426 }
1427 }
1428
1429 bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1430 DCHECK(shared->allows_lazy_compilation_without_context());
1431 DCHECK(!IsEvalToplevel(shared));
1432 Zone zone;
1433 ParseInfo parse_info(&zone, shared);
1434 CompilationInfo info(&parse_info);
1435 return CompileForDebugging(&info);
1436 }
1437
1438 // TODO(turbofan): In the future, unoptimized code with deopt support could
1439 // be generated lazily once deopt is triggered.
1440 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1441 DCHECK_NOT_NULL(info->literal());
1442 DCHECK(info->has_scope());
1443 Handle<SharedFunctionInfo> shared = info->shared_info();
1444 if (!shared->has_deoptimization_support()) {
1445 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile.
1446 CompilationInfoWithZone unoptimized(info->closure());
1447 // Note that we use the same AST that we will use for generating the
1448 // optimized code.
1449 ParseInfo* parse_info = unoptimized.parse_info();
1450 parse_info->set_literal(info->literal());
1451 parse_info->set_scope(info->scope());
1452 parse_info->set_context(info->context());
1453 unoptimized.EnableDeoptimizationSupport();
1454 // If the current code has reloc info for serialization, also include
1455 // reloc info for serialization for the new code, so that deopt support
1456 // can be added without losing IC state.
1457 if (shared->code()->kind() == Code::FUNCTION &&
1458 shared->code()->has_reloc_info_for_serialization()) {
1459 unoptimized.PrepareForSerializing();
1460 }
1461 if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1462
1463 shared->EnableDeoptimizationSupport(*unoptimized.code());
1464 shared->set_feedback_vector(*unoptimized.feedback_vector());
1465
1466 info->MarkAsCompiled();
1467
1468 // The scope info might not have been set if a lazily compiled
1469 // function is inlined before being called for the first time.
1470 if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1471 Handle<ScopeInfo> target_scope_info =
1472 ScopeInfo::Create(info->isolate(), info->zone(), info->scope());
1473 shared->set_scope_info(*target_scope_info);
1474 }
1475
1476 // The existing unoptimized code was replaced with the new one.
1477 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
1478 }
1479 return true;
1480 }
1481
1482 void Compiler::CompileForLiveEdit(Handle<Script> script) {
1483 // TODO(635): support extensions.
1484 Zone zone;
1485 ParseInfo parse_info(&zone, script);
1486 CompilationInfo info(&parse_info);
1487 PostponeInterruptsScope postpone(info.isolate());
1488 VMState<COMPILER> state(info.isolate());
1489
1490 // Get rid of old list of shared function infos.
1491 info.MarkAsFirstCompile();
1492 info.MarkAsDebug();
1493 info.parse_info()->set_global();
1494 if (!Parser::ParseStatic(info.parse_info())) return;
1495
1496 LiveEditFunctionTracker tracker(info.isolate(), parse_info.literal());
1497 if (!CompileUnoptimizedCode(&info)) return;
1498 if (info.has_shared_info()) {
1499 Handle<ScopeInfo> scope_info =
1500 ScopeInfo::Create(info.isolate(), info.zone(), info.scope());
1501 info.shared_info()->set_scope_info(*scope_info);
1502 }
1503 tracker.RecordRootFunctionInfo(info.code());
1504 }
1503 1505
1504 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( 1506 MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1505 Handle<String> source, Handle<SharedFunctionInfo> outer_info, 1507 Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1506 Handle<Context> context, LanguageMode language_mode, 1508 Handle<Context> context, LanguageMode language_mode,
1507 ParseRestriction restriction, int line_offset, int column_offset, 1509 ParseRestriction restriction, int line_offset, int column_offset,
1508 Handle<Object> script_name, ScriptOriginOptions options) { 1510 Handle<Object> script_name, ScriptOriginOptions options) {
1509 Isolate* isolate = source->GetIsolate(); 1511 Isolate* isolate = source->GetIsolate();
1510 int source_length = source->length(); 1512 int source_length = source->length();
1511 isolate->counters()->total_eval_size()->Increment(source_length); 1513 isolate->counters()->total_eval_size()->Increment(source_length);
1512 isolate->counters()->total_compile_size()->Increment(source_length); 1514 isolate->counters()->total_compile_size()->Increment(source_length);
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1946 1948
1947 // Cache context-specific literals. 1949 // Cache context-specific literals.
1948 MaybeHandle<Code> code; 1950 MaybeHandle<Code> code;
1949 if (cached.code != nullptr) code = handle(cached.code); 1951 if (cached.code != nullptr) code = handle(cached.code);
1950 Handle<Context> native_context(function->context()->native_context()); 1952 Handle<Context> native_context(function->context()->native_context());
1951 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code, 1953 SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
1952 literals, BailoutId::None()); 1954 literals, BailoutId::None());
1953 } 1955 }
1954 } 1956 }
1955 1957
1956 #if DEBUG
1957 void CompilationInfo::PrintAstForTesting() {
1958 PrintF("--- Source from AST ---\n%s\n",
1959 PrettyPrinter(isolate()).PrintProgram(literal()));
1960 }
1961 #endif
1962
1963 } // namespace internal 1958 } // namespace internal
1964 } // namespace v8 1959 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698