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