| 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1159 case MethodRecognizer::kFloat64x2ArraySetIndexed: | 1159 case MethodRecognizer::kFloat64x2ArraySetIndexed: |
| 1160 return kTypedDataFloat64x2ArrayCid; | 1160 return kTypedDataFloat64x2ArrayCid; |
| 1161 | 1161 |
| 1162 default: | 1162 default: |
| 1163 break; | 1163 break; |
| 1164 } | 1164 } |
| 1165 return kIllegalCid; | 1165 return kIllegalCid; |
| 1166 } | 1166 } |
| 1167 | 1167 |
| 1168 | 1168 |
| 1169 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 1169 bool FlowGraphOptimizer::TryReplaceWithIndexedOp(InstanceCallInstr* call) { |
| 1170 // Check for monomorphic IC data. | 1170 // Check for monomorphic IC data. |
| 1171 if (!call->HasICData()) return false; | 1171 if (!call->HasICData()) return false; |
| 1172 const ICData& ic_data = | 1172 const ICData& ic_data = |
| 1173 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | 1173 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
| 1174 if (ic_data.NumberOfChecks() != 1) { | 1174 if (ic_data.NumberOfChecks() != 1) { |
| 1175 return false; | 1175 return false; |
| 1176 } | 1176 } |
| 1177 ASSERT(ic_data.NumberOfUsedChecks() == 1); | 1177 return TryReplaceInstanceCallWithInline(call); |
| 1178 ASSERT(ic_data.HasOneTarget()); | |
| 1179 | |
| 1180 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | |
| 1181 TargetEntryInstr* entry; | |
| 1182 Definition* last; | |
| 1183 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | |
| 1184 target, | |
| 1185 call, | |
| 1186 call->ArgumentAt(0), | |
| 1187 call->token_pos(), | |
| 1188 *call->ic_data(), | |
| 1189 &entry, &last)) { | |
| 1190 return false; | |
| 1191 } | |
| 1192 // Insert receiver class check. | |
| 1193 AddReceiverCheck(call); | |
| 1194 // Remove the original push arguments. | |
| 1195 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | |
| 1196 PushArgumentInstr* push = call->PushArgumentAt(i); | |
| 1197 push->ReplaceUsesWith(push->value()->definition()); | |
| 1198 push->RemoveFromGraph(); | |
| 1199 } | |
| 1200 // Replace all uses of this definition with the result. | |
| 1201 call->ReplaceUsesWith(last); | |
| 1202 // Finally insert the sequence other definition in place of this one in the | |
| 1203 // graph. | |
| 1204 call->previous()->LinkTo(entry->next()); | |
| 1205 entry->UnuseAllInputs(); // Entry block is not in the graph. | |
| 1206 last->LinkTo(call); | |
| 1207 // Remove through the iterator. | |
| 1208 ASSERT(current_iterator()->Current() == call); | |
| 1209 current_iterator()->RemoveCurrentFromGraph(); | |
| 1210 call->set_previous(NULL); | |
| 1211 call->set_next(NULL); | |
| 1212 return true; | |
| 1213 } | 1178 } |
| 1214 | 1179 |
| 1215 | 1180 |
| 1216 bool FlowGraphOptimizer::InlineSetIndexed( | 1181 bool FlowGraphOptimizer::InlineSetIndexed( |
| 1217 MethodRecognizer::Kind kind, | 1182 MethodRecognizer::Kind kind, |
| 1218 const Function& target, | 1183 const Function& target, |
| 1219 Instruction* call, | 1184 Instruction* call, |
| 1220 Definition* receiver, | 1185 Definition* receiver, |
| 1221 intptr_t token_pos, | 1186 intptr_t token_pos, |
| 1222 const ICData* ic_data, | |
| 1223 const ICData& value_check, | 1187 const ICData& value_check, |
| 1224 TargetEntryInstr** entry, | 1188 TargetEntryInstr** entry, |
| 1225 Definition** last) { | 1189 Definition** last) { |
| 1226 intptr_t array_cid = MethodKindToCid(kind); | 1190 intptr_t array_cid = MethodKindToCid(kind); |
| 1227 ASSERT(array_cid != kIllegalCid); | 1191 ASSERT(array_cid != kIllegalCid); |
| 1228 | 1192 |
| 1229 Definition* array = receiver; | 1193 Definition* array = receiver; |
| 1230 Definition* index = call->ArgumentAt(1); | 1194 Definition* index = call->ArgumentAt(1); |
| 1231 Definition* stored_value = call->ArgumentAt(2); | 1195 Definition* stored_value = call->ArgumentAt(2); |
| 1232 | 1196 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 case MethodRecognizer::kImmutableArrayGetIndexed: | 1368 case MethodRecognizer::kImmutableArrayGetIndexed: |
| 1405 case MethodRecognizer::kObjectArrayGetIndexed: | 1369 case MethodRecognizer::kObjectArrayGetIndexed: |
| 1406 case MethodRecognizer::kGrowableArrayGetIndexed: | 1370 case MethodRecognizer::kGrowableArrayGetIndexed: |
| 1407 case MethodRecognizer::kInt8ArrayGetIndexed: | 1371 case MethodRecognizer::kInt8ArrayGetIndexed: |
| 1408 case MethodRecognizer::kUint8ArrayGetIndexed: | 1372 case MethodRecognizer::kUint8ArrayGetIndexed: |
| 1409 case MethodRecognizer::kUint8ClampedArrayGetIndexed: | 1373 case MethodRecognizer::kUint8ClampedArrayGetIndexed: |
| 1410 case MethodRecognizer::kExternalUint8ArrayGetIndexed: | 1374 case MethodRecognizer::kExternalUint8ArrayGetIndexed: |
| 1411 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed: | 1375 case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed: |
| 1412 case MethodRecognizer::kInt16ArrayGetIndexed: | 1376 case MethodRecognizer::kInt16ArrayGetIndexed: |
| 1413 case MethodRecognizer::kUint16ArrayGetIndexed: | 1377 case MethodRecognizer::kUint16ArrayGetIndexed: |
| 1414 return InlineGetIndexed(kind, call, receiver, ic_data, entry, last); | 1378 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1415 case MethodRecognizer::kFloat32ArrayGetIndexed: | 1379 case MethodRecognizer::kFloat32ArrayGetIndexed: |
| 1416 case MethodRecognizer::kFloat64ArrayGetIndexed: | 1380 case MethodRecognizer::kFloat64ArrayGetIndexed: |
| 1417 if (!CanUnboxDouble()) { | 1381 if (!CanUnboxDouble()) { |
| 1418 return false; | 1382 return false; |
| 1419 } | 1383 } |
| 1420 return InlineGetIndexed(kind, call, receiver, ic_data, entry, last); | 1384 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1421 case MethodRecognizer::kFloat32x4ArrayGetIndexed: | 1385 case MethodRecognizer::kFloat32x4ArrayGetIndexed: |
| 1422 case MethodRecognizer::kFloat64x2ArrayGetIndexed: | 1386 case MethodRecognizer::kFloat64x2ArrayGetIndexed: |
| 1423 if (!ShouldInlineSimd()) { | 1387 if (!ShouldInlineSimd()) { |
| 1424 return false; | 1388 return false; |
| 1425 } | 1389 } |
| 1426 return InlineGetIndexed(kind, call, receiver, ic_data, entry, last); | 1390 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1427 case MethodRecognizer::kInt32ArrayGetIndexed: | 1391 case MethodRecognizer::kInt32ArrayGetIndexed: |
| 1428 case MethodRecognizer::kUint32ArrayGetIndexed: | 1392 case MethodRecognizer::kUint32ArrayGetIndexed: |
| 1429 if (!CanUnboxInt32()) return false; | 1393 if (!CanUnboxInt32()) return false; |
| 1430 return InlineGetIndexed(kind, call, receiver, ic_data, entry, last); | 1394 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1431 | 1395 |
| 1432 case MethodRecognizer::kInt64ArrayGetIndexed: | 1396 case MethodRecognizer::kInt64ArrayGetIndexed: |
| 1433 if (!ShouldInlineInt64ArrayOps()) { | 1397 if (!ShouldInlineInt64ArrayOps()) { |
| 1434 return false; | 1398 return false; |
| 1435 } | 1399 } |
| 1436 return InlineGetIndexed(kind, call, receiver, ic_data, entry, last); | 1400 return InlineGetIndexed(kind, call, receiver, entry, last); |
| 1437 // Recognized []= operators. | 1401 // Recognized []= operators. |
| 1438 case MethodRecognizer::kObjectArraySetIndexed: | 1402 case MethodRecognizer::kObjectArraySetIndexed: |
| 1439 case MethodRecognizer::kGrowableArraySetIndexed: | 1403 case MethodRecognizer::kGrowableArraySetIndexed: |
| 1440 if (ArgIsAlways(kSmiCid, ic_data, 2)) { | 1404 if (ArgIsAlways(kSmiCid, ic_data, 2)) { |
| 1441 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1405 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1442 } | 1406 } |
| 1443 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1407 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1444 &ic_data, value_check, entry, last); | 1408 value_check, entry, last); |
| 1445 case MethodRecognizer::kInt8ArraySetIndexed: | 1409 case MethodRecognizer::kInt8ArraySetIndexed: |
| 1446 case MethodRecognizer::kUint8ArraySetIndexed: | 1410 case MethodRecognizer::kUint8ArraySetIndexed: |
| 1447 case MethodRecognizer::kUint8ClampedArraySetIndexed: | 1411 case MethodRecognizer::kUint8ClampedArraySetIndexed: |
| 1448 case MethodRecognizer::kExternalUint8ArraySetIndexed: | 1412 case MethodRecognizer::kExternalUint8ArraySetIndexed: |
| 1449 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: | 1413 case MethodRecognizer::kExternalUint8ClampedArraySetIndexed: |
| 1450 case MethodRecognizer::kInt16ArraySetIndexed: | 1414 case MethodRecognizer::kInt16ArraySetIndexed: |
| 1451 case MethodRecognizer::kUint16ArraySetIndexed: | 1415 case MethodRecognizer::kUint16ArraySetIndexed: |
| 1452 if (!ArgIsAlways(kSmiCid, ic_data, 2)) { | 1416 if (!ArgIsAlways(kSmiCid, ic_data, 2)) { |
| 1453 return false; | 1417 return false; |
| 1454 } | 1418 } |
| 1455 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1419 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1456 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1420 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1457 &ic_data, value_check, entry, last); | 1421 value_check, entry, last); |
| 1458 case MethodRecognizer::kInt32ArraySetIndexed: | 1422 case MethodRecognizer::kInt32ArraySetIndexed: |
| 1459 case MethodRecognizer::kUint32ArraySetIndexed: | 1423 case MethodRecognizer::kUint32ArraySetIndexed: |
| 1460 // Check that value is always smi or mint. We use Int32/Uint32 unboxing | 1424 // Check that value is always smi or mint. We use Int32/Uint32 unboxing |
| 1461 // which can only deal unbox these values. | 1425 // which can only deal unbox these values. |
| 1462 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1426 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1463 if (!HasOnlySmiOrMint(value_check)) { | 1427 if (!HasOnlySmiOrMint(value_check)) { |
| 1464 return false; | 1428 return false; |
| 1465 } | 1429 } |
| 1466 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1430 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1467 &ic_data, value_check, entry, last); | 1431 value_check, entry, last); |
| 1468 case MethodRecognizer::kInt64ArraySetIndexed: | 1432 case MethodRecognizer::kInt64ArraySetIndexed: |
| 1469 if (!ShouldInlineInt64ArrayOps()) { | 1433 if (!ShouldInlineInt64ArrayOps()) { |
| 1470 return false; | 1434 return false; |
| 1471 } | 1435 } |
| 1472 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1436 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1473 &ic_data, value_check, entry, last); | 1437 value_check, entry, last); |
| 1474 case MethodRecognizer::kFloat32ArraySetIndexed: | 1438 case MethodRecognizer::kFloat32ArraySetIndexed: |
| 1475 case MethodRecognizer::kFloat64ArraySetIndexed: | 1439 case MethodRecognizer::kFloat64ArraySetIndexed: |
| 1476 if (!CanUnboxDouble()) { | 1440 if (!CanUnboxDouble()) { |
| 1477 return false; | 1441 return false; |
| 1478 } | 1442 } |
| 1479 // Check that value is always double. | 1443 // Check that value is always double. |
| 1480 if (!ArgIsAlways(kDoubleCid, ic_data, 2)) { | 1444 if (!ArgIsAlways(kDoubleCid, ic_data, 2)) { |
| 1481 return false; | 1445 return false; |
| 1482 } | 1446 } |
| 1483 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1447 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1484 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1448 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1485 &ic_data, value_check, entry, last); | 1449 value_check, entry, last); |
| 1486 case MethodRecognizer::kFloat32x4ArraySetIndexed: | 1450 case MethodRecognizer::kFloat32x4ArraySetIndexed: |
| 1487 if (!ShouldInlineSimd()) { | 1451 if (!ShouldInlineSimd()) { |
| 1488 return false; | 1452 return false; |
| 1489 } | 1453 } |
| 1490 // Check that value is always a Float32x4. | 1454 // Check that value is always a Float32x4. |
| 1491 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) { | 1455 if (!ArgIsAlways(kFloat32x4Cid, ic_data, 2)) { |
| 1492 return false; | 1456 return false; |
| 1493 } | 1457 } |
| 1494 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1458 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1495 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1459 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1496 &ic_data, value_check, entry, last); | 1460 value_check, entry, last); |
| 1497 case MethodRecognizer::kFloat64x2ArraySetIndexed: | 1461 case MethodRecognizer::kFloat64x2ArraySetIndexed: |
| 1498 if (!ShouldInlineSimd()) { | 1462 if (!ShouldInlineSimd()) { |
| 1499 return false; | 1463 return false; |
| 1500 } | 1464 } |
| 1501 // Check that value is always a Float32x4. | 1465 // Check that value is always a Float32x4. |
| 1502 if (!ArgIsAlways(kFloat64x2Cid, ic_data, 2)) { | 1466 if (!ArgIsAlways(kFloat64x2Cid, ic_data, 2)) { |
| 1503 return false; | 1467 return false; |
| 1504 } | 1468 } |
| 1505 value_check = ic_data.AsUnaryClassChecksForArgNr(2); | 1469 value_check = ic_data.AsUnaryClassChecksForArgNr(2); |
| 1506 return InlineSetIndexed(kind, target, call, receiver, token_pos, | 1470 return InlineSetIndexed(kind, target, call, receiver, token_pos, |
| 1507 &ic_data, value_check, entry, last); | 1471 value_check, entry, last); |
| 1508 case MethodRecognizer::kByteArrayBaseGetInt8: | 1472 case MethodRecognizer::kByteArrayBaseGetInt8: |
| 1509 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1473 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
| 1510 kTypedDataInt8ArrayCid, | 1474 kTypedDataInt8ArrayCid, |
| 1511 ic_data, entry, last); | 1475 ic_data, entry, last); |
| 1512 case MethodRecognizer::kByteArrayBaseGetUint8: | 1476 case MethodRecognizer::kByteArrayBaseGetUint8: |
| 1513 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1477 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
| 1514 kTypedDataUint8ArrayCid, | 1478 kTypedDataUint8ArrayCid, |
| 1515 ic_data, entry, last); | 1479 ic_data, entry, last); |
| 1516 case MethodRecognizer::kByteArrayBaseGetInt16: | 1480 case MethodRecognizer::kByteArrayBaseGetInt16: |
| 1517 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1481 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 FlowGraph::kValue); | 1662 FlowGraph::kValue); |
| 1699 *array = elements; | 1663 *array = elements; |
| 1700 } | 1664 } |
| 1701 return array_cid; | 1665 return array_cid; |
| 1702 } | 1666 } |
| 1703 | 1667 |
| 1704 | 1668 |
| 1705 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, | 1669 bool FlowGraphOptimizer::InlineGetIndexed(MethodRecognizer::Kind kind, |
| 1706 Instruction* call, | 1670 Instruction* call, |
| 1707 Definition* receiver, | 1671 Definition* receiver, |
| 1708 const ICData& ic_data, | |
| 1709 TargetEntryInstr** entry, | 1672 TargetEntryInstr** entry, |
| 1710 Definition** last) { | 1673 Definition** last) { |
| 1711 intptr_t array_cid = MethodKindToCid(kind); | 1674 intptr_t array_cid = MethodKindToCid(kind); |
| 1712 ASSERT(array_cid != kIllegalCid); | 1675 ASSERT(array_cid != kIllegalCid); |
| 1713 | 1676 |
| 1714 Definition* array = receiver; | 1677 Definition* array = receiver; |
| 1715 Definition* index = call->ArgumentAt(1); | 1678 Definition* index = call->ArgumentAt(1); |
| 1716 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | 1679 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 1717 call->GetBlock()->try_index()); | 1680 call->GetBlock()->try_index()); |
| 1718 (*entry)->InheritDeoptTarget(I, call); | 1681 (*entry)->InheritDeoptTarget(I, call); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1749 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); | 1712 *last = new(I) FloatToDoubleInstr(new(I) Value(*last), deopt_id); |
| 1750 flow_graph()->AppendTo(cursor, | 1713 flow_graph()->AppendTo(cursor, |
| 1751 *last, | 1714 *last, |
| 1752 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, | 1715 deopt_id != Isolate::kNoDeoptId ? call->env() : NULL, |
| 1753 FlowGraph::kValue); | 1716 FlowGraph::kValue); |
| 1754 } | 1717 } |
| 1755 return true; | 1718 return true; |
| 1756 } | 1719 } |
| 1757 | 1720 |
| 1758 | 1721 |
| 1759 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | |
| 1760 // Check for monomorphic IC data. | |
| 1761 if (!call->HasICData()) return false; | |
| 1762 const ICData& ic_data = | |
| 1763 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | |
| 1764 if (ic_data.NumberOfChecks() != 1) { | |
| 1765 return false; | |
| 1766 } | |
| 1767 ASSERT(ic_data.NumberOfUsedChecks() == 1); | |
| 1768 ASSERT(ic_data.HasOneTarget()); | |
| 1769 | |
| 1770 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | |
| 1771 TargetEntryInstr* entry; | |
| 1772 Definition* last; | |
| 1773 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | |
| 1774 target, | |
| 1775 call, | |
| 1776 call->ArgumentAt(0), | |
| 1777 call->token_pos(), | |
| 1778 *call->ic_data(), | |
| 1779 &entry, &last)) { | |
| 1780 return false; | |
| 1781 } | |
| 1782 | |
| 1783 // Insert receiver class check. | |
| 1784 AddReceiverCheck(call); | |
| 1785 // Remove the original push arguments. | |
| 1786 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | |
| 1787 PushArgumentInstr* push = call->PushArgumentAt(i); | |
| 1788 push->ReplaceUsesWith(push->value()->definition()); | |
| 1789 push->RemoveFromGraph(); | |
| 1790 } | |
| 1791 // Replace all uses of this definition with the result. | |
| 1792 call->ReplaceUsesWith(last); | |
| 1793 // Finally insert the sequence other definition in place of this one in the | |
| 1794 // graph. | |
| 1795 call->previous()->LinkTo(entry->next()); | |
| 1796 entry->UnuseAllInputs(); // Entry block is not in the graph. | |
| 1797 last->LinkTo(call); | |
| 1798 // Remove through the iterator. | |
| 1799 ASSERT(current_iterator()->Current() == call); | |
| 1800 current_iterator()->RemoveCurrentFromGraph(); | |
| 1801 call->set_previous(NULL); | |
| 1802 call->set_next(NULL); | |
| 1803 return true; | |
| 1804 } | |
| 1805 | |
| 1806 | |
| 1807 // Return true if d is a string of length one (a constant or result from | 1722 // Return true if d is a string of length one (a constant or result from |
| 1808 // from string-from-char-code instruction. | 1723 // from string-from-char-code instruction. |
| 1809 static bool IsLengthOneString(Definition* d) { | 1724 static bool IsLengthOneString(Definition* d) { |
| 1810 if (d->IsConstant()) { | 1725 if (d->IsConstant()) { |
| 1811 const Object& obj = d->AsConstant()->value(); | 1726 const Object& obj = d->AsConstant()->value(); |
| 1812 if (obj.IsString()) { | 1727 if (obj.IsString()) { |
| 1813 return String::Cast(obj).Length() == 1; | 1728 return String::Cast(obj).Length() == 1; |
| 1814 } else { | 1729 } else { |
| 1815 return false; | 1730 return false; |
| 1816 } | 1731 } |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2702 // inlining in FlowGraphInliner. | 2617 // inlining in FlowGraphInliner. |
| 2703 return false; | 2618 return false; |
| 2704 } | 2619 } |
| 2705 InlineImplicitInstanceGetter(call); | 2620 InlineImplicitInstanceGetter(call); |
| 2706 return true; | 2621 return true; |
| 2707 } | 2622 } |
| 2708 | 2623 |
| 2709 | 2624 |
| 2710 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( | 2625 bool FlowGraphOptimizer::TryReplaceInstanceCallWithInline( |
| 2711 InstanceCallInstr* call) { | 2626 InstanceCallInstr* call) { |
| 2712 ASSERT(call->HasICData()); | |
| 2713 Function& target = Function::Handle(I); | 2627 Function& target = Function::Handle(I); |
| 2714 GrowableArray<intptr_t> class_ids; | 2628 GrowableArray<intptr_t> class_ids; |
| 2715 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2629 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2716 const intptr_t receiver_cid = class_ids[0]; | 2630 const intptr_t receiver_cid = class_ids[0]; |
| 2717 | 2631 |
| 2718 TargetEntryInstr* entry; | 2632 TargetEntryInstr* entry; |
| 2719 Definition* last; | 2633 Definition* last; |
| 2720 if (!TryInlineRecognizedMethod(receiver_cid, | 2634 if (!TryInlineRecognizedMethod(receiver_cid, |
| 2721 target, | 2635 target, |
| 2722 call, | 2636 call, |
| (...skipping 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4268 const intptr_t max_checks = (op_kind == Token::kEQ) | 4182 const intptr_t max_checks = (op_kind == Token::kEQ) |
| 4269 ? FLAG_max_equality_polymorphic_checks | 4183 ? FLAG_max_equality_polymorphic_checks |
| 4270 : FLAG_max_polymorphic_checks; | 4184 : FLAG_max_polymorphic_checks; |
| 4271 if ((unary_checks.NumberOfChecks() > max_checks) && | 4185 if ((unary_checks.NumberOfChecks() > max_checks) && |
| 4272 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { | 4186 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { |
| 4273 // Too many checks, it will be megamorphic which needs unary checks. | 4187 // Too many checks, it will be megamorphic which needs unary checks. |
| 4274 instr->set_ic_data(&unary_checks); | 4188 instr->set_ic_data(&unary_checks); |
| 4275 return; | 4189 return; |
| 4276 } | 4190 } |
| 4277 | 4191 |
| 4278 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { | 4192 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithIndexedOp(instr)) { |
| 4279 return; | 4193 return; |
| 4280 } | 4194 } |
| 4281 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { | 4195 if ((op_kind == Token::kINDEX) && TryReplaceWithIndexedOp(instr)) { |
| 4282 return; | 4196 return; |
| 4283 } | 4197 } |
| 4284 | 4198 |
| 4285 if (op_kind == Token::kEQ && TryReplaceWithEqualityOp(instr, op_kind)) { | 4199 if (op_kind == Token::kEQ && TryReplaceWithEqualityOp(instr, op_kind)) { |
| 4286 return; | 4200 return; |
| 4287 } | 4201 } |
| 4288 | 4202 |
| 4289 if (Token::IsRelationalOperator(op_kind) && | 4203 if (Token::IsRelationalOperator(op_kind) && |
| 4290 TryReplaceWithRelationalOp(instr, op_kind)) { | 4204 TryReplaceWithRelationalOp(instr, op_kind)) { |
| 4291 return; | 4205 return; |
| (...skipping 4175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8467 | 8381 |
| 8468 // Insert materializations at environment uses. | 8382 // Insert materializations at environment uses. |
| 8469 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8383 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 8470 CreateMaterializationAt( | 8384 CreateMaterializationAt( |
| 8471 exits_collector_.exits()[i], alloc, *slots); | 8385 exits_collector_.exits()[i], alloc, *slots); |
| 8472 } | 8386 } |
| 8473 } | 8387 } |
| 8474 | 8388 |
| 8475 | 8389 |
| 8476 } // namespace dart | 8390 } // namespace dart |
| OLD | NEW |