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

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

Issue 436643002: Faster IC stubs by specializing them for Binary Smi operations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 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
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/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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698