Chromium Code Reviews| 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 753 return false; | 753 return false; |
| 754 } | 754 } |
| 755 | 755 |
| 756 BuildStoreIndexed(call, value_check, class_id); | 756 BuildStoreIndexed(call, value_check, class_id); |
| 757 return true; | 757 return true; |
| 758 } | 758 } |
| 759 | 759 |
| 760 | 760 |
| 761 bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) { | 761 bool FlowGraphOptimizer::TryInlineByteArraySetIndexed(InstanceCallInstr* call) { |
| 762 const intptr_t class_id = ReceiverClassId(call); | 762 const intptr_t class_id = ReceiverClassId(call); |
| 763 if (class_id == kInt32ArrayCid || class_id == kUint32ArrayCid) { | |
| 764 // Check if elements fit into a smi or the platform supports unboxed mints. | |
| 765 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) { | |
|
Vyacheslav Egorov (Google)
2013/03/11 11:45:27
I think you can move it back down.
Florian Schneider
2013/03/11 12:14:12
Done.
| |
| 766 return false; | |
| 767 } | |
| 768 } | |
| 763 ICData& value_check = ICData::ZoneHandle(); | 769 ICData& value_check = ICData::ZoneHandle(); |
| 764 switch (class_id) { | 770 switch (class_id) { |
| 765 case kInt8ArrayCid: | 771 case kInt8ArrayCid: |
| 766 case kUint8ArrayCid: | 772 case kUint8ArrayCid: |
| 767 case kUint8ClampedArrayCid: | 773 case kUint8ClampedArrayCid: |
| 768 case kExternalUint8ArrayCid: | 774 case kExternalUint8ArrayCid: |
| 769 case kExternalUint8ClampedArrayCid: | 775 case kExternalUint8ClampedArrayCid: |
| 770 case kInt16ArrayCid: | 776 case kInt16ArrayCid: |
| 771 case kUint16ArrayCid: { | 777 case kUint16ArrayCid: { |
| 772 // Check that value is always smi. | 778 // Check that value is always smi. |
| 773 value_check = ICData::New(Function::Handle(), | 779 value_check = ICData::New(Function::Handle(), |
| 774 String::Handle(), | 780 String::Handle(), |
| 775 Isolate::kNoDeoptId, | 781 Isolate::kNoDeoptId, |
| 776 1); | 782 1); |
| 777 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | 783 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); |
| 778 break; | 784 break; |
| 779 } | 785 } |
| 780 case kInt32ArrayCid: | 786 case kInt32ArrayCid: |
| 781 case kUint32ArrayCid: | 787 case kUint32ArrayCid: |
| 782 // Check if elements fit into a smi or the platform supports unboxed | |
| 783 // mints. | |
| 784 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) { | |
| 785 return false; | |
| 786 } | |
| 787 // We don't have ICData for the value stored, so we optimistically assume | 788 // We don't have ICData for the value stored, so we optimistically assume |
| 788 // smis first. If we ever deoptimized here, we require to unbox the value | 789 // smis first. If we ever deoptimized here, we require to unbox the value |
| 789 // before storing to handle the mint case, too. | 790 // before storing to handle the mint case, too. |
| 790 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { | 791 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { |
| 791 value_check = ICData::New(Function::Handle(), | 792 value_check = ICData::New(Function::Handle(), |
| 792 String::Handle(), | 793 String::Handle(), |
| 793 Isolate::kNoDeoptId, | 794 Isolate::kNoDeoptId, |
| 794 1); | 795 1); |
| 795 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | 796 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); |
| 796 } | 797 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 ? kNoStoreBarrier | 889 ? kNoStoreBarrier |
| 889 : kEmitStoreBarrier; | 890 : kEmitStoreBarrier; |
| 890 if (!value_check.IsNull()) { | 891 if (!value_check.IsNull()) { |
| 891 // No store barrier needed because checked value is a smi, an unboxed mint | 892 // No store barrier needed because checked value is a smi, an unboxed mint |
| 892 // or unboxed double. | 893 // or unboxed double. |
| 893 needs_store_barrier = kNoStoreBarrier; | 894 needs_store_barrier = kNoStoreBarrier; |
| 894 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | 895 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), |
| 895 call); | 896 call); |
| 896 } | 897 } |
| 897 | 898 |
| 899 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | |
| 898 Definition* array_op = new StoreIndexedInstr(new Value(array), | 900 Definition* array_op = new StoreIndexedInstr(new Value(array), |
| 899 new Value(index), | 901 new Value(index), |
| 900 new Value(stored_value), | 902 new Value(stored_value), |
| 901 needs_store_barrier, | 903 needs_store_barrier, |
| 904 index_scale, | |
| 902 array_cid, | 905 array_cid, |
| 903 call->deopt_id()); | 906 call->deopt_id()); |
| 904 ReplaceCall(call, array_op); | 907 ReplaceCall(call, array_op); |
| 905 } | 908 } |
| 906 | 909 |
| 907 | 910 |
| 908 | 911 |
| 909 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 912 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 910 const intptr_t class_id = ReceiverClassId(call); | 913 const intptr_t class_id = ReceiverClassId(call); |
| 911 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. | 914 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 939 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? | 942 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? |
| 940 call->deopt_id() : Isolate::kNoDeoptId; | 943 call->deopt_id() : Isolate::kNoDeoptId; |
| 941 } | 944 } |
| 942 break; | 945 break; |
| 943 default: | 946 default: |
| 944 return false; | 947 return false; |
| 945 } | 948 } |
| 946 Definition* array = call->ArgumentAt(0); | 949 Definition* array = call->ArgumentAt(0); |
| 947 Definition* index = call->ArgumentAt(1); | 950 Definition* index = call->ArgumentAt(1); |
| 948 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); | 951 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); |
| 952 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | |
| 949 Definition* array_op = | 953 Definition* array_op = |
| 950 new LoadIndexedInstr(new Value(array), | 954 new LoadIndexedInstr(new Value(array), |
| 951 new Value(index), | 955 new Value(index), |
| 952 FlowGraphCompiler::ElementSizeFor(array_cid), | 956 index_scale, |
| 953 array_cid, | 957 array_cid, |
| 954 deopt_id); | 958 deopt_id); |
| 955 ReplaceCall(call, array_op); | 959 ReplaceCall(call, array_op); |
| 956 return true; | 960 return true; |
| 957 } | 961 } |
| 958 | 962 |
| 959 | 963 |
| 960 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, | 964 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, |
| 961 Token::Kind op_kind) { | 965 Token::Kind op_kind) { |
| 962 intptr_t operands_type = kIllegalCid; | 966 intptr_t operands_type = kIllegalCid; |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 } | 1600 } |
| 1597 return true; | 1601 return true; |
| 1598 default: | 1602 default: |
| 1599 // Unsupported method. | 1603 // Unsupported method. |
| 1600 return false; | 1604 return false; |
| 1601 } | 1605 } |
| 1602 } | 1606 } |
| 1603 | 1607 |
| 1604 if (IsSupportedByteArrayCid(class_ids[0]) && | 1608 if (IsSupportedByteArrayCid(class_ids[0]) && |
| 1605 (ic_data.NumberOfChecks() == 1)) { | 1609 (ic_data.NumberOfChecks() == 1)) { |
| 1606 Definition* array_op = NULL; | 1610 // For elements that may not fit into a smi on all platforms, check if |
| 1611 // elements fit into a smi or the platform supports unboxed mints. | |
| 1612 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) || | |
| 1613 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) || | |
| 1614 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) || | |
| 1615 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) { | |
| 1616 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) { | |
|
Vyacheslav Egorov (Google)
2013/03/11 11:45:27
Maybe make a helper
static bool CanLoadUnboxedIn
Florian Schneider
2013/03/11 12:14:12
Done.
| |
| 1617 return false; | |
| 1618 } | |
| 1619 } | |
| 1620 | |
| 1607 switch (recognized_kind) { | 1621 switch (recognized_kind) { |
| 1622 // ByteArray getters. | |
| 1608 case MethodRecognizer::kByteArrayBaseGetInt8: | 1623 case MethodRecognizer::kByteArrayBaseGetInt8: |
| 1609 array_op = BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid); | 1624 return BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid); |
| 1610 break; | |
| 1611 case MethodRecognizer::kByteArrayBaseGetUint8: | 1625 case MethodRecognizer::kByteArrayBaseGetUint8: |
| 1612 array_op = BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid); | 1626 return BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid); |
| 1613 break; | |
| 1614 case MethodRecognizer::kByteArrayBaseGetInt16: | 1627 case MethodRecognizer::kByteArrayBaseGetInt16: |
| 1615 array_op = BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid); | 1628 return BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid); |
| 1616 break; | |
| 1617 case MethodRecognizer::kByteArrayBaseGetUint16: | 1629 case MethodRecognizer::kByteArrayBaseGetUint16: |
| 1618 array_op = BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid); | 1630 return BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid); |
| 1619 break; | |
| 1620 case MethodRecognizer::kByteArrayBaseGetInt32: | 1631 case MethodRecognizer::kByteArrayBaseGetInt32: |
| 1621 // Check if elements fit into a smi or the platform supports unboxed | 1632 return BuildByteArrayViewLoad(call, class_ids[0], kInt32ArrayCid); |
| 1622 // mints. | |
| 1623 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) { | |
| 1624 return false; | |
| 1625 } | |
| 1626 array_op = BuildByteArrayViewLoad(call, class_ids[0], kInt32ArrayCid); | |
| 1627 break; | |
| 1628 case MethodRecognizer::kByteArrayBaseGetUint32: | 1633 case MethodRecognizer::kByteArrayBaseGetUint32: |
| 1629 // Check if elements fit into a smi or the platform supports unboxed | 1634 return BuildByteArrayViewLoad(call, class_ids[0], kUint32ArrayCid); |
| 1630 // mints. | |
| 1631 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) { | |
| 1632 return false; | |
| 1633 } | |
| 1634 array_op = BuildByteArrayViewLoad(call, class_ids[0], kUint32ArrayCid); | |
| 1635 break; | |
| 1636 case MethodRecognizer::kByteArrayBaseGetFloat32: | 1635 case MethodRecognizer::kByteArrayBaseGetFloat32: |
| 1637 array_op = BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid); | 1636 return BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid); |
| 1638 break; | |
| 1639 case MethodRecognizer::kByteArrayBaseGetFloat64: | 1637 case MethodRecognizer::kByteArrayBaseGetFloat64: |
| 1640 array_op = BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid); | 1638 return BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid); |
| 1641 break; | 1639 |
| 1640 // ByteArray setters. | |
| 1641 case MethodRecognizer::kByteArrayBaseSetInt8: | |
| 1642 return BuildByteArrayViewStore(call, class_ids[0], kInt8ArrayCid); | |
| 1643 case MethodRecognizer::kByteArrayBaseSetUint8: | |
| 1644 return BuildByteArrayViewStore(call, class_ids[0], kUint8ArrayCid); | |
| 1645 case MethodRecognizer::kByteArrayBaseSetInt16: | |
| 1646 return BuildByteArrayViewStore(call, class_ids[0], kInt16ArrayCid); | |
| 1647 case MethodRecognizer::kByteArrayBaseSetUint16: | |
| 1648 return BuildByteArrayViewStore(call, class_ids[0], kUint16ArrayCid); | |
| 1649 case MethodRecognizer::kByteArrayBaseSetInt32: | |
| 1650 return BuildByteArrayViewStore(call, class_ids[0], kInt32ArrayCid); | |
| 1651 case MethodRecognizer::kByteArrayBaseSetUint32: | |
| 1652 return BuildByteArrayViewStore(call, class_ids[0], kUint32ArrayCid); | |
| 1653 case MethodRecognizer::kByteArrayBaseSetFloat32: | |
| 1654 return BuildByteArrayViewStore(call, class_ids[0], kFloat32ArrayCid); | |
| 1655 case MethodRecognizer::kByteArrayBaseSetFloat64: | |
| 1656 return BuildByteArrayViewStore(call, class_ids[0], kFloat64ArrayCid); | |
| 1642 default: | 1657 default: |
| 1643 // Unsupported method. | 1658 // Unsupported method. |
| 1644 return false; | 1659 return false; |
| 1645 } | 1660 } |
| 1646 ASSERT(array_op != NULL); | |
| 1647 ReplaceCall(call, array_op); | |
| 1648 return true; | |
| 1649 } | 1661 } |
| 1650 return false; | 1662 return false; |
| 1651 } | 1663 } |
| 1652 | 1664 |
| 1653 | 1665 |
| 1654 LoadIndexedInstr* FlowGraphOptimizer::BuildByteArrayViewLoad( | 1666 bool FlowGraphOptimizer::BuildByteArrayViewLoad( |
| 1667 InstanceCallInstr* call, | |
| 1668 intptr_t receiver_cid, | |
| 1669 intptr_t view_cid) { | |
| 1670 PrepareByteArrayViewOp(call, receiver_cid, view_cid); | |
| 1671 | |
| 1672 Definition* array = call->ArgumentAt(0); | |
| 1673 Definition* byte_index = call->ArgumentAt(1); | |
| 1674 | |
| 1675 // Optimistically build a smi-checked load for Int32 and Uint32 | |
| 1676 // loads on ia32 like we do for normal array loads, and only revert to | |
| 1677 // mint case after deoptimizing here. | |
| 1678 intptr_t deopt_id = Isolate::kNoDeoptId; | |
| 1679 if ((view_cid == kInt32ArrayCid || view_cid == kUint32ArrayCid) && | |
| 1680 call->ic_data()->deopt_reason() == kDeoptUnknown) { | |
| 1681 deopt_id = call->deopt_id(); | |
| 1682 } | |
| 1683 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), | |
| 1684 new Value(byte_index), | |
| 1685 1, // Index scale. | |
| 1686 view_cid, | |
| 1687 deopt_id); | |
| 1688 ReplaceCall(call, array_op); | |
| 1689 return true; | |
| 1690 } | |
| 1691 | |
| 1692 | |
| 1693 bool FlowGraphOptimizer::BuildByteArrayViewStore( | |
| 1694 InstanceCallInstr* call, | |
| 1695 intptr_t receiver_cid, | |
| 1696 intptr_t view_cid) { | |
| 1697 PrepareByteArrayViewOp(call, receiver_cid, view_cid); | |
| 1698 ICData& value_check = ICData::ZoneHandle(); | |
| 1699 switch (view_cid) { | |
| 1700 case kInt8ArrayCid: | |
| 1701 case kUint8ArrayCid: | |
| 1702 case kUint8ClampedArrayCid: | |
| 1703 case kExternalUint8ArrayCid: | |
| 1704 case kExternalUint8ClampedArrayCid: | |
| 1705 case kInt16ArrayCid: | |
| 1706 case kUint16ArrayCid: { | |
| 1707 // Check that value is always smi. | |
| 1708 value_check = ICData::New(Function::Handle(), | |
| 1709 String::Handle(), | |
| 1710 Isolate::kNoDeoptId, | |
| 1711 1); | |
| 1712 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | |
| 1713 break; | |
| 1714 } | |
| 1715 case kInt32ArrayCid: | |
| 1716 case kUint32ArrayCid: | |
| 1717 // We don't have ICData for the value stored, so we optimistically assume | |
| 1718 // smis first. If we ever deoptimized here, we require to unbox the value | |
| 1719 // before storing to handle the mint case, too. | |
| 1720 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { | |
| 1721 value_check = ICData::New(Function::Handle(), | |
| 1722 String::Handle(), | |
| 1723 Isolate::kNoDeoptId, | |
| 1724 1); | |
| 1725 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); | |
| 1726 } | |
| 1727 break; | |
| 1728 case kFloat32ArrayCid: | |
| 1729 case kFloat64ArrayCid: { | |
| 1730 // Check that value is always double. | |
| 1731 value_check = ICData::New(Function::Handle(), | |
| 1732 String::Handle(), | |
| 1733 Isolate::kNoDeoptId, | |
| 1734 1); | |
| 1735 value_check.AddReceiverCheck(kDoubleCid, Function::Handle()); | |
| 1736 break; | |
| 1737 } | |
| 1738 default: | |
| 1739 // Array cids are already checked in the caller. | |
| 1740 UNREACHABLE(); | |
| 1741 return NULL; | |
| 1742 } | |
| 1743 | |
| 1744 Definition* array = call->ArgumentAt(0); | |
| 1745 Definition* index = call->ArgumentAt(1); | |
| 1746 Definition* stored_value = call->ArgumentAt(2); | |
| 1747 if (!value_check.IsNull()) { | |
| 1748 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), | |
| 1749 call); | |
| 1750 } | |
| 1751 StoreBarrierType needs_store_barrier = kNoStoreBarrier; | |
| 1752 | |
| 1753 | |
| 1754 // result = index + bytesPerElement. | |
| 1755 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); | |
| 1756 ConstantInstr* bytes_per_element = | |
| 1757 new ConstantInstr(Smi::Handle(Smi::New(element_size))); | |
| 1758 InsertBefore(call, bytes_per_element, NULL, Definition::kValue); | |
| 1759 BinarySmiOpInstr* result = | |
| 1760 new BinarySmiOpInstr(Token::kADD, | |
|
Vyacheslav Egorov (Google)
2013/03/11 11:45:27
why kADD.
Florian Schneider
2013/03/11 12:14:12
This is the return value of the setter: index + el
| |
| 1761 call, | |
| 1762 new Value(index), | |
| 1763 new Value(bytes_per_element)); | |
| 1764 InsertBefore(call, result, call->env(), Definition::kValue); | |
| 1765 | |
| 1766 StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array), | |
| 1767 new Value(index), | |
| 1768 new Value(stored_value), | |
| 1769 needs_store_barrier, | |
| 1770 1, // Index scale | |
| 1771 view_cid, | |
| 1772 call->deopt_id()); | |
| 1773 call->ReplaceUsesWith(result); // Fix uses of the call's return value. | |
| 1774 ReplaceCall(call, array_op); | |
| 1775 array_op->ClearSSATempIndex(); // Store has no uses. | |
| 1776 return true; | |
| 1777 } | |
| 1778 | |
| 1779 | |
| 1780 void FlowGraphOptimizer::PrepareByteArrayViewOp( | |
| 1655 InstanceCallInstr* call, | 1781 InstanceCallInstr* call, |
| 1656 intptr_t receiver_cid, | 1782 intptr_t receiver_cid, |
| 1657 intptr_t view_cid) { | 1783 intptr_t view_cid) { |
| 1658 Definition* array = call->ArgumentAt(0); | 1784 Definition* array = call->ArgumentAt(0); |
| 1659 Definition* byte_index = call->ArgumentAt(1); | 1785 Definition* byte_index = call->ArgumentAt(1); |
| 1660 | 1786 |
| 1661 AddReceiverCheck(call); | 1787 AddReceiverCheck(call); |
| 1662 const bool is_immutable = true; | 1788 const bool is_immutable = true; |
| 1663 LoadFieldInstr* length = new LoadFieldInstr( | 1789 LoadFieldInstr* length = new LoadFieldInstr( |
| 1664 new Value(array), | 1790 new Value(array), |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1683 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); | 1809 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); |
| 1684 | 1810 |
| 1685 // Check byte_index < len_in_bytes. | 1811 // Check byte_index < len_in_bytes. |
| 1686 InsertBefore(call, | 1812 InsertBefore(call, |
| 1687 new CheckArrayBoundInstr(new Value(len_in_bytes), | 1813 new CheckArrayBoundInstr(new Value(len_in_bytes), |
| 1688 new Value(byte_index), | 1814 new Value(byte_index), |
| 1689 receiver_cid, | 1815 receiver_cid, |
| 1690 call), | 1816 call), |
| 1691 call->env(), | 1817 call->env(), |
| 1692 Definition::kEffect); | 1818 Definition::kEffect); |
| 1693 | |
| 1694 // TODO(fschneider): Optimistically build smi load for Int32 and Uint32 | |
| 1695 // loads on ia32 like we do for normal array loads, and only revert to | |
| 1696 // mint case after deoptimizing here. | |
| 1697 return new LoadIndexedInstr(new Value(array), | |
| 1698 new Value(byte_index), | |
| 1699 1, // Index scale. | |
| 1700 view_cid, | |
| 1701 Isolate::kNoDeoptId); // Can't deoptimize. | |
| 1702 } | 1819 } |
| 1703 | 1820 |
| 1704 | 1821 |
| 1705 // Returns a Boolean constant if all classes in ic_data yield the same type-test | 1822 // Returns a Boolean constant if all classes in ic_data yield the same type-test |
| 1706 // result and the type tests do not depend on type arguments. Otherwise return | 1823 // result and the type tests do not depend on type arguments. Otherwise return |
| 1707 // Bool::null(). | 1824 // Bool::null(). |
| 1708 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data, | 1825 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data, |
| 1709 const AbstractType& type) const { | 1826 const AbstractType& type) const { |
| 1710 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. | 1827 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. |
| 1711 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null(); | 1828 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null(); |
| (...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4549 if (changed) { | 4666 if (changed) { |
| 4550 // We may have changed the block order and the dominator tree. | 4667 // We may have changed the block order and the dominator tree. |
| 4551 flow_graph->DiscoverBlocks(); | 4668 flow_graph->DiscoverBlocks(); |
| 4552 GrowableArray<BitVector*> dominance_frontier; | 4669 GrowableArray<BitVector*> dominance_frontier; |
| 4553 flow_graph->ComputeDominators(&dominance_frontier); | 4670 flow_graph->ComputeDominators(&dominance_frontier); |
| 4554 } | 4671 } |
| 4555 } | 4672 } |
| 4556 | 4673 |
| 4557 | 4674 |
| 4558 } // namespace dart | 4675 } // namespace dart |
| OLD | NEW |