Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: runtime/vm/flow_graph_compiler.cc

Issue 2833413002: Revert "Use off-heap data for type feedback in PolymorphicInstanceCallInstr" (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_compiler.h ('k') | runtime/vm/flow_graph_compiler_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "vm/compiler.h" 11 #include "vm/compiler.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/debugger.h" 13 #include "vm/debugger.h"
14 #include "vm/deopt_instructions.h" 14 #include "vm/deopt_instructions.h"
15 #include "vm/exceptions.h" 15 #include "vm/exceptions.h"
16 #include "vm/flags.h" 16 #include "vm/flags.h"
17 #include "vm/flow_graph_allocator.h" 17 #include "vm/flow_graph_allocator.h"
18 #include "vm/il_printer.h" 18 #include "vm/il_printer.h"
19 #include "vm/intrinsifier.h" 19 #include "vm/intrinsifier.h"
20 #include "vm/locations.h" 20 #include "vm/locations.h"
21 #include "vm/log.h" 21 #include "vm/log.h"
22 #include "vm/longjump.h" 22 #include "vm/longjump.h"
23 #include "vm/object_store.h" 23 #include "vm/object_store.h"
24 #include "vm/parser.h" 24 #include "vm/parser.h"
25 #include "vm/raw_object.h" 25 #include "vm/raw_object.h"
26 #include "vm/resolver.h"
27 #include "vm/stack_frame.h" 26 #include "vm/stack_frame.h"
28 #include "vm/stub_code.h" 27 #include "vm/stub_code.h"
29 #include "vm/symbols.h" 28 #include "vm/symbols.h"
30 #include "vm/timeline.h" 29 #include "vm/timeline.h"
31 30
32 namespace dart { 31 namespace dart {
33 32
34 DEFINE_FLAG(bool, 33 DEFINE_FLAG(bool,
35 enable_simd_inline, 34 enable_simd_inline,
36 true, 35 true,
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 *StubCode::TwoArgsOptimizedCheckInlineCache_entry(), ic_data, 1162 *StubCode::TwoArgsOptimizedCheckInlineCache_entry(), ic_data,
1164 argument_count, deopt_id, token_pos, locs); 1163 argument_count, deopt_id, token_pos, locs);
1165 return; 1164 return;
1166 default: 1165 default:
1167 UNIMPLEMENTED(); 1166 UNIMPLEMENTED();
1168 } 1167 }
1169 return; 1168 return;
1170 } 1169 }
1171 1170
1172 if (is_optimizing()) { 1171 if (is_optimizing()) {
1173 String& name = String::Handle(ic_data_in.target_name()); 1172 EmitMegamorphicInstanceCall(ic_data_in, argument_count, deopt_id, token_pos,
1174 Array& arguments_descriptor = 1173 locs, CatchClauseNode::kInvalidTryIndex);
1175 Array::Handle(ic_data_in.arguments_descriptor());
1176 EmitMegamorphicInstanceCall(name, arguments_descriptor, argument_count,
1177 deopt_id, token_pos, locs,
1178 CatchClauseNode::kInvalidTryIndex);
1179 return; 1174 return;
1180 } 1175 }
1181 1176
1182 switch (ic_data.NumArgsTested()) { 1177 switch (ic_data.NumArgsTested()) {
1183 case 1: 1178 case 1:
1184 EmitInstanceCall(*StubCode::OneArgCheckInlineCache_entry(), ic_data, 1179 EmitInstanceCall(*StubCode::OneArgCheckInlineCache_entry(), ic_data,
1185 argument_count, deopt_id, token_pos, locs); 1180 argument_count, deopt_id, token_pos, locs);
1186 break; 1181 break;
1187 case 2: 1182 case 2:
1188 EmitInstanceCall(*StubCode::TwoArgsCheckInlineCache_entry(), ic_data, 1183 EmitInstanceCall(*StubCode::TwoArgsCheckInlineCache_entry(), ic_data,
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
1785 code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize()); 1780 code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize());
1786 } 1781 }
1787 1782
1788 1783
1789 void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) { 1784 void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) {
1790 code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(), 1785 code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(),
1791 token_pos); 1786 token_pos);
1792 } 1787 }
1793 1788
1794 1789
1795 const CallTargets* FlowGraphCompiler::ResolveCallTargetsForReceiverCid( 1790 const ICData& FlowGraphCompiler::TrySpecializeICDataByReceiverCid(
1796 intptr_t cid, 1791 const ICData& ic_data,
1797 const String& selector, 1792 intptr_t cid) {
1798 const Array& args_desc_array) {
1799 Zone* zone = Thread::Current()->zone(); 1793 Zone* zone = Thread::Current()->zone();
1794 if (ic_data.NumArgsTested() != 1) return ic_data;
1800 1795
1801 ArgumentsDescriptor args_desc(args_desc_array); 1796 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) {
1797 return ic_data; // Nothing to do
1798 }
1802 1799
1803 Function& fn = Function::ZoneHandle(zone); 1800 intptr_t count = 1;
1804 if (!LookupMethodFor(cid, selector, args_desc, &fn)) return NULL; 1801 const Function& function =
1802 Function::Handle(zone, ic_data.GetTargetForReceiverClassId(cid, &count));
1803 // TODO(fschneider): Try looking up the function on the class if it is
1804 // not found in the ICData.
1805 if (!function.IsNull()) {
1806 const ICData& new_ic_data = ICData::ZoneHandle(
1807 zone, ICData::New(Function::Handle(zone, ic_data.Owner()),
1808 String::Handle(zone, ic_data.target_name()),
1809 Object::empty_array(), // Dummy argument descriptor.
1810 ic_data.deopt_id(), ic_data.NumArgsTested(), false));
1811 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
1812 new_ic_data.AddReceiverCheck(cid, function, count);
1813 return new_ic_data;
1814 }
1805 1815
1806 CallTargets* targets = new (zone) CallTargets(); 1816 return ic_data;
1807 targets->Add(CidRangeTarget(cid, cid, &fn, /* count = */ 1));
1808
1809 return targets;
1810 } 1817 }
1811 1818
1812 1819
1813 bool FlowGraphCompiler::LookupMethodFor(int class_id, 1820 intptr_t FlowGraphCompiler::ComputeGoodBiasForCidComparison(
1814 const String& name, 1821 const GrowableArray<CidRangeTarget>& sorted,
1815 const ArgumentsDescriptor& args_desc, 1822 intptr_t max_immediate) {
1816 Function* fn_return) { 1823 // Sometimes a bias can be useful so we can emit more compact compare
1817 Thread* thread = Thread::Current(); 1824 // instructions.
1818 Isolate* isolate = thread->isolate(); 1825 intptr_t min_cid = 1000000;
1819 Zone* zone = thread->zone(); 1826 intptr_t max_cid = -1;
1820 if (class_id < 0) return false;
1821 if (class_id >= isolate->class_table()->NumCids()) return false;
1822 1827
1823 RawClass* raw_class = isolate->class_table()->At(class_id); 1828 const intptr_t sorted_len = sorted.length();
1824 if (raw_class == NULL) return false;
1825 Class& cls = Class::Handle(zone, raw_class);
1826 if (cls.IsNull()) return false;
1827 if (!cls.is_finalized()) return false;
1828 if (Array::Handle(cls.functions()).IsNull()) return false;
1829 1829
1830 const bool allow_add = false; 1830 for (intptr_t i = 0; i < sorted_len + 1; i++) {
1831 Function& target_function = 1831 bool done = (i == sorted_len);
1832 Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass( 1832 intptr_t start = done ? 0 : sorted[i].cid_start;
1833 cls, name, args_desc, allow_add)); 1833 intptr_t end = done ? 0 : sorted[i].cid_end;
1834 if (target_function.IsNull()) return false; 1834 bool is_range = start != end;
1835 *fn_return ^= target_function.raw(); 1835 bool spread_too_big = start - min_cid > max_immediate;
1836 return true; 1836 if (done || is_range || spread_too_big) {
1837 if (i >= 2 && max_cid - min_cid <= max_immediate &&
1838 max_cid > max_immediate) {
1839 return min_cid;
1840 } else {
1841 return 0;
1842 }
1843 }
1844 min_cid = Utils::Minimum(min_cid, start);
1845 max_cid = Utils::Maximum(max_cid, end);
1846 }
1847 UNREACHABLE();
1848 return 0;
1837 } 1849 }
1838 1850
1839 1851
1840 #if !defined(TARGET_ARCH_DBC) 1852 #if !defined(TARGET_ARCH_DBC)
1841 // DBC emits calls very differently from other architectures due to its 1853 // DBC emits calls very differently from other architectures due to its
1842 // interpreted nature. 1854 // interpreted nature.
1843 void FlowGraphCompiler::EmitPolymorphicInstanceCall( 1855 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data,
1844 const CallTargets& targets, 1856 intptr_t argument_count,
1845 const InstanceCallInstr& original_call, 1857 const Array& argument_names,
1846 intptr_t argument_count, 1858 intptr_t deopt_id,
1847 const Array& argument_names, 1859 TokenPosition token_pos,
1848 intptr_t deopt_id, 1860 LocationSummary* locs,
1849 TokenPosition token_pos, 1861 bool complete,
1850 LocationSummary* locs, 1862 intptr_t total_ic_calls) {
1851 bool complete,
1852 intptr_t total_ic_calls) {
1853 if (FLAG_polymorphic_with_deopt) { 1863 if (FLAG_polymorphic_with_deopt) {
1854 Label* deopt = 1864 Label* deopt =
1855 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); 1865 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
1856 Label ok; 1866 Label ok;
1857 EmitTestAndCall(targets, original_call.function_name(), argument_count, 1867 EmitTestAndCall(ic_data, argument_count, argument_names,
1858 argument_names,
1859 deopt, // No cid match. 1868 deopt, // No cid match.
1860 &ok, // Found cid. 1869 &ok, // Found cid.
1861 deopt_id, token_pos, locs, complete, total_ic_calls); 1870 deopt_id, token_pos, locs, complete, total_ic_calls);
1862 assembler()->Bind(&ok); 1871 assembler()->Bind(&ok);
1863 } else { 1872 } else {
1864 if (complete) { 1873 if (complete) {
1865 Label ok; 1874 Label ok;
1866 EmitTestAndCall(targets, original_call.function_name(), argument_count, 1875 EmitTestAndCall(ic_data, argument_count, argument_names,
1867 argument_names,
1868 NULL, // No cid match. 1876 NULL, // No cid match.
1869 &ok, // Found cid. 1877 &ok, // Found cid.
1870 deopt_id, token_pos, locs, true, total_ic_calls); 1878 deopt_id, token_pos, locs, true, total_ic_calls);
1871 assembler()->Bind(&ok); 1879 assembler()->Bind(&ok);
1872 } else { 1880 } else {
1873 const ICData& unary_checks = ICData::ZoneHandle( 1881 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos,
1874 zone(), original_call.ic_data()->AsUnaryClassChecks()); 1882 locs);
1875 EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id,
1876 token_pos, locs);
1877 } 1883 }
1878 } 1884 }
1879 } 1885 }
1880
1881
1882 #define __ assembler()->
1883 void FlowGraphCompiler::EmitTestAndCall(const CallTargets& targets,
1884 const String& function_name,
1885 intptr_t argument_count,
1886 const Array& argument_names,
1887 Label* failed,
1888 Label* match_found,
1889 intptr_t deopt_id,
1890 TokenPosition token_index,
1891 LocationSummary* locs,
1892 bool complete,
1893 intptr_t total_ic_calls) {
1894 ASSERT(is_optimizing());
1895
1896 const Array& arguments_descriptor = Array::ZoneHandle(
1897 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1898
1899 EmitTestAndCallLoadReceiver(argument_count, arguments_descriptor);
1900
1901 static const int kNoCase = -1;
1902 int smi_case = kNoCase;
1903 int which_case_to_skip = kNoCase;
1904
1905 const int length = targets.length();
1906 ASSERT(length > 0);
1907 int non_smi_length = length;
1908
1909 // Find out if one of the classes in one of the cases is the Smi class. We
1910 // will be handling that specially.
1911 for (int i = 0; i < length; i++) {
1912 const intptr_t start = targets[i].cid_start;
1913 if (start > kSmiCid) continue;
1914 const intptr_t end = targets[i].cid_end;
1915 if (end >= kSmiCid) {
1916 smi_case = i;
1917 if (start == kSmiCid && end == kSmiCid) {
1918 // If this case has only the Smi class then we won't need to emit it at
1919 // all later.
1920 which_case_to_skip = i;
1921 non_smi_length--;
1922 }
1923 break;
1924 }
1925 }
1926
1927 if (smi_case != kNoCase) {
1928 Label after_smi_test;
1929 EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
1930 false); // Jump if receiver is not Smi.
1931
1932 // 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.
1934 const Function& function = *targets[smi_case].target;
1935 GenerateStaticDartCall(deopt_id, token_index,
1936 *StubCode::CallStaticFunction_entry(),
1937 RawPcDescriptors::kOther, locs, function);
1938 __ Drop(argument_count);
1939 if (match_found != NULL) {
1940 __ Jump(match_found);
1941 }
1942 __ Bind(&after_smi_test);
1943 } else {
1944 if (!complete) {
1945 // Smi is not a valid class.
1946 EmitTestAndCallSmiBranch(failed,
1947 true); // Jump to failed if it's a Smi.
1948 }
1949 }
1950
1951 if (non_smi_length == 0) {
1952 // If non_smi_length is 0 then only a Smi check was needed; the Smi check
1953 // above will fail if there was only one check and receiver is not Smi.
1954 return;
1955 }
1956
1957 bool add_megamorphic_call = false;
1958 int bias = 0;
1959
1960 // Value is not Smi.
1961 EmitTestAndCallLoadCid();
1962
1963 int last_check = which_case_to_skip == length - 1 ? length - 2 : length - 1;
1964
1965 for (intptr_t i = 0; i < length; i++) {
1966 if (i == which_case_to_skip) continue;
1967 const bool is_last_check = (i == last_check);
1968 const int count = targets[i].count;
1969 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1970 // This case is hit too rarely to be worth writing class-id checks inline
1971 // for. Note that we can't do this for calls with only one target because
1972 // the type propagator may have made use of that and expects a deopt if
1973 // a new class is seen at this calls site. See IsMonomorphic.
1974 add_megamorphic_call = true;
1975 break;
1976 }
1977 Label next_test;
1978 if (!complete || !is_last_check) {
1979 bias = EmitTestAndCallCheckCid(is_last_check ? failed : &next_test,
1980 targets[i], bias);
1981 }
1982 // Do not use the code from the function, but let the code be patched so
1983 // that we can record the outgoing edges to other code.
1984 const Function& function = *targets[i].target;
1985 GenerateStaticDartCall(deopt_id, token_index,
1986 *StubCode::CallStaticFunction_entry(),
1987 RawPcDescriptors::kOther, locs, function);
1988 __ Drop(argument_count);
1989 if (!is_last_check || add_megamorphic_call) {
1990 __ Jump(match_found);
1991 }
1992 __ Bind(&next_test);
1993 }
1994 if (add_megamorphic_call) {
1995 int try_index = CatchClauseNode::kInvalidTryIndex;
1996 EmitMegamorphicInstanceCall(function_name, arguments_descriptor,
1997 argument_count, deopt_id, token_index, locs,
1998 try_index);
1999 }
2000 }
2001 #undef __
2002 #endif 1886 #endif
2003 1887
2004 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1888 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
2005 // TODO(vegorov) re-enable frame state tracking on DBC. It is 1889 // TODO(vegorov) re-enable frame state tracking on DBC. It is
2006 // currently disabled because it relies on LocationSummaries and 1890 // currently disabled because it relies on LocationSummaries and
2007 // we don't use them during unoptimized compilation on DBC. 1891 // we don't use them during unoptimized compilation on DBC.
2008 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { 1892 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
2009 ASSERT(!is_optimizing()); 1893 ASSERT(!is_optimizing());
2010 1894
2011 switch (instr->tag()) { 1895 switch (instr->tag()) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 1954
2071 1955
2072 void FlowGraphCompiler::FrameStateClear() { 1956 void FlowGraphCompiler::FrameStateClear() {
2073 ASSERT(!is_optimizing()); 1957 ASSERT(!is_optimizing());
2074 frame_state_.TruncateTo(0); 1958 frame_state_.TruncateTo(0);
2075 } 1959 }
2076 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1960 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC)
2077 1961
2078 1962
2079 } // namespace dart 1963 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler.h ('k') | runtime/vm/flow_graph_compiler_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698