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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
145 if (it.CurrentLocation().IsInvalid()) { | 145 if (it.CurrentLocation().IsInvalid()) { |
146 MaterializeObjectInstr* mat = | 146 MaterializeObjectInstr* mat = |
147 it.CurrentValue()->definition()->AsMaterializeObject(); | 147 it.CurrentValue()->definition()->AsMaterializeObject(); |
148 ASSERT(mat != NULL); | 148 ASSERT(mat != NULL); |
149 builder->AddMaterialization(mat); | 149 builder->AddMaterialization(mat); |
150 } | 150 } |
151 } | 151 } |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 // Returns true if OnebyteString is a frequent receiver class. We inline | |
156 // Smi check as well, since a Smi check must be done anyway. | |
157 // TODO(srdjan): Add check and code if Smi class is hot. | |
158 bool FlowGraphCompiler::ShouldInlineSmiStringHashCode(const ICData& ic_data) { | |
159 if (!FLAG_inline_smi_string_hashcode || | |
160 (ic_data.target_name() != Symbols::hashCode().raw())) { | |
161 return false; | |
162 } | |
163 // Precompiled code has no ICData, optimistically inline it. | |
164 if (ic_data.IsNull() || ic_data.NumberOfChecksIs(0)) { | |
165 return true; | |
166 } | |
167 // Check if OneByteString is hot enough. | |
168 const ICData& ic_data_sorted = | |
169 ICData::Handle(ic_data.AsUnaryClassChecksSortedByCount()); | |
170 ASSERT(!ic_data_sorted.NumberOfChecksIs(0)); | |
171 if (ic_data_sorted.GetReceiverClassIdAt(0) == kOneByteStringCid) { | |
172 const intptr_t total_count = ic_data_sorted.AggregateCount(); | |
173 const intptr_t ratio = (ic_data_sorted.GetCountAt(0) * 100) / total_count; | |
174 return ratio > FLAG_inline_smi_string_hashcode_ratio; | |
Vyacheslav Egorov (Google)
2017/03/10 10:31:30
if you killed the code, kill the flag.
but also w
erikcorry
2017/03/10 13:30:01
Flag killed.
It was introduced here with no expla
| |
175 } | |
176 return false; | |
177 } | |
178 | |
179 | |
180 FlowGraphCompiler::FlowGraphCompiler( | 155 FlowGraphCompiler::FlowGraphCompiler( |
181 Assembler* assembler, | 156 Assembler* assembler, |
182 FlowGraph* flow_graph, | 157 FlowGraph* flow_graph, |
183 const ParsedFunction& parsed_function, | 158 const ParsedFunction& parsed_function, |
184 bool is_optimizing, | 159 bool is_optimizing, |
185 const GrowableArray<const Function*>& inline_id_to_function, | 160 const GrowableArray<const Function*>& inline_id_to_function, |
186 const GrowableArray<TokenPosition>& inline_id_to_token_pos, | 161 const GrowableArray<TokenPosition>& inline_id_to_token_pos, |
187 const GrowableArray<intptr_t>& caller_inline_id) | 162 const GrowableArray<intptr_t>& caller_inline_id) |
188 : thread_(Thread::Current()), | 163 : thread_(Thread::Current()), |
189 zone_(Thread::Current()->zone()), | 164 zone_(Thread::Current()->zone()), |
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1611 } | 1586 } |
1612 | 1587 |
1613 | 1588 |
1614 ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() { | 1589 ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() { |
1615 if (spilled_) { | 1590 if (spilled_) { |
1616 resolver_->RestoreScratch(reg_); | 1591 resolver_->RestoreScratch(reg_); |
1617 } | 1592 } |
1618 } | 1593 } |
1619 | 1594 |
1620 | 1595 |
1621 static int HighestCountFirst(const CidTarget* a, const CidTarget* b) { | 1596 template <typename T> |
1597 static int HighestCountFirst(const T* a, const T* b) { | |
1622 // Negative if 'a' should sort before 'b'. | 1598 // Negative if 'a' should sort before 'b'. |
1623 return b->count - a->count; | 1599 return b->count - a->count; |
1624 } | 1600 } |
1625 | 1601 |
1626 | 1602 |
1603 static int LowestCidFirst(const CidRangeTarget* a, const CidRangeTarget* b) { | |
1604 // Negative if 'a' should sort before 'b'. | |
1605 return a->cid_start - b->cid_start; | |
1606 } | |
1607 | |
1608 | |
1627 // Returns 'sorted' array in decreasing count order. | 1609 // Returns 'sorted' array in decreasing count order. |
1628 // The expected number of elements to sort is less than 10. | 1610 // The expected number of elements to sort is less than 10. |
1629 void FlowGraphCompiler::SortICDataByCount(const ICData& ic_data, | 1611 void FlowGraphCompiler::SortICDataByCount( |
1630 GrowableArray<CidTarget>* sorted, | 1612 const ICData& ic_data, |
1631 bool drop_smi) { | 1613 GrowableArray<CidRangeTarget>* sorted_arg, |
1614 bool drop_smi) { | |
1615 GrowableArray<CidRangeTarget>& sorted = *sorted_arg; | |
1632 ASSERT(ic_data.NumArgsTested() == 1); | 1616 ASSERT(ic_data.NumArgsTested() == 1); |
1633 const intptr_t len = ic_data.NumberOfChecks(); | 1617 const intptr_t len = ic_data.NumberOfChecks(); |
1634 sorted->Clear(); | 1618 sorted.Clear(); |
1635 | 1619 |
1636 for (int i = 0; i < len; i++) { | 1620 for (int i = 0; i < len; i++) { |
1637 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i); | 1621 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i); |
1638 if (drop_smi && (receiver_cid == kSmiCid)) continue; | 1622 if (drop_smi && (receiver_cid == kSmiCid)) continue; |
1639 sorted->Add(CidTarget(receiver_cid, | 1623 Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
1640 &Function::ZoneHandle(ic_data.GetTargetAt(i)), | 1624 sorted.Add(CidRangeTarget(receiver_cid, receiver_cid, &target, |
1641 ic_data.GetCountAt(i))); | 1625 ic_data.GetCountAt(i))); |
1642 } | 1626 } |
1643 sorted->Sort(HighestCountFirst); | 1627 sorted.Sort(LowestCidFirst); |
1628 int dest = 0; | |
1629 | |
1630 // Merge adjacent ranges. | |
1631 for (int src = 0; src < sorted.length(); src++) { | |
1632 if (src > 0 && sorted[src - 1].cid_end + 1 == sorted[src].cid_start && | |
1633 sorted[src - 1].target->raw() == sorted[src].target->raw()) { | |
1634 sorted[dest - 1].cid_end++; | |
1635 sorted[dest - 1].count += sorted[dest].count; | |
1636 } else { | |
1637 sorted[dest++] = sorted[src]; | |
1638 } | |
1639 } | |
1640 | |
1641 sorted.SetLength(dest); | |
1642 sorted.Sort(HighestCountFirst); | |
1644 } | 1643 } |
1645 | 1644 |
1646 | 1645 |
1647 const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData( | 1646 const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData( |
1648 intptr_t deopt_id, | 1647 intptr_t deopt_id, |
1649 const String& target_name, | 1648 const String& target_name, |
1650 const Array& arguments_descriptor, | 1649 const Array& arguments_descriptor, |
1651 intptr_t num_args_tested) { | 1650 intptr_t num_args_tested) { |
1652 if ((deopt_id_to_ic_data_ != NULL) && | 1651 if ((deopt_id_to_ic_data_ != NULL) && |
1653 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { | 1652 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1775 ic_data.deopt_id(), ic_data.NumArgsTested(), false)); | 1774 ic_data.deopt_id(), ic_data.NumArgsTested(), false)); |
1776 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); | 1775 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); |
1777 new_ic_data.AddReceiverCheck(cid, function, count); | 1776 new_ic_data.AddReceiverCheck(cid, function, count); |
1778 return new_ic_data; | 1777 return new_ic_data; |
1779 } | 1778 } |
1780 | 1779 |
1781 return ic_data; | 1780 return ic_data; |
1782 } | 1781 } |
1783 | 1782 |
1784 | 1783 |
1784 intptr_t FlowGraphCompiler::GetGoodBias( | |
1785 const GrowableArray<CidRangeTarget>& sorted, | |
1786 intptr_t max_immediate) { | |
1787 // Sometimes a bias can be useful so we can emit more compact compare | |
1788 // instructions. | |
1789 intptr_t min_cid = 1000000; | |
1790 intptr_t max_cid = -1; | |
1791 | |
1792 const intptr_t sorted_len = sorted.length(); | |
1793 | |
1794 for (intptr_t i = 0; i < sorted_len + 1; i++) { | |
1795 bool done = (i == sorted_len); | |
1796 intptr_t start = done ? 0 : sorted[i].cid_start; | |
1797 intptr_t end = done ? 0 : sorted[i].cid_end; | |
1798 bool is_range = start != end; | |
1799 bool spread_too_big = start - min_cid > max_immediate; | |
1800 if (done || is_range || spread_too_big) { | |
1801 if (i >= 2 && max_cid - min_cid <= max_immediate && | |
1802 max_cid > max_immediate) { | |
1803 return min_cid; | |
1804 } else { | |
1805 return 0; | |
1806 } | |
1807 } | |
1808 min_cid = Utils::Minimum(min_cid, start); | |
1809 max_cid = Utils::Maximum(max_cid, end); | |
1810 } | |
1811 UNREACHABLE(); | |
1812 return 0; | |
1813 } | |
1814 | |
1815 | |
1785 #if !defined(TARGET_ARCH_DBC) | 1816 #if !defined(TARGET_ARCH_DBC) |
1786 // DBC emits calls very differently from other architectures due to its | 1817 // DBC emits calls very differently from other architectures due to its |
1787 // interpreted nature. | 1818 // interpreted nature. |
1788 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data, | 1819 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data, |
1789 intptr_t argument_count, | 1820 intptr_t argument_count, |
1790 const Array& argument_names, | 1821 const Array& argument_names, |
1791 intptr_t deopt_id, | 1822 intptr_t deopt_id, |
1792 TokenPosition token_pos, | 1823 TokenPosition token_pos, |
1793 LocationSummary* locs, | 1824 LocationSummary* locs, |
1794 bool complete) { | 1825 bool complete, |
1826 intptr_t total_ic_calls) { | |
1795 if (FLAG_polymorphic_with_deopt) { | 1827 if (FLAG_polymorphic_with_deopt) { |
1796 Label* deopt = | 1828 Label* deopt = |
1797 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); | 1829 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); |
1798 Label ok; | 1830 Label ok; |
1799 EmitTestAndCall(ic_data, argument_count, argument_names, | 1831 EmitTestAndCall(ic_data, argument_count, argument_names, |
1800 deopt, // No cid match. | 1832 deopt, // No cid match. |
1801 &ok, // Found cid. | 1833 &ok, // Found cid. |
1802 deopt_id, token_pos, locs, complete); | 1834 deopt_id, token_pos, locs, complete, total_ic_calls); |
1803 assembler()->Bind(&ok); | 1835 assembler()->Bind(&ok); |
1804 } else { | 1836 } else { |
1805 if (complete) { | 1837 if (complete) { |
1806 Label ok; | 1838 Label ok; |
1807 EmitTestAndCall(ic_data, argument_count, argument_names, | 1839 EmitTestAndCall(ic_data, argument_count, argument_names, |
1808 NULL, // No cid match. | 1840 NULL, // No cid match. |
1809 &ok, // Found cid. | 1841 &ok, // Found cid. |
1810 deopt_id, token_pos, locs, true); | 1842 deopt_id, token_pos, locs, true, total_ic_calls); |
1811 assembler()->Bind(&ok); | 1843 assembler()->Bind(&ok); |
1812 } else { | 1844 } else { |
1813 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos, | 1845 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos, |
1814 locs); | 1846 locs); |
1815 } | 1847 } |
1816 } | 1848 } |
1817 } | 1849 } |
1818 #endif | 1850 #endif |
1819 | 1851 |
1820 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 1852 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1886 | 1918 |
1887 | 1919 |
1888 void FlowGraphCompiler::FrameStateClear() { | 1920 void FlowGraphCompiler::FrameStateClear() { |
1889 ASSERT(!is_optimizing()); | 1921 ASSERT(!is_optimizing()); |
1890 frame_state_.TruncateTo(0); | 1922 frame_state_.TruncateTo(0); |
1891 } | 1923 } |
1892 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) | 1924 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) |
1893 | 1925 |
1894 | 1926 |
1895 } // namespace dart | 1927 } // namespace dart |
OLD | NEW |