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

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

Issue 2102663003: Refactor inlining of recognized methods. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed missing inlining, more cleanup Created 4 years, 5 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
« no previous file with comments | « no previous file | runtime/vm/flow_graph_inliner.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/aot_optimizer.h" 5 #include "vm/aot_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 739
740 740
741 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { 741 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
742 // Check for monomorphic IC data. 742 // Check for monomorphic IC data.
743 if (!call->HasICData()) return false; 743 if (!call->HasICData()) return false;
744 const ICData& ic_data = 744 const ICData& ic_data =
745 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); 745 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
746 if (ic_data.NumberOfChecks() != 1) { 746 if (ic_data.NumberOfChecks() != 1) {
747 return false; 747 return false;
748 } 748 }
749 return TryReplaceInstanceCallWithInline(call); 749 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
750 flow_graph_, current_iterator(), call);
750 } 751 }
751 752
752 753
753 // Return true if d is a string of length one (a constant or result from 754 // Return true if d is a string of length one (a constant or result from
754 // from string-from-char-code instruction. 755 // from string-from-char-code instruction.
755 static bool IsLengthOneString(Definition* d) { 756 static bool IsLengthOneString(Definition* d) {
756 if (d->IsConstant()) { 757 if (d->IsConstant()) {
757 const Object& obj = d->AsConstant()->value(); 758 const Object& obj = d->AsConstant()->value();
758 if (obj.IsString()) { 759 if (obj.IsString()) {
759 return String::Cast(obj).Length() == 1; 760 return String::Cast(obj).Length() == 1;
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); 1623 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0));
1623 if (target.kind() != RawFunction::kImplicitGetter) { 1624 if (target.kind() != RawFunction::kImplicitGetter) {
1624 // Non-implicit getters are inlined like normal methods by conventional 1625 // Non-implicit getters are inlined like normal methods by conventional
1625 // inlining in FlowGraphInliner. 1626 // inlining in FlowGraphInliner.
1626 return false; 1627 return false;
1627 } 1628 }
1628 return InlineImplicitInstanceGetter(call); 1629 return InlineImplicitInstanceGetter(call);
1629 } 1630 }
1630 1631
1631 1632
1632 bool AotOptimizer::TryReplaceInstanceCallWithInline(
1633 InstanceCallInstr* call) {
1634 if (!IsAllowedForInlining(call->deopt_id())) return false;
1635 Function& target = Function::Handle(Z);
1636 GrowableArray<intptr_t> class_ids;
1637 call->ic_data()->GetCheckAt(0, &class_ids, &target);
1638 const intptr_t receiver_cid = class_ids[0];
1639
1640 TargetEntryInstr* entry;
1641 Definition* last;
1642 if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph_,
1643 receiver_cid,
1644 target,
1645 call,
1646 call->ArgumentAt(0),
1647 call->token_pos(),
1648 *call->ic_data(),
1649 &entry, &last)) {
1650 return false;
1651 }
1652
1653 // Insert receiver class check.
1654 AddReceiverCheck(call);
1655 // Remove the original push arguments.
1656 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
1657 PushArgumentInstr* push = call->PushArgumentAt(i);
1658 push->ReplaceUsesWith(push->value()->definition());
1659 push->RemoveFromGraph();
1660 }
1661 // Replace all uses of this definition with the result.
1662 call->ReplaceUsesWith(last);
1663 // Finally insert the sequence other definition in place of this one in the
1664 // graph.
1665 call->previous()->LinkTo(entry->next());
1666 entry->UnuseAllInputs(); // Entry block is not in the graph.
1667 last->LinkTo(call);
1668 // Remove through the iterator.
1669 ASSERT(current_iterator()->Current() == call);
1670 current_iterator()->RemoveCurrentFromGraph();
1671 call->set_previous(NULL);
1672 call->set_next(NULL);
1673 return true;
1674 }
1675
1676
1677 void AotOptimizer::ReplaceWithMathCFunction( 1633 void AotOptimizer::ReplaceWithMathCFunction(
1678 InstanceCallInstr* call, 1634 InstanceCallInstr* call,
1679 MethodRecognizer::Kind recognized_kind) { 1635 MethodRecognizer::Kind recognized_kind) {
1680 AddReceiverCheck(call); 1636 AddReceiverCheck(call);
1681 ZoneGrowableArray<Value*>* args = 1637 ZoneGrowableArray<Value*>* args =
1682 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 1638 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
1683 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 1639 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
1684 args->Add(new(Z) Value(call->ArgumentAt(i))); 1640 args->Add(new(Z) Value(call->ArgumentAt(i)));
1685 } 1641 }
1686 InvokeMathCFunctionInstr* invoke = 1642 InvokeMathCFunctionInstr* invoke =
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 // No type feedback collected or multiple targets found. 1678 // No type feedback collected or multiple targets found.
1723 return false; 1679 return false;
1724 } 1680 }
1725 1681
1726 Function& target = Function::Handle(Z); 1682 Function& target = Function::Handle(Z);
1727 GrowableArray<intptr_t> class_ids; 1683 GrowableArray<intptr_t> class_ids;
1728 ic_data.GetCheckAt(0, &class_ids, &target); 1684 ic_data.GetCheckAt(0, &class_ids, &target);
1729 MethodRecognizer::Kind recognized_kind = 1685 MethodRecognizer::Kind recognized_kind =
1730 MethodRecognizer::RecognizeKind(target); 1686 MethodRecognizer::RecognizeKind(target);
1731 1687
1732 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) &&
1733 (ic_data.NumberOfChecks() == 1) &&
1734 (class_ids[0] == kGrowableObjectArrayCid)) {
1735 // This is an internal method, no need to check argument types.
1736 Definition* array = call->ArgumentAt(0);
1737 Definition* value = call->ArgumentAt(1);
1738 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1739 GrowableObjectArray::data_offset(),
1740 new(Z) Value(array),
1741 new(Z) Value(value),
1742 kEmitStoreBarrier,
1743 call->token_pos());
1744 ReplaceCall(call, store);
1745 return true;
1746 }
1747
1748 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) &&
1749 (ic_data.NumberOfChecks() == 1) &&
1750 (class_ids[0] == kGrowableObjectArrayCid)) {
1751 // This is an internal method, no need to check argument types nor
1752 // range.
1753 Definition* array = call->ArgumentAt(0);
1754 Definition* value = call->ArgumentAt(1);
1755 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1756 GrowableObjectArray::length_offset(),
1757 new(Z) Value(array),
1758 new(Z) Value(value),
1759 kNoStoreBarrier,
1760 call->token_pos());
1761 ReplaceCall(call, store);
1762 return true;
1763 }
1764
1765 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || 1688 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) ||
1766 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || 1689 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) ||
1767 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || 1690 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) ||
1768 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt)) { 1691 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) ||
1692 (recognized_kind == MethodRecognizer::kGrowableArraySetData) ||
1693 (recognized_kind == MethodRecognizer::kGrowableArraySetLength)) {
1769 ASSERT(ic_data.NumberOfChecks() == 1); 1694 ASSERT(ic_data.NumberOfChecks() == 1);
1770 ASSERT((class_ids[0] == kOneByteStringCid) || 1695 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1771 (class_ids[0] == kTwoByteStringCid) || 1696 flow_graph_, current_iterator(), call);
1772 (class_ids[0] == kExternalOneByteStringCid) ||
1773 (class_ids[0] == kExternalTwoByteStringCid));
1774 return TryReplaceInstanceCallWithInline(call);
1775 } 1697 }
1776 1698
1777 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && 1699 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
1778 (ic_data.NumberOfChecks() == 1)) { 1700 (ic_data.NumberOfChecks() == 1)) {
1779 ASSERT((class_ids[0] == kOneByteStringCid) || 1701 ASSERT((class_ids[0] == kOneByteStringCid) ||
1780 (class_ids[0] == kTwoByteStringCid) || 1702 (class_ids[0] == kTwoByteStringCid) ||
1781 (class_ids[0] == kExternalOneByteStringCid) || 1703 (class_ids[0] == kExternalOneByteStringCid) ||
1782 (class_ids[0] == kExternalTwoByteStringCid)); 1704 (class_ids[0] == kExternalTwoByteStringCid));
1783 return TryReplaceInstanceCallWithInline(call); 1705 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1706 flow_graph_, current_iterator(), call);
1784 } 1707 }
1785 1708
1786 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { 1709 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) {
1787 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { 1710 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
1788 // This is an internal method, no need to check argument types nor 1711 // This is an internal method, no need to check argument types nor
1789 // range. 1712 // range.
1790 Definition* str = call->ArgumentAt(0); 1713 Definition* str = call->ArgumentAt(0);
1791 Definition* index = call->ArgumentAt(1); 1714 Definition* index = call->ArgumentAt(1);
1792 Definition* value = call->ArgumentAt(2); 1715 Definition* value = call->ArgumentAt(2);
1793 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( 1716 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1861 DoubleToDoubleInstr* d2d_instr = 1784 DoubleToDoubleInstr* d2d_instr =
1862 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), 1785 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
1863 recognized_kind, call->deopt_id()); 1786 recognized_kind, call->deopt_id());
1864 ReplaceCall(call, d2d_instr); 1787 ReplaceCall(call, d2d_instr);
1865 } 1788 }
1866 return true; 1789 return true;
1867 case MethodRecognizer::kDoubleAdd: 1790 case MethodRecognizer::kDoubleAdd:
1868 case MethodRecognizer::kDoubleSub: 1791 case MethodRecognizer::kDoubleSub:
1869 case MethodRecognizer::kDoubleMul: 1792 case MethodRecognizer::kDoubleMul:
1870 case MethodRecognizer::kDoubleDiv: 1793 case MethodRecognizer::kDoubleDiv:
1871 return TryReplaceInstanceCallWithInline(call); 1794 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1795 flow_graph_, current_iterator(), call);
1872 default: 1796 default:
1873 // Unsupported method. 1797 // Unsupported method.
1874 return false; 1798 return false;
1875 } 1799 }
1876 } 1800 }
1877 1801
1878 if (IsSupportedByteArrayViewCid(class_ids[0]) && 1802 if (IsSupportedByteArrayViewCid(class_ids[0]) &&
1879 (ic_data.NumberOfChecks() == 1)) { 1803 (ic_data.NumberOfChecks() == 1)) {
1880 return TryReplaceInstanceCallWithInline(call); 1804 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1805 flow_graph_, current_iterator(), call);
1881 } 1806 }
1882 1807
1883 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { 1808 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1884 return TryInlineFloat32x4Method(call, recognized_kind); 1809 return TryInlineFloat32x4Method(call, recognized_kind);
1885 } 1810 }
1886 1811
1887 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) { 1812 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1888 return TryInlineInt32x4Method(call, recognized_kind); 1813 return TryInlineInt32x4Method(call, recognized_kind);
1889 } 1814 }
1890 1815
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 2740
2816 // Discard the environment from the original instruction because the store 2741 // Discard the environment from the original instruction because the store
2817 // can't deoptimize. 2742 // can't deoptimize.
2818 instr->RemoveEnvironment(); 2743 instr->RemoveEnvironment();
2819 ReplaceCall(instr, store); 2744 ReplaceCall(instr, store);
2820 return true; 2745 return true;
2821 } 2746 }
2822 2747
2823 2748
2824 } // namespace dart 2749 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_inliner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698