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" |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 // This function is called after successful resolving and compilation of | 416 // This function is called after successful resolving and compilation of |
417 // the target method. | 417 // the target method. |
418 ASSERT(arguments.Count() == kPatchStaticCallRuntimeEntry.argument_count()); | 418 ASSERT(arguments.Count() == kPatchStaticCallRuntimeEntry.argument_count()); |
419 DartFrameIterator iterator; | 419 DartFrameIterator iterator; |
420 DartFrame* caller_frame = iterator.NextFrame(); | 420 DartFrame* caller_frame = iterator.NextFrame(); |
421 ASSERT(caller_frame != NULL); | 421 ASSERT(caller_frame != NULL); |
422 uword target = 0; | 422 uword target = 0; |
423 Function& target_function = Function::Handle(); | 423 Function& target_function = Function::Handle(); |
424 CodePatcher::GetStaticCallAt(caller_frame->pc(), &target_function, &target); | 424 CodePatcher::GetStaticCallAt(caller_frame->pc(), &target_function, &target); |
425 ASSERT(target_function.HasCode()); | 425 ASSERT(target_function.HasCode()); |
426 uword new_target = Code::Handle(target_function.code()).EntryPoint(); | 426 uword new_target = Code::Handle(target_function.CurrentCode()).EntryPoint(); |
427 // Verify that we are not patching repeatedly. | 427 // Verify that we are not patching repeatedly. |
428 ASSERT(target != new_target); | 428 ASSERT(target != new_target); |
429 CodePatcher::PatchStaticCallAt(caller_frame->pc(), new_target); | 429 CodePatcher::PatchStaticCallAt(caller_frame->pc(), new_target); |
430 if (FLAG_trace_patching) { | 430 if (FLAG_trace_patching) { |
431 OS::Print("PatchStaticCall: patching from 0x%x to '%s' 0x%x\n", | 431 OS::Print("PatchStaticCall: patching from 0x%x to '%s' 0x%x\n", |
432 caller_frame->pc(), | 432 caller_frame->pc(), |
433 target_function.ToFullyQualifiedCString(), | 433 target_function.ToFullyQualifiedCString(), |
434 new_target); | 434 new_target); |
435 } | 435 } |
436 } | 436 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 } else { | 481 } else { |
482 if (!function.HasCode()) { | 482 if (!function.HasCode()) { |
483 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 483 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
484 if (!error.IsNull()) { | 484 if (!error.IsNull()) { |
485 Exceptions::PropagateError(error); | 485 Exceptions::PropagateError(error); |
486 } | 486 } |
487 } | 487 } |
488 functions_cache.AddCompiledFunction(function, | 488 functions_cache.AddCompiledFunction(function, |
489 num_arguments, | 489 num_arguments, |
490 num_named_arguments); | 490 num_named_arguments); |
491 return function.code(); | 491 return function.CurrentCode(); |
492 } | 492 } |
493 } | 493 } |
494 | 494 |
495 | 495 |
496 // Result of an invoke may be an unhandled exception, in which case we | 496 // Result of an invoke may be an unhandled exception, in which case we |
497 // rethrow it. | 497 // rethrow it. |
498 static void CheckResultError(const Object& result) { | 498 static void CheckResultError(const Object& result) { |
499 if (result.IsError()) { | 499 if (result.IsError()) { |
500 Exceptions::PropagateError(result); | 500 Exceptions::PropagateError(result); |
501 } | 501 } |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 const Array& func_arguments = Array::CheckedHandle(arguments.At(2)); | 792 const Array& func_arguments = Array::CheckedHandle(arguments.At(2)); |
793 const Function& function = Function::Handle(closure.function()); | 793 const Function& function = Function::Handle(closure.function()); |
794 ASSERT(!function.IsNull()); | 794 ASSERT(!function.IsNull()); |
795 if (!function.HasCode()) { | 795 if (!function.HasCode()) { |
796 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 796 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
797 if (!error.IsNull()) { | 797 if (!error.IsNull()) { |
798 Exceptions::PropagateError(error); | 798 Exceptions::PropagateError(error); |
799 } | 799 } |
800 } | 800 } |
801 const Context& context = Context::Handle(closure.context()); | 801 const Context& context = Context::Handle(closure.context()); |
802 const Code& code = Code::Handle(function.code()); | 802 const Code& code = Code::Handle(function.CurrentCode()); |
803 ASSERT(!code.IsNull()); | 803 ASSERT(!code.IsNull()); |
804 const Instructions& instrs = Instructions::Handle(code.instructions()); | 804 const Instructions& instrs = Instructions::Handle(code.instructions()); |
805 ASSERT(!instrs.IsNull()); | 805 ASSERT(!instrs.IsNull()); |
806 | 806 |
807 // Adjust arguments descriptor array to account for removal of the receiver | 807 // Adjust arguments descriptor array to account for removal of the receiver |
808 // parameter. Since the arguments descriptor array is canonicalized, create a | 808 // parameter. Since the arguments descriptor array is canonicalized, create a |
809 // new one instead of patching the original one. | 809 // new one instead of patching the original one. |
810 const intptr_t len = arg_descriptor.Length(); | 810 const intptr_t len = arg_descriptor.Length(); |
811 const intptr_t num_named_args = (len - 3) / 2; | 811 const intptr_t num_named_args = (len - 3) / 2; |
812 const Array& adjusted_arg_descriptor = Array::Handle(Array::New(len)); | 812 const Array& adjusted_arg_descriptor = Array::Handle(Array::New(len)); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { | 959 DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) { |
960 ASSERT(arguments.Count() == | 960 ASSERT(arguments.Count() == |
961 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); | 961 kOptimizeInvokedFunctionRuntimeEntry.argument_count()); |
962 const Function& function = Function::CheckedHandle(arguments.At(0)); | 962 const Function& function = Function::CheckedHandle(arguments.At(0)); |
963 if (function.deoptimization_counter() >= | 963 if (function.deoptimization_counter() >= |
964 FLAG_deoptimization_counter_threshold) { | 964 FLAG_deoptimization_counter_threshold) { |
965 // TODO(srdjan): Investigate excessive deoptimization. | 965 // TODO(srdjan): Investigate excessive deoptimization. |
966 function.set_usage_counter(0); | 966 function.set_usage_counter(0); |
967 return; | 967 return; |
968 } | 968 } |
969 if (Code::Handle(function.code()).is_optimized()) { | 969 if (function.HasOptimizedCode()) { |
970 // The caller has been already optimized. | 970 // The caller has been already optimized. |
971 // TODO(srdjan): This is a significant slowdown, the caller is probably in | 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. | 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 | 973 // If this happens from optimized code, then it means that the optimized |
974 // code needs to be reoptimized. | 974 // code needs to be reoptimized. |
975 function.set_usage_counter(0); | 975 function.set_usage_counter(0); |
976 return; | 976 return; |
977 } | 977 } |
978 if (function.is_optimizable()) { | 978 if (function.is_optimizable()) { |
979 ASSERT(!Code::Handle(function.code()).is_optimized()); | 979 ASSERT(!function.HasOptimizedCode()); |
980 const Code& unoptimized_code = Code::Handle(function.code()); | 980 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
981 // Compilation patches the entry of unoptimized code. | 981 // Compilation patches the entry of unoptimized code. |
982 const Error& error = | 982 const Error& error = |
983 Error::Handle(Compiler::CompileOptimizedFunction(function)); | 983 Error::Handle(Compiler::CompileOptimizedFunction(function)); |
984 if (!error.IsNull()) { | 984 if (!error.IsNull()) { |
985 Exceptions::PropagateError(error); | 985 Exceptions::PropagateError(error); |
986 } | 986 } |
987 const Code& optimized_code = Code::Handle(function.code()); | 987 const Code& optimized_code = Code::Handle(function.CurrentCode()); |
988 ASSERT(!optimized_code.IsNull()); | 988 ASSERT(!optimized_code.IsNull()); |
989 ASSERT(!unoptimized_code.IsNull()); | 989 ASSERT(!unoptimized_code.IsNull()); |
990 } else { | 990 } else { |
991 // TODO(5442338): Abort as this should not happen. | 991 // TODO(5442338): Abort as this should not happen. |
992 function.set_usage_counter(0); | 992 function.set_usage_counter(0); |
993 } | 993 } |
994 } | 994 } |
995 | 995 |
996 | 996 |
997 // 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. |
998 // Patch static call to point to 'new_entry_point'. | 998 // Patch static call to point to 'new_entry_point'. |
999 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { | 999 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 1) { |
1000 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); | 1000 ASSERT(arguments.Count() == kFixCallersTargetRuntimeEntry.argument_count()); |
1001 const Function& function = Function::CheckedHandle(arguments.At(0)); | 1001 const Function& function = Function::CheckedHandle(arguments.At(0)); |
1002 ASSERT(!function.IsNull()); | 1002 ASSERT(!function.IsNull()); |
1003 ASSERT(function.HasCode()); | 1003 ASSERT(function.HasCode()); |
1004 | 1004 |
1005 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); | 1005 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); |
1006 StackFrame* frame = iterator.NextFrame(); | 1006 StackFrame* frame = iterator.NextFrame(); |
1007 while (frame != NULL && !frame->IsDartFrame() && !frame->IsEntryFrame()) { | 1007 while (frame != NULL && !frame->IsDartFrame() && !frame->IsEntryFrame()) { |
1008 frame = iterator.NextFrame(); | 1008 frame = iterator.NextFrame(); |
1009 } | 1009 } |
1010 ASSERT(frame != NULL); | 1010 ASSERT(frame != NULL); |
1011 if (frame->IsDartFrame()) { | 1011 if (frame->IsDartFrame()) { |
1012 uword target = 0; | 1012 uword target = 0; |
1013 Function& target_function = Function::Handle(); | 1013 Function& target_function = Function::Handle(); |
1014 CodePatcher::GetStaticCallAt(frame->pc(), &target_function, &target); | 1014 CodePatcher::GetStaticCallAt(frame->pc(), &target_function, &target); |
1015 const uword new_entry_point = Code::Handle(function.code()).EntryPoint(); | 1015 ASSERT(target_function.HasCode()); |
| 1016 const uword new_entry_point = |
| 1017 Code::Handle(function.CurrentCode()).EntryPoint(); |
1016 ASSERT(target != new_entry_point); // Why patch otherwise. | 1018 ASSERT(target != new_entry_point); // Why patch otherwise. |
1017 ASSERT(target_function.HasCode()); | |
1018 CodePatcher::PatchStaticCallAt(frame->pc(), new_entry_point); | 1019 CodePatcher::PatchStaticCallAt(frame->pc(), new_entry_point); |
1019 if (FLAG_trace_patching) { | 1020 if (FLAG_trace_patching) { |
1020 OS::Print("FixCallersTarget: patching from 0x%x to '%s' 0x%x\n", | 1021 OS::Print("FixCallersTarget: patching from 0x%x to '%s' 0x%x\n", |
1021 frame->pc(), | 1022 frame->pc(), |
1022 target_function.ToFullyQualifiedCString(), | 1023 target_function.ToFullyQualifiedCString(), |
1023 new_entry_point); | 1024 new_entry_point); |
1024 } | 1025 } |
1025 } | 1026 } |
1026 } | 1027 } |
1027 | 1028 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1080 } | 1081 } |
1081 caller_frame->set_pc(continue_at_pc); | 1082 caller_frame->set_pc(continue_at_pc); |
1082 // Clear invocation counter so that the function gets optimized after | 1083 // Clear invocation counter so that the function gets optimized after |
1083 // types/classes have been collected. | 1084 // types/classes have been collected. |
1084 function.set_usage_counter(0); | 1085 function.set_usage_counter(0); |
1085 function.set_deoptimization_counter(function.deoptimization_counter() + 1); | 1086 function.set_deoptimization_counter(function.deoptimization_counter() + 1); |
1086 | 1087 |
1087 // We have to skip the following otherwise the compiler will complain | 1088 // We have to skip the following otherwise the compiler will complain |
1088 // when it attempts to install unoptimized code into a function that | 1089 // when it attempts to install unoptimized code into a function that |
1089 // was already deoptimized. | 1090 // was already deoptimized. |
1090 if (Code::Handle(function.code()).is_optimized()) { | 1091 if (function.HasOptimizedCode()) { |
1091 // Get unoptimized code. Compilation restores (reenables) the entry of | 1092 // Get unoptimized code. Compilation restores (reenables) the entry of |
1092 // unoptimized code. | 1093 // unoptimized code. |
1093 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 1094 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
1094 if (!error.IsNull()) { | 1095 if (!error.IsNull()) { |
1095 Exceptions::PropagateError(error); | 1096 Exceptions::PropagateError(error); |
1096 } | 1097 } |
1097 } | 1098 } |
1098 // TODO(srdjan): Handle better complex cases, e.g. when an older optimized | 1099 // TODO(srdjan): Handle better complex cases, e.g. when an older optimized |
1099 // code is alive on frame and gets deoptimized after the function was | 1100 // code is alive on frame and gets deoptimized after the function was |
1100 // optimized a second time. | 1101 // optimized a second time. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 if (function_name.Equals(test_name)) { | 1166 if (function_name.Equals(test_name)) { |
1166 Smi& smi = Smi::Handle(); | 1167 Smi& smi = Smi::Handle(); |
1167 smi ^= cache.At(i + FunctionsCache::kArgCount); | 1168 smi ^= cache.At(i + FunctionsCache::kArgCount); |
1168 if (num_arguments == smi.Value()) { | 1169 if (num_arguments == smi.Value()) { |
1169 smi ^= cache.At(i + FunctionsCache::kNamedArgCount); | 1170 smi ^= cache.At(i + FunctionsCache::kNamedArgCount); |
1170 if (num_named_arguments == smi.Value()) { | 1171 if (num_named_arguments == smi.Value()) { |
1171 Function& result = Function::Handle(); | 1172 Function& result = Function::Handle(); |
1172 result ^= cache.At(i + FunctionsCache::kFunction); | 1173 result ^= cache.At(i + FunctionsCache::kFunction); |
1173 ASSERT(!result.IsNull()); | 1174 ASSERT(!result.IsNull()); |
1174 ASSERT(result.HasCode()); | 1175 ASSERT(result.HasCode()); |
1175 return result.code(); | 1176 return result.CurrentCode(); |
1176 } | 1177 } |
1177 } | 1178 } |
1178 } | 1179 } |
1179 } | 1180 } |
1180 // The cache is null terminated, therefore the loop above should never | 1181 // The cache is null terminated, therefore the loop above should never |
1181 // terminate by itself. | 1182 // terminate by itself. |
1182 UNREACHABLE(); | 1183 UNREACHABLE(); |
1183 return Code::null(); | 1184 return Code::null(); |
1184 } | 1185 } |
1185 | 1186 |
1186 } // namespace dart | 1187 } // namespace dart |
OLD | NEW |