Chromium Code Reviews| 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" |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |