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/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, | 850 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, |
|
zra
2014/08/20 20:17:10
Could this function be implemented by calling ICDa
srdjan
2014/08/21 17:30:22
Done.
| |
| 852 intptr_t receiver_class_id, | 851 intptr_t receiver_class_id, |
| 853 intptr_t argument_class_id) { | 852 intptr_t argument_class_id) { |
| 854 ASSERT(receiver_class_id != kIllegalCid); | 853 ASSERT(receiver_class_id != kIllegalCid); |
| 855 ASSERT(argument_class_id != kIllegalCid); | 854 ASSERT(argument_class_id != kIllegalCid); |
| 856 if (ic_data.NumArgsTested() != 2) return false; | 855 if (ic_data.NumArgsTested() != 2) { |
| 856 return false; | |
| 857 } | |
| 857 | 858 |
| 858 Function& target = Function::Handle(); | 859 Function& target = Function::Handle(); |
| 859 const intptr_t len = ic_data.NumberOfChecks(); | 860 const intptr_t len = ic_data.NumberOfChecks(); |
| 860 for (intptr_t i = 0; i < len; i++) { | 861 for (intptr_t i = 0; i < len; i++) { |
| 861 GrowableArray<intptr_t> class_ids; | 862 GrowableArray<intptr_t> class_ids; |
| 862 ic_data.GetCheckAt(i, &class_ids, &target); | 863 if (ic_data.IsUsedAt(i)) { |
| 863 ASSERT(class_ids.length() == 2); | 864 ic_data.GetCheckAt(i, &class_ids, &target); |
| 864 if ((class_ids[0] == receiver_class_id) && | 865 ASSERT(class_ids.length() == 2); |
| 865 (class_ids[1] == argument_class_id)) { | 866 if ((class_ids[0] == receiver_class_id) && |
| 866 return true; | 867 (class_ids[1] == argument_class_id)) { |
| 868 return true; | |
| 869 } | |
| 867 } | 870 } |
| 868 } | 871 } |
| 869 return false; | 872 return false; |
| 870 } | 873 } |
| 871 | 874 |
| 872 | 875 |
| 873 static bool ClassIdIsOneOf(intptr_t class_id, | 876 static bool ClassIdIsOneOf(intptr_t class_id, |
| 874 const GrowableArray<intptr_t>& class_ids) { | 877 const GrowableArray<intptr_t>& class_ids) { |
| 875 for (intptr_t i = 0; i < class_ids.length(); i++) { | 878 for (intptr_t i = 0; i < class_ids.length(); i++) { |
|
zra
2014/08/20 20:17:10
maybe ASSERT(class_ids[i] != kIllegalCid); to matc
srdjan
2014/08/21 17:30:22
Done.
| |
| 876 if (class_ids[i] == class_id) { | 879 if (class_ids[i] == class_id) { |
| 877 return true; | 880 return true; |
| 878 } | 881 } |
| 879 } | 882 } |
| 880 return false; | 883 return false; |
| 881 } | 884 } |
| 882 | 885 |
| 883 | 886 |
| 884 // Returns true if ICData tests two arguments and all ICData cids are in the | 887 // 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. | 888 // required sets 'receiver_class_ids' or 'argument_class_ids', respectively. |
| 886 static bool ICDataHasOnlyReceiverArgumentClassIds( | 889 static bool ICDataHasOnlyReceiverArgumentClassIds( |
| 887 const ICData& ic_data, | 890 const ICData& ic_data, |
| 888 const GrowableArray<intptr_t>& receiver_class_ids, | 891 const GrowableArray<intptr_t>& receiver_class_ids, |
| 889 const GrowableArray<intptr_t>& argument_class_ids) { | 892 const GrowableArray<intptr_t>& argument_class_ids) { |
| 890 if (ic_data.NumArgsTested() != 2) return false; | 893 if (ic_data.NumArgsTested() != 2) { |
| 894 return false; | |
| 895 } | |
| 891 Function& target = Function::Handle(); | 896 Function& target = Function::Handle(); |
| 892 const intptr_t len = ic_data.NumberOfChecks(); | 897 const intptr_t len = ic_data.NumberOfChecks(); |
| 893 for (intptr_t i = 0; i < len; i++) { | 898 for (intptr_t i = 0; i < len; i++) { |
| 894 GrowableArray<intptr_t> class_ids; | 899 if (ic_data.IsUsedAt(i)) { |
| 895 ic_data.GetCheckAt(i, &class_ids, &target); | 900 GrowableArray<intptr_t> class_ids; |
| 896 ASSERT(class_ids.length() == 2); | 901 ic_data.GetCheckAt(i, &class_ids, &target); |
| 897 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | 902 ASSERT(class_ids.length() == 2); |
| 898 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | 903 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || |
| 899 return false; | 904 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { |
| 905 return false; | |
| 906 } | |
| 900 } | 907 } |
| 901 } | 908 } |
| 902 return true; | 909 return true; |
| 903 } | 910 } |
| 904 | 911 |
| 905 | 912 |
| 906 static bool HasOnlyOneSmi(const ICData& ic_data) { | 913 static bool HasOnlyOneSmi(const ICData& ic_data) { |
| 907 return (ic_data.NumberOfChecks() == 1) | 914 return (ic_data.NumberOfUsedChecks() == 1) |
| 908 && ic_data.HasReceiverClassId(kSmiCid); | 915 && ic_data.HasReceiverClassId(kSmiCid); |
| 909 } | 916 } |
| 910 | 917 |
| 911 | 918 |
| 912 static bool HasOnlySmiOrMint(const ICData& ic_data) { | 919 static bool HasOnlySmiOrMint(const ICData& ic_data) { |
| 913 if (ic_data.NumberOfChecks() == 1) { | 920 if (ic_data.NumberOfUsedChecks() == 1) { |
| 914 return ic_data.HasReceiverClassId(kSmiCid) | 921 return ic_data.HasReceiverClassId(kSmiCid) |
| 915 || ic_data.HasReceiverClassId(kMintCid); | 922 || ic_data.HasReceiverClassId(kMintCid); |
| 916 } | 923 } |
| 917 return (ic_data.NumberOfChecks() == 2) | 924 return (ic_data.NumberOfUsedChecks() == 2) |
| 918 && ic_data.HasReceiverClassId(kSmiCid) | 925 && ic_data.HasReceiverClassId(kSmiCid) |
| 919 && ic_data.HasReceiverClassId(kMintCid); | 926 && ic_data.HasReceiverClassId(kMintCid); |
| 920 } | 927 } |
| 921 | 928 |
| 922 | 929 |
| 923 static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) { | 930 static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) { |
| 924 return (ic_data.NumberOfChecks() == 1) && | 931 if (ic_data.NumberOfUsedChecks() != 1) { |
| 925 ICDataHasReceiverArgumentClassIds(ic_data, cid, cid); | 932 return false; |
| 933 } | |
| 934 GrowableArray<intptr_t> first; | |
| 935 GrowableArray<intptr_t> second; | |
| 936 ic_data.GetUsedCidsForTwoArgs(&first, &second); | |
| 937 return (first[0] == cid) && (second[0] == cid); | |
| 926 } | 938 } |
| 927 | 939 |
| 928 // Returns false if the ICData contains anything other than the 4 combinations | 940 // Returns false if the ICData contains anything other than the 4 combinations |
| 929 // of Mint and Smi for the receiver and argument classes. | 941 // of Mint and Smi for the receiver and argument classes. |
| 930 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 942 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
| 931 GrowableArray<intptr_t> class_ids(2); | 943 GrowableArray<intptr_t> first; |
| 932 class_ids.Add(kSmiCid); | 944 GrowableArray<intptr_t> second; |
| 933 class_ids.Add(kMintCid); | 945 ic_data.GetUsedCidsForTwoArgs(&first, &second); |
| 934 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 946 for (intptr_t i = 0; i < first.length(); i++) { |
| 947 if ((first[i] != kSmiCid) && (first[i] != kMintCid)) { | |
| 948 return false; | |
| 949 } | |
| 950 if ((second[i] != kSmiCid) && (second[i] != kMintCid)) { | |
| 951 return false; | |
| 952 } | |
| 953 } | |
| 954 return true; | |
| 935 } | 955 } |
| 936 | 956 |
| 937 | 957 |
| 938 // Returns false if the ICData contains anything other than the 4 combinations | 958 // Returns false if the ICData contains anything other than the 4 combinations |
| 939 // of Double and Smi for the receiver and argument classes. | 959 // of Double and Smi for the receiver and argument classes. |
| 940 static bool HasTwoDoubleOrSmi(const ICData& ic_data) { | 960 static bool HasTwoDoubleOrSmi(const ICData& ic_data) { |
| 941 GrowableArray<intptr_t> class_ids(2); | 961 GrowableArray<intptr_t> class_ids(2); |
| 942 class_ids.Add(kSmiCid); | 962 class_ids.Add(kSmiCid); |
| 943 class_ids.Add(kDoubleCid); | 963 class_ids.Add(kDoubleCid); |
| 944 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 964 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
| 945 } | 965 } |
| 946 | 966 |
| 947 | 967 |
| 948 static bool HasOnlyOneDouble(const ICData& ic_data) { | 968 static bool HasOnlyOneDouble(const ICData& ic_data) { |
| 949 return (ic_data.NumberOfChecks() == 1) | 969 return (ic_data.NumberOfUsedChecks() == 1) |
| 950 && ic_data.HasReceiverClassId(kDoubleCid); | 970 && ic_data.HasReceiverClassId(kDoubleCid); |
| 951 } | 971 } |
| 952 | 972 |
| 953 | 973 |
| 954 static bool ShouldSpecializeForDouble(const ICData& ic_data) { | 974 static bool ShouldSpecializeForDouble(const ICData& ic_data) { |
| 955 // Don't specialize for double if we can't unbox them. | 975 // Don't specialize for double if we can't unbox them. |
| 956 if (!CanUnboxDouble()) { | 976 if (!CanUnboxDouble()) { |
| 957 return false; | 977 return false; |
| 958 } | 978 } |
| 959 | 979 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 994 deopt_environment, | 1014 deopt_environment, |
| 995 FlowGraph::kEffect); | 1015 FlowGraph::kEffect); |
| 996 } | 1016 } |
| 997 } | 1017 } |
| 998 | 1018 |
| 999 | 1019 |
| 1000 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, | 1020 Instruction* FlowGraphOptimizer::GetCheckClass(Definition* to_check, |
| 1001 const ICData& unary_checks, | 1021 const ICData& unary_checks, |
| 1002 intptr_t deopt_id, | 1022 intptr_t deopt_id, |
| 1003 intptr_t token_pos) { | 1023 intptr_t token_pos) { |
| 1004 if ((unary_checks.NumberOfChecks() == 1) && | 1024 if ((unary_checks.NumberOfUsedChecks() == 1) && |
| 1005 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { | 1025 unary_checks.HasReceiverClassId(kSmiCid)) { |
| 1006 return new(I) CheckSmiInstr(new(I) Value(to_check), | 1026 return new(I) CheckSmiInstr(new(I) Value(to_check), |
| 1007 deopt_id, | 1027 deopt_id, |
| 1008 token_pos); | 1028 token_pos); |
| 1009 } | 1029 } |
| 1010 return new(I) CheckClassInstr( | 1030 return new(I) CheckClassInstr( |
| 1011 new(I) Value(to_check), deopt_id, unary_checks, token_pos); | 1031 new(I) Value(to_check), deopt_id, unary_checks, token_pos); |
| 1012 } | 1032 } |
| 1013 | 1033 |
| 1014 | 1034 |
| 1015 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, | 1035 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1030 call->deopt_id(), | 1050 call->deopt_id(), |
| 1031 call->env(), | 1051 call->env(), |
| 1032 call); | 1052 call); |
| 1033 } | 1053 } |
| 1034 | 1054 |
| 1035 | 1055 |
| 1036 static bool ArgIsAlways(intptr_t cid, | 1056 static bool ArgIsAlways(intptr_t cid, |
| 1037 const ICData& ic_data, | 1057 const ICData& ic_data, |
| 1038 intptr_t arg_number) { | 1058 intptr_t arg_number) { |
| 1039 ASSERT(ic_data.NumArgsTested() > arg_number); | 1059 ASSERT(ic_data.NumArgsTested() > arg_number); |
| 1060 if (ic_data.NumberOfUsedChecks() == 0) { | |
| 1061 return false; | |
| 1062 } | |
| 1040 const intptr_t num_checks = ic_data.NumberOfChecks(); | 1063 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++) { | 1064 for (intptr_t i = 0; i < num_checks; i++) { |
| 1043 if (ic_data.GetClassIdAt(i, arg_number) != cid) return false; | 1065 if (ic_data.IsUsedAt(i) && ic_data.GetClassIdAt(i, arg_number) != cid) { |
| 1066 return false; | |
| 1067 } | |
| 1044 } | 1068 } |
| 1045 return true; | 1069 return true; |
| 1046 } | 1070 } |
| 1047 | 1071 |
| 1048 | 1072 |
| 1049 static bool CanUnboxInt32() { | 1073 static bool CanUnboxInt32() { |
| 1050 // Int32/Uint32 can be unboxed if it fits into a smi or the platform | 1074 // Int32/Uint32 can be unboxed if it fits into a smi or the platform |
| 1051 // supports unboxed mints. | 1075 // supports unboxed mints. |
| 1052 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); | 1076 return (kSmiBits >= 32) || FlowGraphCompiler::SupportsUnboxedMints(); |
| 1053 } | 1077 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1127 } | 1151 } |
| 1128 return kIllegalCid; | 1152 return kIllegalCid; |
| 1129 } | 1153 } |
| 1130 | 1154 |
| 1131 | 1155 |
| 1132 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 1156 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
| 1133 // Check for monomorphic IC data. | 1157 // Check for monomorphic IC data. |
| 1134 if (!call->HasICData()) return false; | 1158 if (!call->HasICData()) return false; |
| 1135 const ICData& ic_data = | 1159 const ICData& ic_data = |
| 1136 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | 1160 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
| 1137 if (ic_data.NumberOfChecks() != 1) return false; | 1161 if (ic_data.NumberOfChecks() != 1) { |
| 1162 return false; | |
| 1163 } | |
| 1164 ASSERT(ic_data.NumberOfUsedChecks() == 1); | |
| 1138 ASSERT(ic_data.HasOneTarget()); | 1165 ASSERT(ic_data.HasOneTarget()); |
| 1139 | 1166 |
| 1140 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | 1167 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
| 1141 TargetEntryInstr* entry; | 1168 TargetEntryInstr* entry; |
| 1142 Definition* last; | 1169 Definition* last; |
| 1143 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1170 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
| 1144 target, | 1171 target, |
| 1145 call, | 1172 call, |
| 1146 call->ArgumentAt(0), | 1173 call->ArgumentAt(0), |
| 1147 call->token_pos(), | 1174 call->token_pos(), |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1686 } | 1713 } |
| 1687 return true; | 1714 return true; |
| 1688 } | 1715 } |
| 1689 | 1716 |
| 1690 | 1717 |
| 1691 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { | 1718 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { |
| 1692 // Check for monomorphic IC data. | 1719 // Check for monomorphic IC data. |
| 1693 if (!call->HasICData()) return false; | 1720 if (!call->HasICData()) return false; |
| 1694 const ICData& ic_data = | 1721 const ICData& ic_data = |
| 1695 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); | 1722 ICData::Handle(I, call->ic_data()->AsUnaryClassChecks()); |
| 1696 if (ic_data.NumberOfChecks() != 1) return false; | 1723 if (ic_data.NumberOfChecks() != 1) { |
| 1724 return false; | |
| 1725 } | |
| 1726 ASSERT(ic_data.NumberOfUsedChecks() == 1); | |
| 1697 ASSERT(ic_data.HasOneTarget()); | 1727 ASSERT(ic_data.HasOneTarget()); |
| 1698 | 1728 |
| 1699 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); | 1729 const Function& target = Function::Handle(I, ic_data.GetTargetAt(0)); |
| 1700 TargetEntryInstr* entry; | 1730 TargetEntryInstr* entry; |
| 1701 Definition* last; | 1731 Definition* last; |
| 1702 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), | 1732 if (!TryInlineRecognizedMethod(ic_data.GetReceiverClassIdAt(0), |
| 1703 target, | 1733 target, |
| 1704 call, | 1734 call, |
| 1705 call->ArgumentAt(0), | 1735 call->ArgumentAt(0), |
| 1706 call->token_pos(), | 1736 call->token_pos(), |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2621 call->deopt_id()); | 2651 call->deopt_id()); |
| 2622 ReplaceCall(call, float64x2_bin_op); | 2652 ReplaceCall(call, float64x2_bin_op); |
| 2623 return true; | 2653 return true; |
| 2624 } | 2654 } |
| 2625 | 2655 |
| 2626 | 2656 |
| 2627 // Only unique implicit instance getters can be currently handled. | 2657 // Only unique implicit instance getters can be currently handled. |
| 2628 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 2658 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
| 2629 ASSERT(call->HasICData()); | 2659 ASSERT(call->HasICData()); |
| 2630 const ICData& ic_data = *call->ic_data(); | 2660 const ICData& ic_data = *call->ic_data(); |
| 2631 if (ic_data.NumberOfChecks() == 0) { | 2661 if (ic_data.NumberOfUsedChecks() == 0) { |
| 2632 // No type feedback collected. | 2662 // No type feedback collected. |
| 2633 return false; | 2663 return false; |
| 2634 } | 2664 } |
| 2635 | 2665 |
| 2636 if (!ic_data.HasOneTarget()) { | 2666 if (!ic_data.HasOneTarget()) { |
| 2637 // Polymorphic sites are inlined like normal methods by conventional | 2667 // Polymorphic sites are inlined like normal methods by conventional |
| 2638 // inlining in FlowGraphInliner. | 2668 // inlining in FlowGraphInliner. |
| 2639 return false; | 2669 return false; |
| 2640 } | 2670 } |
| 2641 | 2671 |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2827 default: | 2857 default: |
| 2828 return false; | 2858 return false; |
| 2829 } | 2859 } |
| 2830 } | 2860 } |
| 2831 | 2861 |
| 2832 | 2862 |
| 2833 // Inline only simple, frequently called core library methods. | 2863 // Inline only simple, frequently called core library methods. |
| 2834 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 2864 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
| 2835 ASSERT(call->HasICData()); | 2865 ASSERT(call->HasICData()); |
| 2836 const ICData& ic_data = *call->ic_data(); | 2866 const ICData& ic_data = *call->ic_data(); |
| 2837 if ((ic_data.NumberOfChecks() == 0) || !ic_data.HasOneTarget()) { | 2867 if ((ic_data.NumberOfUsedChecks() == 0) || !ic_data.HasOneTarget()) { |
| 2838 // No type feedback collected or multiple targets found. | 2868 // No type feedback collected or multiple targets found. |
| 2839 return false; | 2869 return false; |
| 2840 } | 2870 } |
| 2841 | 2871 |
| 2842 Function& target = Function::Handle(I); | 2872 Function& target = Function::Handle(I); |
| 2843 GrowableArray<intptr_t> class_ids; | 2873 GrowableArray<intptr_t> class_ids; |
| 2844 ic_data.GetCheckAt(0, &class_ids, &target); | 2874 ic_data.GetCheckAt(0, &class_ids, &target); |
| 2845 MethodRecognizer::Kind recognized_kind = | 2875 MethodRecognizer::Kind recognized_kind = |
| 2846 MethodRecognizer::RecognizeKind(target); | 2876 MethodRecognizer::RecognizeKind(target); |
| 2847 | 2877 |
| (...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4122 // must have a deoptimization id that is valid for lookup in the unoptimized | 4152 // must have a deoptimization id that is valid for lookup in the unoptimized |
| 4123 // code. | 4153 // code. |
| 4124 assert_as->deopt_id_ = call->deopt_id(); | 4154 assert_as->deopt_id_ = call->deopt_id(); |
| 4125 ReplaceCall(call, assert_as); | 4155 ReplaceCall(call, assert_as); |
| 4126 } | 4156 } |
| 4127 | 4157 |
| 4128 | 4158 |
| 4129 // Tries to optimize instance call by replacing it with a faster instruction | 4159 // Tries to optimize instance call by replacing it with a faster instruction |
| 4130 // (e.g, binary op, field load, ..). | 4160 // (e.g, binary op, field load, ..). |
| 4131 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { | 4161 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallInstr* instr) { |
| 4132 if (!instr->HasICData() || (instr->ic_data()->NumberOfChecks() == 0)) { | 4162 if (!instr->HasICData() || (instr->ic_data()->NumberOfUsedChecks() == 0)) { |
| 4133 return; | 4163 return; |
| 4134 } | 4164 } |
| 4135 | 4165 |
| 4136 const Token::Kind op_kind = instr->token_kind(); | 4166 const Token::Kind op_kind = instr->token_kind(); |
| 4137 // Type test is special as it always gets converted into inlined code. | 4167 // Type test is special as it always gets converted into inlined code. |
| 4138 if (Token::IsTypeTestOperator(op_kind)) { | 4168 if (Token::IsTypeTestOperator(op_kind)) { |
| 4139 ReplaceWithInstanceOf(instr); | 4169 ReplaceWithInstanceOf(instr); |
| 4140 return; | 4170 return; |
| 4141 } | 4171 } |
| 4142 | 4172 |
| 4143 if (Token::IsTypeCastOperator(op_kind)) { | 4173 if (Token::IsTypeCastOperator(op_kind)) { |
| 4144 ReplaceWithTypeCast(instr); | 4174 ReplaceWithTypeCast(instr); |
| 4145 return; | 4175 return; |
| 4146 } | 4176 } |
| 4147 | 4177 |
| 4148 const ICData& unary_checks = | 4178 const ICData& unary_checks = |
| 4149 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); | 4179 ICData::ZoneHandle(I, instr->ic_data()->AsUnaryClassChecks()); |
| 4150 | 4180 |
| 4151 intptr_t max_checks = (op_kind == Token::kEQ) | 4181 const intptr_t max_checks = (op_kind == Token::kEQ) |
| 4152 ? FLAG_max_equality_polymorphic_checks | 4182 ? FLAG_max_equality_polymorphic_checks |
| 4153 : FLAG_max_polymorphic_checks; | 4183 : FLAG_max_polymorphic_checks; |
| 4154 if ((unary_checks.NumberOfChecks() > max_checks) && | 4184 if ((unary_checks.NumberOfChecks() > max_checks) && |
| 4155 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { | 4185 InstanceCallNeedsClassCheck(instr, RawFunction::kRegularFunction)) { |
| 4156 // Too many checks, it will be megamorphic which needs unary checks. | 4186 // Too many checks, it will be megamorphic which needs unary checks. |
| 4157 instr->set_ic_data(&unary_checks); | 4187 instr->set_ic_data(&unary_checks); |
| 4158 return; | 4188 return; |
| 4159 } | 4189 } |
| 4160 | 4190 |
| 4161 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { | 4191 if ((op_kind == Token::kASSIGN_INDEX) && TryReplaceWithStoreIndexed(instr)) { |
| (...skipping 5385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9547 | 9577 |
| 9548 // Insert materializations at environment uses. | 9578 // Insert materializations at environment uses. |
| 9549 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 9579 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 9550 CreateMaterializationAt( | 9580 CreateMaterializationAt( |
| 9551 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 9581 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 9552 } | 9582 } |
| 9553 } | 9583 } |
| 9554 | 9584 |
| 9555 | 9585 |
| 9556 } // namespace dart | 9586 } // namespace dart |
| OLD | NEW |