| 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 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); | 709 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 710 } | 710 } |
| 711 break; | 711 break; |
| 712 case kInt8ArrayCid: | 712 case kInt8ArrayCid: |
| 713 case kUint8ArrayCid: | 713 case kUint8ArrayCid: |
| 714 case kUint8ClampedArrayCid: | 714 case kUint8ClampedArrayCid: |
| 715 case kExternalUint8ArrayCid: | 715 case kExternalUint8ArrayCid: |
| 716 case kExternalUint8ClampedArrayCid: | 716 case kExternalUint8ClampedArrayCid: |
| 717 case kInt16ArrayCid: | 717 case kInt16ArrayCid: |
| 718 case kUint16ArrayCid: | 718 case kUint16ArrayCid: |
| 719 case kTypedDataInt8ArrayCid: |
| 720 case kTypedDataUint8ArrayCid: |
| 721 case kTypedDataUint8ClampedArrayCid: |
| 722 case kExternalTypedDataUint8ArrayCid: |
| 723 case kExternalTypedDataUint8ClampedArrayCid: |
| 724 case kTypedDataInt16ArrayCid: |
| 725 case kTypedDataUint16ArrayCid: |
| 719 // Check that value is always smi. | 726 // Check that value is always smi. |
| 720 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); | 727 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 721 if ((value_check.NumberOfChecks() != 1) || | 728 if ((value_check.NumberOfChecks() != 1) || |
| 722 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) { | 729 (value_check.GetReceiverClassIdAt(0) != kSmiCid)) { |
| 723 return false; | 730 return false; |
| 724 } | 731 } |
| 725 break; | 732 break; |
| 726 case kInt32ArrayCid: | 733 case kInt32ArrayCid: |
| 727 case kUint32ArrayCid: { | 734 case kUint32ArrayCid: |
| 735 case kTypedDataInt32ArrayCid: |
| 736 case kTypedDataUint32ArrayCid: { |
| 728 if (!CanUnboxInt32()) return false; | 737 if (!CanUnboxInt32()) return false; |
| 729 // Check that value is always smi or mint, if the platform has unboxed | 738 // Check that value is always smi or mint, if the platform has unboxed |
| 730 // mints (ia32 with at least SSE 4.1). | 739 // mints (ia32 with at least SSE 4.1). |
| 731 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); | 740 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 732 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) { | 741 for (intptr_t i = 0; i < value_check.NumberOfChecks(); i++) { |
| 733 intptr_t cid = value_check.GetReceiverClassIdAt(i); | 742 intptr_t cid = value_check.GetReceiverClassIdAt(i); |
| 734 if (FlowGraphCompiler::SupportsUnboxedMints()) { | 743 if (FlowGraphCompiler::SupportsUnboxedMints()) { |
| 735 if ((cid != kSmiCid) && (cid != kMintCid)) { | 744 if ((cid != kSmiCid) && (cid != kMintCid)) { |
| 736 return false; | 745 return false; |
| 737 } | 746 } |
| 738 } else if (cid != kSmiCid) { | 747 } else if (cid != kSmiCid) { |
| 739 return false; | 748 return false; |
| 740 } | 749 } |
| 741 } | 750 } |
| 742 break; | 751 break; |
| 743 } | 752 } |
| 744 case kFloat32ArrayCid: | 753 case kFloat32ArrayCid: |
| 745 case kFloat64ArrayCid: { | 754 case kFloat64ArrayCid: |
| 755 case kTypedDataFloat32ArrayCid: |
| 756 case kTypedDataFloat64ArrayCid: { |
| 746 // Check that value is always double. | 757 // Check that value is always double. |
| 747 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); | 758 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); |
| 748 if ((value_check.NumberOfChecks() != 1) || | 759 if ((value_check.NumberOfChecks() != 1) || |
| 749 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { | 760 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { |
| 750 return false; | 761 return false; |
| 751 } | 762 } |
| 752 break; | 763 break; |
| 753 } | 764 } |
| 754 default: | 765 default: |
| 755 // TODO(fschneider): Add support for other array types. | 766 // TODO(fschneider): Add support for other array types. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 } | 857 } |
| 847 case kInt8ArrayCid: | 858 case kInt8ArrayCid: |
| 848 case kUint8ArrayCid: | 859 case kUint8ArrayCid: |
| 849 case kUint8ClampedArrayCid: | 860 case kUint8ClampedArrayCid: |
| 850 case kExternalUint8ArrayCid: | 861 case kExternalUint8ArrayCid: |
| 851 case kExternalUint8ClampedArrayCid: | 862 case kExternalUint8ClampedArrayCid: |
| 852 case kInt16ArrayCid: | 863 case kInt16ArrayCid: |
| 853 case kUint16ArrayCid: | 864 case kUint16ArrayCid: |
| 854 case kInt32ArrayCid: | 865 case kInt32ArrayCid: |
| 855 case kUint32ArrayCid: | 866 case kUint32ArrayCid: |
| 867 case kTypedDataInt8ArrayCid: |
| 868 case kTypedDataUint8ArrayCid: |
| 869 case kTypedDataUint8ClampedArrayCid: |
| 870 case kExternalTypedDataUint8ArrayCid: |
| 871 case kExternalTypedDataUint8ClampedArrayCid: |
| 872 case kTypedDataInt16ArrayCid: |
| 873 case kTypedDataUint16ArrayCid: |
| 874 case kTypedDataInt32ArrayCid: |
| 875 case kTypedDataUint32ArrayCid: |
| 856 ASSERT(value_type.IsIntType()); | 876 ASSERT(value_type.IsIntType()); |
| 857 // Fall through. | 877 // Fall through. |
| 858 case kFloat32ArrayCid: | 878 case kFloat32ArrayCid: |
| 859 case kFloat64ArrayCid: { | 879 case kFloat64ArrayCid: |
| 880 case kTypedDataFloat32ArrayCid: |
| 881 case kTypedDataFloat64ArrayCid: { |
| 860 type_args = instantiator = flow_graph_->constant_null(); | 882 type_args = instantiator = flow_graph_->constant_null(); |
| 861 ASSERT((class_id != kFloat32ArrayCid && class_id != kFloat64ArrayCid) || | 883 ASSERT((class_id != kFloat32ArrayCid && |
| 884 class_id != kFloat64ArrayCid && |
| 885 class_id != kTypedDataFloat32ArrayCid && |
| 886 class_id != kTypedDataFloat64ArrayCid) || |
| 862 value_type.IsDoubleType()); | 887 value_type.IsDoubleType()); |
| 863 ASSERT(value_type.IsInstantiated()); | 888 ASSERT(value_type.IsInstantiated()); |
| 864 break; | 889 break; |
| 865 } | 890 } |
| 866 default: | 891 default: |
| 867 // TODO(fschneider): Add support for other array types. | 892 // TODO(fschneider): Add support for other array types. |
| 868 UNREACHABLE(); | 893 UNREACHABLE(); |
| 869 } | 894 } |
| 870 AssertAssignableInstr* assert_value = | 895 AssertAssignableInstr* assert_value = |
| 871 new AssertAssignableInstr(call->token_pos(), | 896 new AssertAssignableInstr(call->token_pos(), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 case kGrowableObjectArrayCid: | 943 case kGrowableObjectArrayCid: |
| 919 case kFloat32ArrayCid: | 944 case kFloat32ArrayCid: |
| 920 case kFloat64ArrayCid: | 945 case kFloat64ArrayCid: |
| 921 case kInt8ArrayCid: | 946 case kInt8ArrayCid: |
| 922 case kUint8ArrayCid: | 947 case kUint8ArrayCid: |
| 923 case kUint8ClampedArrayCid: | 948 case kUint8ClampedArrayCid: |
| 924 case kExternalUint8ArrayCid: | 949 case kExternalUint8ArrayCid: |
| 925 case kExternalUint8ClampedArrayCid: | 950 case kExternalUint8ClampedArrayCid: |
| 926 case kInt16ArrayCid: | 951 case kInt16ArrayCid: |
| 927 case kUint16ArrayCid: | 952 case kUint16ArrayCid: |
| 953 case kTypedDataFloat32ArrayCid: |
| 954 case kTypedDataFloat64ArrayCid: |
| 955 case kTypedDataInt8ArrayCid: |
| 956 case kTypedDataUint8ArrayCid: |
| 957 case kTypedDataUint8ClampedArrayCid: |
| 958 case kExternalTypedDataUint8ArrayCid: |
| 959 case kExternalTypedDataUint8ClampedArrayCid: |
| 960 case kTypedDataInt16ArrayCid: |
| 961 case kTypedDataUint16ArrayCid: |
| 928 break; | 962 break; |
| 929 case kInt32ArrayCid: | 963 case kInt32ArrayCid: |
| 930 case kUint32ArrayCid: { | 964 case kUint32ArrayCid: |
| 965 case kTypedDataInt32ArrayCid: |
| 966 case kTypedDataUint32ArrayCid: { |
| 931 if (!CanUnboxInt32()) return false; | 967 if (!CanUnboxInt32()) return false; |
| 932 | 968 |
| 933 // Set deopt_id if we can optimistically assume that the result is Smi. | 969 // Set deopt_id if we can optimistically assume that the result is Smi. |
| 934 // Assume mixed Mint/Smi if this instruction caused deoptimization once. | 970 // Assume mixed Mint/Smi if this instruction caused deoptimization once. |
| 935 ASSERT(call->HasICData()); | 971 ASSERT(call->HasICData()); |
| 936 const ICData& ic_data = *call->ic_data(); | 972 const ICData& ic_data = *call->ic_data(); |
| 937 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? | 973 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? |
| 938 call->deopt_id() : Isolate::kNoDeoptId; | 974 call->deopt_id() : Isolate::kNoDeoptId; |
| 939 } | 975 } |
| 940 break; | 976 break; |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 } | 1356 } |
| 1321 | 1357 |
| 1322 | 1358 |
| 1323 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { | 1359 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { |
| 1324 switch (kind) { | 1360 switch (kind) { |
| 1325 case MethodRecognizer::kObjectArrayLength: | 1361 case MethodRecognizer::kObjectArrayLength: |
| 1326 case MethodRecognizer::kImmutableArrayLength: | 1362 case MethodRecognizer::kImmutableArrayLength: |
| 1327 return Array::length_offset(); | 1363 return Array::length_offset(); |
| 1328 case MethodRecognizer::kByteArrayBaseLength: | 1364 case MethodRecognizer::kByteArrayBaseLength: |
| 1329 return ByteArray::length_offset(); | 1365 return ByteArray::length_offset(); |
| 1366 case MethodRecognizer::kTypedDataLength: |
| 1367 // .length is defined in _TypedList which is the base class for internal |
| 1368 // and external typed data. |
| 1369 ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset()); |
| 1370 return TypedData::length_offset(); |
| 1330 case MethodRecognizer::kGrowableArrayLength: | 1371 case MethodRecognizer::kGrowableArrayLength: |
| 1331 return GrowableObjectArray::length_offset(); | 1372 return GrowableObjectArray::length_offset(); |
| 1332 default: | 1373 default: |
| 1333 UNREACHABLE(); | 1374 UNREACHABLE(); |
| 1334 return 0; | 1375 return 0; |
| 1335 } | 1376 } |
| 1336 } | 1377 } |
| 1337 | 1378 |
| 1338 | 1379 |
| 1339 // Only unique implicit instance getters can be currently handled. | 1380 // Only unique implicit instance getters can be currently handled. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1358 | 1399 |
| 1359 // Not an implicit getter. | 1400 // Not an implicit getter. |
| 1360 MethodRecognizer::Kind recognized_kind = | 1401 MethodRecognizer::Kind recognized_kind = |
| 1361 MethodRecognizer::RecognizeKind(target); | 1402 MethodRecognizer::RecognizeKind(target); |
| 1362 | 1403 |
| 1363 // VM objects length getter. | 1404 // VM objects length getter. |
| 1364 switch (recognized_kind) { | 1405 switch (recognized_kind) { |
| 1365 case MethodRecognizer::kObjectArrayLength: | 1406 case MethodRecognizer::kObjectArrayLength: |
| 1366 case MethodRecognizer::kImmutableArrayLength: | 1407 case MethodRecognizer::kImmutableArrayLength: |
| 1367 case MethodRecognizer::kByteArrayBaseLength: | 1408 case MethodRecognizer::kByteArrayBaseLength: |
| 1409 case MethodRecognizer::kTypedDataLength: |
| 1368 case MethodRecognizer::kGrowableArrayLength: { | 1410 case MethodRecognizer::kGrowableArrayLength: { |
| 1369 if (!ic_data.HasOneTarget()) { | 1411 if (!ic_data.HasOneTarget()) { |
| 1370 // TODO(srdjan): Implement for mutiple targets. | 1412 // TODO(srdjan): Implement for mutiple targets. |
| 1371 return false; | 1413 return false; |
| 1372 } | 1414 } |
| 1373 const bool is_immutable = | 1415 const bool is_immutable = |
| 1374 (recognized_kind == MethodRecognizer::kObjectArrayLength) || | 1416 (recognized_kind == MethodRecognizer::kObjectArrayLength) || |
| 1375 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || | 1417 (recognized_kind == MethodRecognizer::kImmutableArrayLength) || |
| 1376 (recognized_kind == MethodRecognizer::kByteArrayBaseLength); | 1418 (recognized_kind == MethodRecognizer::kByteArrayBaseLength) || |
| 1419 (recognized_kind == MethodRecognizer::kTypedDataLength); |
| 1377 InlineArrayLengthGetter(call, | 1420 InlineArrayLengthGetter(call, |
| 1378 OffsetForLengthGetter(recognized_kind), | 1421 OffsetForLengthGetter(recognized_kind), |
| 1379 is_immutable, | 1422 is_immutable, |
| 1380 recognized_kind); | 1423 recognized_kind); |
| 1381 return true; | 1424 return true; |
| 1382 } | 1425 } |
| 1383 case MethodRecognizer::kGrowableArrayCapacity: | 1426 case MethodRecognizer::kGrowableArrayCapacity: |
| 1384 InlineGrowableArrayCapacityGetter(call); | 1427 InlineGrowableArrayCapacityGetter(call); |
| 1385 return true; | 1428 return true; |
| 1386 case MethodRecognizer::kStringBaseLength: | 1429 case MethodRecognizer::kStringBaseLength: |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 const ICData& unary_checks = | 1936 const ICData& unary_checks = |
| 1894 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); | 1937 ICData::ZoneHandle(instr->ic_data()->AsUnaryClassChecks()); |
| 1895 | 1938 |
| 1896 if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) && | 1939 if ((unary_checks.NumberOfChecks() > FLAG_max_polymorphic_checks) && |
| 1897 InstanceCallNeedsClassCheck(instr)) { | 1940 InstanceCallNeedsClassCheck(instr)) { |
| 1898 // Too many checks, it will be megamorphic which needs unary checks. | 1941 // Too many checks, it will be megamorphic which needs unary checks. |
| 1899 instr->set_ic_data(&unary_checks); | 1942 instr->set_ic_data(&unary_checks); |
| 1900 return; | 1943 return; |
| 1901 } | 1944 } |
| 1902 | 1945 |
| 1903 if ((op_kind == Token::kASSIGN_INDEX) && | 1946 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { |
| 1904 TryReplaceWithStoreIndexed(instr)) { | |
| 1905 return; | 1947 return; |
| 1906 } | 1948 } |
| 1907 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { | 1949 if ((op_kind == Token::kINDEX) && TryReplaceWithLoadIndexed(instr)) { |
| 1908 return; | 1950 return; |
| 1909 } | 1951 } |
| 1910 if (Token::IsBinaryOperator(op_kind) && | 1952 if (Token::IsBinaryOperator(op_kind) && |
| 1911 TryReplaceWithBinaryOp(instr, op_kind)) { | 1953 TryReplaceWithBinaryOp(instr, op_kind)) { |
| 1912 return; | 1954 return; |
| 1913 } | 1955 } |
| 1914 if (Token::IsPrefixOperator(op_kind) && | 1956 if (Token::IsPrefixOperator(op_kind) && |
| (...skipping 2751 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4666 if (changed) { | 4708 if (changed) { |
| 4667 // We may have changed the block order and the dominator tree. | 4709 // We may have changed the block order and the dominator tree. |
| 4668 flow_graph->DiscoverBlocks(); | 4710 flow_graph->DiscoverBlocks(); |
| 4669 GrowableArray<BitVector*> dominance_frontier; | 4711 GrowableArray<BitVector*> dominance_frontier; |
| 4670 flow_graph->ComputeDominators(&dominance_frontier); | 4712 flow_graph->ComputeDominators(&dominance_frontier); |
| 4671 } | 4713 } |
| 4672 } | 4714 } |
| 4673 | 4715 |
| 4674 | 4716 |
| 4675 } // namespace dart | 4717 } // namespace dart |
| OLD | NEW |