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