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

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

Issue 2098643003: VM: [AOT] Make sure that we inline all resolved accessor invocations. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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 | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/assembler_arm.cc » ('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 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 const intptr_t num_checks = ic_data.NumberOfChecks(); 731 const intptr_t num_checks = ic_data.NumberOfChecks();
732 for (intptr_t i = 0; i < num_checks; i++) { 732 for (intptr_t i = 0; i < num_checks; i++) {
733 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { 733 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) {
734 return false; 734 return false;
735 } 735 }
736 } 736 }
737 return true; 737 return true;
738 } 738 }
739 739
740 740
741 bool AotOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) {
Florian Schneider 2016/06/24 16:09:58 I'd keep this code around: FlowGraphInliner::TryI
Vyacheslav Egorov (Google) 2016/06/24 16:13:04 I think it does not make much sense to keep around
Florian Schneider 2016/06/24 22:48:17 We should make TryInlineRecognizedMethod work with
742 // Check for monomorphic IC data.
743 if (!call->HasICData()) return false;
744 const ICData& ic_data =
745 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
746 if (ic_data.NumberOfChecks() != 1) {
747 return false;
748 }
749 return TryReplaceInstanceCallWithInline(call);
750 }
751
752
753 // Return true if d is a string of length one (a constant or result from 741 // Return true if d is a string of length one (a constant or result from
754 // from string-from-char-code instruction. 742 // from string-from-char-code instruction.
755 static bool IsLengthOneString(Definition* d) { 743 static bool IsLengthOneString(Definition* d) {
756 if (d->IsConstant()) { 744 if (d->IsConstant()) {
757 const Object& obj = d->AsConstant()->value(); 745 const Object& obj = d->AsConstant()->value();
758 if (obj.IsString()) { 746 if (obj.IsString()) {
759 return String::Cast(obj).Length() == 1; 747 return String::Cast(obj).Length() == 1;
760 } else { 748 } else {
761 return false; 749 return false;
762 } 750 }
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); 1610 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0));
1623 if (target.kind() != RawFunction::kImplicitGetter) { 1611 if (target.kind() != RawFunction::kImplicitGetter) {
1624 // Non-implicit getters are inlined like normal methods by conventional 1612 // Non-implicit getters are inlined like normal methods by conventional
1625 // inlining in FlowGraphInliner. 1613 // inlining in FlowGraphInliner.
1626 return false; 1614 return false;
1627 } 1615 }
1628 return InlineImplicitInstanceGetter(call); 1616 return InlineImplicitInstanceGetter(call);
1629 } 1617 }
1630 1618
1631 1619
1632 bool AotOptimizer::TryReplaceInstanceCallWithInline(
1633 InstanceCallInstr* call) {
1634 Function& target = Function::Handle(Z);
1635 GrowableArray<intptr_t> class_ids;
1636 call->ic_data()->GetCheckAt(0, &class_ids, &target);
1637 const intptr_t receiver_cid = class_ids[0];
1638
1639 TargetEntryInstr* entry;
1640 Definition* last;
1641 if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph_,
1642 receiver_cid,
1643 target,
1644 call,
1645 call->ArgumentAt(0),
1646 call->token_pos(),
1647 *call->ic_data(),
1648 &entry, &last)) {
1649 return false;
1650 }
1651
1652 // Insert receiver class check.
1653 AddReceiverCheck(call);
1654 // Remove the original push arguments.
1655 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
1656 PushArgumentInstr* push = call->PushArgumentAt(i);
1657 push->ReplaceUsesWith(push->value()->definition());
1658 push->RemoveFromGraph();
1659 }
1660 // Replace all uses of this definition with the result.
1661 call->ReplaceUsesWith(last);
1662 // Finally insert the sequence other definition in place of this one in the
1663 // graph.
1664 call->previous()->LinkTo(entry->next());
1665 entry->UnuseAllInputs(); // Entry block is not in the graph.
1666 last->LinkTo(call);
1667 // Remove through the iterator.
1668 ASSERT(current_iterator()->Current() == call);
1669 current_iterator()->RemoveCurrentFromGraph();
1670 call->set_previous(NULL);
1671 call->set_next(NULL);
1672 return true;
1673 }
1674
1675
1676 void AotOptimizer::ReplaceWithMathCFunction( 1620 void AotOptimizer::ReplaceWithMathCFunction(
1677 InstanceCallInstr* call, 1621 InstanceCallInstr* call,
1678 MethodRecognizer::Kind recognized_kind) { 1622 MethodRecognizer::Kind recognized_kind) {
1679 AddReceiverCheck(call); 1623 AddReceiverCheck(call);
1680 ZoneGrowableArray<Value*>* args = 1624 ZoneGrowableArray<Value*>* args =
1681 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 1625 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
1682 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 1626 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
1683 args->Add(new(Z) Value(call->ArgumentAt(i))); 1627 args->Add(new(Z) Value(call->ArgumentAt(i)));
1684 } 1628 }
1685 InvokeMathCFunctionInstr* invoke = 1629 InvokeMathCFunctionInstr* invoke =
1686 new(Z) InvokeMathCFunctionInstr(args, 1630 new(Z) InvokeMathCFunctionInstr(args,
1687 call->deopt_id(), 1631 call->deopt_id(),
1688 recognized_kind, 1632 recognized_kind,
1689 call->token_pos()); 1633 call->token_pos());
1690 ReplaceCall(call, invoke); 1634 ReplaceCall(call, invoke);
1691 } 1635 }
1692 1636
1693 1637
1694 static bool IsSupportedByteArrayViewCid(intptr_t cid) {
1695 switch (cid) {
1696 case kTypedDataInt8ArrayCid:
1697 case kTypedDataUint8ArrayCid:
1698 case kExternalTypedDataUint8ArrayCid:
1699 case kTypedDataUint8ClampedArrayCid:
1700 case kExternalTypedDataUint8ClampedArrayCid:
1701 case kTypedDataInt16ArrayCid:
1702 case kTypedDataUint16ArrayCid:
1703 case kTypedDataInt32ArrayCid:
1704 case kTypedDataUint32ArrayCid:
1705 case kTypedDataFloat32ArrayCid:
1706 case kTypedDataFloat64ArrayCid:
1707 case kTypedDataFloat32x4ArrayCid:
1708 case kTypedDataInt32x4ArrayCid:
1709 return true;
1710 default:
1711 return false;
1712 }
1713 }
1714
1715
1716 // Inline only simple, frequently called core library methods.
1717 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
1718 ASSERT(call->HasICData());
1719 const ICData& ic_data = *call->ic_data();
1720 if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) {
1721 // No type feedback collected or multiple targets found.
1722 return false;
1723 }
1724
1725 Function& target = Function::Handle(Z);
1726 GrowableArray<intptr_t> class_ids;
1727 ic_data.GetCheckAt(0, &class_ids, &target);
1728 MethodRecognizer::Kind recognized_kind =
1729 MethodRecognizer::RecognizeKind(target);
1730
1731 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) &&
1732 (ic_data.NumberOfChecks() == 1) &&
1733 (class_ids[0] == kGrowableObjectArrayCid)) {
1734 // This is an internal method, no need to check argument types.
1735 Definition* array = call->ArgumentAt(0);
1736 Definition* value = call->ArgumentAt(1);
1737 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1738 GrowableObjectArray::data_offset(),
1739 new(Z) Value(array),
1740 new(Z) Value(value),
1741 kEmitStoreBarrier,
1742 call->token_pos());
1743 ReplaceCall(call, store);
1744 return true;
1745 }
1746
1747 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) &&
1748 (ic_data.NumberOfChecks() == 1) &&
1749 (class_ids[0] == kGrowableObjectArrayCid)) {
1750 // This is an internal method, no need to check argument types nor
1751 // range.
1752 Definition* array = call->ArgumentAt(0);
1753 Definition* value = call->ArgumentAt(1);
1754 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr(
1755 GrowableObjectArray::length_offset(),
1756 new(Z) Value(array),
1757 new(Z) Value(value),
1758 kNoStoreBarrier,
1759 call->token_pos());
1760 ReplaceCall(call, store);
1761 return true;
1762 }
1763
1764 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) ||
1765 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) ||
1766 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) ||
1767 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt)) {
1768 ASSERT(ic_data.NumberOfChecks() == 1);
1769 ASSERT((class_ids[0] == kOneByteStringCid) ||
1770 (class_ids[0] == kTwoByteStringCid) ||
1771 (class_ids[0] == kExternalOneByteStringCid) ||
1772 (class_ids[0] == kExternalTwoByteStringCid));
1773 return TryReplaceInstanceCallWithInline(call);
1774 }
1775
1776 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) &&
1777 (ic_data.NumberOfChecks() == 1)) {
1778 ASSERT((class_ids[0] == kOneByteStringCid) ||
1779 (class_ids[0] == kTwoByteStringCid) ||
1780 (class_ids[0] == kExternalOneByteStringCid) ||
1781 (class_ids[0] == kExternalTwoByteStringCid));
1782 return TryReplaceInstanceCallWithInline(call);
1783 }
1784
1785 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) {
1786 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
1787 // This is an internal method, no need to check argument types nor
1788 // range.
1789 Definition* str = call->ArgumentAt(0);
1790 Definition* index = call->ArgumentAt(1);
1791 Definition* value = call->ArgumentAt(2);
1792 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr(
1793 new(Z) Value(str),
1794 new(Z) Value(index),
1795 new(Z) Value(value),
1796 kNoStoreBarrier,
1797 1, // Index scale
1798 kOneByteStringCid,
1799 call->deopt_id(),
1800 call->token_pos());
1801 ReplaceCall(call, store_op);
1802 return true;
1803 }
1804 return false;
1805 }
1806
1807 if (CanUnboxDouble() &&
1808 (recognized_kind == MethodRecognizer::kIntegerToDouble) &&
1809 (ic_data.NumberOfChecks() == 1)) {
1810 if (class_ids[0] == kSmiCid) {
1811 AddReceiverCheck(call);
1812 ReplaceCall(call,
1813 new(Z) SmiToDoubleInstr(
1814 new(Z) Value(call->ArgumentAt(0)),
1815 call->token_pos()));
1816 return true;
1817 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) {
1818 AddReceiverCheck(call);
1819 ReplaceCall(call,
1820 new(Z) MintToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
1821 call->deopt_id()));
1822 return true;
1823 }
1824 }
1825
1826 if (class_ids[0] == kDoubleCid) {
1827 if (!CanUnboxDouble()) {
1828 return false;
1829 }
1830 switch (recognized_kind) {
1831 case MethodRecognizer::kDoubleToInteger: {
1832 AddReceiverCheck(call);
1833 ASSERT(call->HasICData());
1834 const ICData& ic_data = *call->ic_data();
1835 Definition* input = call->ArgumentAt(0);
1836 Definition* d2i_instr = NULL;
1837 if (ic_data.HasDeoptReason(ICData::kDeoptDoubleToSmi)) {
1838 // Do not repeatedly deoptimize because result didn't fit into Smi.
1839 d2i_instr = new(Z) DoubleToIntegerInstr(
1840 new(Z) Value(input), call);
1841 } else {
1842 // Optimistically assume result fits into Smi.
1843 d2i_instr = new(Z) DoubleToSmiInstr(
1844 new(Z) Value(input), call->deopt_id());
1845 }
1846 ReplaceCall(call, d2i_instr);
1847 return true;
1848 }
1849 case MethodRecognizer::kDoubleMod:
1850 case MethodRecognizer::kDoubleRound:
1851 ReplaceWithMathCFunction(call, recognized_kind);
1852 return true;
1853 case MethodRecognizer::kDoubleTruncate:
1854 case MethodRecognizer::kDoubleFloor:
1855 case MethodRecognizer::kDoubleCeil:
1856 if (!TargetCPUFeatures::double_truncate_round_supported()) {
1857 ReplaceWithMathCFunction(call, recognized_kind);
1858 } else {
1859 AddReceiverCheck(call);
1860 DoubleToDoubleInstr* d2d_instr =
1861 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
1862 recognized_kind, call->deopt_id());
1863 ReplaceCall(call, d2d_instr);
1864 }
1865 return true;
1866 case MethodRecognizer::kDoubleAdd:
1867 case MethodRecognizer::kDoubleSub:
1868 case MethodRecognizer::kDoubleMul:
1869 case MethodRecognizer::kDoubleDiv:
1870 return TryReplaceInstanceCallWithInline(call);
1871 default:
1872 // Unsupported method.
1873 return false;
1874 }
1875 }
1876
1877 if (IsSupportedByteArrayViewCid(class_ids[0]) &&
1878 (ic_data.NumberOfChecks() == 1)) {
1879 return TryReplaceInstanceCallWithInline(call);
1880 }
1881
1882 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1883 return TryInlineFloat32x4Method(call, recognized_kind);
1884 }
1885
1886 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1887 return TryInlineInt32x4Method(call, recognized_kind);
1888 }
1889
1890 if ((class_ids[0] == kFloat64x2Cid) && (ic_data.NumberOfChecks() == 1)) {
1891 return TryInlineFloat64x2Method(call, recognized_kind);
1892 }
1893
1894 return false;
1895 }
1896
1897
1898 bool AotOptimizer::TryInlineFloat32x4Constructor( 1638 bool AotOptimizer::TryInlineFloat32x4Constructor(
1899 StaticCallInstr* call, 1639 StaticCallInstr* call,
1900 MethodRecognizer::Kind recognized_kind) { 1640 MethodRecognizer::Kind recognized_kind) {
1901 // Cannot handle unboxed instructions. 1641 // Cannot handle unboxed instructions.
1902 ASSERT(FLAG_precompiled_mode); 1642 ASSERT(FLAG_precompiled_mode);
1903 return false; 1643 return false;
1904 } 1644 }
1905 1645
1906 1646
1907 bool AotOptimizer::TryInlineFloat64x2Constructor( 1647 bool AotOptimizer::TryInlineFloat64x2Constructor(
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2285 } 2025 }
2286 // If all of the inputs are known smis or the result of CheckedSmiOp, 2026 // If all of the inputs are known smis or the result of CheckedSmiOp,
2287 // we guess the operand to be likely smi. 2027 // we guess the operand to be likely smi.
2288 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) { 2028 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
2289 if (!instr->ArgumentAt(i)->IsCheckedSmiOp()) return false; 2029 if (!instr->ArgumentAt(i)->IsCheckedSmiOp()) return false;
2290 } 2030 }
2291 return true; 2031 return true;
2292 } 2032 }
2293 2033
2294 2034
2035 bool AotOptimizer::TryInlineFieldAccess(InstanceCallInstr* call) {
2036 const Token::Kind op_kind = call->token_kind();
2037 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(call)) {
2038 return true;
2039 }
2040
2041 const ICData& unary_checks =
2042 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks());
2043 if ((unary_checks.NumberOfChecks() > 0) &&
2044 (op_kind == Token::kSET) &&
2045 TryInlineInstanceSetter(call, unary_checks)) {
2046 return true;
2047 }
2048
2049 return false;
2050 }
2051
2052
2295 // Tries to optimize instance call by replacing it with a faster instruction 2053 // Tries to optimize instance call by replacing it with a faster instruction
2296 // (e.g, binary op, field load, ..). 2054 // (e.g, binary op, field load, ..).
2297 void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { 2055 void AotOptimizer::VisitInstanceCall(InstanceCallInstr* instr) {
2298 ASSERT(FLAG_precompiled_mode); 2056 ASSERT(FLAG_precompiled_mode);
2299 // TODO(srdjan): Investigate other attempts, as they are not allowed to 2057 // TODO(srdjan): Investigate other attempts, as they are not allowed to
2300 // deoptimize. 2058 // deoptimize.
2301 2059
2302 // Type test is special as it always gets converted into inlined code. 2060 // Type test is special as it always gets converted into inlined code.
2303 const Token::Kind op_kind = instr->token_kind(); 2061 const Token::Kind op_kind = instr->token_kind();
2304 if (Token::IsTypeTestOperator(op_kind)) { 2062 if (Token::IsTypeTestOperator(op_kind)) {
2305 ReplaceWithInstanceOf(instr); 2063 ReplaceWithInstanceOf(instr);
2306 return; 2064 return;
2307 } 2065 }
2308 if (Token::IsTypeCastOperator(op_kind)) { 2066 if (Token::IsTypeCastOperator(op_kind)) {
2309 ReplaceWithTypeCast(instr); 2067 ReplaceWithTypeCast(instr);
2310 return; 2068 return;
2311 } 2069 }
2312 2070
2313 if ((op_kind == Token::kGET) && 2071 if (TryInlineFieldAccess(instr)) {
2314 TryInlineInstanceGetter(instr)) {
2315 return;
2316 }
2317 const ICData& unary_checks =
2318 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
2319 if ((unary_checks.NumberOfChecks() > 0) &&
2320 (op_kind == Token::kSET) &&
2321 TryInlineInstanceSetter(instr, unary_checks)) {
2322 return; 2072 return;
2323 } 2073 }
2324 2074
2075 const ICData& unary_checks =
2076 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
2325 if (IsAllowedForInlining(instr->deopt_id()) && 2077 if (IsAllowedForInlining(instr->deopt_id()) &&
2326 (unary_checks.NumberOfChecks() > 0)) { 2078 (unary_checks.NumberOfChecks() > 0)) {
2327 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) {
2328 return;
2329 }
2330 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) {
2331 return;
2332 }
2333 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) { 2079 if ((op_kind == Token::kEQ) && TryReplaceWithEqualityOp(instr, op_kind)) {
2334 return; 2080 return;
2335 } 2081 }
2336 2082
2337 if (Token::IsRelationalOperator(op_kind) && 2083 if (Token::IsRelationalOperator(op_kind) &&
2338 TryReplaceWithRelationalOp(instr, op_kind)) { 2084 TryReplaceWithRelationalOp(instr, op_kind)) {
2339 return; 2085 return;
2340 } 2086 }
2341 2087
2342 if (Token::IsBinaryOperator(op_kind) && 2088 if (Token::IsBinaryOperator(op_kind) &&
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2506 2252
2507 single_target = Function::null(); 2253 single_target = Function::null();
2508 } 2254 }
2509 2255
2510 ASSERT(ic_data.raw() != ICData::null()); 2256 ASSERT(ic_data.raw() != ICData::null());
2511 ASSERT(single_target.raw() == Function::null()); 2257 ASSERT(single_target.raw() == Function::null());
2512 ic_data.AddReceiverCheck(cid, target); 2258 ic_data.AddReceiverCheck(cid, target);
2513 } 2259 }
2514 2260
2515 if (single_target.raw() != Function::null()) { 2261 if (single_target.raw() != Function::null()) {
2262 // If this is a getter or setter invocation try inlining it right away
2263 // instead of replacing it with a static call.
2264 if ((op_kind == Token::kGET) || (op_kind == Token::kSET)) {
2265 // Create fake IC data with the resolved target.
2266 const ICData& ic_data = ICData::Handle(
2267 ICData::New(flow_graph_->function(),
2268 instr->function_name(),
2269 args_desc_array,
2270 Thread::kNoDeoptId,
2271 /* args_tested = */ 1,
2272 false));
2273 cls = single_target.Owner();
2274 ic_data.AddReceiverCheck(cls.id(), single_target);
2275 instr->set_ic_data(&ic_data);
2276
2277 if (TryInlineFieldAccess(instr)) {
2278 return;
2279 }
2280 }
2281
2516 // We have computed that there is only a single target for this call 2282 // We have computed that there is only a single target for this call
2517 // within the whole hierarchy. Replace InstanceCall with StaticCall. 2283 // within the whole hierarchy. Replace InstanceCall with StaticCall.
2518 ZoneGrowableArray<PushArgumentInstr*>* args = 2284 ZoneGrowableArray<PushArgumentInstr*>* args =
2519 new (Z) ZoneGrowableArray<PushArgumentInstr*>( 2285 new (Z) ZoneGrowableArray<PushArgumentInstr*>(
2520 instr->ArgumentCount()); 2286 instr->ArgumentCount());
2521 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { 2287 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
2522 args->Add(instr->PushArgumentAt(i)); 2288 args->Add(instr->PushArgumentAt(i));
2523 } 2289 }
2524 StaticCallInstr* call = new (Z) StaticCallInstr( 2290 StaticCallInstr* call = new (Z) StaticCallInstr(
2525 instr->token_pos(), 2291 instr->token_pos(),
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
2778 2544
2779 // Discard the environment from the original instruction because the store 2545 // Discard the environment from the original instruction because the store
2780 // can't deoptimize. 2546 // can't deoptimize.
2781 instr->RemoveEnvironment(); 2547 instr->RemoveEnvironment();
2782 ReplaceCall(instr, store); 2548 ReplaceCall(instr, store);
2783 return true; 2549 return true;
2784 } 2550 }
2785 2551
2786 2552
2787 } // namespace dart 2553 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/assembler_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698