| 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/jit_optimizer.h" | 5 #include "vm/jit_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 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 | 734 |
| 735 | 735 |
| 736 bool JitOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { | 736 bool JitOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { |
| 737 // Check for monomorphic IC data. | 737 // Check for monomorphic IC data. |
| 738 if (!call->HasICData()) return false; | 738 if (!call->HasICData()) return false; |
| 739 const ICData& ic_data = | 739 const ICData& ic_data = |
| 740 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); | 740 ICData::Handle(Z, call->ic_data()->AsUnaryClassChecks()); |
| 741 if (ic_data.NumberOfChecks() != 1) { | 741 if (ic_data.NumberOfChecks() != 1) { |
| 742 return false; | 742 return false; |
| 743 } | 743 } |
| 744 return TryReplaceInstanceCallWithInline(call); | 744 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 745 flow_graph_, current_iterator(), call); |
| 745 } | 746 } |
| 746 | 747 |
| 747 | 748 |
| 748 // Return true if d is a string of length one (a constant or result from | 749 // Return true if d is a string of length one (a constant or result from |
| 749 // from string-from-char-code instruction. | 750 // from string-from-char-code instruction. |
| 750 static bool IsLengthOneString(Definition* d) { | 751 static bool IsLengthOneString(Definition* d) { |
| 751 if (d->IsConstant()) { | 752 if (d->IsConstant()) { |
| 752 const Object& obj = d->AsConstant()->value(); | 753 const Object& obj = d->AsConstant()->value(); |
| 753 if (obj.IsString()) { | 754 if (obj.IsString()) { |
| 754 return String::Cast(obj).Length() == 1; | 755 return String::Cast(obj).Length() == 1; |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); | 1629 const Function& target = Function::Handle(Z, ic_data.GetTargetAt(0)); |
| 1629 if (target.kind() != RawFunction::kImplicitGetter) { | 1630 if (target.kind() != RawFunction::kImplicitGetter) { |
| 1630 // Non-implicit getters are inlined like normal methods by conventional | 1631 // Non-implicit getters are inlined like normal methods by conventional |
| 1631 // inlining in FlowGraphInliner. | 1632 // inlining in FlowGraphInliner. |
| 1632 return false; | 1633 return false; |
| 1633 } | 1634 } |
| 1634 return InlineImplicitInstanceGetter(call); | 1635 return InlineImplicitInstanceGetter(call); |
| 1635 } | 1636 } |
| 1636 | 1637 |
| 1637 | 1638 |
| 1638 bool JitOptimizer::TryReplaceInstanceCallWithInline( | |
| 1639 InstanceCallInstr* call) { | |
| 1640 Function& target = Function::Handle(Z); | |
| 1641 GrowableArray<intptr_t> class_ids; | |
| 1642 call->ic_data()->GetCheckAt(0, &class_ids, &target); | |
| 1643 const intptr_t receiver_cid = class_ids[0]; | |
| 1644 | |
| 1645 TargetEntryInstr* entry; | |
| 1646 Definition* last; | |
| 1647 if (!FlowGraphInliner::TryInlineRecognizedMethod(flow_graph_, | |
| 1648 receiver_cid, | |
| 1649 target, | |
| 1650 call, | |
| 1651 call->ArgumentAt(0), | |
| 1652 call->token_pos(), | |
| 1653 *call->ic_data(), | |
| 1654 &entry, &last)) { | |
| 1655 return false; | |
| 1656 } | |
| 1657 | |
| 1658 // Insert receiver class check. | |
| 1659 AddReceiverCheck(call); | |
| 1660 // Remove the original push arguments. | |
| 1661 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | |
| 1662 PushArgumentInstr* push = call->PushArgumentAt(i); | |
| 1663 push->ReplaceUsesWith(push->value()->definition()); | |
| 1664 push->RemoveFromGraph(); | |
| 1665 } | |
| 1666 // Replace all uses of this definition with the result. | |
| 1667 call->ReplaceUsesWith(last); | |
| 1668 // Finally insert the sequence other definition in place of this one in the | |
| 1669 // graph. | |
| 1670 call->previous()->LinkTo(entry->next()); | |
| 1671 entry->UnuseAllInputs(); // Entry block is not in the graph. | |
| 1672 last->LinkTo(call); | |
| 1673 // Remove through the iterator. | |
| 1674 ASSERT(current_iterator()->Current() == call); | |
| 1675 current_iterator()->RemoveCurrentFromGraph(); | |
| 1676 call->set_previous(NULL); | |
| 1677 call->set_next(NULL); | |
| 1678 return true; | |
| 1679 } | |
| 1680 | |
| 1681 | |
| 1682 void JitOptimizer::ReplaceWithMathCFunction( | 1639 void JitOptimizer::ReplaceWithMathCFunction( |
| 1683 InstanceCallInstr* call, | 1640 InstanceCallInstr* call, |
| 1684 MethodRecognizer::Kind recognized_kind) { | 1641 MethodRecognizer::Kind recognized_kind) { |
| 1685 AddReceiverCheck(call); | 1642 AddReceiverCheck(call); |
| 1686 ZoneGrowableArray<Value*>* args = | 1643 ZoneGrowableArray<Value*>* args = |
| 1687 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); | 1644 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); |
| 1688 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | 1645 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { |
| 1689 args->Add(new(Z) Value(call->ArgumentAt(i))); | 1646 args->Add(new(Z) Value(call->ArgumentAt(i))); |
| 1690 } | 1647 } |
| 1691 InvokeMathCFunctionInstr* invoke = | 1648 InvokeMathCFunctionInstr* invoke = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1727 // No type feedback collected or multiple targets found. | 1684 // No type feedback collected or multiple targets found. |
| 1728 return false; | 1685 return false; |
| 1729 } | 1686 } |
| 1730 | 1687 |
| 1731 Function& target = Function::Handle(Z); | 1688 Function& target = Function::Handle(Z); |
| 1732 GrowableArray<intptr_t> class_ids; | 1689 GrowableArray<intptr_t> class_ids; |
| 1733 ic_data.GetCheckAt(0, &class_ids, &target); | 1690 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1734 MethodRecognizer::Kind recognized_kind = | 1691 MethodRecognizer::Kind recognized_kind = |
| 1735 MethodRecognizer::RecognizeKind(target); | 1692 MethodRecognizer::RecognizeKind(target); |
| 1736 | 1693 |
| 1737 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | |
| 1738 (ic_data.NumberOfChecks() == 1) && | |
| 1739 (class_ids[0] == kGrowableObjectArrayCid)) { | |
| 1740 // This is an internal method, no need to check argument types. | |
| 1741 Definition* array = call->ArgumentAt(0); | |
| 1742 Definition* value = call->ArgumentAt(1); | |
| 1743 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | |
| 1744 GrowableObjectArray::data_offset(), | |
| 1745 new(Z) Value(array), | |
| 1746 new(Z) Value(value), | |
| 1747 kEmitStoreBarrier, | |
| 1748 call->token_pos()); | |
| 1749 ReplaceCall(call, store); | |
| 1750 return true; | |
| 1751 } | |
| 1752 | |
| 1753 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | |
| 1754 (ic_data.NumberOfChecks() == 1) && | |
| 1755 (class_ids[0] == kGrowableObjectArrayCid)) { | |
| 1756 // This is an internal method, no need to check argument types nor | |
| 1757 // range. | |
| 1758 Definition* array = call->ArgumentAt(0); | |
| 1759 Definition* value = call->ArgumentAt(1); | |
| 1760 StoreInstanceFieldInstr* store = new(Z) StoreInstanceFieldInstr( | |
| 1761 GrowableObjectArray::length_offset(), | |
| 1762 new(Z) Value(array), | |
| 1763 new(Z) Value(value), | |
| 1764 kNoStoreBarrier, | |
| 1765 call->token_pos()); | |
| 1766 ReplaceCall(call, store); | |
| 1767 return true; | |
| 1768 } | |
| 1769 | |
| 1770 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || | 1694 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || |
| 1771 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || | 1695 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || |
| 1772 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || | 1696 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || |
| 1773 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt)) { | 1697 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) || |
| 1698 (recognized_kind == MethodRecognizer::kGrowableArraySetData) || |
| 1699 (recognized_kind == MethodRecognizer::kGrowableArraySetLength)) { |
| 1774 ASSERT(ic_data.NumberOfChecks() == 1); | 1700 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1775 ASSERT((class_ids[0] == kOneByteStringCid) || | 1701 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1776 (class_ids[0] == kTwoByteStringCid) || | 1702 flow_graph_, current_iterator(), call); |
| 1777 (class_ids[0] == kExternalOneByteStringCid) || | |
| 1778 (class_ids[0] == kExternalTwoByteStringCid)); | |
| 1779 return TryReplaceInstanceCallWithInline(call); | |
| 1780 } | 1703 } |
| 1781 | 1704 |
| 1782 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && | 1705 if ((recognized_kind == MethodRecognizer::kStringBaseCharAt) && |
| 1783 (ic_data.NumberOfChecks() == 1)) { | 1706 (ic_data.NumberOfChecks() == 1)) { |
| 1784 ASSERT((class_ids[0] == kOneByteStringCid) || | 1707 ASSERT((class_ids[0] == kOneByteStringCid) || |
| 1785 (class_ids[0] == kTwoByteStringCid) || | 1708 (class_ids[0] == kTwoByteStringCid) || |
| 1786 (class_ids[0] == kExternalOneByteStringCid) || | 1709 (class_ids[0] == kExternalOneByteStringCid) || |
| 1787 (class_ids[0] == kExternalTwoByteStringCid)); | 1710 (class_ids[0] == kExternalTwoByteStringCid)); |
| 1788 return TryReplaceInstanceCallWithInline(call); | 1711 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1712 flow_graph_, current_iterator(), call); |
| 1789 } | 1713 } |
| 1790 | 1714 |
| 1791 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 1715 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 1792 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 1716 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 1793 // This is an internal method, no need to check argument types nor | 1717 // This is an internal method, no need to check argument types nor |
| 1794 // range. | 1718 // range. |
| 1795 Definition* str = call->ArgumentAt(0); | 1719 Definition* str = call->ArgumentAt(0); |
| 1796 Definition* index = call->ArgumentAt(1); | 1720 Definition* index = call->ArgumentAt(1); |
| 1797 Definition* value = call->ArgumentAt(2); | 1721 Definition* value = call->ArgumentAt(2); |
| 1798 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( | 1722 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1866 DoubleToDoubleInstr* d2d_instr = | 1790 DoubleToDoubleInstr* d2d_instr = |
| 1867 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), | 1791 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), |
| 1868 recognized_kind, call->deopt_id()); | 1792 recognized_kind, call->deopt_id()); |
| 1869 ReplaceCall(call, d2d_instr); | 1793 ReplaceCall(call, d2d_instr); |
| 1870 } | 1794 } |
| 1871 return true; | 1795 return true; |
| 1872 case MethodRecognizer::kDoubleAdd: | 1796 case MethodRecognizer::kDoubleAdd: |
| 1873 case MethodRecognizer::kDoubleSub: | 1797 case MethodRecognizer::kDoubleSub: |
| 1874 case MethodRecognizer::kDoubleMul: | 1798 case MethodRecognizer::kDoubleMul: |
| 1875 case MethodRecognizer::kDoubleDiv: | 1799 case MethodRecognizer::kDoubleDiv: |
| 1876 return TryReplaceInstanceCallWithInline(call); | 1800 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1801 flow_graph_, current_iterator(), call); |
| 1877 default: | 1802 default: |
| 1878 // Unsupported method. | 1803 // Unsupported method. |
| 1879 return false; | 1804 return false; |
| 1880 } | 1805 } |
| 1881 } | 1806 } |
| 1882 | 1807 |
| 1883 if (IsSupportedByteArrayViewCid(class_ids[0]) && | 1808 if (IsSupportedByteArrayViewCid(class_ids[0]) && |
| 1884 (ic_data.NumberOfChecks() == 1)) { | 1809 (ic_data.NumberOfChecks() == 1)) { |
| 1885 return TryReplaceInstanceCallWithInline(call); | 1810 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1811 flow_graph_, current_iterator(), call); |
| 1886 } | 1812 } |
| 1887 | 1813 |
| 1888 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 1814 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
| 1889 return TryInlineFloat32x4Method(call, recognized_kind); | 1815 return TryInlineFloat32x4Method(call, recognized_kind); |
| 1890 } | 1816 } |
| 1891 | 1817 |
| 1892 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 1818 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
| 1893 return TryInlineInt32x4Method(call, recognized_kind); | 1819 return TryInlineInt32x4Method(call, recognized_kind); |
| 1894 } | 1820 } |
| 1895 | 1821 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2034 return InlineFloat32x4Getter(call, recognized_kind); | 1960 return InlineFloat32x4Getter(call, recognized_kind); |
| 2035 | 1961 |
| 2036 case MethodRecognizer::kFloat32x4Equal: | 1962 case MethodRecognizer::kFloat32x4Equal: |
| 2037 case MethodRecognizer::kFloat32x4GreaterThan: | 1963 case MethodRecognizer::kFloat32x4GreaterThan: |
| 2038 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 1964 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 2039 case MethodRecognizer::kFloat32x4LessThan: | 1965 case MethodRecognizer::kFloat32x4LessThan: |
| 2040 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 1966 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 2041 case MethodRecognizer::kFloat32x4NotEqual: { | 1967 case MethodRecognizer::kFloat32x4NotEqual: { |
| 2042 Definition* left = call->ArgumentAt(0); | 1968 Definition* left = call->ArgumentAt(0); |
| 2043 Definition* right = call->ArgumentAt(1); | 1969 Definition* right = call->ArgumentAt(1); |
| 2044 // Type check left. | |
| 2045 AddCheckClass(left, | |
| 2046 ICData::ZoneHandle( | |
| 2047 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2048 call->deopt_id(), | |
| 2049 call->env(), | |
| 2050 call); | |
| 2051 // Replace call. | |
| 2052 Float32x4ComparisonInstr* cmp = | 1970 Float32x4ComparisonInstr* cmp = |
| 2053 new(Z) Float32x4ComparisonInstr(recognized_kind, | 1971 new(Z) Float32x4ComparisonInstr(recognized_kind, |
| 2054 new(Z) Value(left), | 1972 new(Z) Value(left), |
| 2055 new(Z) Value(right), | 1973 new(Z) Value(right), |
| 2056 call->deopt_id()); | 1974 call->deopt_id()); |
| 2057 ReplaceCall(call, cmp); | 1975 ReplaceCall(call, cmp); |
| 2058 return true; | 1976 return true; |
| 2059 } | 1977 } |
| 2060 case MethodRecognizer::kFloat32x4Min: | 1978 case MethodRecognizer::kFloat32x4Min: |
| 2061 case MethodRecognizer::kFloat32x4Max: { | 1979 case MethodRecognizer::kFloat32x4Max: { |
| 2062 Definition* left = call->ArgumentAt(0); | 1980 Definition* left = call->ArgumentAt(0); |
| 2063 Definition* right = call->ArgumentAt(1); | 1981 Definition* right = call->ArgumentAt(1); |
| 2064 // Type check left. | |
| 2065 AddCheckClass(left, | |
| 2066 ICData::ZoneHandle( | |
| 2067 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2068 call->deopt_id(), | |
| 2069 call->env(), | |
| 2070 call); | |
| 2071 Float32x4MinMaxInstr* minmax = | 1982 Float32x4MinMaxInstr* minmax = |
| 2072 new(Z) Float32x4MinMaxInstr( | 1983 new(Z) Float32x4MinMaxInstr( |
| 2073 recognized_kind, | 1984 recognized_kind, |
| 2074 new(Z) Value(left), | 1985 new(Z) Value(left), |
| 2075 new(Z) Value(right), | 1986 new(Z) Value(right), |
| 2076 call->deopt_id()); | 1987 call->deopt_id()); |
| 2077 ReplaceCall(call, minmax); | 1988 ReplaceCall(call, minmax); |
| 2078 return true; | 1989 return true; |
| 2079 } | 1990 } |
| 2080 case MethodRecognizer::kFloat32x4Scale: { | 1991 case MethodRecognizer::kFloat32x4Scale: { |
| 2081 Definition* left = call->ArgumentAt(0); | 1992 Definition* left = call->ArgumentAt(0); |
| 2082 Definition* right = call->ArgumentAt(1); | 1993 Definition* right = call->ArgumentAt(1); |
| 2083 // Type check left. | |
| 2084 AddCheckClass(left, | |
| 2085 ICData::ZoneHandle( | |
| 2086 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2087 call->deopt_id(), | |
| 2088 call->env(), | |
| 2089 call); | |
| 2090 // Left and right values are swapped when handed to the instruction, | 1994 // Left and right values are swapped when handed to the instruction, |
| 2091 // this is done so that the double value is loaded into the output | 1995 // this is done so that the double value is loaded into the output |
| 2092 // register and can be destroyed. | 1996 // register and can be destroyed. |
| 2093 Float32x4ScaleInstr* scale = | 1997 Float32x4ScaleInstr* scale = |
| 2094 new(Z) Float32x4ScaleInstr(recognized_kind, | 1998 new(Z) Float32x4ScaleInstr(recognized_kind, |
| 2095 new(Z) Value(right), | 1999 new(Z) Value(right), |
| 2096 new(Z) Value(left), | 2000 new(Z) Value(left), |
| 2097 call->deopt_id()); | 2001 call->deopt_id()); |
| 2098 ReplaceCall(call, scale); | 2002 ReplaceCall(call, scale); |
| 2099 return true; | 2003 return true; |
| 2100 } | 2004 } |
| 2101 case MethodRecognizer::kFloat32x4Sqrt: | 2005 case MethodRecognizer::kFloat32x4Sqrt: |
| 2102 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 2006 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 2103 case MethodRecognizer::kFloat32x4Reciprocal: { | 2007 case MethodRecognizer::kFloat32x4Reciprocal: { |
| 2104 Definition* left = call->ArgumentAt(0); | 2008 Definition* left = call->ArgumentAt(0); |
| 2105 AddCheckClass(left, | |
| 2106 ICData::ZoneHandle( | |
| 2107 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2108 call->deopt_id(), | |
| 2109 call->env(), | |
| 2110 call); | |
| 2111 Float32x4SqrtInstr* sqrt = | 2009 Float32x4SqrtInstr* sqrt = |
| 2112 new(Z) Float32x4SqrtInstr(recognized_kind, | 2010 new(Z) Float32x4SqrtInstr(recognized_kind, |
| 2113 new(Z) Value(left), | 2011 new(Z) Value(left), |
| 2114 call->deopt_id()); | 2012 call->deopt_id()); |
| 2115 ReplaceCall(call, sqrt); | 2013 ReplaceCall(call, sqrt); |
| 2116 return true; | 2014 return true; |
| 2117 } | 2015 } |
| 2118 case MethodRecognizer::kFloat32x4WithX: | 2016 case MethodRecognizer::kFloat32x4WithX: |
| 2119 case MethodRecognizer::kFloat32x4WithY: | 2017 case MethodRecognizer::kFloat32x4WithY: |
| 2120 case MethodRecognizer::kFloat32x4WithZ: | 2018 case MethodRecognizer::kFloat32x4WithZ: |
| 2121 case MethodRecognizer::kFloat32x4WithW: { | 2019 case MethodRecognizer::kFloat32x4WithW: { |
| 2122 Definition* left = call->ArgumentAt(0); | 2020 Definition* left = call->ArgumentAt(0); |
| 2123 Definition* right = call->ArgumentAt(1); | 2021 Definition* right = call->ArgumentAt(1); |
| 2124 // Type check left. | |
| 2125 AddCheckClass(left, | |
| 2126 ICData::ZoneHandle( | |
| 2127 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2128 call->deopt_id(), | |
| 2129 call->env(), | |
| 2130 call); | |
| 2131 Float32x4WithInstr* with = new(Z) Float32x4WithInstr(recognized_kind, | 2022 Float32x4WithInstr* with = new(Z) Float32x4WithInstr(recognized_kind, |
| 2132 new(Z) Value(left), | 2023 new(Z) Value(left), |
| 2133 new(Z) Value(right), | 2024 new(Z) Value(right), |
| 2134 call->deopt_id()); | 2025 call->deopt_id()); |
| 2135 ReplaceCall(call, with); | 2026 ReplaceCall(call, with); |
| 2136 return true; | 2027 return true; |
| 2137 } | 2028 } |
| 2138 case MethodRecognizer::kFloat32x4Absolute: | 2029 case MethodRecognizer::kFloat32x4Absolute: |
| 2139 case MethodRecognizer::kFloat32x4Negate: { | 2030 case MethodRecognizer::kFloat32x4Negate: { |
| 2140 Definition* left = call->ArgumentAt(0); | 2031 Definition* left = call->ArgumentAt(0); |
| 2141 // Type check left. | |
| 2142 AddCheckClass(left, | |
| 2143 ICData::ZoneHandle( | |
| 2144 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2145 call->deopt_id(), | |
| 2146 call->env(), | |
| 2147 call); | |
| 2148 Float32x4ZeroArgInstr* zeroArg = | 2032 Float32x4ZeroArgInstr* zeroArg = |
| 2149 new(Z) Float32x4ZeroArgInstr( | 2033 new(Z) Float32x4ZeroArgInstr( |
| 2150 recognized_kind, new(Z) Value(left), call->deopt_id()); | 2034 recognized_kind, new(Z) Value(left), call->deopt_id()); |
| 2151 ReplaceCall(call, zeroArg); | 2035 ReplaceCall(call, zeroArg); |
| 2152 return true; | 2036 return true; |
| 2153 } | 2037 } |
| 2154 case MethodRecognizer::kFloat32x4Clamp: { | 2038 case MethodRecognizer::kFloat32x4Clamp: { |
| 2155 Definition* left = call->ArgumentAt(0); | 2039 Definition* left = call->ArgumentAt(0); |
| 2156 Definition* lower = call->ArgumentAt(1); | 2040 Definition* lower = call->ArgumentAt(1); |
| 2157 Definition* upper = call->ArgumentAt(2); | 2041 Definition* upper = call->ArgumentAt(2); |
| 2158 // Type check left. | |
| 2159 AddCheckClass(left, | |
| 2160 ICData::ZoneHandle( | |
| 2161 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2162 call->deopt_id(), | |
| 2163 call->env(), | |
| 2164 call); | |
| 2165 Float32x4ClampInstr* clamp = new(Z) Float32x4ClampInstr( | 2042 Float32x4ClampInstr* clamp = new(Z) Float32x4ClampInstr( |
| 2166 new(Z) Value(left), | 2043 new(Z) Value(left), |
| 2167 new(Z) Value(lower), | 2044 new(Z) Value(lower), |
| 2168 new(Z) Value(upper), | 2045 new(Z) Value(upper), |
| 2169 call->deopt_id()); | 2046 call->deopt_id()); |
| 2170 ReplaceCall(call, clamp); | 2047 ReplaceCall(call, clamp); |
| 2171 return true; | 2048 return true; |
| 2172 } | 2049 } |
| 2173 case MethodRecognizer::kFloat32x4ShuffleMix: | 2050 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 2174 case MethodRecognizer::kFloat32x4Shuffle: { | 2051 case MethodRecognizer::kFloat32x4Shuffle: { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2191 case MethodRecognizer::kFloat64x2GetX: | 2068 case MethodRecognizer::kFloat64x2GetX: |
| 2192 case MethodRecognizer::kFloat64x2GetY: | 2069 case MethodRecognizer::kFloat64x2GetY: |
| 2193 ASSERT(call->ic_data()->HasReceiverClassId(kFloat64x2Cid)); | 2070 ASSERT(call->ic_data()->HasReceiverClassId(kFloat64x2Cid)); |
| 2194 ASSERT(call->ic_data()->HasOneTarget()); | 2071 ASSERT(call->ic_data()->HasOneTarget()); |
| 2195 return InlineFloat64x2Getter(call, recognized_kind); | 2072 return InlineFloat64x2Getter(call, recognized_kind); |
| 2196 case MethodRecognizer::kFloat64x2Negate: | 2073 case MethodRecognizer::kFloat64x2Negate: |
| 2197 case MethodRecognizer::kFloat64x2Abs: | 2074 case MethodRecognizer::kFloat64x2Abs: |
| 2198 case MethodRecognizer::kFloat64x2Sqrt: | 2075 case MethodRecognizer::kFloat64x2Sqrt: |
| 2199 case MethodRecognizer::kFloat64x2GetSignMask: { | 2076 case MethodRecognizer::kFloat64x2GetSignMask: { |
| 2200 Definition* left = call->ArgumentAt(0); | 2077 Definition* left = call->ArgumentAt(0); |
| 2201 // Type check left. | |
| 2202 AddCheckClass(left, | |
| 2203 ICData::ZoneHandle( | |
| 2204 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2205 call->deopt_id(), | |
| 2206 call->env(), | |
| 2207 call); | |
| 2208 Float64x2ZeroArgInstr* zeroArg = | 2078 Float64x2ZeroArgInstr* zeroArg = |
| 2209 new(Z) Float64x2ZeroArgInstr( | 2079 new(Z) Float64x2ZeroArgInstr( |
| 2210 recognized_kind, new(Z) Value(left), call->deopt_id()); | 2080 recognized_kind, new(Z) Value(left), call->deopt_id()); |
| 2211 ReplaceCall(call, zeroArg); | 2081 ReplaceCall(call, zeroArg); |
| 2212 return true; | 2082 return true; |
| 2213 } | 2083 } |
| 2214 case MethodRecognizer::kFloat64x2Scale: | 2084 case MethodRecognizer::kFloat64x2Scale: |
| 2215 case MethodRecognizer::kFloat64x2WithX: | 2085 case MethodRecognizer::kFloat64x2WithX: |
| 2216 case MethodRecognizer::kFloat64x2WithY: | 2086 case MethodRecognizer::kFloat64x2WithY: |
| 2217 case MethodRecognizer::kFloat64x2Min: | 2087 case MethodRecognizer::kFloat64x2Min: |
| 2218 case MethodRecognizer::kFloat64x2Max: { | 2088 case MethodRecognizer::kFloat64x2Max: { |
| 2219 Definition* left = call->ArgumentAt(0); | 2089 Definition* left = call->ArgumentAt(0); |
| 2220 Definition* right = call->ArgumentAt(1); | 2090 Definition* right = call->ArgumentAt(1); |
| 2221 // Type check left. | |
| 2222 AddCheckClass(left, | |
| 2223 ICData::ZoneHandle( | |
| 2224 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2225 call->deopt_id(), | |
| 2226 call->env(), | |
| 2227 call); | |
| 2228 Float64x2OneArgInstr* zeroArg = | 2091 Float64x2OneArgInstr* zeroArg = |
| 2229 new(Z) Float64x2OneArgInstr(recognized_kind, | 2092 new(Z) Float64x2OneArgInstr(recognized_kind, |
| 2230 new(Z) Value(left), | 2093 new(Z) Value(left), |
| 2231 new(Z) Value(right), | 2094 new(Z) Value(right), |
| 2232 call->deopt_id()); | 2095 call->deopt_id()); |
| 2233 ReplaceCall(call, zeroArg); | 2096 ReplaceCall(call, zeroArg); |
| 2234 return true; | 2097 return true; |
| 2235 } | 2098 } |
| 2236 default: | 2099 default: |
| 2237 return false; | 2100 return false; |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 | 2946 |
| 3084 // Discard the environment from the original instruction because the store | 2947 // Discard the environment from the original instruction because the store |
| 3085 // can't deoptimize. | 2948 // can't deoptimize. |
| 3086 instr->RemoveEnvironment(); | 2949 instr->RemoveEnvironment(); |
| 3087 ReplaceCall(instr, store); | 2950 ReplaceCall(instr, store); |
| 3088 return true; | 2951 return true; |
| 3089 } | 2952 } |
| 3090 | 2953 |
| 3091 | 2954 |
| 3092 } // namespace dart | 2955 } // namespace dart |
| OLD | NEW |