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

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: Feedback from Slava 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 16 matching lines...) Expand all
27 #include "vm/stub_code.h" 27 #include "vm/stub_code.h"
28 #include "vm/symbols.h" 28 #include "vm/symbols.h"
29 #include "vm/timeline.h" 29 #include "vm/timeline.h"
30 30
31 namespace dart { 31 namespace dart {
32 32
33 DEFINE_FLAG(bool, 33 DEFINE_FLAG(bool,
34 enable_simd_inline, 34 enable_simd_inline,
35 true, 35 true,
36 "Enable inlining of SIMD related method calls."); 36 "Enable inlining of SIMD related method calls.");
37 DEFINE_FLAG(
38 bool,
39 inline_smi_string_hashcode,
40 true,
41 "Inline hashcode for Smi and one-byte strings in case of megamorphic call");
42 DEFINE_FLAG(
43 int,
44 inline_smi_string_hashcode_ratio,
45 50,
46 "Minimal hotness (0..100) of one-byte-string before inlining its hashcode");
47 DEFINE_FLAG(int, 37 DEFINE_FLAG(int,
48 min_optimization_counter_threshold, 38 min_optimization_counter_threshold,
49 5000, 39 5000,
50 "The minimum invocation count for a function."); 40 "The minimum invocation count for a function.");
51 DEFINE_FLAG(int, 41 DEFINE_FLAG(int,
52 optimization_counter_scale, 42 optimization_counter_scale,
53 2000, 43 2000,
54 "The scale of invocation count, by size of the function."); 44 "The scale of invocation count, by size of the function.");
55 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment."); 45 DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
56 DEFINE_FLAG(bool, 46 DEFINE_FLAG(bool,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 if (it.CurrentLocation().IsInvalid()) { 135 if (it.CurrentLocation().IsInvalid()) {
146 MaterializeObjectInstr* mat = 136 MaterializeObjectInstr* mat =
147 it.CurrentValue()->definition()->AsMaterializeObject(); 137 it.CurrentValue()->definition()->AsMaterializeObject();
148 ASSERT(mat != NULL); 138 ASSERT(mat != NULL);
149 builder->AddMaterialization(mat); 139 builder->AddMaterialization(mat);
150 } 140 }
151 } 141 }
152 } 142 }
153 143
154 144
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;
175 }
176 return false;
177 }
178
179
180 FlowGraphCompiler::FlowGraphCompiler( 145 FlowGraphCompiler::FlowGraphCompiler(
181 Assembler* assembler, 146 Assembler* assembler,
182 FlowGraph* flow_graph, 147 FlowGraph* flow_graph,
183 const ParsedFunction& parsed_function, 148 const ParsedFunction& parsed_function,
184 bool is_optimizing, 149 bool is_optimizing,
185 const GrowableArray<const Function*>& inline_id_to_function, 150 const GrowableArray<const Function*>& inline_id_to_function,
186 const GrowableArray<TokenPosition>& inline_id_to_token_pos, 151 const GrowableArray<TokenPosition>& inline_id_to_token_pos,
187 const GrowableArray<intptr_t>& caller_inline_id) 152 const GrowableArray<intptr_t>& caller_inline_id)
188 : thread_(Thread::Current()), 153 : thread_(Thread::Current()),
189 zone_(Thread::Current()->zone()), 154 zone_(Thread::Current()->zone()),
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1611 } 1576 }
1612 1577
1613 1578
1614 ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() { 1579 ParallelMoveResolver::ScratchRegisterScope::~ScratchRegisterScope() {
1615 if (spilled_) { 1580 if (spilled_) {
1616 resolver_->RestoreScratch(reg_); 1581 resolver_->RestoreScratch(reg_);
1617 } 1582 }
1618 } 1583 }
1619 1584
1620 1585
1621 static int HighestCountFirst(const CidTarget* a, const CidTarget* b) { 1586 template <typename T>
1587 static int HighestCountFirst(const T* a, const T* b) {
1622 // Negative if 'a' should sort before 'b'. 1588 // Negative if 'a' should sort before 'b'.
1623 return b->count - a->count; 1589 return b->count - a->count;
1624 } 1590 }
1625 1591
1626 1592
1593 static int LowestCidFirst(const CidRangeTarget* a, const CidRangeTarget* b) {
1594 // Negative if 'a' should sort before 'b'.
1595 return a->cid_start - b->cid_start;
1596 }
1597
1598
1627 // Returns 'sorted' array in decreasing count order. 1599 // Returns 'sorted' array in decreasing count order.
1628 // The expected number of elements to sort is less than 10. 1600 // The expected number of elements to sort is less than 10.
1629 void FlowGraphCompiler::SortICDataByCount(const ICData& ic_data, 1601 void FlowGraphCompiler::SortICDataByCount(
1630 GrowableArray<CidTarget>* sorted, 1602 const ICData& ic_data,
1631 bool drop_smi) { 1603 GrowableArray<CidRangeTarget>* sorted_arg,
1604 bool drop_smi) {
1605 GrowableArray<CidRangeTarget>& sorted = *sorted_arg;
1632 ASSERT(ic_data.NumArgsTested() == 1); 1606 ASSERT(ic_data.NumArgsTested() == 1);
1633 const intptr_t len = ic_data.NumberOfChecks(); 1607 const intptr_t len = ic_data.NumberOfChecks();
1634 sorted->Clear(); 1608 sorted.Clear();
1635 1609
1636 for (int i = 0; i < len; i++) { 1610 for (int i = 0; i < len; i++) {
1637 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i); 1611 intptr_t receiver_cid = ic_data.GetReceiverClassIdAt(i);
1638 if (drop_smi && (receiver_cid == kSmiCid)) continue; 1612 if (drop_smi && (receiver_cid == kSmiCid)) continue;
1639 sorted->Add(CidTarget(receiver_cid, 1613 Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
1640 &Function::ZoneHandle(ic_data.GetTargetAt(i)), 1614 sorted.Add(CidRangeTarget(receiver_cid, receiver_cid, &target,
1641 ic_data.GetCountAt(i))); 1615 ic_data.GetCountAt(i)));
1642 } 1616 }
1643 sorted->Sort(HighestCountFirst); 1617 sorted.Sort(LowestCidFirst);
1618 int dest = 0;
1619
1620 // Merge adjacent ranges.
1621 for (int src = 0; src < sorted.length(); src++) {
1622 if (src > 0 && sorted[src - 1].cid_end + 1 == sorted[src].cid_start &&
1623 sorted[src - 1].target->raw() == sorted[src].target->raw()) {
1624 sorted[dest - 1].cid_end++;
1625 sorted[dest - 1].count += sorted[dest].count;
1626 } else {
1627 sorted[dest++] = sorted[src];
1628 }
1629 }
1630
1631 sorted.SetLength(dest);
1632 sorted.Sort(HighestCountFirst);
1644 } 1633 }
1645 1634
1646 1635
1647 const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData( 1636 const ICData* FlowGraphCompiler::GetOrAddInstanceCallICData(
1648 intptr_t deopt_id, 1637 intptr_t deopt_id,
1649 const String& target_name, 1638 const String& target_name,
1650 const Array& arguments_descriptor, 1639 const Array& arguments_descriptor,
1651 intptr_t num_args_tested) { 1640 intptr_t num_args_tested) {
1652 if ((deopt_id_to_ic_data_ != NULL) && 1641 if ((deopt_id_to_ic_data_ != NULL) &&
1653 ((*deopt_id_to_ic_data_)[deopt_id] != NULL)) { 1642 ((*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)); 1764 ic_data.deopt_id(), ic_data.NumArgsTested(), false));
1776 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons()); 1765 new_ic_data.SetDeoptReasons(ic_data.DeoptReasons());
1777 new_ic_data.AddReceiverCheck(cid, function, count); 1766 new_ic_data.AddReceiverCheck(cid, function, count);
1778 return new_ic_data; 1767 return new_ic_data;
1779 } 1768 }
1780 1769
1781 return ic_data; 1770 return ic_data;
1782 } 1771 }
1783 1772
1784 1773
1774 intptr_t FlowGraphCompiler::ComputeGoodBiasForCidComparison(
1775 const GrowableArray<CidRangeTarget>& sorted,
1776 intptr_t max_immediate) {
1777 // Sometimes a bias can be useful so we can emit more compact compare
1778 // instructions.
1779 intptr_t min_cid = 1000000;
1780 intptr_t max_cid = -1;
1781
1782 const intptr_t sorted_len = sorted.length();
1783
1784 for (intptr_t i = 0; i < sorted_len + 1; i++) {
1785 bool done = (i == sorted_len);
1786 intptr_t start = done ? 0 : sorted[i].cid_start;
1787 intptr_t end = done ? 0 : sorted[i].cid_end;
1788 bool is_range = start != end;
1789 bool spread_too_big = start - min_cid > max_immediate;
1790 if (done || is_range || spread_too_big) {
1791 if (i >= 2 && max_cid - min_cid <= max_immediate &&
1792 max_cid > max_immediate) {
1793 return min_cid;
1794 } else {
1795 return 0;
1796 }
1797 }
1798 min_cid = Utils::Minimum(min_cid, start);
1799 max_cid = Utils::Maximum(max_cid, end);
1800 }
1801 UNREACHABLE();
1802 return 0;
1803 }
1804
1805
1785 #if !defined(TARGET_ARCH_DBC) 1806 #if !defined(TARGET_ARCH_DBC)
1786 // DBC emits calls very differently from other architectures due to its 1807 // DBC emits calls very differently from other architectures due to its
1787 // interpreted nature. 1808 // interpreted nature.
1788 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data, 1809 void FlowGraphCompiler::EmitPolymorphicInstanceCall(const ICData& ic_data,
1789 intptr_t argument_count, 1810 intptr_t argument_count,
1790 const Array& argument_names, 1811 const Array& argument_names,
1791 intptr_t deopt_id, 1812 intptr_t deopt_id,
1792 TokenPosition token_pos, 1813 TokenPosition token_pos,
1793 LocationSummary* locs, 1814 LocationSummary* locs,
1794 bool complete) { 1815 bool complete,
1816 intptr_t total_ic_calls) {
1795 if (FLAG_polymorphic_with_deopt) { 1817 if (FLAG_polymorphic_with_deopt) {
1796 Label* deopt = 1818 Label* deopt =
1797 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail); 1819 AddDeoptStub(deopt_id, ICData::kDeoptPolymorphicInstanceCallTestFail);
1798 Label ok; 1820 Label ok;
1799 EmitTestAndCall(ic_data, argument_count, argument_names, 1821 EmitTestAndCall(ic_data, argument_count, argument_names,
1800 deopt, // No cid match. 1822 deopt, // No cid match.
1801 &ok, // Found cid. 1823 &ok, // Found cid.
1802 deopt_id, token_pos, locs, complete); 1824 deopt_id, token_pos, locs, complete, total_ic_calls);
1803 assembler()->Bind(&ok); 1825 assembler()->Bind(&ok);
1804 } else { 1826 } else {
1805 if (complete) { 1827 if (complete) {
1806 Label ok; 1828 Label ok;
1807 EmitTestAndCall(ic_data, argument_count, argument_names, 1829 EmitTestAndCall(ic_data, argument_count, argument_names,
1808 NULL, // No cid match. 1830 NULL, // No cid match.
1809 &ok, // Found cid. 1831 &ok, // Found cid.
1810 deopt_id, token_pos, locs, true); 1832 deopt_id, token_pos, locs, true, total_ic_calls);
1811 assembler()->Bind(&ok); 1833 assembler()->Bind(&ok);
1812 } else { 1834 } else {
1813 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos, 1835 EmitSwitchableInstanceCall(ic_data, argument_count, deopt_id, token_pos,
1814 locs); 1836 locs);
1815 } 1837 }
1816 } 1838 }
1817 } 1839 }
1818 #endif 1840 #endif
1819 1841
1820 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1842 #if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 1908
1887 1909
1888 void FlowGraphCompiler::FrameStateClear() { 1910 void FlowGraphCompiler::FrameStateClear() {
1889 ASSERT(!is_optimizing()); 1911 ASSERT(!is_optimizing());
1890 frame_state_.TruncateTo(0); 1912 frame_state_.TruncateTo(0);
1891 } 1913 }
1892 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC) 1914 #endif // defined(DEBUG) && !defined(TARGET_ARCH_DBC)
1893 1915
1894 1916
1895 } // namespace dart 1917 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698