Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 12378039: Inline ByteArray setters like setUint8 in the optimizer. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 Type::ZoneHandle(Type::DynamicType())); 685 Type::ZoneHandle(Type::DynamicType()));
686 elements->set_result_cid(kArrayCid); 686 elements->set_result_cid(kArrayCid);
687 InsertBefore(call, elements, NULL, Definition::kValue); 687 InsertBefore(call, elements, NULL, Definition::kValue);
688 *array = elements; 688 *array = elements;
689 return kArrayCid; 689 return kArrayCid;
690 } 690 }
691 return class_id; 691 return class_id;
692 } 692 }
693 693
694 694
695 static bool CanUnboxInt32() {
696 // Int32/Uint32 can be unboxed if it fits into a smi or the platform
697 // supports unboxed mints.
698 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints();
699 }
700
701
695 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { 702 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) {
696 const intptr_t class_id = ReceiverClassId(call); 703 const intptr_t class_id = ReceiverClassId(call);
697 ICData& value_check = ICData::ZoneHandle(); 704 ICData& value_check = ICData::ZoneHandle();
698 switch (class_id) { 705 switch (class_id) {
699 case kArrayCid: 706 case kArrayCid:
700 case kGrowableObjectArrayCid: 707 case kGrowableObjectArrayCid:
701 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) { 708 if (ArgIsAlwaysSmi(*call->ic_data(), 2)) {
702 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 709 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
703 } 710 }
704 break; 711 break;
705 case kInt8ArrayCid: 712 case kInt8ArrayCid:
706 case kUint8ArrayCid: 713 case kUint8ArrayCid:
707 case kUint8ClampedArrayCid: 714 case kUint8ClampedArrayCid:
708 case kExternalUint8ArrayCid: 715 case kExternalUint8ArrayCid:
709 case kExternalUint8ClampedArrayCid: 716 case kExternalUint8ClampedArrayCid:
710 case kInt16ArrayCid: 717 case kInt16ArrayCid:
711 case kUint16ArrayCid: 718 case kUint16ArrayCid:
712 // Check that value is always smi. 719 // Check that value is always smi.
713 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 720 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
714 if ((value_check.NumberOfChecks() != 1) || 721 if ((value_check.NumberOfChecks() != 1) ||
715 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) { 722 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) {
716 return false; 723 return false;
717 } 724 }
718 break; 725 break;
719 case kInt32ArrayCid: 726 case kInt32ArrayCid:
720 case kUint32ArrayCid: { 727 case kUint32ArrayCid: {
721 // Check if elements fit into a smi or the platform supports unboxed 728 if (!CanUnboxInt32()) return false;
722 // mints.
723 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) {
724 return false;
725 }
726 // Check that value is always smi or mint, if the platform has unboxed 729 // Check that value is always smi or mint, if the platform has unboxed
727 // mints (ia32 with at least SSE 4.1). 730 // mints (ia32 with at least SSE 4.1).
728 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 731 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
729 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) { 732 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) {
730 intptr_t cid = value_check.GetReceiverClassIdAt(i); 733 intptr_t cid = value_check.GetReceiverClassIdAt(i);
731 if (FlowGraphCompiler::SupportsUnboxedMints()) { 734 if (FlowGraphCompiler::SupportsUnboxedMints()) {
732 if ((cid != kSmiCid) && (cid != kMintCid)) { 735 if ((cid != kSmiCid) && (cid != kMintCid)) {
733 return false; 736 return false;
734 } 737 }
735 } else if (cid != kSmiCid) { 738 } else if (cid != kSmiCid) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 // Check that value is always smi. 775 // Check that value is always smi.
773 value_check = ICData::New(Function::Handle(), 776 value_check = ICData::New(Function::Handle(),
774 String::Handle(), 777 String::Handle(),
775 Isolate::kNoDeoptId, 778 Isolate::kNoDeoptId,
776 1); 779 1);
777 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); 780 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
778 break; 781 break;
779 } 782 }
780 case kInt32ArrayCid: 783 case kInt32ArrayCid:
781 case kUint32ArrayCid: 784 case kUint32ArrayCid:
782 // Check if elements fit into a smi or the platform supports unboxed 785 if (!CanUnboxInt32()) return false;
783 // mints. 786
784 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) {
785 return false;
786 }
787 // We don't have ICData for the value stored, so we optimistically assume 787 // 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 788 // smis first. If we ever deoptimized here, we require to unbox the value
789 // before storing to handle the mint case, too. 789 // before storing to handle the mint case, too.
790 if (call->ic_data()->deopt_reason() == kDeoptUnknown) { 790 if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
791 value_check = ICData::New(Function::Handle(), 791 value_check = ICData::New(Function::Handle(),
792 String::Handle(), 792 String::Handle(),
793 Isolate::kNoDeoptId, 793 Isolate::kNoDeoptId,
794 1); 794 1);
795 value_check.AddReceiverCheck(kSmiCid, Function::Handle()); 795 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
796 } 796 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 ? kNoStoreBarrier 888 ? kNoStoreBarrier
889 : kEmitStoreBarrier; 889 : kEmitStoreBarrier;
890 if (!value_check.IsNull()) { 890 if (!value_check.IsNull()) {
891 // No store barrier needed because checked value is a smi, an unboxed mint 891 // No store barrier needed because checked value is a smi, an unboxed mint
892 // or unboxed double. 892 // or unboxed double.
893 needs_store_barrier = kNoStoreBarrier; 893 needs_store_barrier = kNoStoreBarrier;
894 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(), 894 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
895 call); 895 call);
896 } 896 }
897 897
898 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
898 Definition* array_op = new StoreIndexedInstr(new Value(array), 899 Definition* array_op = new StoreIndexedInstr(new Value(array),
899 new Value(index), 900 new Value(index),
900 new Value(stored_value), 901 new Value(stored_value),
901 needs_store_barrier, 902 needs_store_barrier,
903 index_scale,
902 array_cid, 904 array_cid,
903 call->deopt_id()); 905 call->deopt_id());
904 ReplaceCall(call, array_op); 906 ReplaceCall(call, array_op);
905 } 907 }
906 908
907 909
908 910
909 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { 911 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
910 const intptr_t class_id = ReceiverClassId(call); 912 const intptr_t class_id = ReceiverClassId(call);
911 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. 913 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt.
912 intptr_t deopt_id = Isolate::kNoDeoptId; 914 intptr_t deopt_id = Isolate::kNoDeoptId;
913 switch (class_id) { 915 switch (class_id) {
914 case kArrayCid: 916 case kArrayCid:
915 case kImmutableArrayCid: 917 case kImmutableArrayCid:
916 case kGrowableObjectArrayCid: 918 case kGrowableObjectArrayCid:
917 case kFloat32ArrayCid: 919 case kFloat32ArrayCid:
918 case kFloat64ArrayCid: 920 case kFloat64ArrayCid:
919 case kInt8ArrayCid: 921 case kInt8ArrayCid:
920 case kUint8ArrayCid: 922 case kUint8ArrayCid:
921 case kUint8ClampedArrayCid: 923 case kUint8ClampedArrayCid:
922 case kExternalUint8ArrayCid: 924 case kExternalUint8ArrayCid:
923 case kExternalUint8ClampedArrayCid: 925 case kExternalUint8ClampedArrayCid:
924 case kInt16ArrayCid: 926 case kInt16ArrayCid:
925 case kUint16ArrayCid: 927 case kUint16ArrayCid:
926 break; 928 break;
927 case kInt32ArrayCid: 929 case kInt32ArrayCid:
928 case kUint32ArrayCid: 930 case kUint32ArrayCid: {
929 // Check if elements fit into a smi or the platform supports unboxed 931 if (!CanUnboxInt32()) return false;
930 // mints. 932
931 if ((kSmiBits < 32) && !FlowGraphCompiler::SupportsUnboxedMints()) {
932 return false;
933 }
934 {
935 // Set deopt_id if we can optimistically assume that the result is Smi. 933 // Set deopt_id if we can optimistically assume that the result is Smi.
936 // Assume mixed Mint/Smi if this instruction caused deoptimization once. 934 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
937 ASSERT(call->HasICData()); 935 ASSERT(call->HasICData());
938 const ICData& ic_data = *call->ic_data(); 936 const ICData& ic_data = *call->ic_data();
939 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? 937 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
940 call->deopt_id() : Isolate::kNoDeoptId; 938 call->deopt_id() : Isolate::kNoDeoptId;
941 } 939 }
942 break; 940 break;
943 default: 941 default:
944 return false; 942 return false;
945 } 943 }
946 Definition* array = call->ArgumentAt(0); 944 Definition* array = call->ArgumentAt(0);
947 Definition* index = call->ArgumentAt(1); 945 Definition* index = call->ArgumentAt(1);
948 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index); 946 intptr_t array_cid = PrepareIndexedOp(call, class_id, &array, &index);
947 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid);
949 Definition* array_op = 948 Definition* array_op =
950 new LoadIndexedInstr(new Value(array), 949 new LoadIndexedInstr(new Value(array),
951 new Value(index), 950 new Value(index),
952 FlowGraphCompiler::ElementSizeFor(array_cid), 951 index_scale,
953 array_cid, 952 array_cid,
954 deopt_id); 953 deopt_id);
955 ReplaceCall(call, array_op); 954 ReplaceCall(call, array_op);
956 return true; 955 return true;
957 } 956 }
958 957
959 958
960 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call, 959 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallInstr* call,
961 Token::Kind op_kind) { 960 Token::Kind op_kind) {
962 intptr_t operands_type = kIllegalCid; 961 intptr_t operands_type = kIllegalCid;
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 } 1595 }
1597 return true; 1596 return true;
1598 default: 1597 default:
1599 // Unsupported method. 1598 // Unsupported method.
1600 return false; 1599 return false;
1601 } 1600 }
1602 } 1601 }
1603 1602
1604 if (IsSupportedByteArrayCid(class_ids[0]) && 1603 if (IsSupportedByteArrayCid(class_ids[0]) &&
1605 (ic_data.NumberOfChecks() == 1)) { 1604 (ic_data.NumberOfChecks() == 1)) {
1606 Definition* array_op = NULL; 1605 // For elements that may not fit into a smi on all platforms, check if
1606 // elements fit into a smi or the platform supports unboxed mints.
1607 if ((recognized_kind == MethodRecognizer::kByteArrayBaseGetInt32) ||
1608 (recognized_kind == MethodRecognizer::kByteArrayBaseGetUint32) ||
1609 (recognized_kind == MethodRecognizer::kByteArrayBaseSetInt32) ||
1610 (recognized_kind == MethodRecognizer::kByteArrayBaseSetUint32)) {
1611 if (!CanUnboxInt32()) return false;
1612 }
1613
1607 switch (recognized_kind) { 1614 switch (recognized_kind) {
1615 // ByteArray getters.
1608 case MethodRecognizer::kByteArrayBaseGetInt8: 1616 case MethodRecognizer::kByteArrayBaseGetInt8:
1609 array_op = BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid); 1617 return BuildByteArrayViewLoad(call, class_ids[0], kInt8ArrayCid);
1610 break;
1611 case MethodRecognizer::kByteArrayBaseGetUint8: 1618 case MethodRecognizer::kByteArrayBaseGetUint8:
1612 array_op = BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid); 1619 return BuildByteArrayViewLoad(call, class_ids[0], kUint8ArrayCid);
1613 break;
1614 case MethodRecognizer::kByteArrayBaseGetInt16: 1620 case MethodRecognizer::kByteArrayBaseGetInt16:
1615 array_op = BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid); 1621 return BuildByteArrayViewLoad(call, class_ids[0], kInt16ArrayCid);
1616 break;
1617 case MethodRecognizer::kByteArrayBaseGetUint16: 1622 case MethodRecognizer::kByteArrayBaseGetUint16:
1618 array_op = BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid); 1623 return BuildByteArrayViewLoad(call, class_ids[0], kUint16ArrayCid);
1619 break;
1620 case MethodRecognizer::kByteArrayBaseGetInt32: 1624 case MethodRecognizer::kByteArrayBaseGetInt32:
1621 // Check if elements fit into a smi or the platform supports unboxed 1625 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: 1626 case MethodRecognizer::kByteArrayBaseGetUint32:
1629 // Check if elements fit into a smi or the platform supports unboxed 1627 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: 1628 case MethodRecognizer::kByteArrayBaseGetFloat32:
1637 array_op = BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid); 1629 return BuildByteArrayViewLoad(call, class_ids[0], kFloat32ArrayCid);
1638 break;
1639 case MethodRecognizer::kByteArrayBaseGetFloat64: 1630 case MethodRecognizer::kByteArrayBaseGetFloat64:
1640 array_op = BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid); 1631 return BuildByteArrayViewLoad(call, class_ids[0], kFloat64ArrayCid);
1641 break; 1632
1633 // ByteArray setters.
1634 case MethodRecognizer::kByteArrayBaseSetInt8:
1635 return BuildByteArrayViewStore(call, class_ids[0], kInt8ArrayCid);
1636 case MethodRecognizer::kByteArrayBaseSetUint8:
1637 return BuildByteArrayViewStore(call, class_ids[0], kUint8ArrayCid);
1638 case MethodRecognizer::kByteArrayBaseSetInt16:
1639 return BuildByteArrayViewStore(call, class_ids[0], kInt16ArrayCid);
1640 case MethodRecognizer::kByteArrayBaseSetUint16:
1641 return BuildByteArrayViewStore(call, class_ids[0], kUint16ArrayCid);
1642 case MethodRecognizer::kByteArrayBaseSetInt32:
1643 return BuildByteArrayViewStore(call, class_ids[0], kInt32ArrayCid);
1644 case MethodRecognizer::kByteArrayBaseSetUint32:
1645 return BuildByteArrayViewStore(call, class_ids[0], kUint32ArrayCid);
1646 case MethodRecognizer::kByteArrayBaseSetFloat32:
1647 return BuildByteArrayViewStore(call, class_ids[0], kFloat32ArrayCid);
1648 case MethodRecognizer::kByteArrayBaseSetFloat64:
1649 return BuildByteArrayViewStore(call, class_ids[0], kFloat64ArrayCid);
1642 default: 1650 default:
1643 // Unsupported method. 1651 // Unsupported method.
1644 return false; 1652 return false;
1645 } 1653 }
1646 ASSERT(array_op != NULL);
1647 ReplaceCall(call, array_op);
1648 return true;
1649 } 1654 }
1650 return false; 1655 return false;
1651 } 1656 }
1652 1657
1653 1658
1654 LoadIndexedInstr* FlowGraphOptimizer::BuildByteArrayViewLoad( 1659 bool FlowGraphOptimizer::BuildByteArrayViewLoad(
1660 InstanceCallInstr* call,
1661 intptr_t receiver_cid,
1662 intptr_t view_cid) {
1663 PrepareByteArrayViewOp(call, receiver_cid, view_cid);
1664
1665 Definition* array = call->ArgumentAt(0);
1666 Definition* byte_index = call->ArgumentAt(1);
1667
1668 // Optimistically build a smi-checked load for Int32 and Uint32
1669 // loads on ia32 like we do for normal array loads, and only revert to
1670 // mint case after deoptimizing here.
1671 intptr_t deopt_id = Isolate::kNoDeoptId;
1672 if ((view_cid == kInt32ArrayCid || view_cid == kUint32ArrayCid) &&
1673 call->ic_data()->deopt_reason() == kDeoptUnknown) {
1674 deopt_id = call->deopt_id();
1675 }
1676 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
1677 new Value(byte_index),
1678 1, // Index scale.
1679 view_cid,
1680 deopt_id);
1681 ReplaceCall(call, array_op);
1682 return true;
1683 }
1684
1685
1686 bool FlowGraphOptimizer::BuildByteArrayViewStore(
1687 InstanceCallInstr* call,
1688 intptr_t receiver_cid,
1689 intptr_t view_cid) {
1690 PrepareByteArrayViewOp(call, receiver_cid, view_cid);
1691 ICData& value_check = ICData::ZoneHandle();
1692 switch (view_cid) {
1693 case kInt8ArrayCid:
1694 case kUint8ArrayCid:
1695 case kUint8ClampedArrayCid:
1696 case kExternalUint8ArrayCid:
1697 case kExternalUint8ClampedArrayCid:
1698 case kInt16ArrayCid:
1699 case kUint16ArrayCid: {
1700 // Check that value is always smi.
1701 value_check = ICData::New(Function::Handle(),
1702 String::Handle(),
1703 Isolate::kNoDeoptId,
1704 1);
1705 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
1706 break;
1707 }
1708 case kInt32ArrayCid:
1709 case kUint32ArrayCid:
1710 // We don't have ICData for the value stored, so we optimistically assume
1711 // smis first. If we ever deoptimized here, we require to unbox the value
1712 // before storing to handle the mint case, too.
1713 if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
1714 value_check = ICData::New(Function::Handle(),
1715 String::Handle(),
1716 Isolate::kNoDeoptId,
1717 1);
1718 value_check.AddReceiverCheck(kSmiCid, Function::Handle());
1719 }
1720 break;
1721 case kFloat32ArrayCid:
1722 case kFloat64ArrayCid: {
1723 // Check that value is always double.
1724 value_check = ICData::New(Function::Handle(),
1725 String::Handle(),
1726 Isolate::kNoDeoptId,
1727 1);
1728 value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
1729 break;
1730 }
1731 default:
1732 // Array cids are already checked in the caller.
1733 UNREACHABLE();
1734 return NULL;
1735 }
1736
1737 Definition* array = call->ArgumentAt(0);
1738 Definition* index = call->ArgumentAt(1);
1739 Definition* stored_value = call->ArgumentAt(2);
1740 if (!value_check.IsNull()) {
1741 AddCheckClass(stored_value, value_check, call->deopt_id(), call->env(),
1742 call);
1743 }
1744 StoreBarrierType needs_store_barrier = kNoStoreBarrier;
1745
1746
1747 // result = index + bytesPerElement.
1748 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
1749 ConstantInstr* bytes_per_element =
1750 new ConstantInstr(Smi::Handle(Smi::New(element_size)));
1751 InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
1752 BinarySmiOpInstr* result =
1753 new BinarySmiOpInstr(Token::kADD,
1754 call,
1755 new Value(index),
1756 new Value(bytes_per_element));
1757 InsertBefore(call, result, call->env(), Definition::kValue);
1758
1759 StoreIndexedInstr* array_op = new StoreIndexedInstr(new Value(array),
1760 new Value(index),
1761 new Value(stored_value),
1762 needs_store_barrier,
1763 1, // Index scale
1764 view_cid,
1765 call->deopt_id());
1766 call->ReplaceUsesWith(result); // Fix uses of the call's return value.
1767 ReplaceCall(call, array_op);
1768 array_op->ClearSSATempIndex(); // Store has no uses.
1769 return true;
1770 }
1771
1772
1773 void FlowGraphOptimizer::PrepareByteArrayViewOp(
1655 InstanceCallInstr* call, 1774 InstanceCallInstr* call,
1656 intptr_t receiver_cid, 1775 intptr_t receiver_cid,
1657 intptr_t view_cid) { 1776 intptr_t view_cid) {
1658 Definition* array = call->ArgumentAt(0); 1777 Definition* array = call->ArgumentAt(0);
1659 Definition* byte_index = call->ArgumentAt(1); 1778 Definition* byte_index = call->ArgumentAt(1);
1660 1779
1661 AddReceiverCheck(call); 1780 AddReceiverCheck(call);
1662 const bool is_immutable = true; 1781 const bool is_immutable = true;
1663 LoadFieldInstr* length = new LoadFieldInstr( 1782 LoadFieldInstr* length = new LoadFieldInstr(
1664 new Value(array), 1783 new Value(array),
(...skipping 18 matching lines...) Expand all
1683 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); 1802 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue);
1684 1803
1685 // Check byte_index < len_in_bytes. 1804 // Check byte_index < len_in_bytes.
1686 InsertBefore(call, 1805 InsertBefore(call,
1687 new CheckArrayBoundInstr(new Value(len_in_bytes), 1806 new CheckArrayBoundInstr(new Value(len_in_bytes),
1688 new Value(byte_index), 1807 new Value(byte_index),
1689 receiver_cid, 1808 receiver_cid,
1690 call), 1809 call),
1691 call->env(), 1810 call->env(),
1692 Definition::kEffect); 1811 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 } 1812 }
1703 1813
1704 1814
1705 // Returns a Boolean constant if all classes in ic_data yield the same type-test 1815 // 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 1816 // result and the type tests do not depend on type arguments. Otherwise return
1707 // Bool::null(). 1817 // Bool::null().
1708 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data, 1818 RawBool* FlowGraphOptimizer::InstanceOfAsBool(const ICData& ic_data,
1709 const AbstractType& type) const { 1819 const AbstractType& type) const {
1710 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only. 1820 ASSERT(ic_data.num_args_tested() == 1); // Unary checks only.
1711 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null(); 1821 if (!type.IsInstantiated() || type.IsMalformed()) return Bool::null();
(...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after
4549 if (changed) { 4659 if (changed) {
4550 // We may have changed the block order and the dominator tree. 4660 // We may have changed the block order and the dominator tree.
4551 flow_graph->DiscoverBlocks(); 4661 flow_graph->DiscoverBlocks();
4552 GrowableArray<BitVector*> dominance_frontier; 4662 GrowableArray<BitVector*> dominance_frontier;
4553 flow_graph->ComputeDominators(&dominance_frontier); 4663 flow_graph->ComputeDominators(&dominance_frontier);
4554 } 4664 }
4555 } 4665 }
4556 4666
4557 4667
4558 } // namespace dart 4668 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698