| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 105 |
| 106 // TODO(srdjan): Test/support other number types as well. | 106 // TODO(srdjan): Test/support other number types as well. |
| 107 static bool IsNumberCid(intptr_t cid) { | 107 static bool IsNumberCid(intptr_t cid) { |
| 108 return (cid == kSmiCid) || (cid == kDoubleCid); | 108 return (cid == kSmiCid) || (cid == kDoubleCid); |
| 109 } | 109 } |
| 110 | 110 |
| 111 | 111 |
| 112 // Attempt to build ICData for call using propagated class-ids. | 112 // Attempt to build ICData for call using propagated class-ids. |
| 113 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 113 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| 114 ASSERT(call->HasICData()); | 114 ASSERT(call->HasICData()); |
| 115 if (call->ic_data()->NumberOfChecks() > 0) { | 115 if (call->ic_data()->NumberOfUsedChecks() > 0) { |
| 116 // This occurs when an instance call has too many checks, will be converted | 116 // This occurs when an instance call has too many checks, will be converted |
| 117 // to megamorphic call. | 117 // to megamorphic call. |
| 118 return false; | 118 return false; |
| 119 } | 119 } |
| 120 if (FLAG_warn_on_javascript_compatibility) { | 120 if (FLAG_warn_on_javascript_compatibility) { |
| 121 // Do not make the instance call megamorphic if the callee needs to decode | 121 // Do not make the instance call megamorphic if the callee needs to decode |
| 122 // the calling code sequence to lookup the ic data and verify if a warning | 122 // the calling code sequence to lookup the ic data and verify if a warning |
| 123 // has already been issued or not. | 123 // has already been issued or not. |
| 124 // TryCreateICData is only invoked if the ic_data target has not been called | 124 // TryCreateICData is only invoked if the ic_data target has not been called |
| 125 // yet, so no warning can possibly have been issued. | 125 // yet, so no warning can possibly have been issued. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 } | 188 } |
| 189 call->set_ic_data(&ic_data); | 189 call->set_ic_data(&ic_data); |
| 190 return true; | 190 return true; |
| 191 } | 191 } |
| 192 | 192 |
| 193 | 193 |
| 194 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, | 194 const ICData& FlowGraphOptimizer::TrySpecializeICData(const ICData& ic_data, |
| 195 intptr_t cid) { | 195 intptr_t cid) { |
| 196 ASSERT(ic_data.NumArgsTested() == 1); | 196 ASSERT(ic_data.NumArgsTested() == 1); |
| 197 | 197 |
| 198 if ((ic_data.NumberOfChecks() == 1) && | 198 if ((ic_data.NumberOfUsedChecks() == 1) && ic_data.HasReceiverClassId(cid)) { |
| 199 (ic_data.GetReceiverClassIdAt(0) == cid)) { | |
| 200 return ic_data; // Nothing to do | 199 return ic_data; // Nothing to do |
| 201 } | 200 } |
| 202 | 201 |
| 203 const Function& function = | 202 const Function& function = |
| 204 Function::Handle(I, ic_data.GetTargetForReceiverClassId(cid)); | 203 Function::Handle(I, ic_data.GetTargetForReceiverClassId(cid)); |
| 205 // TODO(fschneider): Try looking up the function on the class if it is | 204 // TODO(fschneider): Try looking up the function on the class if it is |
| 206 // not found in the ICData. | 205 // not found in the ICData. |
| 207 if (!function.IsNull()) { | 206 if (!function.IsNull()) { |
| 208 const ICData& new_ic_data = ICData::ZoneHandle(I, ICData::New( | 207 const ICData& new_ic_data = ICData::ZoneHandle(I, ICData::New( |
| 209 Function::Handle(I, ic_data.owner()), | 208 Function::Handle(I, ic_data.owner()), |
| (...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 840 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 842 Definition* def = it.Current()->AsDefinition(); | 841 Definition* def = it.Current()->AsDefinition(); |
| 843 if (def != NULL) { | 842 if (def != NULL) { |
| 844 InsertConversionsFor(def); | 843 InsertConversionsFor(def); |
| 845 } | 844 } |
| 846 } | 845 } |
| 847 } | 846 } |
| 848 } | 847 } |
| 849 | 848 |
| 850 | 849 |
| 851 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, | |
| 852 intptr_t receiver_class_id, | |
| 853 intptr_t argument_class_id) { | |
| 854 ASSERT(receiver_class_id != kIllegalCid); | |
| 855 ASSERT(argument_class_id != kIllegalCid); | |
| 856 if (ic_data.NumArgsTested() != 2) return false; | |
| 857 | |
| 858 Function& target = Function::Handle(); | |
| 859 const intptr_t len = ic_data.NumberOfChecks(); | |
| 860 for (intptr_t i = 0; i < len; i++) { | |
| 861 GrowableArray<intptr_t> class_ids; | |
| 862 ic_data.GetCheckAt(i, &class_ids, &target); | |
| 863 ASSERT(class_ids.length() == 2); | |
| 864 if ((class_ids[0] == receiver_class_id) && | |
| 865 (class_ids[1] == argument_class_id)) { | |
| 866 return true; | |
| 867 } | |
| 868 } | |
| 869 return false; | |
| 870 } | |
| 871 | |
| 872 | |
| 873 static bool ClassIdIsOneOf(intptr_t class_id, | 850 static bool ClassIdIsOneOf(intptr_t class_id, |
| 874 const GrowableArray<intptr_t>& class_ids) { | 851 const GrowableArray<intptr_t>& class_ids) { |
| 875 for (intptr_t i = 0; i < class_ids.length(); i++) { | 852 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 853 ASSERT(class_ids[i] != kIllegalCid); |
| 876 if (class_ids[i] == class_id) { | 854 if (class_ids[i] == class_id) { |
| 877 return true; | 855 return true; |
| 878 } | 856 } |
| 879 } | 857 } |
| 880 return false; | 858 return false; |
| 881 } | 859 } |
| 882 | 860 |
| 883 | 861 |
| 884 // Returns true if ICData tests two arguments and all ICData cids are in the | 862 // Returns true if ICData tests two arguments and all ICData cids are in the |
| 885 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively. | 863 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively. |
| 886 static bool ICDataHasOnlyReceiverArgumentClassIds( | 864 static bool ICDataHasOnlyReceiverArgumentClassIds( |
| 887 const ICData& ic_data, | 865 const ICData& ic_data, |
| 888 const GrowableArray<intptr_t>& receiver_class_ids, | 866 const GrowableArray<intptr_t>& receiver_class_ids, |
| 889 const GrowableArray<intptr_t>& argument_class_ids) { | 867 const GrowableArray<intptr_t>& argument_class_ids) { |
| 890 if (ic_data.NumArgsTested() != 2) return false; | 868 if (ic_data.NumArgsTested() != 2) { |
| 869 return false; |
| 870 } |
| 891 Function& target = Function::Handle(); | 871 Function& target = Function::Handle(); |
| 892 const intptr_t len = ic_data.NumberOfChecks(); | 872 const intptr_t len = ic_data.NumberOfChecks(); |
| 893 for (intptr_t i = 0; i < len; i++) { | 873 for (intptr_t i = 0; i < len; i++) { |
| 894 GrowableArray<intptr_t> class_ids; | 874 if (ic_data.IsUsedAt(i)) { |
| 895 ic_data.GetCheckAt(i, &class_ids, &target); | 875 GrowableArray<intptr_t> class_ids; |
| 896 ASSERT(class_ids.length() == 2); | 876 ic_data.GetCheckAt(i, &class_ids, &target); |
| 897 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | 877 ASSERT(class_ids.length() == 2); |
| 898 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | 878 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || |
| 879 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { |
| 880 return false; |
| 881 } |
| 882 } |
| 883 } |
| 884 return true; |
| 885 } |
| 886 |
| 887 |
| 888 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, |
| 889 intptr_t receiver_class_id, |
| 890 intptr_t argument_class_id) { |
| 891 GrowableArray<intptr_t> receiver_cids(1); |
| 892 receiver_cids.Add(receiver_class_id); |
| 893 GrowableArray<intptr_t> argument_cids(1); |
| 894 argument_cids.Add(argument_class_id); |
| 895 return ICDataHasOnlyReceiverArgumentClassIds( |
| 896 ic_data, receiver_cids, argument_cids); |
| 897 } |
| 898 |
| 899 |
| 900 static bool HasOnlyOneSmi(const ICData& ic_data) { |
| 901 return (ic_data.NumberOfUsedChecks() == 1) |
| 902 && ic_data.HasReceiverClassId(kSmiCid); |
| 903 } |
| 904 |
| 905 |
| 906 static bool HasOnlySmiOrMint(const ICData& ic_data) { |
| 907 if (ic_data.NumberOfUsedChecks() == 1) { |
| 908 return ic_data.HasReceiverClassId(kSmiCid) |
| 909 || ic_data.HasReceiverClassId(kMintCid); |
| 910 } |
| 911 return (ic_data.NumberOfUsedChecks() == 2) |
| 912 && ic_data.HasReceiverClassId(kSmiCid) |
| 913 && ic_data.HasReceiverClassId(kMintCid); |
| 914 } |
| 915 |
| 916 |
| 917 static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) { |
| 918 if (ic_data.NumberOfUsedChecks() != 1) { |
| 919 return false; |
| 920 } |
| 921 GrowableArray<intptr_t> first; |
| 922 GrowableArray<intptr_t> second; |
| 923 ic_data.GetUsedCidsForTwoArgs(&first, &second); |
| 924 return (first[0] == cid) && (second[0] == cid); |
| 925 } |
| 926 |
| 927 // Returns false if the ICData contains anything other than the 4 combinations |
| 928 // of Mint and Smi for the receiver and argument classes. |
| 929 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 930 GrowableArray<intptr_t> first; |
| 931 GrowableArray<intptr_t> second; |
| 932 ic_data.GetUsedCidsForTwoArgs(&first, &second); |
| 933 for (intptr_t i = 0; i < first.length(); i++) { |
| 934 if ((first[i] != kSmiCid) && (first[i] != kMintCid)) { |
| 935 return false; |
| 936 } |
| 937 if ((second[i] != kSmiCid) && (second[i] != kMintCid)) { |
| 899 return false; | 938 return false; |
| 900 } | 939 } |
| 901 } | 940 } |
| 902 return true; | 941 return true; |
| 903 } | 942 } |
| 904 | 943 |
| 905 | 944 |
| 906 static bool HasOnlyOneSmi(const ICData& ic_data) { | |
| 907 return (ic_data.NumberOfChecks() == 1) | |
| 908 && ic_data.HasReceiverClassId(kSmiCid); | |
| 909 } | |
| 910 | |
| 911 | |
| 912 static bool HasOnlySmiOrMint(const ICData& ic_data) { | |
| 913 if (ic_data.NumberOfChecks() == 1) { | |
| 914 return ic_data.HasReceiverClassId(kSmiCid) | |
| 915 || ic_data.HasReceiverClassId(kMintCid); | |
| 916 } | |
| 917 return (ic_data.NumberOfChecks() == 2) | |
| 918 && ic_data.HasReceiverClassId(kSmiCid) | |
| 919 && ic_data.HasReceiverClassId(kMintCid); | |
| 920 } | |
| 921 | |
| 922 | |
| 923 static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) { | |
| 924 return (ic_data.NumberOfChecks() == 1) && | |
| 925 ICDataHasReceiverArgumentClassIds(ic_data, cid, cid); | |
| 926 } | |
| 927 | |
| 928 // Returns false if the ICData contains anything other than the 4 combinations | |
| 929 // of Mint and Smi for the receiver and argument classes. | |
| 930 static bool HasTwoMintOrSmi(const ICData& ic_data) { | |
| 931 GrowableArray<intptr_t> class_ids(2); | |
| 932 class_ids.Add(kSmiCid); | |
| 933 class_ids.Add(kMintCid); | |
| 934 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | |
| 935 } | |
| 936 | |
| 937 | |
| 938 // Returns false if the ICData contains anything other than the 4 combinations | 945 // Returns false if the ICData contains anything other than the 4 combinations |
| 939 // of Double and Smi for the receiver and argument classes. | 946 // of Double and Smi for the receiver and argument classes. |
| 940 static bool HasTwoDoubleOrSmi(const ICData& ic_data) { | 947 static bool HasTwoDoubleOrSmi(const ICData& ic_data) { |
| 941 GrowableArray<intptr_t> class_ids(2); | 948 GrowableArray<intptr_t> class_ids(2); |
| 942 class_ids.Add(kSmiCid); | 949 class_ids.Add(kSmiCid); |
| 943 class_ids.Add(kDoubleCid); | 950 class_ids.Add(kDoubleCid); |
| 944 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 951 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 945 } | 952 } |
| 946 | 953 |
| 947 | 954 |
| 948 static bool HasOnlyOneDouble(const ICData& ic_data) { | 955 static bool HasOnlyOneDouble(const ICData& ic_data) { |
| 949 return (ic_data.NumberOfChecks() == 1) | 956 return (ic_data.NumberOfUsedChecks() == 1) |
| 950 && ic_data.HasReceiverClassId(kDoubleCid); | 957 && ic_data.HasReceiverClassId(kDoubleCid); |
| 951 } | 958 } |
| 952 | 959 |
| 953 | 960 |
| 954 static bool ShouldSpecializeForDouble(const ICData& ic_data) { | 961 static bool ShouldSpecializeForDouble(const ICData& ic_data) { |
| 955 // Don't specialize for double if we can't unbox them. | 962 // Don't specialize for double if we can't unbox them. |
| 956 if (!CanUnboxDouble()) { | 963 if (!CanUnboxDouble()) { |
| 957 return false; | 964 return false; |
| 958 } | 965 } |
| 959 | 966 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 994 deopt_environment, | 1001 deopt_environment, |
| 995 FlowGraph::kEffect); | 1002 FlowGraph::kEffect); |
| 996 } | 1003 } |
| 997 } | 1004 } |
| 998 | 1005 |
| 999 | 1006 |
| 1000 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 1007 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
| 1001 const ICData& unary_checks, | 1008 const ICData& unary_checks, |
| 1002 intptr_t deopt_id, | 1009 intptr_t deopt_id, |
| 1003 intptr_t token_pos) { | 1010 intptr_t token_pos) { |
| 1004 if ((unary_checks.NumberOfChecks() == 1) && | 1011 if ((unary_checks.NumberOfUsedChecks() == 1) && |
| 1005 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 1012 unary_checks.HasReceiverClassId(kSmiCid)) { |
| 1006 return new(I) CheckSmiInstr(new(I) Value(to_check), | 1013 return new(I) CheckSmiInstr(new(I) Value(to_check), |
| 1007 deopt_id, | 1014 deopt_id, |
| 1008 token_pos); | 1015 token_pos); |
| 1009 } | 1016 } |
| 1010 return new(I) CheckClassInstr( | 1017 return new(I) CheckClassInstr( |
| 1011 new(I) Value(to_check), deopt_id, unary_checks, token_pos); | 1018 new(I) Value(to_check), deopt_id, unary_checks, token_pos); |
| 1012 } | 1019 } |
| 1013 | 1020 |
| 1014 | 1021 |
| 1015 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 1022 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1030 call->deopt_id(), | 1037 call->deopt_id(), |
| 1031 call->env(), | 1038 call->env(), |
| 1032 call); | 1039 call); |
| 1033 } | 1040 } |
| 1034 | 1041 |
| 1035 | 1042 |
| 1036 static bool ArgIsAlways(intptr_t cid, | 1043 static bool ArgIsAlways(intptr_t cid, |
| 1037 const ICData& ic_data, | 1044 const ICData& ic_data, |
| 1038 intptr_t arg_number) { | 1045 intptr_t arg_number) { |
| 1039 ASSERT(ic_data.NumArgsTested() > arg_number); | 1046 ASSERT(ic_data.NumArgsTested() > arg_number); |
| 1047 if (ic_data.NumberOfUsedChecks() == 0) { |
| 1048 return false; |
| 1049 } |
| 1040 const intptr_t num_checks = ic_data.NumberOfChecks(); | 1050 const intptr_t num_checks = ic_data.NumberOfChecks(); |
| 1041 if (num_checks == 0) return false; | |
| 1042 for (intptr_t i = 0; i < num_checks; i++) { | 1051 for (intptr_t i = 0; i < num_checks; i++) { |
| 1043 if (ic_data.GetClassIdAt(i, arg_number) != cid) return false; | 1052 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { |
| 1053 return false; |
| 1054 } |
| 1044 } | 1055 } |
| 1045 return true; | 1056 return true; |
| 1046 } | 1057 } |
| 1047 | 1058 |
| 1048 | 1059 |
| 1049 static bool CanUnboxInt32() { | 1060 static bool CanUnboxInt32() { |
| 1050 // Int32/Uint32 can be unboxed if it fits into a smi or the platform | 1061 // Int32/Uint32 can be unboxed if it fits into a smi or the platform |
| 1051 // supports unboxed mints. | 1062 // supports unboxed mints. |
| 1052 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); | 1063 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); |
| 1053 } | 1064 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 } | 1138 } |
| 1128 return kIllegalCid; | 1139 return kIllegalCid; |
| 1129 } | 1140 } |
| 1130 | 1141 |
| 1131 | 1142 |
| 1132 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 1143 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
| 1133 // Check for monomorphic IC data. | 1144 // Check for monomorphic IC data. |
| 1134 if (!call->HasICData()) return false; | 1145 if (!call->HasICData()) return false; |
| 1135 const ICData& ic_data = | 1146 const ICData& ic_data = |
| 1136 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | 1147 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
| 1137 if (ic_data.NumberOfChecks() != 1) return false; | 1148 if (ic_data.NumberOfChecks() != 1) { |
| 1149 return false; |
| 1150 } |
| 1151 ASSERT(ic_data.NumberOfUsedChecks() == 1); |
| 1138 ASSERT(ic_data.HasOneTarget()); | 1152 ASSERT(ic_data.HasOneTarget()); |
| 1139 | 1153 |
| 1140 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | 1154 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
| 1141 TargetEntryInstr* entry; | 1155 TargetEntryInstr* entry; |
| 1142 Definition* last; | 1156 Definition* last; |
| 1143 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1157 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
| 1144 target, | 1158 target, |
| 1145 call, | 1159 call, |
| 1146 call->ArgumentAt(0), | 1160 call->ArgumentAt(0), |
| 1147 call->token_pos(), | 1161 call->token_pos(), |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1694 } | 1708 } |
| 1695 return true; | 1709 return true; |
| 1696 } | 1710 } |
| 1697 | 1711 |
| 1698 | 1712 |
| 1699 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1713 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 1700 // Check for monomorphic IC data. | 1714 // Check for monomorphic IC data. |
| 1701 if (!call->HasICData()) return false; | 1715 if (!call->HasICData()) return false; |
| 1702 const ICData& ic_data = | 1716 const ICData& ic_data = |
| 1703 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | 1717 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
| 1704 if (ic_data.NumberOfChecks() != 1) return false; | 1718 if (ic_data.NumberOfChecks() != 1) { |
| 1719 return false; |
| 1720 } |
| 1721 ASSERT(ic_data.NumberOfUsedChecks() == 1); |
| 1705 ASSERT(ic_data.HasOneTarget()); | 1722 ASSERT(ic_data.HasOneTarget()); |
| 1706 | 1723 |
| 1707 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | 1724 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
| 1708 TargetEntryInstr* entry; | 1725 TargetEntryInstr* entry; |
| 1709 Definition* last; | 1726 Definition* last; |
| 1710 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1727 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
| 1711 target, | 1728 target, |
| 1712 call, | 1729 call, |
| 1713 call->ArgumentAt(0), | 1730 call->ArgumentAt(0), |
| 1714 call->token_pos(), | 1731 call->token_pos(), |
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2614 call->deopt_id()); | 2631 call->deopt_id()); |
| 2615 ReplaceCall(call, float64x2_bin_op); | 2632 ReplaceCall(call, float64x2_bin_op); |
| 2616 return true; | 2633 return true; |
| 2617 } | 2634 } |
| 2618 | 2635 |
| 2619 | 2636 |
| 2620 // Only unique implicit instance getters can be currently handled. | 2637 // Only unique implicit instance getters can be currently handled. |
| 2621 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 2638 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
| 2622 ASSERT(call->HasICData()); | 2639 ASSERT(call->HasICData()); |
| 2623 const ICData& ic_data = *call->ic_data(); | 2640 const ICData& ic_data = *call->ic_data(); |
| 2624 if (ic_data.NumberOfChecks() == 0) { | 2641 if (ic_data.NumberOfUsedChecks() == 0) { |
| 2625 // No type feedback collected. | 2642 // No type feedback collected. |
| 2626 return false; | 2643 return false; |
| 2627 } | 2644 } |
| 2628 | 2645 |
| 2629 if (!ic_data.HasOneTarget()) { | 2646 if (!ic_data.HasOneTarget()) { |
| 2630 // Polymorphic sites are inlined like normal methods by conventional | 2647 // Polymorphic sites are inlined like normal methods by conventional |
| 2631 // inlining in FlowGraphInliner. | 2648 // inlining in FlowGraphInliner. |
| 2632 return false; | 2649 return false; |
| 2633 } | 2650 } |
| 2634 | 2651 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2854 default: | 2871 default: |
| 2855 return false; | 2872 return false; |
| 2856 } | 2873 } |
| 2857 } | 2874 } |
| 2858 | 2875 |
| 2859 | 2876 |
| 2860 // Inline only simple, frequently called core library methods. | 2877 // Inline only simple, frequently called core library methods. |
| 2861 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 2878 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 2862 ASSERT(call->HasICData()); | 2879 ASSERT(call->HasICData()); |
| 2863 const ICData& ic_data = *call->ic_data(); | 2880 const ICData& ic_data = *call->ic_data(); |
| 2864 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 2881 if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) { |
| 2865 // No type feedback collected or multiple targets found. | 2882 // No type feedback collected or multiple targets found. |
| 2866 return false; | 2883 return false; |
| 2867 } | 2884 } |
| 2868 | 2885 |
| 2869 Function& target = Function::Handle(I); | 2886 Function& target = Function::Handle(I); |
| 2870 GrowableArray<intptr_t> class_ids; | 2887 GrowableArray<intptr_t> class_ids; |
| 2871 ic_data.GetCheckAt(0, &class_ids, &target); | 2888 ic_data.GetCheckAt(0, &class_ids, &target); |
| 2872 MethodRecognizer::Kind recognized_kind = | 2889 MethodRecognizer::Kind recognized_kind = |
| 2873 MethodRecognizer::RecognizeKind(target); | 2890 MethodRecognizer::RecognizeKind(target); |
| 2874 | 2891 |
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4154 // must have a deoptimization id that is valid for lookup in the unoptimized | 4171 // must have a deoptimization id that is valid for lookup in the unoptimized |
| 4155 // code. | 4172 // code. |
| 4156 assert_as->deopt_id_ = call->deopt_id(); | 4173 assert_as->deopt_id_ = call->deopt_id(); |
| 4157 ReplaceCall(call, assert_as); | 4174 ReplaceCall(call, assert_as); |
| 4158 } | 4175 } |
| 4159 | 4176 |
| 4160 | 4177 |
| 4161 // Tries to optimize instance call by replacing it with a faster instruction | 4178 // Tries to optimize instance call by replacing it with a faster instruction |
| 4162 // (e.g, binary op, field load, ..). | 4179 // (e.g, binary op, field load, ..). |
| 4163 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4180 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 4164 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { | 4181 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { |
| 4165 return; | 4182 return; |
| 4166 } | 4183 } |
| 4167 | 4184 |
| 4168 const Token::Kind op_kind = instr->token_kind(); | 4185 const Token::Kind op_kind = instr->token_kind(); |
| 4169 // Type test is special as it always gets converted into inlined code. | 4186 // Type test is special as it always gets converted into inlined code. |
| 4170 if (Token::IsTypeTestOperator(op_kind)) { | 4187 if (Token::IsTypeTestOperator(op_kind)) { |
| 4171 ReplaceWithInstanceOf(instr); | 4188 ReplaceWithInstanceOf(instr); |
| 4172 return; | 4189 return; |
| 4173 } | 4190 } |
| 4174 | 4191 |
| 4175 if (Token::IsTypeCastOperator(op_kind)) { | 4192 if (Token::IsTypeCastOperator(op_kind)) { |
| 4176 ReplaceWithTypeCast(instr); | 4193 ReplaceWithTypeCast(instr); |
| 4177 return; | 4194 return; |
| 4178 } | 4195 } |
| 4179 | 4196 |
| 4180 const ICData& unary_checks = | 4197 const ICData& unary_checks = |
| 4181 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); | 4198 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); |
| 4182 | 4199 |
| 4183 intptr_t max_checks = (op_kind == Token::kEQ) | 4200 const intptr_t max_checks = (op_kind == Token::kEQ) |
| 4184 ? FLAG_max_equality_polymorphic_checks | 4201 ? FLAG_max_equality_polymorphic_checks |
| 4185 : FLAG_max_polymorphic_checks; | 4202 : FLAG_max_polymorphic_checks; |
| 4186 if ((unary_checks.NumberOfChecks() > max_checks) && | 4203 if ((unary_checks.NumberOfChecks() > max_checks) && |
| 4187 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { | 4204 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { |
| 4188 // Too many checks, it will be megamorphic which needs unary checks. | 4205 // Too many checks, it will be megamorphic which needs unary checks. |
| 4189 instr->set_ic_data(&unary_checks); | 4206 instr->set_ic_data(&unary_checks); |
| 4190 return; | 4207 return; |
| 4191 } | 4208 } |
| 4192 | 4209 |
| 4193 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { | 4210 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { |
| (...skipping 5402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9596 | 9613 |
| 9597 // Insert materializations at environment uses. | 9614 // Insert materializations at environment uses. |
| 9598 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 9615 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 9599 CreateMaterializationAt( | 9616 CreateMaterializationAt( |
| 9600 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 9617 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 9601 } | 9618 } |
| 9602 } | 9619 } |
| 9603 | 9620 |
| 9604 | 9621 |
| 9605 } // namespace dart | 9622 } // namespace dart |
| OLD | NEW |