| 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 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 } | 1215 } |
| 1216 InvokeMathCFunctionInstr* invoke = | 1216 InvokeMathCFunctionInstr* invoke = |
| 1217 new(Z) InvokeMathCFunctionInstr(args, | 1217 new(Z) InvokeMathCFunctionInstr(args, |
| 1218 call->deopt_id(), | 1218 call->deopt_id(), |
| 1219 recognized_kind, | 1219 recognized_kind, |
| 1220 call->token_pos()); | 1220 call->token_pos()); |
| 1221 ReplaceCall(call, invoke); | 1221 ReplaceCall(call, invoke); |
| 1222 } | 1222 } |
| 1223 | 1223 |
| 1224 | 1224 |
| 1225 static bool IsSupportedByteArrayViewCid(intptr_t cid) { | |
| 1226 switch (cid) { | |
| 1227 case kTypedDataInt8ArrayCid: | |
| 1228 case kTypedDataUint8ArrayCid: | |
| 1229 case kExternalTypedDataUint8ArrayCid: | |
| 1230 case kTypedDataUint8ClampedArrayCid: | |
| 1231 case kExternalTypedDataUint8ClampedArrayCid: | |
| 1232 case kTypedDataInt16ArrayCid: | |
| 1233 case kTypedDataUint16ArrayCid: | |
| 1234 case kTypedDataInt32ArrayCid: | |
| 1235 case kTypedDataUint32ArrayCid: | |
| 1236 case kTypedDataFloat32ArrayCid: | |
| 1237 case kTypedDataFloat64ArrayCid: | |
| 1238 case kTypedDataFloat32x4ArrayCid: | |
| 1239 case kTypedDataInt32x4ArrayCid: | |
| 1240 return true; | |
| 1241 default: | |
| 1242 return false; | |
| 1243 } | |
| 1244 } | |
| 1245 | |
| 1246 | |
| 1247 // Inline only simple, frequently called core library methods. | 1225 // Inline only simple, frequently called core library methods. |
| 1248 bool JitOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 1226 bool JitOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 1249 ASSERT(call->HasICData()); | 1227 ASSERT(call->HasICData()); |
| 1250 const ICData& ic_data = *call->ic_data(); | 1228 const ICData& ic_data = *call->ic_data(); |
| 1251 if (ic_data.NumberOfUsedChecks() != 1) { | 1229 if (ic_data.NumberOfUsedChecks() != 1) { |
| 1252 // No type feedback collected or multiple targets found. | 1230 // No type feedback collected or multiple targets found. |
| 1253 return false; | 1231 return false; |
| 1254 } | 1232 } |
| 1255 | 1233 |
| 1256 Function& target = Function::Handle(Z); | 1234 Function& target = Function::Handle(Z); |
| 1257 GrowableArray<intptr_t> class_ids; | 1235 GrowableArray<intptr_t> class_ids; |
| 1258 ic_data.GetCheckAt(0, &class_ids, &target); | 1236 ic_data.GetCheckAt(0, &class_ids, &target); |
| 1259 MethodRecognizer::Kind recognized_kind = | 1237 MethodRecognizer::Kind recognized_kind = |
| 1260 MethodRecognizer::RecognizeKind(target); | 1238 MethodRecognizer::RecognizeKind(target); |
| 1261 | 1239 |
| 1262 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) || | |
| 1263 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) || | |
| 1264 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) || | |
| 1265 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) || | |
| 1266 (recognized_kind == MethodRecognizer::kGrowableArraySetData) || | |
| 1267 (recognized_kind == MethodRecognizer::kGrowableArraySetLength) || | |
| 1268 (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi)) { | |
| 1269 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1270 flow_graph_, current_iterator(), call); | |
| 1271 } | |
| 1272 | |
| 1273 if (recognized_kind == MethodRecognizer::kStringBaseCharAt) { | |
| 1274 ASSERT((class_ids[0] == kOneByteStringCid) || | |
| 1275 (class_ids[0] == kTwoByteStringCid) || | |
| 1276 (class_ids[0] == kExternalOneByteStringCid) || | |
| 1277 (class_ids[0] == kExternalTwoByteStringCid)); | |
| 1278 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1279 flow_graph_, current_iterator(), call); | |
| 1280 } | |
| 1281 | |
| 1282 if (class_ids[0] == kOneByteStringCid) { | |
| 1283 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | |
| 1284 // This is an internal method, no need to check argument types nor | |
| 1285 // range. | |
| 1286 Definition* str = call->ArgumentAt(0); | |
| 1287 Definition* index = call->ArgumentAt(1); | |
| 1288 Definition* value = call->ArgumentAt(2); | |
| 1289 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr( | |
| 1290 new(Z) Value(str), | |
| 1291 new(Z) Value(index), | |
| 1292 new(Z) Value(value), | |
| 1293 kNoStoreBarrier, | |
| 1294 1, // Index scale | |
| 1295 kOneByteStringCid, | |
| 1296 call->deopt_id(), | |
| 1297 call->token_pos()); | |
| 1298 ReplaceCall(call, store_op); | |
| 1299 return true; | |
| 1300 } | |
| 1301 return false; | |
| 1302 } | |
| 1303 | |
| 1304 if (CanUnboxDouble() && | 1240 if (CanUnboxDouble() && |
| 1305 (recognized_kind == MethodRecognizer::kIntegerToDouble)) { | 1241 (recognized_kind == MethodRecognizer::kIntegerToDouble)) { |
| 1306 if (class_ids[0] == kSmiCid) { | 1242 if (class_ids[0] == kSmiCid) { |
| 1307 AddReceiverCheck(call); | 1243 AddReceiverCheck(call); |
| 1308 ReplaceCall(call, | 1244 ReplaceCall(call, |
| 1309 new(Z) SmiToDoubleInstr( | 1245 new(Z) SmiToDoubleInstr( |
| 1310 new(Z) Value(call->ArgumentAt(0)), | 1246 new(Z) Value(call->ArgumentAt(0)), |
| 1311 call->token_pos())); | 1247 call->token_pos())); |
| 1312 return true; | 1248 return true; |
| 1313 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { | 1249 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 if (!TargetCPUFeatures::double_truncate_round_supported()) { | 1288 if (!TargetCPUFeatures::double_truncate_round_supported()) { |
| 1353 ReplaceWithMathCFunction(call, recognized_kind); | 1289 ReplaceWithMathCFunction(call, recognized_kind); |
| 1354 } else { | 1290 } else { |
| 1355 AddReceiverCheck(call); | 1291 AddReceiverCheck(call); |
| 1356 DoubleToDoubleInstr* d2d_instr = | 1292 DoubleToDoubleInstr* d2d_instr = |
| 1357 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), | 1293 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), |
| 1358 recognized_kind, call->deopt_id()); | 1294 recognized_kind, call->deopt_id()); |
| 1359 ReplaceCall(call, d2d_instr); | 1295 ReplaceCall(call, d2d_instr); |
| 1360 } | 1296 } |
| 1361 return true; | 1297 return true; |
| 1362 case MethodRecognizer::kDoubleAdd: | |
| 1363 case MethodRecognizer::kDoubleSub: | |
| 1364 case MethodRecognizer::kDoubleMul: | |
| 1365 case MethodRecognizer::kDoubleDiv: | |
| 1366 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1367 flow_graph_, current_iterator(), call); | |
| 1368 default: | 1298 default: |
| 1369 // Unsupported method. | 1299 break; |
| 1370 return false; | |
| 1371 } | 1300 } |
| 1372 } | 1301 } |
| 1373 | 1302 |
| 1374 if (IsSupportedByteArrayViewCid(class_ids[0]) || | 1303 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1375 (class_ids[0] == kFloat32x4Cid) || | 1304 flow_graph_, current_iterator(), call); |
| 1376 (class_ids[0] == kInt32x4Cid) || | |
| 1377 (class_ids[0] == kFloat64x2Cid)) { | |
| 1378 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | |
| 1379 flow_graph_, current_iterator(), call); | |
| 1380 } | |
| 1381 | |
| 1382 return false; | |
| 1383 } | 1305 } |
| 1384 | 1306 |
| 1385 | 1307 |
| 1386 // If type tests specified by 'ic_data' do not depend on type arguments, | 1308 // If type tests specified by 'ic_data' do not depend on type arguments, |
| 1387 // return mapping cid->result in 'results' (i : cid; i + 1: result). | 1309 // return mapping cid->result in 'results' (i : cid; i + 1: result). |
| 1388 // If all tests yield the same result, return it otherwise return Bool::null. | 1310 // If all tests yield the same result, return it otherwise return Bool::null. |
| 1389 // If no mapping is possible, 'results' is empty. | 1311 // If no mapping is possible, 'results' is empty. |
| 1390 // An instance-of test returning all same results can be converted to a class | 1312 // An instance-of test returning all same results can be converted to a class |
| 1391 // check. | 1313 // check. |
| 1392 RawBool* JitOptimizer::InstanceOfAsBool( | 1314 RawBool* JitOptimizer::InstanceOfAsBool( |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 PolymorphicInstanceCallInstr* call = | 1738 PolymorphicInstanceCallInstr* call = |
| 1817 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, | 1739 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, |
| 1818 call_with_checks, | 1740 call_with_checks, |
| 1819 /* complete = */ false); | 1741 /* complete = */ false); |
| 1820 instr->ReplaceWith(call, current_iterator()); | 1742 instr->ReplaceWith(call, current_iterator()); |
| 1821 } | 1743 } |
| 1822 } | 1744 } |
| 1823 | 1745 |
| 1824 | 1746 |
| 1825 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) { | 1747 void JitOptimizer::VisitStaticCall(StaticCallInstr* call) { |
| 1826 if (!CanUnboxDouble()) { | |
| 1827 return; | |
| 1828 } | |
| 1829 MethodRecognizer::Kind recognized_kind = | 1748 MethodRecognizer::Kind recognized_kind = |
| 1830 MethodRecognizer::RecognizeKind(call->function()); | 1749 MethodRecognizer::RecognizeKind(call->function()); |
| 1831 MathUnaryInstr::MathUnaryKind unary_kind; | |
| 1832 switch (recognized_kind) { | 1750 switch (recognized_kind) { |
| 1833 case MethodRecognizer::kMathSqrt: | 1751 case MethodRecognizer::kObjectConstructor: |
| 1834 unary_kind = MathUnaryInstr::kSqrt; | 1752 case MethodRecognizer::kObjectArrayAllocate: |
| 1835 break; | |
| 1836 case MethodRecognizer::kMathSin: | |
| 1837 unary_kind = MathUnaryInstr::kSin; | |
| 1838 break; | |
| 1839 case MethodRecognizer::kMathCos: | |
| 1840 unary_kind = MathUnaryInstr::kCos; | |
| 1841 break; | |
| 1842 default: | |
| 1843 unary_kind = MathUnaryInstr::kIllegal; | |
| 1844 break; | |
| 1845 } | |
| 1846 if (unary_kind != MathUnaryInstr::kIllegal) { | |
| 1847 MathUnaryInstr* math_unary = | |
| 1848 new(Z) MathUnaryInstr(unary_kind, | |
| 1849 new(Z) Value(call->ArgumentAt(0)), | |
| 1850 call->deopt_id()); | |
| 1851 ReplaceCall(call, math_unary); | |
| 1852 return; | |
| 1853 } | |
| 1854 switch (recognized_kind) { | |
| 1855 case MethodRecognizer::kFloat32x4Zero: | 1753 case MethodRecognizer::kFloat32x4Zero: |
| 1856 case MethodRecognizer::kFloat32x4Splat: | 1754 case MethodRecognizer::kFloat32x4Splat: |
| 1857 case MethodRecognizer::kFloat32x4Constructor: | 1755 case MethodRecognizer::kFloat32x4Constructor: |
| 1858 case MethodRecognizer::kFloat32x4FromFloat64x2: | 1756 case MethodRecognizer::kFloat32x4FromFloat64x2: |
| 1859 case MethodRecognizer::kFloat64x2Constructor: | 1757 case MethodRecognizer::kFloat64x2Constructor: |
| 1860 case MethodRecognizer::kFloat64x2Zero: | 1758 case MethodRecognizer::kFloat64x2Zero: |
| 1861 case MethodRecognizer::kFloat64x2Splat: | 1759 case MethodRecognizer::kFloat64x2Splat: |
| 1862 case MethodRecognizer::kFloat64x2FromFloat32x4: | 1760 case MethodRecognizer::kFloat64x2FromFloat32x4: |
| 1863 case MethodRecognizer::kInt32x4BoolConstructor: | 1761 case MethodRecognizer::kInt32x4BoolConstructor: |
| 1864 case MethodRecognizer::kInt32x4Constructor: | 1762 case MethodRecognizer::kInt32x4Constructor: |
| 1763 case MethodRecognizer::kMathSqrt: |
| 1764 case MethodRecognizer::kMathDoublePow: |
| 1765 case MethodRecognizer::kMathSin: |
| 1766 case MethodRecognizer::kMathCos: |
| 1767 case MethodRecognizer::kMathTan: |
| 1768 case MethodRecognizer::kMathAsin: |
| 1769 case MethodRecognizer::kMathAcos: |
| 1770 case MethodRecognizer::kMathAtan: |
| 1771 case MethodRecognizer::kMathAtan2: |
| 1865 FlowGraphInliner::TryReplaceStaticCallWithInline( | 1772 FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 1866 flow_graph_, current_iterator(), call); | 1773 flow_graph_, current_iterator(), call); |
| 1867 break; | 1774 break; |
| 1868 case MethodRecognizer::kObjectConstructor: { | |
| 1869 // Remove the original push arguments. | |
| 1870 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | |
| 1871 PushArgumentInstr* push = call->PushArgumentAt(i); | |
| 1872 push->ReplaceUsesWith(push->value()->definition()); | |
| 1873 push->RemoveFromGraph(); | |
| 1874 } | |
| 1875 // Manually replace call with global null constant. ReplaceCall can't | |
| 1876 // be used for definitions that are already in the graph. | |
| 1877 call->ReplaceUsesWith(flow_graph_->constant_null()); | |
| 1878 ASSERT(current_iterator()->Current() == call); | |
| 1879 current_iterator()->RemoveCurrentFromGraph(); | |
| 1880 break; | |
| 1881 } | |
| 1882 case MethodRecognizer::kMathMin: | 1775 case MethodRecognizer::kMathMin: |
| 1883 case MethodRecognizer::kMathMax: { | 1776 case MethodRecognizer::kMathMax: { |
| 1884 // We can handle only monomorphic min/max call sites with both arguments | 1777 // We can handle only monomorphic min/max call sites with both arguments |
| 1885 // being either doubles or smis. | 1778 // being either doubles or smis. |
| 1886 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 1779 if (CanUnboxDouble() && |
| 1780 call->HasICData() && |
| 1781 (call->ic_data()->NumberOfChecks() == 1)) { |
| 1887 const ICData& ic_data = *call->ic_data(); | 1782 const ICData& ic_data = *call->ic_data(); |
| 1888 intptr_t result_cid = kIllegalCid; | 1783 intptr_t result_cid = kIllegalCid; |
| 1889 if (ICDataHasReceiverArgumentClassIds(ic_data, | 1784 if (ICDataHasReceiverArgumentClassIds(ic_data, |
| 1890 kDoubleCid, kDoubleCid)) { | 1785 kDoubleCid, kDoubleCid)) { |
| 1891 result_cid = kDoubleCid; | 1786 result_cid = kDoubleCid; |
| 1892 } else if (ICDataHasReceiverArgumentClassIds(ic_data, | 1787 } else if (ICDataHasReceiverArgumentClassIds(ic_data, |
| 1893 kSmiCid, kSmiCid)) { | 1788 kSmiCid, kSmiCid)) { |
| 1894 result_cid = kSmiCid; | 1789 result_cid = kSmiCid; |
| 1895 } | 1790 } |
| 1896 if (result_cid != kIllegalCid) { | 1791 if (result_cid != kIllegalCid) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1910 AddCheckClass(min_max->right()->definition(), | 1805 AddCheckClass(min_max->right()->definition(), |
| 1911 unary_checks, | 1806 unary_checks, |
| 1912 call->deopt_id(), | 1807 call->deopt_id(), |
| 1913 call->env(), | 1808 call->env(), |
| 1914 call); | 1809 call); |
| 1915 ReplaceCall(call, min_max); | 1810 ReplaceCall(call, min_max); |
| 1916 } | 1811 } |
| 1917 } | 1812 } |
| 1918 break; | 1813 break; |
| 1919 } | 1814 } |
| 1920 case MethodRecognizer::kMathDoublePow: | 1815 |
| 1921 case MethodRecognizer::kMathTan: | |
| 1922 case MethodRecognizer::kMathAsin: | |
| 1923 case MethodRecognizer::kMathAcos: | |
| 1924 case MethodRecognizer::kMathAtan: | |
| 1925 case MethodRecognizer::kMathAtan2: { | |
| 1926 // InvokeMathCFunctionInstr requires unboxed doubles. UnboxDouble | |
| 1927 // instructions contain type checks and conversions to double. | |
| 1928 ZoneGrowableArray<Value*>* args = | |
| 1929 new(Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); | |
| 1930 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { | |
| 1931 args->Add(new(Z) Value(call->ArgumentAt(i))); | |
| 1932 } | |
| 1933 InvokeMathCFunctionInstr* invoke = | |
| 1934 new(Z) InvokeMathCFunctionInstr(args, | |
| 1935 call->deopt_id(), | |
| 1936 recognized_kind, | |
| 1937 call->token_pos()); | |
| 1938 ReplaceCall(call, invoke); | |
| 1939 break; | |
| 1940 } | |
| 1941 case MethodRecognizer::kDoubleFromInteger: { | 1816 case MethodRecognizer::kDoubleFromInteger: { |
| 1942 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { | 1817 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { |
| 1943 const ICData& ic_data = *call->ic_data(); | 1818 const ICData& ic_data = *call->ic_data(); |
| 1944 if (CanUnboxDouble()) { | 1819 if (CanUnboxDouble()) { |
| 1945 if (ArgIsAlways(kSmiCid, ic_data, 1)) { | 1820 if (ArgIsAlways(kSmiCid, ic_data, 1)) { |
| 1946 Definition* arg = call->ArgumentAt(1); | 1821 Definition* arg = call->ArgumentAt(1); |
| 1947 AddCheckSmi(arg, call->deopt_id(), call->env(), call); | 1822 AddCheckSmi(arg, call->deopt_id(), call->env(), call); |
| 1948 ReplaceCall(call, | 1823 ReplaceCall(call, |
| 1949 new(Z) SmiToDoubleInstr(new(Z) Value(arg), | 1824 new(Z) SmiToDoubleInstr(new(Z) Value(arg), |
| 1950 call->token_pos())); | 1825 call->token_pos())); |
| 1951 } else if (ArgIsAlways(kMintCid, ic_data, 1) && | 1826 } else if (ArgIsAlways(kMintCid, ic_data, 1) && |
| 1952 CanConvertUnboxedMintToDouble()) { | 1827 CanConvertUnboxedMintToDouble()) { |
| 1953 Definition* arg = call->ArgumentAt(1); | 1828 Definition* arg = call->ArgumentAt(1); |
| 1954 ReplaceCall(call, | 1829 ReplaceCall(call, |
| 1955 new(Z) MintToDoubleInstr(new(Z) Value(arg), | 1830 new(Z) MintToDoubleInstr(new(Z) Value(arg), |
| 1956 call->deopt_id())); | 1831 call->deopt_id())); |
| 1957 } | 1832 } |
| 1958 } | 1833 } |
| 1959 } | 1834 } |
| 1960 break; | 1835 break; |
| 1961 } | 1836 } |
| 1962 default: { | 1837 default: |
| 1963 if (call->function().IsFactory()) { | 1838 break; |
| 1964 const Class& function_class = | |
| 1965 Class::Handle(Z, call->function().Owner()); | |
| 1966 if ((function_class.library() == Library::CoreLibrary()) || | |
| 1967 (function_class.library() == Library::TypedDataLibrary())) { | |
| 1968 intptr_t cid = FactoryRecognizer::ResultCid(call->function()); | |
| 1969 switch (cid) { | |
| 1970 case kArrayCid: { | |
| 1971 Value* type = new(Z) Value(call->ArgumentAt(0)); | |
| 1972 Value* num_elements = new(Z) Value(call->ArgumentAt(1)); | |
| 1973 if (num_elements->BindsToConstant() && | |
| 1974 num_elements->BoundConstant().IsSmi()) { | |
| 1975 intptr_t length = | |
| 1976 Smi::Cast(num_elements->BoundConstant()).Value(); | |
| 1977 if (length >= 0 && length <= Array::kMaxElements) { | |
| 1978 CreateArrayInstr* create_array = | |
| 1979 new(Z) CreateArrayInstr( | |
| 1980 call->token_pos(), type, num_elements); | |
| 1981 ReplaceCall(call, create_array); | |
| 1982 } | |
| 1983 } | |
| 1984 } | |
| 1985 default: | |
| 1986 break; | |
| 1987 } | |
| 1988 } | |
| 1989 } | |
| 1990 } | |
| 1991 } | 1839 } |
| 1992 } | 1840 } |
| 1993 | 1841 |
| 1994 | 1842 |
| 1995 void JitOptimizer::VisitStoreInstanceField( | 1843 void JitOptimizer::VisitStoreInstanceField( |
| 1996 StoreInstanceFieldInstr* instr) { | 1844 StoreInstanceFieldInstr* instr) { |
| 1997 if (instr->IsUnboxedStore()) { | 1845 if (instr->IsUnboxedStore()) { |
| 1998 // Determine if this field should be unboxed based on the usage of getter | 1846 // Determine if this field should be unboxed based on the usage of getter |
| 1999 // and setter functions: The heuristic requires that the setter has a | 1847 // and setter functions: The heuristic requires that the setter has a |
| 2000 // usage count of at least 1/kGetterSetterRatio of the getter usage count. | 1848 // usage count of at least 1/kGetterSetterRatio of the getter usage count. |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 | 2013 |
| 2166 // Discard the environment from the original instruction because the store | 2014 // Discard the environment from the original instruction because the store |
| 2167 // can't deoptimize. | 2015 // can't deoptimize. |
| 2168 instr->RemoveEnvironment(); | 2016 instr->RemoveEnvironment(); |
| 2169 ReplaceCall(instr, store); | 2017 ReplaceCall(instr, store); |
| 2170 return true; | 2018 return true; |
| 2171 } | 2019 } |
| 2172 | 2020 |
| 2173 | 2021 |
| 2174 } // namespace dart | 2022 } // namespace dart |
| OLD | NEW |