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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
6 | 6 |
7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
8 | 8 |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
(...skipping 1179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1190 break; | 1190 break; |
1191 default: | 1191 default: |
1192 UNIMPLEMENTED(); | 1192 UNIMPLEMENTED(); |
1193 } | 1193 } |
1194 } | 1194 } |
1195 | 1195 |
1196 | 1196 |
1197 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, | 1197 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, |
1198 TokenPosition token_pos, | 1198 TokenPosition token_pos, |
1199 const Function& function, | 1199 const Function& function, |
1200 intptr_t argument_count, | 1200 ArgumentsInfo args_info, |
1201 const Array& argument_names, | |
1202 LocationSummary* locs, | 1201 LocationSummary* locs, |
1203 const ICData& ic_data_in) { | 1202 const ICData& ic_data_in) { |
1204 const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original()); | 1203 const ICData& ic_data = ICData::ZoneHandle(ic_data_in.Original()); |
1205 const Array& arguments_descriptor = | 1204 const Array& arguments_descriptor = Array::ZoneHandle( |
1206 Array::ZoneHandle(ic_data.IsNull() ? ArgumentsDescriptor::New( | 1205 zone(), ic_data.IsNull() ? args_info.ToArgumentsDescriptor() |
1207 argument_count, argument_names) | 1206 : ic_data.arguments_descriptor()); |
1208 : ic_data.arguments_descriptor()); | |
1209 if (is_optimizing()) { | 1207 if (is_optimizing()) { |
1210 EmitOptimizedStaticCall(function, arguments_descriptor, argument_count, | 1208 EmitOptimizedStaticCall(function, arguments_descriptor, |
1211 deopt_id, token_pos, locs); | 1209 args_info.pushed_argc, deopt_id, token_pos, locs); |
1212 } else { | 1210 } else { |
1213 ICData& call_ic_data = ICData::ZoneHandle(ic_data.raw()); | 1211 ICData& call_ic_data = ICData::ZoneHandle(zone(), ic_data.raw()); |
1214 if (call_ic_data.IsNull()) { | 1212 if (call_ic_data.IsNull()) { |
1215 const intptr_t kNumArgsChecked = 0; | 1213 const intptr_t kNumArgsChecked = 0; |
1216 call_ic_data = | 1214 call_ic_data = |
1217 GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor, | 1215 GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor, |
1218 kNumArgsChecked) | 1216 kNumArgsChecked) |
1219 ->raw(); | 1217 ->raw(); |
1220 } | 1218 } |
1221 AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos); | 1219 AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos); |
1222 EmitUnoptimizedStaticCall(argument_count, deopt_id, token_pos, locs, | 1220 EmitUnoptimizedStaticCall(args_info.pushed_argc, deopt_id, token_pos, locs, |
1223 call_ic_data); | 1221 call_ic_data); |
1224 } | 1222 } |
1225 } | 1223 } |
1226 | 1224 |
1227 | 1225 |
1228 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, | 1226 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, |
1229 const AbstractType& type, | 1227 const AbstractType& type, |
1230 Label* is_instance_lbl, | 1228 Label* is_instance_lbl, |
1231 Label* is_not_instance_lbl) { | 1229 Label* is_not_instance_lbl) { |
1232 assembler()->Comment("NumberTypeCheck"); | 1230 assembler()->Comment("NumberTypeCheck"); |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1786 return true; | 1784 return true; |
1787 } | 1785 } |
1788 | 1786 |
1789 | 1787 |
1790 #if !defined(TARGET_ARCH_DBC) | 1788 #if !defined(TARGET_ARCH_DBC) |
1791 // DBC emits calls very differently from other architectures due to its | 1789 // DBC emits calls very differently from other architectures due to its |
1792 // interpreted nature. | 1790 // interpreted nature. |
1793 void FlowGraphCompiler::EmitPolymorphicInstanceCall( | 1791 void FlowGraphCompiler::EmitPolymorphicInstanceCall( |
1794 const CallTargets& targets, | 1792 const CallTargets& targets, |
1795 const InstanceCallInstr& original_call, | 1793 const InstanceCallInstr& original_call, |
1796 intptr_t argument_count, | 1794 ArgumentsInfo args_info, |
1797 const Array& argument_names, | |
1798 intptr_t deopt_id, | 1795 intptr_t deopt_id, |
1799 TokenPosition token_pos, | 1796 TokenPosition token_pos, |
1800 LocationSummary* locs, | 1797 LocationSummary* locs, |
1801 bool complete, | 1798 bool complete, |
1802 intptr_t total_ic_calls) { | 1799 intptr_t total_ic_calls) { |
1803 if (FLAG_polymorphic_with_deopt) { | 1800 if (FLAG_polymorphic_with_deopt) { |
1804 Label* deopt = | 1801 Label* deopt = |
1805 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); | 1802 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); |
1806 Label ok; | 1803 Label ok; |
1807 EmitTestAndCall(targets, original_call.function_name(), argument_count, | 1804 EmitTestAndCall(targets, original_call.function_name(), args_info, |
1808 argument_names, | |
1809 deopt, // No cid match. | 1805 deopt, // No cid match. |
1810 &ok, // Found cid. | 1806 &ok, // Found cid. |
1811 deopt_id, token_pos, locs, complete, total_ic_calls); | 1807 deopt_id, token_pos, locs, complete, total_ic_calls); |
1812 assembler()->Bind(&ok); | 1808 assembler()->Bind(&ok); |
1813 } else { | 1809 } else { |
1814 if (complete) { | 1810 if (complete) { |
1815 Label ok; | 1811 Label ok; |
1816 EmitTestAndCall(targets, original_call.function_name(), argument_count, | 1812 EmitTestAndCall(targets, original_call.function_name(), args_info, |
1817 argument_names, | |
1818 NULL, // No cid match. | 1813 NULL, // No cid match. |
1819 &ok, // Found cid. | 1814 &ok, // Found cid. |
1820 deopt_id, token_pos, locs, true, total_ic_calls); | 1815 deopt_id, token_pos, locs, true, total_ic_calls); |
1821 assembler()->Bind(&ok); | 1816 assembler()->Bind(&ok); |
1822 } else { | 1817 } else { |
1823 const ICData& unary_checks = ICData::ZoneHandle( | 1818 const ICData& unary_checks = ICData::ZoneHandle( |
1824 zone(), original_call.ic_data()->AsUnaryClassChecks()); | 1819 zone(), original_call.ic_data()->AsUnaryClassChecks()); |
1825 EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id, | 1820 EmitSwitchableInstanceCall(unary_checks, args_info.pushed_argc, deopt_id, |
1826 token_pos, locs); | 1821 token_pos, locs); |
1827 } | 1822 } |
1828 } | 1823 } |
1829 } | 1824 } |
1830 | 1825 |
1831 | 1826 |
1832 #define __ assembler()-> | 1827 #define __ assembler()-> |
1833 void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets, | 1828 void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets, |
1834 const String& function_name, | 1829 const String& function_name, |
1835 intptr_t argument_count, | 1830 ArgumentsInfo args_info, |
1836 const Array& argument_names, | |
1837 Label* failed, | 1831 Label* failed, |
1838 Label* match_found, | 1832 Label* match_found, |
1839 intptr_t deopt_id, | 1833 intptr_t deopt_id, |
1840 TokenPosition token_index, | 1834 TokenPosition token_index, |
1841 LocationSummary* locs, | 1835 LocationSummary* locs, |
1842 bool complete, | 1836 bool complete, |
1843 intptr_t total_ic_calls) { | 1837 intptr_t total_ic_calls) { |
1844 ASSERT(is_optimizing()); | 1838 ASSERT(is_optimizing()); |
1845 | 1839 |
1846 const Array& arguments_descriptor = Array::ZoneHandle( | 1840 const Array& arguments_descriptor = |
1847 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); | 1841 Array::ZoneHandle(zone(), args_info.ToArgumentsDescriptor()); |
1848 | 1842 EmitTestAndCallLoadReceiver(args_info.pushed_argc, arguments_descriptor); |
1849 EmitTestAndCallLoadReceiver(argument_count, arguments_descriptor); | |
1850 | 1843 |
1851 static const int kNoCase = -1; | 1844 static const int kNoCase = -1; |
1852 int smi_case = kNoCase; | 1845 int smi_case = kNoCase; |
1853 int which_case_to_skip = kNoCase; | 1846 int which_case_to_skip = kNoCase; |
1854 | 1847 |
1855 const int length = targets.length(); | 1848 const int length = targets.length(); |
1856 ASSERT(length > 0); | 1849 ASSERT(length > 0); |
1857 int non_smi_length = length; | 1850 int non_smi_length = length; |
1858 | 1851 |
1859 // Find out if one of the classes in one of the cases is the Smi class. We | 1852 // Find out if one of the classes in one of the cases is the Smi class. We |
(...skipping 18 matching lines...) Expand all Loading... |
1878 Label after_smi_test; | 1871 Label after_smi_test; |
1879 EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test, | 1872 EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test, |
1880 /* jump_if_smi= */ false); | 1873 /* jump_if_smi= */ false); |
1881 | 1874 |
1882 // Do not use the code from the function, but let the code be patched so | 1875 // Do not use the code from the function, but let the code be patched so |
1883 // that we can record the outgoing edges to other code. | 1876 // that we can record the outgoing edges to other code. |
1884 const Function& function = *targets.TargetAt(smi_case)->target; | 1877 const Function& function = *targets.TargetAt(smi_case)->target; |
1885 GenerateStaticDartCall(deopt_id, token_index, | 1878 GenerateStaticDartCall(deopt_id, token_index, |
1886 *StubCode::CallStaticFunction_entry(), | 1879 *StubCode::CallStaticFunction_entry(), |
1887 RawPcDescriptors::kOther, locs, function); | 1880 RawPcDescriptors::kOther, locs, function); |
1888 __ Drop(argument_count); | 1881 __ Drop(args_info.pushed_argc); |
1889 if (match_found != NULL) { | 1882 if (match_found != NULL) { |
1890 __ Jump(match_found); | 1883 __ Jump(match_found); |
1891 } | 1884 } |
1892 __ Bind(&after_smi_test); | 1885 __ Bind(&after_smi_test); |
1893 } else { | 1886 } else { |
1894 if (!complete) { | 1887 if (!complete) { |
1895 // Smi is not a valid class. | 1888 // Smi is not a valid class. |
1896 EmitTestAndCallSmiBranch(failed, /* jump_if_smi = */ true); | 1889 EmitTestAndCallSmiBranch(failed, /* jump_if_smi = */ true); |
1897 } | 1890 } |
1898 } | 1891 } |
(...skipping 28 matching lines...) Expand all Loading... |
1927 if (!complete || !is_last_check) { | 1920 if (!complete || !is_last_check) { |
1928 bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test, | 1921 bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test, |
1929 targets[i], bias); | 1922 targets[i], bias); |
1930 } | 1923 } |
1931 // Do not use the code from the function, but let the code be patched so | 1924 // Do not use the code from the function, but let the code be patched so |
1932 // that we can record the outgoing edges to other code. | 1925 // that we can record the outgoing edges to other code. |
1933 const Function& function = *targets.TargetAt(i)->target; | 1926 const Function& function = *targets.TargetAt(i)->target; |
1934 GenerateStaticDartCall(deopt_id, token_index, | 1927 GenerateStaticDartCall(deopt_id, token_index, |
1935 *StubCode::CallStaticFunction_entry(), | 1928 *StubCode::CallStaticFunction_entry(), |
1936 RawPcDescriptors::kOther, locs, function); | 1929 RawPcDescriptors::kOther, locs, function); |
1937 __ Drop(argument_count); | 1930 __ Drop(args_info.pushed_argc); |
1938 if (!is_last_check || add_megamorphic_call) { | 1931 if (!is_last_check || add_megamorphic_call) { |
1939 __ Jump(match_found); | 1932 __ Jump(match_found); |
1940 } | 1933 } |
1941 __ Bind(&next_test); | 1934 __ Bind(&next_test); |
1942 } | 1935 } |
1943 if (add_megamorphic_call) { | 1936 if (add_megamorphic_call) { |
1944 int try_index = CatchClauseNode::kInvalidTryIndex; | 1937 int try_index = CatchClauseNode::kInvalidTryIndex; |
1945 EmitMegamorphicInstanceCall(function_name, arguments_descriptor, | 1938 EmitMegamorphicInstanceCall(function_name, arguments_descriptor, |
1946 argument_count, deopt_id, token_index, locs, | 1939 args_info.pushed_argc, deopt_id, token_index, |
1947 try_index); | 1940 locs, try_index); |
1948 } | 1941 } |
1949 } | 1942 } |
1950 #undef __ | 1943 #undef __ |
1951 #endif | 1944 #endif |
1952 | 1945 |
1953 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 1946 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
1954 // TODO(vegorov) re-enable frame state tracking on DBC. It is | 1947 // TODO(vegorov) re-enable frame state tracking on DBC. It is |
1955 // currently disabled because it relies on LocationSummaries and | 1948 // currently disabled because it relies on LocationSummaries and |
1956 // we don't use them during unoptimized compilation on DBC. | 1949 // we don't use them during unoptimized compilation on DBC. |
1957 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { | 1950 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2019 | 2012 |
2020 | 2013 |
2021 void FlowGraphCompiler::FrameStateClear() { | 2014 void FlowGraphCompiler::FrameStateClear() { |
2022 ASSERT(!is_optimizing()); | 2015 ASSERT(!is_optimizing()); |
2023 frame_state_.TruncateTo(0); | 2016 frame_state_.TruncateTo(0); |
2024 } | 2017 } |
2025 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 2018 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
2026 | 2019 |
2027 | 2020 |
2028 } // namespace dart | 2021 } // namespace dart |
OLD | NEW |