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

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,
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698