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 = |
1206 Array::ZoneHandle(ic_data.IsNull() ? ArgumentsDescriptor::New( | 1205 ic_data.IsNull() |
1207 argument_count, argument_names) | 1206 ? args_info.ToArgumentsDescriptor(zone()) |
1208 : ic_data.arguments_descriptor()); | 1207 : Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
1209 if (is_optimizing()) { | 1208 if (is_optimizing()) { |
1210 EmitOptimizedStaticCall(function, arguments_descriptor, argument_count, | 1209 EmitOptimizedStaticCall(function, arguments_descriptor, |
1211 deopt_id, token_pos, locs); | 1210 args_info.pushed_argc, deopt_id, token_pos, locs); |
1212 } else { | 1211 } else { |
1213 ICData& call_ic_data = ICData::ZoneHandle(ic_data.raw()); | 1212 ICData& call_ic_data = ICData::ZoneHandle(zone(), ic_data.raw()); |
1214 if (call_ic_data.IsNull()) { | 1213 if (call_ic_data.IsNull()) { |
1215 const intptr_t kNumArgsChecked = 0; | 1214 const intptr_t kNumArgsChecked = 0; |
1216 call_ic_data = | 1215 call_ic_data = |
1217 GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor, | 1216 GetOrAddStaticCallICData(deopt_id, function, arguments_descriptor, |
1218 kNumArgsChecked) | 1217 kNumArgsChecked) |
1219 ->raw(); | 1218 ->raw(); |
1220 } | 1219 } |
1221 AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos); | 1220 AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos); |
1222 EmitUnoptimizedStaticCall(argument_count, deopt_id, token_pos, locs, | 1221 EmitUnoptimizedStaticCall(args_info.pushed_argc, deopt_id, token_pos, locs, |
1223 call_ic_data); | 1222 call_ic_data); |
1224 } | 1223 } |
1225 } | 1224 } |
1226 | 1225 |
1227 | 1226 |
1228 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, | 1227 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, |
1229 const AbstractType& type, | 1228 const AbstractType& type, |
1230 Label* is_instance_lbl, | 1229 Label* is_instance_lbl, |
1231 Label* is_not_instance_lbl) { | 1230 Label* is_not_instance_lbl) { |
1232 assembler()->Comment("NumberTypeCheck"); | 1231 assembler()->Comment("NumberTypeCheck"); |
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 return true; | 1835 return true; |
1837 } | 1836 } |
1838 | 1837 |
1839 | 1838 |
1840 #if !defined(TARGET_ARCH_DBC) | 1839 #if !defined(TARGET_ARCH_DBC) |
1841 // DBC emits calls very differently from other architectures due to its | 1840 // DBC emits calls very differently from other architectures due to its |
1842 // interpreted nature. | 1841 // interpreted nature. |
1843 void FlowGraphCompiler::EmitPolymorphicInstanceCall( | 1842 void FlowGraphCompiler::EmitPolymorphicInstanceCall( |
1844 const CallTargets& targets, | 1843 const CallTargets& targets, |
1845 const InstanceCallInstr& original_call, | 1844 const InstanceCallInstr& original_call, |
1846 intptr_t argument_count, | 1845 ArgumentsInfo args_info, |
1847 const Array& argument_names, | |
1848 intptr_t deopt_id, | 1846 intptr_t deopt_id, |
1849 TokenPosition token_pos, | 1847 TokenPosition token_pos, |
1850 LocationSummary* locs, | 1848 LocationSummary* locs, |
1851 bool complete, | 1849 bool complete, |
1852 intptr_t total_ic_calls) { | 1850 intptr_t total_ic_calls) { |
1853 if (FLAG_polymorphic_with_deopt) { | 1851 if (FLAG_polymorphic_with_deopt) { |
1854 Label* deopt = | 1852 Label* deopt = |
1855 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); | 1853 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); |
1856 Label ok; | 1854 Label ok; |
1857 EmitTestAndCall(targets, original_call.function_name(), argument_count, | 1855 EmitTestAndCall(targets, original_call.function_name(), args_info, |
1858 argument_names, | |
1859 deopt, // No cid match. | 1856 deopt, // No cid match. |
1860 &ok, // Found cid. | 1857 &ok, // Found cid. |
1861 deopt_id, token_pos, locs, complete, total_ic_calls); | 1858 deopt_id, token_pos, locs, complete, total_ic_calls); |
1862 assembler()->Bind(&ok); | 1859 assembler()->Bind(&ok); |
1863 } else { | 1860 } else { |
1864 if (complete) { | 1861 if (complete) { |
1865 Label ok; | 1862 Label ok; |
1866 EmitTestAndCall(targets, original_call.function_name(), argument_count, | 1863 EmitTestAndCall(targets, original_call.function_name(), args_info, |
1867 argument_names, | |
1868 NULL, // No cid match. | 1864 NULL, // No cid match. |
1869 &ok, // Found cid. | 1865 &ok, // Found cid. |
1870 deopt_id, token_pos, locs, true, total_ic_calls); | 1866 deopt_id, token_pos, locs, true, total_ic_calls); |
1871 assembler()->Bind(&ok); | 1867 assembler()->Bind(&ok); |
1872 } else { | 1868 } else { |
1873 const ICData& unary_checks = ICData::ZoneHandle( | 1869 const ICData& unary_checks = ICData::ZoneHandle( |
1874 zone(), original_call.ic_data()->AsUnaryClassChecks()); | 1870 zone(), original_call.ic_data()->AsUnaryClassChecks()); |
1875 EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id, | 1871 EmitSwitchableInstanceCall(unary_checks, args_info.pushed_argc, deopt_id, |
1876 token_pos, locs); | 1872 token_pos, locs); |
1877 } | 1873 } |
1878 } | 1874 } |
1879 } | 1875 } |
1880 | 1876 |
1881 | 1877 |
1882 #define __ assembler()-> | 1878 #define __ assembler()-> |
1883 void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets, | 1879 void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets, |
1884 const String& function_name, | 1880 const String& function_name, |
1885 intptr_t argument_count, | 1881 ArgumentsInfo args_info, |
1886 const Array& argument_names, | |
1887 Label* failed, | 1882 Label* failed, |
1888 Label* match_found, | 1883 Label* match_found, |
1889 intptr_t deopt_id, | 1884 intptr_t deopt_id, |
1890 TokenPosition token_index, | 1885 TokenPosition token_index, |
1891 LocationSummary* locs, | 1886 LocationSummary* locs, |
1892 bool complete, | 1887 bool complete, |
1893 intptr_t total_ic_calls) { | 1888 intptr_t total_ic_calls) { |
1894 ASSERT(is_optimizing()); | 1889 ASSERT(is_optimizing()); |
1895 | 1890 |
1896 const Array& arguments_descriptor = Array::ZoneHandle( | 1891 const Array& arguments_descriptor = args_info.ToArgumentsDescriptor(zone()); |
1897 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); | 1892 EmitTestAndCallLoadReceiver(args_info.pushed_argc, arguments_descriptor); |
1898 | |
1899 EmitTestAndCallLoadReceiver(argument_count, arguments_descriptor); | |
1900 | 1893 |
1901 static const int kNoCase = -1; | 1894 static const int kNoCase = -1; |
1902 int smi_case = kNoCase; | 1895 int smi_case = kNoCase; |
1903 int which_case_to_skip = kNoCase; | 1896 int which_case_to_skip = kNoCase; |
1904 | 1897 |
1905 const int length = targets.length(); | 1898 const int length = targets.length(); |
1906 ASSERT(length > 0); | 1899 ASSERT(length > 0); |
1907 int non_smi_length = length; | 1900 int non_smi_length = length; |
1908 | 1901 |
1909 // Find out if one of the classes in one of the cases is the Smi class. We | 1902 // Find out if one of the classes in one of the cases is the Smi class. We |
(...skipping 18 matching lines...) Expand all Loading... |
1928 Label after_smi_test; | 1921 Label after_smi_test; |
1929 EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test, | 1922 EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test, |
1930 /* jump_if_smi= */ false); | 1923 /* jump_if_smi= */ false); |
1931 | 1924 |
1932 // Do not use the code from the function, but let the code be patched so | 1925 // Do not use the code from the function, but let the code be patched so |
1933 // that we can record the outgoing edges to other code. | 1926 // that we can record the outgoing edges to other code. |
1934 const Function& function = *targets[smi_case].target; | 1927 const Function& function = *targets[smi_case].target; |
1935 GenerateStaticDartCall(deopt_id, token_index, | 1928 GenerateStaticDartCall(deopt_id, token_index, |
1936 *StubCode::CallStaticFunction_entry(), | 1929 *StubCode::CallStaticFunction_entry(), |
1937 RawPcDescriptors::kOther, locs, function); | 1930 RawPcDescriptors::kOther, locs, function); |
1938 __ Drop(argument_count); | 1931 __ Drop(args_info.pushed_argc); |
1939 if (match_found != NULL) { | 1932 if (match_found != NULL) { |
1940 __ Jump(match_found); | 1933 __ Jump(match_found); |
1941 } | 1934 } |
1942 __ Bind(&after_smi_test); | 1935 __ Bind(&after_smi_test); |
1943 } else { | 1936 } else { |
1944 if (!complete) { | 1937 if (!complete) { |
1945 // Smi is not a valid class. | 1938 // Smi is not a valid class. |
1946 EmitTestAndCallSmiBranch(failed, /* jump_if_smi = */ true); | 1939 EmitTestAndCallSmiBranch(failed, /* jump_if_smi = */ true); |
1947 } | 1940 } |
1948 } | 1941 } |
(...skipping 28 matching lines...) Expand all Loading... |
1977 if (!complete || !is_last_check) { | 1970 if (!complete || !is_last_check) { |
1978 bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test, | 1971 bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test, |
1979 targets[i], bias); | 1972 targets[i], bias); |
1980 } | 1973 } |
1981 // Do not use the code from the function, but let the code be patched so | 1974 // Do not use the code from the function, but let the code be patched so |
1982 // that we can record the outgoing edges to other code. | 1975 // that we can record the outgoing edges to other code. |
1983 const Function& function = *targets[i].target; | 1976 const Function& function = *targets[i].target; |
1984 GenerateStaticDartCall(deopt_id, token_index, | 1977 GenerateStaticDartCall(deopt_id, token_index, |
1985 *StubCode::CallStaticFunction_entry(), | 1978 *StubCode::CallStaticFunction_entry(), |
1986 RawPcDescriptors::kOther, locs, function); | 1979 RawPcDescriptors::kOther, locs, function); |
1987 __ Drop(argument_count); | 1980 __ Drop(args_info.pushed_argc); |
1988 if (!is_last_check || add_megamorphic_call) { | 1981 if (!is_last_check || add_megamorphic_call) { |
1989 __ Jump(match_found); | 1982 __ Jump(match_found); |
1990 } | 1983 } |
1991 __ Bind(&next_test); | 1984 __ Bind(&next_test); |
1992 } | 1985 } |
1993 if (add_megamorphic_call) { | 1986 if (add_megamorphic_call) { |
1994 int try_index = CatchClauseNode::kInvalidTryIndex; | 1987 int try_index = CatchClauseNode::kInvalidTryIndex; |
1995 EmitMegamorphicInstanceCall(function_name, arguments_descriptor, | 1988 EmitMegamorphicInstanceCall(function_name, arguments_descriptor, |
1996 argument_count, deopt_id, token_index, locs, | 1989 args_info.pushed_argc, deopt_id, token_index, |
1997 try_index); | 1990 locs, try_index); |
1998 } | 1991 } |
1999 } | 1992 } |
2000 #undef __ | 1993 #undef __ |
2001 #endif | 1994 #endif |
2002 | 1995 |
2003 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 1996 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
2004 // TODO(vegorov) re-enable frame state tracking on DBC. It is | 1997 // TODO(vegorov) re-enable frame state tracking on DBC. It is |
2005 // currently disabled because it relies on LocationSummaries and | 1998 // currently disabled because it relies on LocationSummaries and |
2006 // we don't use them during unoptimized compilation on DBC. | 1999 // we don't use them during unoptimized compilation on DBC. |
2007 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { | 2000 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 | 2062 |
2070 | 2063 |
2071 void FlowGraphCompiler::FrameStateClear() { | 2064 void FlowGraphCompiler::FrameStateClear() { |
2072 ASSERT(!is_optimizing()); | 2065 ASSERT(!is_optimizing()); |
2073 frame_state_.TruncateTo(0); | 2066 frame_state_.TruncateTo(0); |
2074 } | 2067 } |
2075 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 2068 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
2076 | 2069 |
2077 | 2070 |
2078 } // namespace dart | 2071 } // namespace dart |
OLD | NEW |