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

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

Issue 2737303003: Allow dispatch to use a range of Class-ids in tests (Closed)
Patch Set: Created 3 years, 9 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"
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698