| 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, |
| 1223 call_ic_data); | 1222 locs, 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"); |
| 1233 GrowableArray<intptr_t> args; | 1232 GrowableArray<intptr_t> args; |
| (...skipping 602 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(), |
| 1876 token_pos, locs); | 1872 deopt_id, 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 |