OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/code_index_table.h" | 7 #include "vm/code_index_table.h" |
8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/debugger.h" | 12 #include "vm/debugger.h" |
13 #include "vm/exceptions.h" | 13 #include "vm/exceptions.h" |
14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
15 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
16 #include "vm/runtime_entry.h" | 16 #include "vm/runtime_entry.h" |
17 #include "vm/stack_frame.h" | 17 #include "vm/stack_frame.h" |
18 #include "vm/verifier.h" | 18 #include "vm/verifier.h" |
19 | 19 |
20 namespace dart { | 20 namespace dart { |
21 | 21 |
22 DEFINE_FLAG(bool, inline_cache, true, "enable inline caches"); | 22 DEFINE_FLAG(bool, inline_cache, true, "enable inline caches"); |
23 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); | 23 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); |
24 DEFINE_FLAG(bool, trace_ic, false, "trace IC handling"); | 24 DEFINE_FLAG(bool, trace_ic, false, "trace IC handling"); |
25 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); | 25 DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code."); |
26 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls."); | 26 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls."); |
| 27 DEFINE_FLAG(int, optimization_counter_threshold, 2000, |
| 28 "function's usage-counter value before it is optimized, -1 means never."); |
| 29 DECLARE_FLAG(bool, trace_type_checks); |
| 30 DECLARE_FLAG(bool, report_usage_count); |
27 DECLARE_FLAG(int, deoptimization_counter_threshold); | 31 DECLARE_FLAG(int, deoptimization_counter_threshold); |
28 DECLARE_FLAG(bool, trace_type_checks); | 32 |
| 33 |
| 34 bool CodeGenerator::CanOptimize() { |
| 35 return |
| 36 !FLAG_report_usage_count && |
| 37 (FLAG_optimization_counter_threshold >= 0) && |
| 38 !Isolate::Current()->debugger()->IsActive(); |
| 39 } |
29 | 40 |
30 | 41 |
31 void CodeGenerator::DescriptorList::AddDescriptor( | 42 void CodeGenerator::DescriptorList::AddDescriptor( |
32 PcDescriptors::Kind kind, | 43 PcDescriptors::Kind kind, |
33 intptr_t pc_offset, | 44 intptr_t pc_offset, |
34 intptr_t node_id, | 45 intptr_t node_id, |
35 intptr_t token_index, | 46 intptr_t token_index, |
36 intptr_t try_index) { | 47 intptr_t try_index) { |
37 struct PcDesc data; | 48 struct PcDesc data; |
38 data.pc_offset = pc_offset; | 49 data.pc_offset = pc_offset; |
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 // Only unoptimized code has invocation counter threshold checking. | 956 // Only unoptimized code has invocation counter threshold checking. |
946 // Once the invocation counter threshold is reached any entry into the | 957 // Once the invocation counter threshold is reached any entry into the |
947 // unoptimized code is redirected to this function. | 958 // unoptimized code is redirected to this function. |
948 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 959 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
949 ASSERT(arguments.Count() == | 960 ASSERT(arguments.Count() == |
950 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); | 961 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); |
951 const Function& function = Function::CheckedHandle(arguments.At(0)); | 962 const Function& function = Function::CheckedHandle(arguments.At(0)); |
952 if (function.deoptimization_counter() >= | 963 if (function.deoptimization_counter() >= |
953 FLAG_deoptimization_counter_threshold) { | 964 FLAG_deoptimization_counter_threshold) { |
954 // TODO(srdjan): Investigate excessive deoptimization. | 965 // TODO(srdjan): Investigate excessive deoptimization. |
955 function.set_invocation_counter(0); | 966 function.set_usage_counter(0); |
| 967 return; |
| 968 } |
| 969 if (Code::Handle(function.code()).is_optimized()) { |
| 970 // The caller has been already optimized. |
| 971 // TODO(srdjan): This is a significant slowdown, the caller is probably in |
| 972 // a loop. Maybe test if the code has been optimized before calling. |
| 973 // If this happens from optimized code, then it means that the optimized |
| 974 // code needs to be reoptimized. |
| 975 function.set_usage_counter(0); |
956 return; | 976 return; |
957 } | 977 } |
958 if (function.is_optimizable()) { | 978 if (function.is_optimizable()) { |
959 ASSERT(!Code::Handle(function.code()).is_optimized()); | 979 ASSERT(!Code::Handle(function.code()).is_optimized()); |
960 const Code& unoptimized_code = Code::Handle(function.code()); | 980 const Code& unoptimized_code = Code::Handle(function.code()); |
961 // Compilation patches the entry of unoptimized code. | 981 // Compilation patches the entry of unoptimized code. |
962 const Error& error = | 982 const Error& error = |
963 Error::Handle(Compiler::CompileOptimizedFunction(function)); | 983 Error::Handle(Compiler::CompileOptimizedFunction(function)); |
964 if (!error.IsNull()) { | 984 if (!error.IsNull()) { |
965 Exceptions::PropagateError(error); | 985 Exceptions::PropagateError(error); |
966 } | 986 } |
967 const Code& optimized_code = Code::Handle(function.code()); | 987 const Code& optimized_code = Code::Handle(function.code()); |
968 ASSERT(!optimized_code.IsNull()); | 988 ASSERT(!optimized_code.IsNull()); |
969 ASSERT(!unoptimized_code.IsNull()); | 989 ASSERT(!unoptimized_code.IsNull()); |
970 } else { | 990 } else { |
971 // TODO(5442338): Abort as this should not happen. | 991 // TODO(5442338): Abort as this should not happen. |
972 function.set_invocation_counter(0); | 992 function.set_usage_counter(0); |
973 } | 993 } |
974 } | 994 } |
975 | 995 |
976 | 996 |
977 // The caller must be a static call in a Dart frame, or an entry frame. | 997 // The caller must be a static call in a Dart frame, or an entry frame. |
978 // Patch static call to point to 'new_entry_point'. | 998 // Patch static call to point to 'new_entry_point'. |
979 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { | 999 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { |
980 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); | 1000 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); |
981 const Function& function = Function::CheckedHandle(arguments.At(0)); | 1001 const Function& function = Function::CheckedHandle(arguments.At(0)); |
982 ASSERT(!function.IsNull()); | 1002 ASSERT(!function.IsNull()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 const Class& cls = Class::Handle(function.owner()); | 1074 const Class& cls = Class::Handle(function.owner()); |
1055 const Script& script = Script::Handle(cls.script()); | 1075 const Script& script = Script::Handle(cls.script()); |
1056 intptr_t line, column; | 1076 intptr_t line, column; |
1057 script.GetTokenLocation(deopt_token_index, &line, &column); | 1077 script.GetTokenLocation(deopt_token_index, &line, &column); |
1058 OS::Print(" Line: %d Column: %d ", line, column); | 1078 OS::Print(" Line: %d Column: %d ", line, column); |
1059 OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString()); | 1079 OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString()); |
1060 } | 1080 } |
1061 caller_frame->set_pc(continue_at_pc); | 1081 caller_frame->set_pc(continue_at_pc); |
1062 // Clear invocation counter so that the function gets optimized after | 1082 // Clear invocation counter so that the function gets optimized after |
1063 // types/classes have been collected. | 1083 // types/classes have been collected. |
1064 function.set_invocation_counter(0); | 1084 function.set_usage_counter(0); |
1065 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1085 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
1066 | 1086 |
1067 // We have to skip the following otherwise the compiler will complain | 1087 // We have to skip the following otherwise the compiler will complain |
1068 // when it attempts to install unoptimized code into a function that | 1088 // when it attempts to install unoptimized code into a function that |
1069 // was already deoptimized. | 1089 // was already deoptimized. |
1070 if (Code::Handle(function.code()).is_optimized()) { | 1090 if (Code::Handle(function.code()).is_optimized()) { |
1071 // Get unoptimized code. Compilation restores (reenables) the entry of | 1091 // Get unoptimized code. Compilation restores (reenables) the entry of |
1072 // unoptimized code. | 1092 // unoptimized code. |
1073 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 1093 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
1074 if (!error.IsNull()) { | 1094 if (!error.IsNull()) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 } | 1177 } |
1158 } | 1178 } |
1159 } | 1179 } |
1160 // The cache is null terminated, therefore the loop above should never | 1180 // The cache is null terminated, therefore the loop above should never |
1161 // terminate by itself. | 1181 // terminate by itself. |
1162 UNREACHABLE(); | 1182 UNREACHABLE(); |
1163 return Code::null(); | 1183 return Code::null(); |
1164 } | 1184 } |
1165 | 1185 |
1166 } // namespace dart | 1186 } // namespace dart |
OLD | NEW |