| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 // Reset value types if guarded_cid was used. | 1383 // Reset value types if guarded_cid was used. |
| 1384 for (Value::Iterator it(load->input_use_list()); | 1384 for (Value::Iterator it(load->input_use_list()); |
| 1385 !it.Done(); | 1385 !it.Done(); |
| 1386 it.Advance()) { | 1386 it.Advance()) { |
| 1387 it.Current()->SetReachingType(NULL); | 1387 it.Current()->SetReachingType(NULL); |
| 1388 } | 1388 } |
| 1389 } | 1389 } |
| 1390 } | 1390 } |
| 1391 | 1391 |
| 1392 | 1392 |
| 1393 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, | |
| 1394 intptr_t length_offset, | |
| 1395 bool is_immutable, | |
| 1396 MethodRecognizer::Kind kind) { | |
| 1397 AddReceiverCheck(call); | |
| 1398 | |
| 1399 LoadFieldInstr* load = new LoadFieldInstr( | |
| 1400 new Value(call->ArgumentAt(0)), | |
| 1401 length_offset, | |
| 1402 Type::ZoneHandle(Type::SmiType()), | |
| 1403 is_immutable); | |
| 1404 load->set_result_cid(kSmiCid); | |
| 1405 load->set_recognized_kind(kind); | |
| 1406 ReplaceCall(call, load); | |
| 1407 } | |
| 1408 | |
| 1409 | |
| 1410 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( | 1393 void FlowGraphOptimizer::InlineGrowableArrayCapacityGetter( |
| 1411 InstanceCallInstr* call) { | 1394 InstanceCallInstr* call) { |
| 1412 AddReceiverCheck(call); | 1395 AddReceiverCheck(call); |
| 1413 | 1396 |
| 1414 // TODO(srdjan): type of load should be GrowableObjectArrayType. | 1397 // TODO(srdjan): type of load should be GrowableObjectArrayType. |
| 1415 LoadFieldInstr* data_load = new LoadFieldInstr( | 1398 LoadFieldInstr* data_load = new LoadFieldInstr( |
| 1416 new Value(call->ArgumentAt(0)), | 1399 new Value(call->ArgumentAt(0)), |
| 1417 Array::data_offset(), | 1400 Array::data_offset(), |
| 1418 Type::ZoneHandle(Type::DynamicType())); | 1401 Type::ZoneHandle(Type::DynamicType())); |
| 1419 data_load->set_result_cid(kArrayCid); | 1402 data_load->set_result_cid(kArrayCid); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1439 new Value(str), | 1422 new Value(str), |
| 1440 String::length_offset(), | 1423 String::length_offset(), |
| 1441 Type::ZoneHandle(Type::SmiType()), | 1424 Type::ZoneHandle(Type::SmiType()), |
| 1442 is_immutable); | 1425 is_immutable); |
| 1443 load->set_result_cid(kSmiCid); | 1426 load->set_result_cid(kSmiCid); |
| 1444 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); | 1427 load->set_recognized_kind(MethodRecognizer::kStringBaseLength); |
| 1445 return load; | 1428 return load; |
| 1446 } | 1429 } |
| 1447 | 1430 |
| 1448 | 1431 |
| 1449 void FlowGraphOptimizer::InlineStringLengthGetter(InstanceCallInstr* call) { | |
| 1450 AddReceiverCheck(call); | |
| 1451 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); | |
| 1452 ReplaceCall(call, load); | |
| 1453 } | |
| 1454 | |
| 1455 | |
| 1456 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { | 1432 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { |
| 1457 AddReceiverCheck(call); | 1433 AddReceiverCheck(call); |
| 1458 | 1434 |
| 1459 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); | 1435 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); |
| 1460 InsertBefore(call, load, NULL, Definition::kValue); | 1436 InsertBefore(call, load, NULL, Definition::kValue); |
| 1461 | 1437 |
| 1462 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); | 1438 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0))); |
| 1463 StrictCompareInstr* compare = | 1439 StrictCompareInstr* compare = |
| 1464 new StrictCompareInstr(call->token_pos(), | 1440 new StrictCompareInstr(call->token_pos(), |
| 1465 Token::kEQ_STRICT, | 1441 Token::kEQ_STRICT, |
| 1466 new Value(load), | 1442 new Value(load), |
| 1467 new Value(zero)); | 1443 new Value(zero)); |
| 1468 ReplaceCall(call, compare); | 1444 ReplaceCall(call, compare); |
| 1469 } | 1445 } |
| 1470 | 1446 |
| 1471 | 1447 |
| 1472 void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) { | 1448 void FlowGraphOptimizer::InlineObjectCid(InstanceCallInstr* call) { |
| 1473 LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0))); | 1449 LoadClassIdInstr* load = new LoadClassIdInstr(new Value(call->ArgumentAt(0))); |
| 1474 ReplaceCall(call, load); | 1450 ReplaceCall(call, load); |
| 1475 } | 1451 } |
| 1476 | 1452 |
| 1477 | 1453 |
| 1478 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { | |
| 1479 switch (kind) { | |
| 1480 case MethodRecognizer::kObjectArrayLength: | |
| 1481 case MethodRecognizer::kImmutableArrayLength: | |
| 1482 return Array::length_offset(); | |
| 1483 case MethodRecognizer::kTypedDataLength: | |
| 1484 // .length is defined in _TypedList which is the base class for internal | |
| 1485 // and external typed data. | |
| 1486 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset()); | |
| 1487 return TypedData::length_offset(); | |
| 1488 case MethodRecognizer::kGrowableArrayLength: | |
| 1489 return GrowableObjectArray::length_offset(); | |
| 1490 default: | |
| 1491 UNREACHABLE(); | |
| 1492 return 0; | |
| 1493 } | |
| 1494 } | |
| 1495 | |
| 1496 | |
| 1497 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | 1454 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, |
| 1498 MethodRecognizer::Kind getter) { | 1455 MethodRecognizer::Kind getter) { |
| 1499 if (!ShouldInlineSimd()) { | 1456 if (!ShouldInlineSimd()) { |
| 1500 return false; | 1457 return false; |
| 1501 } | 1458 } |
| 1502 AddCheckClass(call->ArgumentAt(0), | 1459 AddCheckClass(call->ArgumentAt(0), |
| 1503 ICData::ZoneHandle( | 1460 ICData::ZoneHandle( |
| 1504 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1461 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1505 call->deopt_id(), | 1462 call->deopt_id(), |
| 1506 call->env(), | 1463 call->env(), |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 // Not an implicit getter. | 1628 // Not an implicit getter. |
| 1672 MethodRecognizer::Kind recognized_kind = | 1629 MethodRecognizer::Kind recognized_kind = |
| 1673 MethodRecognizer::RecognizeKind(target); | 1630 MethodRecognizer::RecognizeKind(target); |
| 1674 | 1631 |
| 1675 // VM objects length getter. | 1632 // VM objects length getter. |
| 1676 switch (recognized_kind) { | 1633 switch (recognized_kind) { |
| 1677 case MethodRecognizer::kObjectCid: { | 1634 case MethodRecognizer::kObjectCid: { |
| 1678 InlineObjectCid(call); | 1635 InlineObjectCid(call); |
| 1679 return true; | 1636 return true; |
| 1680 } | 1637 } |
| 1681 case MethodRecognizer::kObjectArrayLength: | |
| 1682 case MethodRecognizer::kImmutableArrayLength: | |
| 1683 case MethodRecognizer::kTypedDataLength: | |
| 1684 case MethodRecognizer::kGrowableArrayLength: { | |
| 1685 if (!ic_data.HasOneTarget()) { | |
| 1686 // TODO(srdjan): Implement for mutiple targets. | |
| 1687 return false; | |
| 1688 } | |
| 1689 const bool is_immutable = | |
| 1690 (recognized_kind == MethodRecognizer::kObjectArrayLength) || | |
| 1691 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || | |
| 1692 (recognized_kind == MethodRecognizer::kTypedDataLength); | |
| 1693 InlineArrayLengthGetter(call, | |
| 1694 OffsetForLengthGetter(recognized_kind), | |
| 1695 is_immutable, | |
| 1696 recognized_kind); | |
| 1697 return true; | |
| 1698 } | |
| 1699 case MethodRecognizer::kGrowableArrayCapacity: | 1638 case MethodRecognizer::kGrowableArrayCapacity: |
| 1700 InlineGrowableArrayCapacityGetter(call); | 1639 InlineGrowableArrayCapacityGetter(call); |
| 1701 return true; | 1640 return true; |
| 1702 case MethodRecognizer::kStringBaseLength: | |
| 1703 if (!ic_data.HasOneTarget()) { | |
| 1704 // Target is not only StringBase_get_length. | |
| 1705 return false; | |
| 1706 } | |
| 1707 InlineStringLengthGetter(call); | |
| 1708 return true; | |
| 1709 case MethodRecognizer::kStringBaseIsEmpty: | 1641 case MethodRecognizer::kStringBaseIsEmpty: |
| 1710 if (!ic_data.HasOneTarget()) { | 1642 if (!ic_data.HasOneTarget()) { |
| 1711 // Target is not only StringBase_get_isEmpty. | 1643 // Target is not only StringBase_get_isEmpty. |
| 1712 return false; | 1644 return false; |
| 1713 } | 1645 } |
| 1714 InlineStringIsEmptyGetter(call); | 1646 InlineStringIsEmptyGetter(call); |
| 1715 return true; | 1647 return true; |
| 1716 case MethodRecognizer::kFloat32x4ShuffleX: | 1648 case MethodRecognizer::kFloat32x4ShuffleX: |
| 1717 case MethodRecognizer::kFloat32x4ShuffleY: | 1649 case MethodRecognizer::kFloat32x4ShuffleY: |
| 1718 case MethodRecognizer::kFloat32x4ShuffleZ: | 1650 case MethodRecognizer::kFloat32x4ShuffleZ: |
| 1719 case MethodRecognizer::kFloat32x4ShuffleW: | 1651 case MethodRecognizer::kFloat32x4ShuffleW: |
| 1720 case MethodRecognizer::kFloat32x4GetSignMask: | 1652 case MethodRecognizer::kFloat32x4GetSignMask: |
| 1721 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || | 1653 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || |
| 1722 !ic_data.HasOneTarget()) { | 1654 !ic_data.HasOneTarget()) { |
| 1723 return false; | 1655 return false; |
| 1724 } | 1656 } |
| 1725 return InlineFloat32x4Getter(call, recognized_kind); | 1657 return InlineFloat32x4Getter(call, recognized_kind); |
| 1726 case MethodRecognizer::kUint32x4GetFlagX: | 1658 case MethodRecognizer::kUint32x4GetFlagX: |
| 1727 case MethodRecognizer::kUint32x4GetFlagY: | 1659 case MethodRecognizer::kUint32x4GetFlagY: |
| 1728 case MethodRecognizer::kUint32x4GetFlagZ: | 1660 case MethodRecognizer::kUint32x4GetFlagZ: |
| 1729 case MethodRecognizer::kUint32x4GetFlagW: | 1661 case MethodRecognizer::kUint32x4GetFlagW: |
| 1730 case MethodRecognizer::kUint32x4GetSignMask: { | 1662 case MethodRecognizer::kUint32x4GetSignMask: { |
| 1731 if (!ic_data.HasReceiverClassId(kUint32x4Cid) || | 1663 if (!ic_data.HasReceiverClassId(kUint32x4Cid) || |
| 1732 !ic_data.HasOneTarget()) { | 1664 !ic_data.HasOneTarget()) { |
| 1733 return false; | 1665 return false; |
| 1734 } | 1666 } |
| 1735 return InlineUint32x4Getter(call, recognized_kind); | 1667 return InlineUint32x4Getter(call, recognized_kind); |
| 1736 } | 1668 } |
| 1737 default: | 1669 default: |
| 1738 ASSERT(recognized_kind == MethodRecognizer::kUnknown); | 1670 break; |
| 1739 } | 1671 } |
| 1740 return false; | 1672 return false; |
| 1741 } | 1673 } |
| 1742 | 1674 |
| 1743 | 1675 |
| 1744 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( | 1676 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( |
| 1745 InstanceCallInstr* call, | 1677 InstanceCallInstr* call, |
| 1746 intptr_t cid) { | 1678 intptr_t cid) { |
| 1747 Definition* str = call->ArgumentAt(0); | 1679 Definition* str = call->ArgumentAt(0); |
| 1748 Definition* index = call->ArgumentAt(1); | 1680 Definition* index = call->ArgumentAt(1); |
| (...skipping 5823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7572 } | 7504 } |
| 7573 | 7505 |
| 7574 // Insert materializations at environment uses. | 7506 // Insert materializations at environment uses. |
| 7575 for (intptr_t i = 0; i < exits.length(); i++) { | 7507 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7576 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7508 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7577 } | 7509 } |
| 7578 } | 7510 } |
| 7579 | 7511 |
| 7580 | 7512 |
| 7581 } // namespace dart | 7513 } // namespace dart |
| OLD | NEW |