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/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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT) | 59 PARSE_INFO_GETTER_WITH_DEFAULT(LanguageMode, language_mode, STRICT) |
60 PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure, | 60 PARSE_INFO_GETTER_WITH_DEFAULT(Handle<JSFunction>, closure, |
61 Handle<JSFunction>::null()) | 61 Handle<JSFunction>::null()) |
62 PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr) | 62 PARSE_INFO_GETTER_WITH_DEFAULT(Scope*, scope, nullptr) |
63 PARSE_INFO_GETTER(Handle<Context>, context) | 63 PARSE_INFO_GETTER(Handle<Context>, context) |
64 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info) | 64 PARSE_INFO_GETTER(Handle<SharedFunctionInfo>, shared_info) |
65 | 65 |
66 #undef PARSE_INFO_GETTER | 66 #undef PARSE_INFO_GETTER |
67 #undef PARSE_INFO_GETTER_WITH_DEFAULT | 67 #undef PARSE_INFO_GETTER_WITH_DEFAULT |
68 | 68 |
| 69 // A wrapper around a CompilationInfo that detaches the Handles from |
| 70 // the underlying DeferredHandleScope and stores them in info_ on |
| 71 // destruction. |
| 72 class CompilationHandleScope BASE_EMBEDDED { |
| 73 public: |
| 74 explicit CompilationHandleScope(CompilationInfo* info) |
| 75 : deferred_(info->isolate()), info_(info) {} |
| 76 ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); } |
| 77 |
| 78 private: |
| 79 DeferredHandleScope deferred_; |
| 80 CompilationInfo* info_; |
| 81 }; |
69 | 82 |
70 // Exactly like a CompilationInfo, except being allocated via {new} and it also | 83 // Exactly like a CompilationInfo, except being allocated via {new} and it also |
71 // creates and enters a Zone on construction and deallocates it on destruction. | 84 // creates and enters a Zone on construction and deallocates it on destruction. |
72 class CompilationInfoWithZone : public CompilationInfo { | 85 class CompilationInfoWithZone : public CompilationInfo { |
73 public: | 86 public: |
74 explicit CompilationInfoWithZone(Handle<JSFunction> function) | 87 explicit CompilationInfoWithZone(Handle<JSFunction> function) |
75 : CompilationInfo(new ParseInfo(&zone_, function)) {} | 88 : CompilationInfo(new ParseInfo(&zone_, function)) {} |
76 | 89 |
77 // Virtual destructor because a CompilationInfoWithZone has to exit the | 90 // Virtual destructor because a CompilationInfoWithZone has to exit the |
78 // zone scope and get rid of dependent maps even when the destructor is | 91 // zone scope and get rid of dependent maps even when the destructor is |
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 DCHECK_NOT_NULL(info->scope()); | 933 DCHECK_NOT_NULL(info->scope()); |
921 return true; | 934 return true; |
922 } | 935 } |
923 | 936 |
924 | 937 |
925 bool Compiler::ParseAndAnalyze(ParseInfo* info) { | 938 bool Compiler::ParseAndAnalyze(ParseInfo* info) { |
926 if (!Parser::ParseStatic(info)) return false; | 939 if (!Parser::ParseStatic(info)) return false; |
927 return Compiler::Analyze(info); | 940 return Compiler::Analyze(info); |
928 } | 941 } |
929 | 942 |
| 943 namespace { |
930 | 944 |
931 static bool GetOptimizedCodeNow(CompilationInfo* info) { | 945 bool GetOptimizedCodeNow(CompilationInfo* info) { |
932 Isolate* isolate = info->isolate(); | 946 Isolate* isolate = info->isolate(); |
933 CanonicalHandleScope canonical(isolate); | 947 CanonicalHandleScope canonical(isolate); |
934 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 948 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
935 TRACE_EVENT0("v8", "V8.OptimizeCode"); | 949 TRACE_EVENT0("v8", "V8.OptimizeCode"); |
936 | 950 |
937 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; | 951 if (!Compiler::ParseAndAnalyze(info->parse_info())) return false; |
938 | 952 |
939 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 953 TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); |
940 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 954 TRACE_EVENT0("v8", "V8.RecompileSynchronous"); |
941 | 955 |
(...skipping 10 matching lines...) Expand all Loading... |
952 } | 966 } |
953 | 967 |
954 // Success! | 968 // Success! |
955 DCHECK(!isolate->has_pending_exception()); | 969 DCHECK(!isolate->has_pending_exception()); |
956 InsertCodeIntoOptimizedCodeMap(info); | 970 InsertCodeIntoOptimizedCodeMap(info); |
957 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, | 971 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, |
958 info->shared_info()); | 972 info->shared_info()); |
959 return true; | 973 return true; |
960 } | 974 } |
961 | 975 |
962 | 976 bool GetOptimizedCodeLater(CompilationInfo* info) { |
963 static bool GetOptimizedCodeLater(CompilationInfo* info) { | |
964 Isolate* isolate = info->isolate(); | 977 Isolate* isolate = info->isolate(); |
965 CanonicalHandleScope canonical(isolate); | 978 CanonicalHandleScope canonical(isolate); |
966 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); | 979 TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate); |
967 TRACE_EVENT0("v8", "V8.OptimizeCode"); | 980 TRACE_EVENT0("v8", "V8.OptimizeCode"); |
968 | 981 |
969 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) { | 982 if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) { |
970 if (FLAG_trace_concurrent_recompilation) { | 983 if (FLAG_trace_concurrent_recompilation) { |
971 PrintF(" ** Compilation queue full, will retry optimizing "); | 984 PrintF(" ** Compilation queue full, will retry optimizing "); |
972 info->closure()->ShortPrint(); | 985 info->closure()->ShortPrint(); |
973 PrintF(" later.\n"); | 986 PrintF(" later.\n"); |
(...skipping 21 matching lines...) Expand all Loading... |
995 info->closure()->ShortPrint(); | 1008 info->closure()->ShortPrint(); |
996 if (info->is_osr()) { | 1009 if (info->is_osr()) { |
997 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); | 1010 PrintF(" for concurrent OSR at %d.\n", info->osr_ast_id().ToInt()); |
998 } else { | 1011 } else { |
999 PrintF(" for concurrent optimization.\n"); | 1012 PrintF(" for concurrent optimization.\n"); |
1000 } | 1013 } |
1001 } | 1014 } |
1002 return true; | 1015 return true; |
1003 } | 1016 } |
1004 | 1017 |
1005 | 1018 MaybeHandle<Code> GetUnoptimizedCode(Handle<JSFunction> function) { |
1006 MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { | |
1007 DCHECK(!function->GetIsolate()->has_pending_exception()); | 1019 DCHECK(!function->GetIsolate()->has_pending_exception()); |
1008 DCHECK(!function->is_compiled()); | 1020 DCHECK(!function->is_compiled()); |
1009 if (function->shared()->is_compiled()) { | 1021 if (function->shared()->is_compiled()) { |
1010 return Handle<Code>(function->shared()->code()); | 1022 return Handle<Code>(function->shared()->code()); |
1011 } | 1023 } |
1012 | 1024 |
1013 CompilationInfoWithZone info(function); | 1025 CompilationInfoWithZone info(function); |
1014 Handle<Code> result; | 1026 Handle<Code> result; |
1015 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, | 1027 ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, |
1016 GetUnoptimizedCodeCommon(&info), | 1028 GetUnoptimizedCodeCommon(&info), |
1017 Code); | 1029 Code); |
1018 return result; | 1030 return result; |
1019 } | 1031 } |
1020 | 1032 |
1021 | 1033 MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) { |
1022 MaybeHandle<Code> Compiler::GetLazyCode(Handle<JSFunction> function) { | |
1023 Isolate* isolate = function->GetIsolate(); | 1034 Isolate* isolate = function->GetIsolate(); |
1024 DCHECK(!isolate->has_pending_exception()); | 1035 DCHECK(!isolate->has_pending_exception()); |
1025 DCHECK(!function->is_compiled()); | 1036 DCHECK(!function->is_compiled()); |
1026 TimerEventScope<TimerEventCompileCode> compile_timer(isolate); | 1037 TimerEventScope<TimerEventCompileCode> compile_timer(isolate); |
1027 TRACE_EVENT0("v8", "V8.CompileCode"); | 1038 TRACE_EVENT0("v8", "V8.CompileCode"); |
1028 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy()); | 1039 AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy()); |
1029 // If the debugger is active, do not compile with turbofan unless we can | 1040 // If the debugger is active, do not compile with turbofan unless we can |
1030 // deopt from turbofan code. | 1041 // deopt from turbofan code. |
1031 if (FLAG_turbo_asm && function->shared()->asm_function() && | 1042 if (FLAG_turbo_asm && function->shared()->asm_function() && |
1032 (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) && | 1043 (FLAG_turbo_asm_deoptimization || !isolate->debug()->is_active()) && |
(...skipping 27 matching lines...) Expand all Loading... |
1060 Handle<Code> opt_code; | 1071 Handle<Code> opt_code; |
1061 if (Compiler::GetOptimizedCode(function, Compiler::NOT_CONCURRENT) | 1072 if (Compiler::GetOptimizedCode(function, Compiler::NOT_CONCURRENT) |
1062 .ToHandle(&opt_code)) { | 1073 .ToHandle(&opt_code)) { |
1063 result = opt_code; | 1074 result = opt_code; |
1064 } | 1075 } |
1065 } | 1076 } |
1066 | 1077 |
1067 return result; | 1078 return result; |
1068 } | 1079 } |
1069 | 1080 |
| 1081 } // namespace |
1070 | 1082 |
1071 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { | 1083 bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) { |
1072 if (function->is_compiled()) return true; | 1084 if (function->is_compiled()) return true; |
1073 MaybeHandle<Code> maybe_code = Compiler::GetLazyCode(function); | 1085 MaybeHandle<Code> maybe_code = GetLazyCode(function); |
1074 Handle<Code> code; | 1086 Handle<Code> code; |
1075 if (!maybe_code.ToHandle(&code)) { | 1087 if (!maybe_code.ToHandle(&code)) { |
1076 if (flag == CLEAR_EXCEPTION) { | 1088 if (flag == CLEAR_EXCEPTION) { |
1077 function->GetIsolate()->clear_pending_exception(); | 1089 function->GetIsolate()->clear_pending_exception(); |
1078 } | 1090 } |
1079 return false; | 1091 return false; |
1080 } | 1092 } |
| 1093 DCHECK(code->IsJavaScriptCode()); |
1081 function->ReplaceCode(*code); | 1094 function->ReplaceCode(*code); |
1082 DCHECK(function->is_compiled()); | 1095 DCHECK(function->is_compiled()); |
1083 return true; | 1096 return true; |
1084 } | 1097 } |
1085 | 1098 |
| 1099 bool Compiler::CompileOptimized(Handle<JSFunction> function, |
| 1100 ConcurrencyMode mode) { |
| 1101 Handle<Code> code; |
| 1102 if (Compiler::GetOptimizedCode(function, mode).ToHandle(&code)) { |
| 1103 // Optimization succeeded, return optimized code. |
| 1104 function->ReplaceCode(*code); |
| 1105 } else { |
| 1106 // Optimization failed, get unoptimized code. |
| 1107 Isolate* isolate = function->GetIsolate(); |
| 1108 if (isolate->has_pending_exception()) { // Possible stack overflow. |
| 1109 return false; |
| 1110 } |
| 1111 code = Handle<Code>(function->shared()->code(), isolate); |
| 1112 if (code->kind() != Code::FUNCTION && |
| 1113 code->kind() != Code::OPTIMIZED_FUNCTION) { |
| 1114 if (!GetUnoptimizedCode(function).ToHandle(&code)) { |
| 1115 return false; |
| 1116 } |
| 1117 } |
| 1118 function->ReplaceCode(*code); |
| 1119 } |
| 1120 |
| 1121 DCHECK(function->code()->kind() == Code::FUNCTION || |
| 1122 function->code()->kind() == Code::OPTIMIZED_FUNCTION || |
| 1123 (function->code()->is_interpreter_entry_trampoline() && |
| 1124 function->shared()->HasBytecodeArray()) || |
| 1125 function->IsInOptimizationQueue()); |
| 1126 return true; |
| 1127 } |
1086 | 1128 |
1087 // TODO(turbofan): In the future, unoptimized code with deopt support could | 1129 // TODO(turbofan): In the future, unoptimized code with deopt support could |
1088 // be generated lazily once deopt is triggered. | 1130 // be generated lazily once deopt is triggered. |
1089 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { | 1131 bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { |
1090 DCHECK_NOT_NULL(info->literal()); | 1132 DCHECK_NOT_NULL(info->literal()); |
1091 DCHECK(info->has_scope()); | 1133 DCHECK(info->has_scope()); |
1092 Handle<SharedFunctionInfo> shared = info->shared_info(); | 1134 Handle<SharedFunctionInfo> shared = info->shared_info(); |
1093 if (!shared->has_deoptimization_support()) { | 1135 if (!shared->has_deoptimization_support()) { |
1094 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. | 1136 // TODO(titzer): just reuse the ParseInfo for the unoptimized compile. |
1095 CompilationInfoWithZone unoptimized(info->closure()); | 1137 CompilationInfoWithZone unoptimized(info->closure()); |
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 | 1901 |
1860 #if DEBUG | 1902 #if DEBUG |
1861 void CompilationInfo::PrintAstForTesting() { | 1903 void CompilationInfo::PrintAstForTesting() { |
1862 PrintF("--- Source from AST ---\n%s\n", | 1904 PrintF("--- Source from AST ---\n%s\n", |
1863 PrettyPrinter(isolate()).PrintProgram(literal())); | 1905 PrettyPrinter(isolate()).PrintProgram(literal())); |
1864 } | 1906 } |
1865 #endif | 1907 #endif |
1866 | 1908 |
1867 } // namespace internal | 1909 } // namespace internal |
1868 } // namespace v8 | 1910 } // namespace v8 |
OLD | NEW |