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

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

Issue 2809583002: 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
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"
26 #include "vm/stack_frame.h" 27 #include "vm/stack_frame.h"
27 #include "vm/stub_code.h" 28 #include "vm/stub_code.h"
28 #include "vm/symbols.h" 29 #include "vm/symbols.h"
29 #include "vm/timeline.h" 30 #include "vm/timeline.h"
30 31
31 namespace dart { 32 namespace dart {
32 33
33 DEFINE_FLAG(bool, 34 DEFINE_FLAG(bool,
34 enable_simd_inline, 35 enable_simd_inline,
35 true, 36 true,
(...skipping 1126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 *StubCode::TwoArgsOptimizedCheckInlineCache_entry(), ic_data, 1163 *StubCode::TwoArgsOptimizedCheckInlineCache_entry(), ic_data,
1163 argument_count, deopt_id, token_pos, locs); 1164 argument_count, deopt_id, token_pos, locs);
1164 return; 1165 return;
1165 default: 1166 default:
1166 UNIMPLEMENTED(); 1167 UNIMPLEMENTED();
1167 } 1168 }
1168 return; 1169 return;
1169 } 1170 }
1170 1171
1171 if (is_optimizing()) { 1172 if (is_optimizing()) {
1172 EmitMegamorphicInstanceCall(ic_data_in, argument_count, deopt_id, token_pos, 1173 String& name = String::Handle(ic_data_in.target_name());
1173 locs, CatchClauseNode::kInvalidTryIndex); 1174 Array& arguments_descriptor =
1175 Array::Handle(ic_data_in.arguments_descriptor());
1176 EmitMegamorphicInstanceCall(name, arguments_descriptor, argument_count,
1177 deopt_id, token_pos, locs,
1178 CatchClauseNode::kInvalidTryIndex);
1174 return; 1179 return;
1175 } 1180 }
1176 1181
1177 switch (ic_data.NumArgsTested()) { 1182 switch (ic_data.NumArgsTested()) {
1178 case 1: 1183 case 1:
1179 EmitInstanceCall(*StubCode::OneArgCheckInlineCache_entry(), ic_data, 1184 EmitInstanceCall(*StubCode::OneArgCheckInlineCache_entry(), ic_data,
1180 argument_count, deopt_id, token_pos, locs); 1185 argument_count, deopt_id, token_pos, locs);
1181 break; 1186 break;
1182 case 2: 1187 case 2:
1183 EmitInstanceCall(*StubCode::TwoArgsCheckInlineCache_entry(), ic_data, 1188 EmitInstanceCall(*StubCode::TwoArgsCheckInlineCache_entry(), ic_data,
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 static int LowestCidFirst(const CidRangeTarget* a, const CidRangeTarget* b) { 1644 static int LowestCidFirst(const CidRangeTarget* a, const CidRangeTarget* b) {
1640 // Negative if 'a' should sort before 'b'. 1645 // Negative if 'a' should sort before 'b'.
1641 return a->cid_start - b->cid_start; 1646 return a->cid_start - b->cid_start;
1642 } 1647 }
1643 1648
1644 1649
1645 // Returns 'sorted' array in decreasing count order. 1650 // Returns 'sorted' array in decreasing count order.
1646 // The expected number of elements to sort is less than 10. 1651 // The expected number of elements to sort is less than 10.
1647 void FlowGraphCompiler::SortICDataByCount( 1652 void FlowGraphCompiler::SortICDataByCount(
1648 const ICData& ic_data, 1653 const ICData& ic_data,
1649 GrowableArray<CidRangeTarget>* sorted_arg, 1654 ZoneGrowableArray<CidRangeTarget>* sorted_arg,
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 why did this suddenly become ZoneGrowableArray?
erikcorry 2017/04/19 15:06:39 Undone.
1650 bool drop_smi) { 1655 bool drop_smi) {
1651 GrowableArray<CidRangeTarget>& sorted = *sorted_arg; 1656 ZoneGrowableArray<CidRangeTarget>& sorted = *sorted_arg;
1652 ASSERT(ic_data.NumArgsTested() == 1); 1657 ASSERT(ic_data.NumArgsTested() == 1);
1653 const intptr_t len = ic_data.NumberOfChecks(); 1658 const intptr_t len = ic_data.NumberOfChecks();
1654 sorted.Clear(); 1659 sorted.Clear();
1655 1660
1656 for (int i = 0; i < len; i++) { 1661 for (int i = 0; i < len; i++) {
1657 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i); 1662 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i);
1658 if (drop_smi && (receiver_cid == kSmiCid)) continue; 1663 if (drop_smi && (receiver_cid == kSmiCid)) continue;
1659 Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); 1664 Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
1660 sorted.Add(CidRangeTarget(receiver_cid, receiver_cid, &target, 1665 sorted.Add(CidRangeTarget(receiver_cid, receiver_cid, &target,
1661 ic_data.GetCountAt(i))); 1666 ic_data.GetCountAt(i)));
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1780 code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize()); 1785 code_source_map_builder_->BeginCodeSourceRange(assembler()->CodeSize());
1781 } 1786 }
1782 1787
1783 1788
1784 void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) { 1789 void FlowGraphCompiler::EndCodeSourceRange(TokenPosition token_pos) {
1785 code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(), 1790 code_source_map_builder_->EndCodeSourceRange(assembler()->CodeSize(),
1786 token_pos); 1791 token_pos);
1787 } 1792 }
1788 1793
1789 1794
1790 const ICData& FlowGraphCompiler::TrySpecializeICDataByReceiverCid( 1795 const PolymorphicTargets* FlowGraphCompiler::TrySpecializeByReceiverCid(
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 I think this name now is confusing given that we d
erikcorry 2017/04/19 15:06:39 Done.
1791 const ICData& ic_data, 1796 const Array& args_desc_array,
1797 const String& selector,
1792 intptr_t cid) { 1798 intptr_t cid) {
1793 Zone* zone = Thread::Current()->zone(); 1799 Zone* zone = Thread::Current()->zone();
1794 if (ic_data.NumArgsTested() != 1) return ic_data;
1795 1800
1796 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { 1801 ArgumentsDescriptor args_desc(args_desc_array);
1797 return ic_data; // Nothing to do
1798 }
1799 1802
1800 intptr_t count = 1; 1803 Function& fn = Function::Handle(zone);
1801 const Function& function = 1804 if (!LookupMethodFor(cid, args_desc, selector, &fn)) return NULL;
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 Similar here: natural arguments order should proba
erikcorry 2017/04/19 15:06:39 Done.
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 }
1815 1805
1816 return ic_data; 1806 PolymorphicTargets* targets = new (zone) PolymorphicTargets(zone);
1807 targets->Add(CidRangeTarget(cid, cid, &fn, 1));
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 this 1 needs a comment, e.g. /*count=*/1
erikcorry 2017/04/19 15:06:39 Done.
1808
1809 return targets;
1817 } 1810 }
1818 1811
1819 1812
1820 intptr_t FlowGraphCompiler::ComputeGoodBiasForCidComparison( 1813 intptr_t FlowGraphCompiler::ComputeGoodBiasForCidComparison(
1821 const GrowableArray<CidRangeTarget>& sorted, 1814 const PolymorphicTargets& sorted,
1822 intptr_t max_immediate) { 1815 intptr_t max_immediate) {
1823 // Sometimes a bias can be useful so we can emit more compact compare 1816 // Sometimes a bias can be useful so we can emit more compact compare
1824 // instructions. 1817 // instructions.
1825 intptr_t min_cid = 1000000; 1818 intptr_t min_cid = 1000000;
1826 intptr_t max_cid = -1; 1819 intptr_t max_cid = -1;
1827 1820
1828 const intptr_t sorted_len = sorted.length(); 1821 const intptr_t sorted_len = sorted.length();
1829 1822
1830 for (intptr_t i = 0; i < sorted_len + 1; i++) { 1823 for (intptr_t i = 0; i < sorted_len + 1; i++) {
1831 bool done = (i == sorted_len); 1824 bool done = (i == sorted_len);
(...skipping 10 matching lines...) Expand all
1842 } 1835 }
1843 } 1836 }
1844 min_cid = Utils::Minimum(min_cid, start); 1837 min_cid = Utils::Minimum(min_cid, start);
1845 max_cid = Utils::Maximum(max_cid, end); 1838 max_cid = Utils::Maximum(max_cid, end);
1846 } 1839 }
1847 UNREACHABLE(); 1840 UNREACHABLE();
1848 return 0; 1841 return 0;
1849 } 1842 }
1850 1843
1851 1844
1845 bool FlowGraphCompiler::LookupMethodFor(int class_id,
1846 const ArgumentsDescriptor& args_desc,
1847 const String& name,
1848 Function* fn_return) {
1849 Thread* thread = Thread::Current();
1850 Isolate* isolate = thread->isolate();
1851 Zone* zone = thread->zone();
1852 if (class_id < 0) return false;
1853 if (class_id >= isolate->class_table()->NumCids()) return false;
1854
1855 RawClass* raw_class = isolate->class_table()->At(class_id);
1856 if (raw_class == NULL) return false;
1857 Class& cls = Class::Handle(zone, raw_class);
1858 if (cls.IsNull()) return false;
1859 if (!cls.is_finalized()) return false;
1860 if (Array::Handle(cls.functions()).IsNull()) return false;
1861
1862 Function& target_function =
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 for named arguments I suggest: const bool allow_a
erikcorry 2017/04/19 15:06:39 Done.
1863 Function::Handle(zone, Resolver::ResolveDynamicForReceiverClass(
1864 cls, name, args_desc, false /* allow add */));
1865 if (target_function.IsNull()) return false;
1866 *fn_return ^= target_function.raw();
1867 return true;
1868 }
1869
1870
1852 #if !defined(TARGET_ARCH_DBC) 1871 #if !defined(TARGET_ARCH_DBC)
1853 // DBC emits calls very differently from other architectures due to its 1872 // DBC emits calls very differently from other architectures due to its
1854 // interpreted nature. 1873 // interpreted nature.
1855 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data, 1874 void FlowGraphCompiler::EmitPolymorphicInstanceCall(
1856 intptr_t argument_count, 1875 const PolymorphicTargets& targets,
1857 const Array& argument_names, 1876 const InstanceCallInstr& original_call_insn,
Vyacheslav Egorov (Google) 2017/04/10 10:59:27 maybe just original_call instead of original_call_
erikcorry 2017/04/19 15:06:39 Done.
1858 intptr_t deopt_id, 1877 intptr_t argument_count,
1859 TokenPosition token_pos, 1878 const Array& argument_names,
1860 LocationSummary* locs, 1879 intptr_t deopt_id,
1861 bool complete, 1880 TokenPosition token_pos,
1862 intptr_t total_ic_calls) { 1881 LocationSummary* locs,
1882 bool complete,
1883 intptr_t total_ic_calls) {
1863 if (FLAG_polymorphic_with_deopt) { 1884 if (FLAG_polymorphic_with_deopt) {
1864 Label* deopt = 1885 Label* deopt =
1865 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); 1886 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
1866 Label ok; 1887 Label ok;
1867 EmitTestAndCall(ic_data, argument_count, argument_names, 1888 EmitTestAndCall(targets, original_call_insn.function_name(), argument_count,
1889 argument_names,
1868 deopt, // No cid match. 1890 deopt, // No cid match.
1869 &ok, // Found cid. 1891 &ok, // Found cid.
1870 deopt_id, token_pos, locs, complete, total_ic_calls); 1892 deopt_id, token_pos, locs, complete, total_ic_calls);
1871 assembler()->Bind(&ok); 1893 assembler()->Bind(&ok);
1872 } else { 1894 } else {
1873 if (complete) { 1895 if (complete) {
1874 Label ok; 1896 Label ok;
1875 EmitTestAndCall(ic_data, argument_count, argument_names, 1897 EmitTestAndCall(targets, original_call_insn.function_name(),
1898 argument_count, argument_names,
1876 NULL, // No cid match. 1899 NULL, // No cid match.
1877 &ok, // Found cid. 1900 &ok, // Found cid.
1878 deopt_id, token_pos, locs, true, total_ic_calls); 1901 deopt_id, token_pos, locs, true, total_ic_calls);
1879 assembler()->Bind(&ok); 1902 assembler()->Bind(&ok);
1880 } else { 1903 } else {
1881 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos, 1904 const ICData& unary_checks = ICData::ZoneHandle(
1882 locs); 1905 zone(), original_call_insn.ic_data()->AsUnaryClassChecks());
1906 EmitSwitchableInstanceCall(unary_checks, argument_count, deopt_id,
1907 token_pos, locs);
1883 } 1908 }
1884 } 1909 }
1885 } 1910 }
1886 #endif 1911 #endif
1887 1912
1888 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1913 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
1889 // TODO(vegorov) re-enable frame state tracking on DBC. It is 1914 // TODO(vegorov) re-enable frame state tracking on DBC. It is
1890 // currently disabled because it relies on LocationSummaries and 1915 // currently disabled because it relies on LocationSummaries and
1891 // we don't use them during unoptimized compilation on DBC. 1916 // we don't use them during unoptimized compilation on DBC.
1892 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) { 1917 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 1979
1955 1980
1956 void FlowGraphCompiler::FrameStateClear() { 1981 void FlowGraphCompiler::FrameStateClear() {
1957 ASSERT(!is_optimizing()); 1982 ASSERT(!is_optimizing());
1958 frame_state_.TruncateTo(0); 1983 frame_state_.TruncateTo(0);
1959 } 1984 }
1960 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1985 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC)
1961 1986
1962 1987
1963 } // namespace dart 1988 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698