OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { | 651 DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) { |
652 DartFrameIterator iterator; | 652 DartFrameIterator iterator; |
653 StackFrame* caller_frame = iterator.NextFrame(); | 653 StackFrame* caller_frame = iterator.NextFrame(); |
654 ASSERT(caller_frame != NULL); | 654 ASSERT(caller_frame != NULL); |
655 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); | 655 const Code& caller_code = Code::Handle(zone, caller_frame->LookupDartCode()); |
656 ASSERT(!caller_code.IsNull()); | 656 ASSERT(!caller_code.IsNull()); |
657 ASSERT(caller_code.is_optimized()); | 657 ASSERT(caller_code.is_optimized()); |
658 const Function& target_function = Function::Handle( | 658 const Function& target_function = Function::Handle( |
659 zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); | 659 zone, caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc())); |
660 if (!target_function.HasCode()) { | 660 if (!target_function.HasCode()) { |
661 const Error& error = | 661 const Object& result = Object::Handle( |
662 Error::Handle(zone, Compiler::CompileFunction(thread, target_function)); | 662 zone, Compiler::CompileFunction(thread, target_function)); |
663 if (!error.IsNull()) { | 663 if (result.IsError()) { |
664 Exceptions::PropagateError(error); | 664 Exceptions::PropagateError(Error::Cast(result)); |
665 } | 665 } |
666 } | 666 } |
667 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); | 667 const Code& target_code = Code::Handle(zone, target_function.CurrentCode()); |
668 // Before patching verify that we are not repeatedly patching to the same | 668 // Before patching verify that we are not repeatedly patching to the same |
669 // target. | 669 // target. |
670 ASSERT(target_code.raw() != | 670 ASSERT(target_code.raw() != |
671 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); | 671 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); |
672 CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code, target_code); | 672 CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code, target_code); |
673 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 673 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
674 if (FLAG_trace_patching) { | 674 if (FLAG_trace_patching) { |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 // seen before. Compile the target if necessary and update the ICData. | 934 // seen before. Compile the target if necessary and update the ICData. |
935 // Arg0: argument. | 935 // Arg0: argument. |
936 // Arg1: IC data object. | 936 // Arg1: IC data object. |
937 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { | 937 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) { |
938 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0)); | 938 const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0)); |
939 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); | 939 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
940 // IC data for static call is prepopulated with the statically known target. | 940 // IC data for static call is prepopulated with the statically known target. |
941 ASSERT(ic_data.NumberOfChecksIs(1)); | 941 ASSERT(ic_data.NumberOfChecksIs(1)); |
942 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 942 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
943 if (!target.HasCode()) { | 943 if (!target.HasCode()) { |
944 const Error& error = | 944 const Object& result = |
945 Error::Handle(Compiler::CompileFunction(thread, target)); | 945 Object::Handle(Compiler::CompileFunction(thread, target)); |
946 if (!error.IsNull()) { | 946 if (result.IsError()) { |
947 Exceptions::PropagateError(error); | 947 Exceptions::PropagateError(Error::Cast(result)); |
948 } | 948 } |
949 } | 949 } |
950 ASSERT(!target.IsNull() && target.HasCode()); | 950 ASSERT(!target.IsNull() && target.HasCode()); |
951 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1); | 951 ic_data.AddReceiverCheck(arg.GetClassId(), target, 1); |
952 if (FLAG_trace_ic) { | 952 if (FLAG_trace_ic) { |
953 DartFrameIterator iterator; | 953 DartFrameIterator iterator; |
954 StackFrame* caller_frame = iterator.NextFrame(); | 954 StackFrame* caller_frame = iterator.NextFrame(); |
955 ASSERT(caller_frame != NULL); | 955 ASSERT(caller_frame != NULL); |
956 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ")\n", | 956 OS::PrintErr("StaticCallMissHandler at %#" Px " target %s (%" Pd ")\n", |
957 caller_frame->pc(), target.ToCString(), arg.GetClassId()); | 957 caller_frame->pc(), target.ToCString(), arg.GetClassId()); |
958 } | 958 } |
959 arguments.SetReturn(target); | 959 arguments.SetReturn(target); |
960 } | 960 } |
961 | 961 |
962 | 962 |
963 // Handles a static call in unoptimized code that has two argument types not | 963 // Handles a static call in unoptimized code that has two argument types not |
964 // seen before. Compile the target if necessary and update the ICData. | 964 // seen before. Compile the target if necessary and update the ICData. |
965 // Arg0: argument 0. | 965 // Arg0: argument 0. |
966 // Arg1: argument 1. | 966 // Arg1: argument 1. |
967 // Arg2: IC data object. | 967 // Arg2: IC data object. |
968 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { | 968 DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { |
969 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0)); | 969 const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0)); |
970 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1)); | 970 const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1)); |
971 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); | 971 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2)); |
972 // IC data for static call is prepopulated with the statically known target. | 972 // IC data for static call is prepopulated with the statically known target. |
973 ASSERT(!ic_data.NumberOfChecksIs(0)); | 973 ASSERT(!ic_data.NumberOfChecksIs(0)); |
974 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); | 974 const Function& target = Function::Handle(ic_data.GetTargetAt(0)); |
975 if (!target.HasCode()) { | 975 if (!target.HasCode()) { |
976 const Error& error = | 976 const Object& result = |
977 Error::Handle(Compiler::CompileFunction(thread, target)); | 977 Object::Handle(Compiler::CompileFunction(thread, target)); |
978 if (!error.IsNull()) { | 978 if (result.IsError()) { |
979 Exceptions::PropagateError(error); | 979 Exceptions::PropagateError(Error::Cast(result)); |
980 } | 980 } |
981 } | 981 } |
982 ASSERT(!target.IsNull() && target.HasCode()); | 982 ASSERT(!target.IsNull() && target.HasCode()); |
983 GrowableArray<intptr_t> cids(2); | 983 GrowableArray<intptr_t> cids(2); |
984 cids.Add(arg0.GetClassId()); | 984 cids.Add(arg0.GetClassId()); |
985 cids.Add(arg1.GetClassId()); | 985 cids.Add(arg1.GetClassId()); |
986 ic_data.AddCheck(cids, target); | 986 ic_data.AddCheck(cids, target); |
987 if (FLAG_trace_ic) { | 987 if (FLAG_trace_ic) { |
988 DartFrameIterator iterator; | 988 DartFrameIterator iterator; |
989 StackFrame* caller_frame = iterator.NextFrame(); | 989 StackFrame* caller_frame = iterator.NextFrame(); |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 if (number_of_checks == 0 && !target_function.HasOptionalParameters() && | 1315 if (number_of_checks == 0 && !target_function.HasOptionalParameters() && |
1316 !Isolate::Current()->compilation_allowed()) { | 1316 !Isolate::Current()->compilation_allowed()) { |
1317 // This call site is unlinked: transition to a monomorphic direct call. | 1317 // This call site is unlinked: transition to a monomorphic direct call. |
1318 // Note we cannot do this if the target has optional parameters because | 1318 // Note we cannot do this if the target has optional parameters because |
1319 // the monomorphic direct call does not load the arguments descriptor. | 1319 // the monomorphic direct call does not load the arguments descriptor. |
1320 // We cannot do this if we are still in the middle of precompiling because | 1320 // We cannot do this if we are still in the middle of precompiling because |
1321 // the monomorphic case hides an live instance selector from the | 1321 // the monomorphic case hides an live instance selector from the |
1322 // treeshaker. | 1322 // treeshaker. |
1323 | 1323 |
1324 if (!target_function.HasCode()) { | 1324 if (!target_function.HasCode()) { |
1325 const Error& error = | 1325 const Object& result = |
1326 Error::Handle(Compiler::CompileFunction(thread, target_function)); | 1326 Object::Handle(Compiler::CompileFunction(thread, target_function)); |
1327 if (!error.IsNull()) { | 1327 if (result.IsError()) { |
1328 Exceptions::PropagateError(error); | 1328 Exceptions::PropagateError(Error::Cast(result)); |
1329 } | 1329 } |
1330 } | 1330 } |
1331 | 1331 |
1332 DartFrameIterator iterator; | 1332 DartFrameIterator iterator; |
1333 StackFrame* miss_function_frame = iterator.NextFrame(); | 1333 StackFrame* miss_function_frame = iterator.NextFrame(); |
1334 ASSERT(miss_function_frame->IsDartFrame()); | 1334 ASSERT(miss_function_frame->IsDartFrame()); |
1335 StackFrame* caller_frame = iterator.NextFrame(); | 1335 StackFrame* caller_frame = iterator.NextFrame(); |
1336 ASSERT(caller_frame->IsDartFrame()); | 1336 ASSERT(caller_frame->IsDartFrame()); |
1337 const Code& caller_code = | 1337 const Code& caller_code = |
1338 Code::Handle(zone, caller_frame->LookupDartCode()); | 1338 Code::Handle(zone, caller_frame->LookupDartCode()); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 ASSERT(function.unoptimized_code() != Object::null()); | 1699 ASSERT(function.unoptimized_code() != Object::null()); |
1700 intptr_t osr_id = | 1700 intptr_t osr_id = |
1701 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc()); | 1701 Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc()); |
1702 ASSERT(osr_id != Compiler::kNoOSRDeoptId); | 1702 ASSERT(osr_id != Compiler::kNoOSRDeoptId); |
1703 if (FLAG_trace_osr) { | 1703 if (FLAG_trace_osr) { |
1704 OS::Print("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n", | 1704 OS::Print("Attempting OSR for %s at id=%" Pd ", count=%" Pd "\n", |
1705 function.ToFullyQualifiedCString(), osr_id, | 1705 function.ToFullyQualifiedCString(), osr_id, |
1706 function.usage_counter()); | 1706 function.usage_counter()); |
1707 } | 1707 } |
1708 | 1708 |
1709 const Code& original_code = Code::Handle(function.CurrentCode()); | |
1710 // Since the code is referenced from the frame and the ZoneHandle, | 1709 // Since the code is referenced from the frame and the ZoneHandle, |
1711 // it cannot have been removed from the function. | 1710 // it cannot have been removed from the function. |
1712 ASSERT(!original_code.IsNull()); | 1711 const Object& result = Object::Handle( |
1713 const Error& error = Error::Handle( | |
1714 Compiler::CompileOptimizedFunction(thread, function, osr_id)); | 1712 Compiler::CompileOptimizedFunction(thread, function, osr_id)); |
1715 if (!error.IsNull()) { | 1713 if (result.IsError()) { |
1716 Exceptions::PropagateError(error); | 1714 Exceptions::PropagateError(Error::Cast(result)); |
1717 } | 1715 } |
1718 | 1716 |
1719 const Code& optimized_code = Code::Handle(function.CurrentCode()); | 1717 if (!result.IsNull()) { |
1720 // The current code will not be changed in the case that the compiler | 1718 const Code& code = Code::Cast(result); |
1721 // bailed out during OSR compilation. | |
1722 if (optimized_code.raw() != original_code.raw()) { | |
1723 // The OSR code does not work for calling the function, so restore the | |
1724 // unoptimized code. Patch the stack frame to return into the OSR | |
1725 // code. | |
1726 uword optimized_entry = | 1719 uword optimized_entry = |
1727 Instructions::UncheckedEntryPoint(optimized_code.instructions()); | 1720 Instructions::UncheckedEntryPoint(code.instructions()); |
1728 function.AttachCode(original_code); | |
1729 frame->set_pc(optimized_entry); | 1721 frame->set_pc(optimized_entry); |
1730 frame->set_pc_marker(optimized_code.raw()); | 1722 frame->set_pc_marker(code.raw()); |
1731 } | 1723 } |
1732 } | 1724 } |
1733 } | 1725 } |
1734 | 1726 |
1735 | 1727 |
1736 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1728 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
1737 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1729 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
1738 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); | 1730 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); |
1739 DartFrameIterator iterator; | 1731 DartFrameIterator iterator; |
1740 StackFrame* frame = iterator.NextFrame(); | 1732 StackFrame* frame = iterator.NextFrame(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1793 | 1785 |
1794 // Reset usage counter for reoptimization before calling optimizer to | 1786 // Reset usage counter for reoptimization before calling optimizer to |
1795 // prevent recursive triggering of function optimization. | 1787 // prevent recursive triggering of function optimization. |
1796 function.set_usage_counter(0); | 1788 function.set_usage_counter(0); |
1797 if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) { | 1789 if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) { |
1798 if (function.HasOptimizedCode()) { | 1790 if (function.HasOptimizedCode()) { |
1799 THR_Print("ReCompiling function: '%s' \n", | 1791 THR_Print("ReCompiling function: '%s' \n", |
1800 function.ToFullyQualifiedCString()); | 1792 function.ToFullyQualifiedCString()); |
1801 } | 1793 } |
1802 } | 1794 } |
1803 const Error& error = Error::Handle( | 1795 const Object& result = Object::Handle( |
1804 zone, Compiler::CompileOptimizedFunction(thread, function)); | 1796 zone, Compiler::CompileOptimizedFunction(thread, function)); |
1805 if (!error.IsNull()) { | 1797 if (result.IsError()) { |
1806 Exceptions::PropagateError(error); | 1798 Exceptions::PropagateError(Error::Cast(result)); |
1807 } | 1799 } |
1808 const Code& optimized_code = Code::Handle(zone, function.CurrentCode()); | |
1809 ASSERT(!optimized_code.IsNull()); | |
1810 } | 1800 } |
1811 arguments.SetReturn(function); | 1801 arguments.SetReturn(function); |
1812 #else | 1802 #else |
1813 UNREACHABLE(); | 1803 UNREACHABLE(); |
1814 #endif // !DART_PRECOMPILED_RUNTIME | 1804 #endif // !DART_PRECOMPILED_RUNTIME |
1815 } | 1805 } |
1816 | 1806 |
1817 | 1807 |
1818 // The caller must be a static call in a Dart frame, or an entry frame. | 1808 // The caller must be a static call in a Dart frame, or an entry frame. |
1819 // Patch static call to point to valid code's entry point. | 1809 // Patch static call to point to valid code's entry point. |
1820 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) { | 1810 DEFINE_RUNTIME_ENTRY(FixCallersTarget, 0) { |
1821 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); | 1811 StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames); |
1822 StackFrame* frame = iterator.NextFrame(); | 1812 StackFrame* frame = iterator.NextFrame(); |
1823 ASSERT(frame != NULL); | 1813 ASSERT(frame != NULL); |
1824 while (frame->IsStubFrame() || frame->IsExitFrame()) { | 1814 while (frame->IsStubFrame() || frame->IsExitFrame()) { |
1825 frame = iterator.NextFrame(); | 1815 frame = iterator.NextFrame(); |
1826 ASSERT(frame != NULL); | 1816 ASSERT(frame != NULL); |
1827 } | 1817 } |
1828 if (frame->IsEntryFrame()) { | 1818 if (frame->IsEntryFrame()) { |
1829 // Since function's current code is always unpatched, the entry frame always | 1819 // Since function's current code is always unpatched, the entry frame always |
1830 // calls to unpatched code. | 1820 // calls to unpatched code. |
1831 UNREACHABLE(); | 1821 UNREACHABLE(); |
1832 } | 1822 } |
1833 ASSERT(frame->IsDartFrame()); | 1823 ASSERT(frame->IsDartFrame()); |
1834 const Code& caller_code = Code::Handle(zone, frame->LookupDartCode()); | 1824 const Code& caller_code = Code::Handle(zone, frame->LookupDartCode()); |
1835 ASSERT(caller_code.is_optimized()); | 1825 ASSERT(caller_code.is_optimized()); |
1836 const Function& target_function = Function::Handle( | 1826 const Function& target_function = Function::Handle( |
1837 zone, caller_code.GetStaticCallTargetFunctionAt(frame->pc())); | 1827 zone, caller_code.GetStaticCallTargetFunctionAt(frame->pc())); |
1838 if (!target_function.HasCode()) { | 1828 if (!target_function.HasCode()) { |
1839 const Error& error = | 1829 const Object& result = |
1840 Error::Handle(zone, Compiler::CompileFunction(thread, target_function)); | 1830 Object::Handle(Compiler::CompileFunction(thread, target_function)); |
1841 if (!error.IsNull()) { | 1831 if (result.IsError()) { |
1842 Exceptions::PropagateError(error); | 1832 Exceptions::PropagateError(Error::Cast(result)); |
1843 } | 1833 } |
1844 } | 1834 } |
1845 ASSERT(target_function.HasCode()); | 1835 ASSERT(target_function.HasCode()); |
1846 | 1836 |
1847 const Code& current_target_code = | 1837 const Code& current_target_code = |
1848 Code::Handle(zone, target_function.CurrentCode()); | 1838 Code::Handle(zone, target_function.CurrentCode()); |
1849 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, current_target_code); | 1839 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, current_target_code); |
1850 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); | 1840 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); |
1851 if (FLAG_trace_patching) { | 1841 if (FLAG_trace_patching) { |
1852 OS::PrintErr("FixCallersTarget: caller %#" Px | 1842 OS::PrintErr("FixCallersTarget: caller %#" Px |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2251 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2262 const TypedData& new_data = | 2252 const TypedData& new_data = |
2263 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2253 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2264 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2254 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2265 typed_data_cell.SetAt(0, new_data); | 2255 typed_data_cell.SetAt(0, new_data); |
2266 arguments.SetReturn(new_data); | 2256 arguments.SetReturn(new_data); |
2267 } | 2257 } |
2268 | 2258 |
2269 | 2259 |
2270 } // namespace dart | 2260 } // namespace dart |
OLD | NEW |