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); | |
31 DECLARE_FLAG(int, optimization_counter_threshold); | |
regis
2012/02/24 23:56:25
It should not be necessary to declare a flag that
srdjan
2012/02/25 00:22:10
Done.
| |
27 DECLARE_FLAG(int, deoptimization_counter_threshold); | 32 DECLARE_FLAG(int, deoptimization_counter_threshold); |
28 DECLARE_FLAG(bool, trace_type_checks); | 33 |
34 | |
35 bool CodeGenerator::CanOptimize() { | |
36 return | |
37 !FLAG_report_usage_count && | |
38 (FLAG_optimization_counter_threshold >= 0) && | |
39 !Isolate::Current()->debugger()->IsActive(); | |
40 } | |
29 | 41 |
30 | 42 |
31 const Array& CodeGenerator::ArgumentsDescriptor( | 43 const Array& CodeGenerator::ArgumentsDescriptor( |
32 int num_arguments, | 44 int num_arguments, |
33 const Array& optional_arguments_names) { | 45 const Array& optional_arguments_names) { |
34 const intptr_t num_named_args = | 46 const intptr_t num_named_args = |
35 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); | 47 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); |
36 const intptr_t num_pos_args = num_arguments - num_named_args; | 48 const intptr_t num_pos_args = num_arguments - num_named_args; |
37 | 49 |
38 // Build the argument descriptor array, which consists of the total number of | 50 // Build the argument descriptor array, which consists of the total number of |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
912 // Only unoptimized code has invocation counter threshold checking. | 924 // Only unoptimized code has invocation counter threshold checking. |
913 // Once the invocation counter threshold is reached any entry into the | 925 // Once the invocation counter threshold is reached any entry into the |
914 // unoptimized code is redirected to this function. | 926 // unoptimized code is redirected to this function. |
915 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 927 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
916 ASSERT(arguments.Count() == | 928 ASSERT(arguments.Count() == |
917 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); | 929 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); |
918 const Function& function = Function::CheckedHandle(arguments.At(0)); | 930 const Function& function = Function::CheckedHandle(arguments.At(0)); |
919 if (function.deoptimization_counter() >= | 931 if (function.deoptimization_counter() >= |
920 FLAG_deoptimization_counter_threshold) { | 932 FLAG_deoptimization_counter_threshold) { |
921 // TODO(srdjan): Investigate excessive deoptimization. | 933 // TODO(srdjan): Investigate excessive deoptimization. |
922 function.set_invocation_counter(0); | 934 function.set_usage_counter(0); |
935 return; | |
936 } | |
937 if (Code::Handle(function.code()).is_optimized()) { | |
938 // The caller has been already optimized. | |
939 // TODO(srdjan): This is a significant slowdown, the caller is probably in | |
940 // a loop. Maybe test if the code has been optimized before calling. | |
941 // If this happens from optimized code, then it means that the optimized | |
942 // code needs to be reoptimized. | |
943 function.set_usage_counter(0); | |
923 return; | 944 return; |
924 } | 945 } |
925 if (function.is_optimizable()) { | 946 if (function.is_optimizable()) { |
926 ASSERT(!Code::Handle(function.code()).is_optimized()); | 947 ASSERT(!Code::Handle(function.code()).is_optimized()); |
927 const Code& unoptimized_code = Code::Handle(function.code()); | 948 const Code& unoptimized_code = Code::Handle(function.code()); |
928 // Compilation patches the entry of unoptimized code. | 949 // Compilation patches the entry of unoptimized code. |
929 const Error& error = | 950 const Error& error = |
930 Error::Handle(Compiler::CompileOptimizedFunction(function)); | 951 Error::Handle(Compiler::CompileOptimizedFunction(function)); |
931 if (!error.IsNull()) { | 952 if (!error.IsNull()) { |
932 Exceptions::PropagateError(error); | 953 Exceptions::PropagateError(error); |
933 } | 954 } |
934 const Code& optimized_code = Code::Handle(function.code()); | 955 const Code& optimized_code = Code::Handle(function.code()); |
935 ASSERT(!optimized_code.IsNull()); | 956 ASSERT(!optimized_code.IsNull()); |
936 ASSERT(!unoptimized_code.IsNull()); | 957 ASSERT(!unoptimized_code.IsNull()); |
937 } else { | 958 } else { |
938 // TODO(5442338): Abort as this should not happen. | 959 // TODO(5442338): Abort as this should not happen. |
939 function.set_invocation_counter(0); | 960 function.set_usage_counter(0); |
940 } | 961 } |
941 } | 962 } |
942 | 963 |
943 | 964 |
944 // The caller must be a static call in a Dart frame, or an entry frame. | 965 // The caller must be a static call in a Dart frame, or an entry frame. |
945 // Patch static call to point to 'new_entry_point'. | 966 // Patch static call to point to 'new_entry_point'. |
946 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { | 967 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { |
947 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); | 968 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); |
948 const Function& function = Function::CheckedHandle(arguments.At(0)); | 969 const Function& function = Function::CheckedHandle(arguments.At(0)); |
949 ASSERT(!function.IsNull()); | 970 ASSERT(!function.IsNull()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1021 const Class& cls = Class::Handle(function.owner()); | 1042 const Class& cls = Class::Handle(function.owner()); |
1022 const Script& script = Script::Handle(cls.script()); | 1043 const Script& script = Script::Handle(cls.script()); |
1023 intptr_t line, column; | 1044 intptr_t line, column; |
1024 script.GetTokenLocation(deopt_token_index, &line, &column); | 1045 script.GetTokenLocation(deopt_token_index, &line, &column); |
1025 OS::Print(" Line: %d Column: %d ", line, column); | 1046 OS::Print(" Line: %d Column: %d ", line, column); |
1026 OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString()); | 1047 OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString()); |
1027 } | 1048 } |
1028 caller_frame->set_pc(continue_at_pc); | 1049 caller_frame->set_pc(continue_at_pc); |
1029 // Clear invocation counter so that the function gets optimized after | 1050 // Clear invocation counter so that the function gets optimized after |
1030 // types/classes have been collected. | 1051 // types/classes have been collected. |
1031 function.set_invocation_counter(0); | 1052 function.set_usage_counter(0); |
1032 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1053 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
1033 | 1054 |
1034 // We have to skip the following otherwise the compiler will complain | 1055 // We have to skip the following otherwise the compiler will complain |
1035 // when it attempts to install unoptimized code into a function that | 1056 // when it attempts to install unoptimized code into a function that |
1036 // was already deoptimized. | 1057 // was already deoptimized. |
1037 if (Code::Handle(function.code()).is_optimized()) { | 1058 if (Code::Handle(function.code()).is_optimized()) { |
1038 // Get unoptimized code. Compilation restores (reenables) the entry of | 1059 // Get unoptimized code. Compilation restores (reenables) the entry of |
1039 // unoptimized code. | 1060 // unoptimized code. |
1040 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 1061 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
1041 if (!error.IsNull()) { | 1062 if (!error.IsNull()) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1124 } | 1145 } |
1125 } | 1146 } |
1126 } | 1147 } |
1127 // The cache is null terminated, therefore the loop above should never | 1148 // The cache is null terminated, therefore the loop above should never |
1128 // terminate by itself. | 1149 // terminate by itself. |
1129 UNREACHABLE(); | 1150 UNREACHABLE(); |
1130 return Code::null(); | 1151 return Code::null(); |
1131 } | 1152 } |
1132 | 1153 |
1133 } // namespace dart | 1154 } // namespace dart |
OLD | NEW |