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

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

Issue 2859673002: Pass type argument vector to generic functions (if --reify-generic-functions is (Closed)
Patch Set: address comments Created 3 years, 7 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
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/aot_optimizer.h" 5 #include "vm/aot_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 return false; 106 return false;
107 } 107 }
108 108
109 if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) { 109 if (call->function_name().raw() != Symbols::GetRuntimeType().raw()) {
110 return false; 110 return false;
111 } 111 }
112 112
113 // There is only a single function Object.get:runtimeType that can be invoked 113 // There is only a single function Object.get:runtimeType that can be invoked
114 // by this call. Convert dynamic invocation to a static one. 114 // by this call. Convert dynamic invocation to a static one.
115 const Class& cls = Class::Handle(Z, I->object_store()->object_class()); 115 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
116 const Array& args_desc_array = Array::Handle( 116 const Array& args_desc_array = call->GetArgumentsDescriptor(Z);
117 Z,
118 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
119 ArgumentsDescriptor args_desc(args_desc_array); 117 ArgumentsDescriptor args_desc(args_desc_array);
120 const Function& function = 118 const Function& function =
121 Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass( 119 Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass(
122 cls, call->function_name(), args_desc)); 120 cls, call->function_name(), args_desc));
123 ASSERT(!function.IsNull()); 121 ASSERT(!function.IsNull());
124 122 const intptr_t kTypeArgsLen = 0;
123 ASSERT(call->type_args_len() == kTypeArgsLen);
125 ZoneGrowableArray<PushArgumentInstr*>* args = 124 ZoneGrowableArray<PushArgumentInstr*>* args =
126 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount()); 125 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount());
127 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 126 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
128 args->Add(call->PushArgumentAt(i)); 127 args->Add(call->PushArgumentAt(i));
129 } 128 }
130 StaticCallInstr* static_call = new (Z) StaticCallInstr( 129 StaticCallInstr* static_call = new (Z) StaticCallInstr(
131 call->token_pos(), Function::ZoneHandle(Z, function.raw()), 130 call->token_pos(), Function::ZoneHandle(Z, function.raw()), kTypeArgsLen,
132 call->argument_names(), args, call->deopt_id()); 131 call->argument_names(), args, call->deopt_id());
133 static_call->set_result_cid(kTypeCid); 132 static_call->set_result_cid(kTypeCid);
134 call->ReplaceWith(static_call, current_iterator()); 133 call->ReplaceWith(static_call, current_iterator());
135 return true; 134 return true;
136 } 135 }
137 136
138 137
139 // Optimize instance calls using cid. This is called after optimizer 138 // Optimize instance calls using cid. This is called after optimizer
140 // converted instance calls to instructions. Any remaining 139 // converted instance calls to instructions. Any remaining
141 // instance calls are either megamorphic calls, cannot be optimized or 140 // instance calls are either megamorphic calls, cannot be optimized or
(...skipping 29 matching lines...) Expand all
171 170
172 171
173 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { 172 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
174 ASSERT(call->HasICData()); 173 ASSERT(call->HasICData());
175 if (call->ic_data()->NumberOfUsedChecks() > 0) { 174 if (call->ic_data()->NumberOfUsedChecks() > 0) {
176 // This occurs when an instance call has too many checks, will be converted 175 // This occurs when an instance call has too many checks, will be converted
177 // to megamorphic call. 176 // to megamorphic call.
178 return false; 177 return false;
179 } 178 }
180 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); 179 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
181 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); 180 const intptr_t receiver_idx =
181 call->ArgumentCount() - call->ArgumentCountWithoutTypeArgs();
182 ASSERT(call->ic_data()->NumArgsTested() <=
183 call->ArgumentCountWithoutTypeArgs());
182 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { 184 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
183 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); 185 class_ids.Add(
186 call->PushArgumentAt(receiver_idx + i)->value()->Type()->ToCid());
184 } 187 }
185 188
186 const Token::Kind op_kind = call->token_kind(); 189 const Token::Kind op_kind = call->token_kind();
187 if (FLAG_guess_icdata_cid) { 190 if (FLAG_guess_icdata_cid) {
188 if (Token::IsBinaryBitwiseOperator(op_kind)) { 191 if (Token::IsBinaryBitwiseOperator(op_kind)) {
189 class_ids[0] = kSmiCid; 192 class_ids[0] = kSmiCid;
190 class_ids[1] = kSmiCid; 193 class_ids[1] = kSmiCid;
191 } 194 }
192 if (Token::IsRelationalOperator(op_kind) || 195 if (Token::IsRelationalOperator(op_kind) ||
193 Token::IsEqualityOperator(op_kind) || 196 Token::IsEqualityOperator(op_kind) ||
(...skipping 21 matching lines...) Expand all
215 218
216 if (all_cids_known) { 219 if (all_cids_known) {
217 const Class& receiver_class = 220 const Class& receiver_class =
218 Class::Handle(Z, isolate()->class_table()->At(class_ids[0])); 221 Class::Handle(Z, isolate()->class_table()->At(class_ids[0]));
219 if (!receiver_class.is_finalized()) { 222 if (!receiver_class.is_finalized()) {
220 // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can 223 // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can
221 // cause class finalization, since callee's receiver class may not be 224 // cause class finalization, since callee's receiver class may not be
222 // finalized yet. 225 // finalized yet.
223 return false; 226 return false;
224 } 227 }
225 const Array& args_desc_array = 228 const Array& args_desc_array = call->GetArgumentsDescriptor(Z);
226 Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(),
227 call->argument_names()));
228 ArgumentsDescriptor args_desc(args_desc_array); 229 ArgumentsDescriptor args_desc(args_desc_array);
229 const Function& function = Function::Handle( 230 const Function& function = Function::Handle(
230 Z, Resolver::ResolveDynamicForReceiverClass( 231 Z, Resolver::ResolveDynamicForReceiverClass(
231 receiver_class, call->function_name(), args_desc)); 232 receiver_class, call->function_name(), args_desc));
232 if (function.IsNull()) { 233 if (function.IsNull()) {
233 return false; 234 return false;
234 } 235 }
235 236
236 // Create new ICData, do not modify the one attached to the instruction 237 // Create new ICData, do not modify the one attached to the instruction
237 // since it is attached to the assembly instruction itself. 238 // since it is attached to the assembly instruction itself.
238 // TODO(srdjan): Prevent modification of ICData object that is 239 // TODO(srdjan): Prevent modification of ICData object that is
239 // referenced in assembly code. 240 // referenced in assembly code.
240 const ICData& ic_data = ICData::ZoneHandle( 241 const ICData& ic_data = ICData::ZoneHandle(
241 Z, ICData::NewFrom(*call->ic_data(), class_ids.length())); 242 Z, ICData::NewFrom(*call->ic_data(), class_ids.length()));
242 if (class_ids.length() > 1) { 243 if (class_ids.length() > 1) {
243 ic_data.AddCheck(class_ids, function); 244 ic_data.AddCheck(class_ids, function);
244 } else { 245 } else {
245 ASSERT(class_ids.length() == 1); 246 ASSERT(class_ids.length() == 1);
246 ic_data.AddReceiverCheck(class_ids[0], function); 247 ic_data.AddReceiverCheck(class_ids[0], function);
247 } 248 }
248 call->set_ic_data(&ic_data); 249 call->set_ic_data(&ic_data);
249 return true; 250 return true;
250 } 251 }
251 252
252 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { 253 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
253 // Check if the target is unique. 254 // Check if the target is unique.
254 Function& target_function = Function::Handle(Z); 255 Function& target_function = Function::Handle(Z);
255 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); 256 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
256 // Calls with named arguments must be resolved/checked at runtime. 257 // Calls passing named arguments and calls to a function taking named
258 // arguments must be resolved/checked at runtime.
259 // Calls passing a type argument vector and calls to a generic function must
260 // be resolved/checked at runtime.
257 if (!target_function.IsNull() && 261 if (!target_function.IsNull() &&
258 !target_function.HasOptionalNamedParameters() && 262 !target_function.HasOptionalNamedParameters() &&
259 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, 263 !target_function.IsGeneric() &&
260 /* error_message = */ NULL)) { 264 target_function.AreValidArgumentCounts(
265 call->type_args_len(), call->ArgumentCountWithoutTypeArgs(),
266 call->argument_names().Length(),
267 /* error_message = */ NULL)) {
261 const Class& cls = Class::Handle(Z, target_function.Owner()); 268 const Class& cls = Class::Handle(Z, target_function.Owner());
262 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) { 269 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
263 const ICData& ic_data = 270 const ICData& ic_data =
264 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1)); 271 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1));
265 ic_data.AddReceiverCheck(cls.id(), target_function); 272 ic_data.AddReceiverCheck(cls.id(), target_function);
266 call->set_ic_data(&ic_data); 273 call->set_ic_data(&ic_data);
267 if (has_unique_no_such_method_) { 274 if (has_unique_no_such_method_) {
268 call->set_has_unique_selector(true); 275 call->set_has_unique_selector(true);
269 // Add redefinition of the receiver to prevent code motion across 276 // Add redefinition of the receiver to prevent code motion across
270 // this call. 277 // this call.
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 } 628 }
622 629
623 630
624 // Recognize a.runtimeType == b.runtimeType and fold it into 631 // Recognize a.runtimeType == b.runtimeType and fold it into
625 // Object._haveSameRuntimeType(a, b). 632 // Object._haveSameRuntimeType(a, b).
626 // Note: this optimization is not speculative. 633 // Note: this optimization is not speculative.
627 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) { 634 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
628 const ICData& ic_data = *call->ic_data(); 635 const ICData& ic_data = *call->ic_data();
629 ASSERT(ic_data.NumArgsTested() == 2); 636 ASSERT(ic_data.NumArgsTested() == 2);
630 637
638 ASSERT(call->type_args_len() == 0);
631 ASSERT(call->ArgumentCount() == 2); 639 ASSERT(call->ArgumentCount() == 2);
632 Definition* left = call->ArgumentAt(0); 640 Definition* left = call->ArgumentAt(0);
633 Definition* right = call->ArgumentAt(1); 641 Definition* right = call->ArgumentAt(1);
634 642
635 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() && 643 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
636 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) { 644 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
637 const Class& cls = Class::Handle(Z, I->object_store()->object_class()); 645 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
638 const Function& have_same_runtime_type = Function::ZoneHandle( 646 const Function& have_same_runtime_type = Function::ZoneHandle(
639 Z, 647 Z,
640 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); 648 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
641 ASSERT(!have_same_runtime_type.IsNull()); 649 ASSERT(!have_same_runtime_type.IsNull());
642 650
643 ZoneGrowableArray<PushArgumentInstr*>* args = 651 ZoneGrowableArray<PushArgumentInstr*>* args =
644 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); 652 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
645 PushArgumentInstr* arg = 653 PushArgumentInstr* arg =
646 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0))); 654 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0)));
647 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 655 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
648 args->Add(arg); 656 args->Add(arg);
649 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0))); 657 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0)));
650 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 658 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
651 args->Add(arg); 659 args->Add(arg);
652 StaticCallInstr* static_call = 660 const intptr_t kTypeArgsLen = 0;
653 new (Z) StaticCallInstr(call->token_pos(), have_same_runtime_type, 661 ASSERT(call->type_args_len() == kTypeArgsLen);
654 Object::null_array(), // argument_names 662 StaticCallInstr* static_call = new (Z)
655 args, call->deopt_id()); 663 StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen,
664 Object::null_array(), // argument_names
665 args, call->deopt_id());
656 static_call->set_result_cid(kBoolCid); 666 static_call->set_result_cid(kBoolCid);
657 ReplaceCall(call, static_call); 667 ReplaceCall(call, static_call);
658 return true; 668 return true;
659 } 669 }
660 670
661 return false; 671 return false;
662 } 672 }
663 673
664 674
665 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 675 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
666 Token::Kind op_kind) { 676 Token::Kind op_kind) {
667 const ICData& ic_data = *call->ic_data(); 677 const ICData& ic_data = *call->ic_data();
668 ASSERT(ic_data.NumArgsTested() == 2); 678 ASSERT(ic_data.NumArgsTested() == 2);
669 679
680 ASSERT(call->type_args_len() == 0);
670 ASSERT(call->ArgumentCount() == 2); 681 ASSERT(call->ArgumentCount() == 2);
671 Definition* left = call->ArgumentAt(0); 682 Definition* left = call->ArgumentAt(0);
672 Definition* right = call->ArgumentAt(1); 683 Definition* right = call->ArgumentAt(1);
673 684
674 intptr_t cid = kIllegalCid; 685 intptr_t cid = kIllegalCid;
675 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 686 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
676 return TryStringLengthOneEquality(call, op_kind); 687 return TryStringLengthOneEquality(call, op_kind);
677 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 688 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
678 InsertBefore(call, 689 InsertBefore(call,
679 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 690 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 ReplaceCall(call, comp); 757 ReplaceCall(call, comp);
747 return true; 758 return true;
748 } 759 }
749 760
750 761
751 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 762 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
752 Token::Kind op_kind) { 763 Token::Kind op_kind) {
753 const ICData& ic_data = *call->ic_data(); 764 const ICData& ic_data = *call->ic_data();
754 ASSERT(ic_data.NumArgsTested() == 2); 765 ASSERT(ic_data.NumArgsTested() == 2);
755 766
767 ASSERT(call->type_args_len() == 0);
756 ASSERT(call->ArgumentCount() == 2); 768 ASSERT(call->ArgumentCount() == 2);
757 Definition* left = call->ArgumentAt(0); 769 Definition* left = call->ArgumentAt(0);
758 Definition* right = call->ArgumentAt(1); 770 Definition* right = call->ArgumentAt(1);
759 771
760 intptr_t cid = kIllegalCid; 772 intptr_t cid = kIllegalCid;
761 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 773 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
762 InsertBefore(call, 774 InsertBefore(call,
763 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 775 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
764 call->token_pos()), 776 call->token_pos()),
765 call->env(), FlowGraph::kEffect); 777 call->env(), FlowGraph::kEffect);
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 } 907 }
896 operands_type = kSmiCid; 908 operands_type = kSmiCid;
897 } else { 909 } else {
898 return false; 910 return false;
899 } 911 }
900 break; 912 break;
901 default: 913 default:
902 UNREACHABLE(); 914 UNREACHABLE();
903 } 915 }
904 916
917 ASSERT(call->type_args_len() == 0);
905 ASSERT(call->ArgumentCount() == 2); 918 ASSERT(call->ArgumentCount() == 2);
906 Definition* left = call->ArgumentAt(0); 919 Definition* left = call->ArgumentAt(0);
907 Definition* right = call->ArgumentAt(1); 920 Definition* right = call->ArgumentAt(1);
908 if (operands_type == kDoubleCid) { 921 if (operands_type == kDoubleCid) {
909 if (!CanUnboxDouble()) { 922 if (!CanUnboxDouble()) {
910 return false; 923 return false;
911 } 924 }
912 // Check that either left or right are not a smi. Result of a 925 // Check that either left or right are not a smi. Result of a
913 // binary operation with two smis is a smi not a double, except '/' which 926 // binary operation with two smis is a smi not a double, except '/' which
914 // returns a double for two smis. 927 // returns a double for two smis.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 BinarySmiOpInstr* bin_op = new (Z) BinarySmiOpInstr( 996 BinarySmiOpInstr* bin_op = new (Z) BinarySmiOpInstr(
984 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 997 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
985 ReplaceCall(call, bin_op); 998 ReplaceCall(call, bin_op);
986 } 999 }
987 return true; 1000 return true;
988 } 1001 }
989 1002
990 1003
991 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 1004 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
992 Token::Kind op_kind) { 1005 Token::Kind op_kind) {
1006 ASSERT(call->type_args_len() == 0);
993 ASSERT(call->ArgumentCount() == 1); 1007 ASSERT(call->ArgumentCount() == 1);
994 Definition* input = call->ArgumentAt(0); 1008 Definition* input = call->ArgumentAt(0);
995 Definition* unary_op = NULL; 1009 Definition* unary_op = NULL;
996 if (HasOnlyOneSmi(*call->ic_data())) { 1010 if (HasOnlyOneSmi(*call->ic_data())) {
997 InsertBefore(call, 1011 InsertBefore(call,
998 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(), 1012 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(),
999 call->token_pos()), 1013 call->token_pos()),
1000 call->env(), FlowGraph::kEffect); 1014 call->env(), FlowGraph::kEffect);
1001 unary_op = new (Z) 1015 unary_op = new (Z)
1002 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); 1016 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 } 1083 }
1070 return true; 1084 return true;
1071 } 1085 }
1072 1086
1073 1087
1074 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 1088 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1075 Token::Kind op_kind) { 1089 Token::Kind op_kind) {
1076 if (!ShouldInlineSimd()) { 1090 if (!ShouldInlineSimd()) {
1077 return false; 1091 return false;
1078 } 1092 }
1093 ASSERT(call->type_args_len() == 0);
1079 ASSERT(call->ArgumentCount() == 2); 1094 ASSERT(call->ArgumentCount() == 2);
1080 Definition* left = call->ArgumentAt(0); 1095 Definition* left = call->ArgumentAt(0);
1081 Definition* right = call->ArgumentAt(1); 1096 Definition* right = call->ArgumentAt(1);
1082 // Type check left. 1097 // Type check left.
1083 AddCheckClass(left, ICData::ZoneHandle( 1098 AddCheckClass(left, ICData::ZoneHandle(
1084 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1099 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1085 call->deopt_id(), call->env(), call); 1100 call->deopt_id(), call->env(), call);
1086 // Type check right. 1101 // Type check right.
1087 AddCheckClass(right, ICData::ZoneHandle( 1102 AddCheckClass(right, ICData::ZoneHandle(
1088 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), 1103 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1089 call->deopt_id(), call->env(), call); 1104 call->deopt_id(), call->env(), call);
1090 // Replace call. 1105 // Replace call.
1091 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( 1106 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr(
1092 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1107 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1093 ReplaceCall(call, float32x4_bin_op); 1108 ReplaceCall(call, float32x4_bin_op);
1094 1109
1095 return true; 1110 return true;
1096 } 1111 }
1097 1112
1098 1113
1099 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, 1114 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
1100 Token::Kind op_kind) { 1115 Token::Kind op_kind) {
1101 if (!ShouldInlineSimd()) { 1116 if (!ShouldInlineSimd()) {
1102 return false; 1117 return false;
1103 } 1118 }
1119 ASSERT(call->type_args_len() == 0);
1104 ASSERT(call->ArgumentCount() == 2); 1120 ASSERT(call->ArgumentCount() == 2);
1105 Definition* left = call->ArgumentAt(0); 1121 Definition* left = call->ArgumentAt(0);
1106 Definition* right = call->ArgumentAt(1); 1122 Definition* right = call->ArgumentAt(1);
1107 // Type check left. 1123 // Type check left.
1108 AddCheckClass(left, ICData::ZoneHandle( 1124 AddCheckClass(left, ICData::ZoneHandle(
1109 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1125 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1110 call->deopt_id(), call->env(), call); 1126 call->deopt_id(), call->env(), call);
1111 // Type check right. 1127 // Type check right.
1112 AddCheckClass(right, ICData::ZoneHandle( 1128 AddCheckClass(right, ICData::ZoneHandle(
1113 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)), 1129 Z, call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1114 call->deopt_id(), call->env(), call); 1130 call->deopt_id(), call->env(), call);
1115 // Replace call. 1131 // Replace call.
1116 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( 1132 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr(
1117 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1133 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1118 ReplaceCall(call, int32x4_bin_op); 1134 ReplaceCall(call, int32x4_bin_op);
1119 return true; 1135 return true;
1120 } 1136 }
1121 1137
1122 1138
1123 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, 1139 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
1124 Token::Kind op_kind) { 1140 Token::Kind op_kind) {
1125 if (!ShouldInlineSimd()) { 1141 if (!ShouldInlineSimd()) {
1126 return false; 1142 return false;
1127 } 1143 }
1144 ASSERT(call->type_args_len() == 0);
1128 ASSERT(call->ArgumentCount() == 2); 1145 ASSERT(call->ArgumentCount() == 2);
1129 Definition* left = call->ArgumentAt(0); 1146 Definition* left = call->ArgumentAt(0);
1130 Definition* right = call->ArgumentAt(1); 1147 Definition* right = call->ArgumentAt(1);
1131 // Type check left. 1148 // Type check left.
1132 AddCheckClass( 1149 AddCheckClass(
1133 left, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1150 left, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1134 call->deopt_id(), call->env(), call); 1151 call->deopt_id(), call->env(), call);
1135 // Type check right. 1152 // Type check right.
1136 AddCheckClass( 1153 AddCheckClass(
1137 right, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)), 1154 right, ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecksForArgNr(1)),
(...skipping 27 matching lines...) Expand all
1165 // inlining in FlowGraphInliner. 1182 // inlining in FlowGraphInliner.
1166 return false; 1183 return false;
1167 } 1184 }
1168 return InlineImplicitInstanceGetter(call); 1185 return InlineImplicitInstanceGetter(call);
1169 } 1186 }
1170 1187
1171 1188
1172 void AotOptimizer::ReplaceWithMathCFunction( 1189 void AotOptimizer::ReplaceWithMathCFunction(
1173 InstanceCallInstr* call, 1190 InstanceCallInstr* call,
1174 MethodRecognizer::Kind recognized_kind) { 1191 MethodRecognizer::Kind recognized_kind) {
1192 ASSERT(call->type_args_len() == 0);
1175 AddReceiverCheck(call); 1193 AddReceiverCheck(call);
1176 ZoneGrowableArray<Value*>* args = 1194 ZoneGrowableArray<Value*>* args =
1177 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 1195 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
1178 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 1196 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
1179 args->Add(new (Z) Value(call->ArgumentAt(i))); 1197 args->Add(new (Z) Value(call->ArgumentAt(i)));
1180 } 1198 }
1181 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr( 1199 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr(
1182 args, call->deopt_id(), recognized_kind, call->token_pos()); 1200 args, call->deopt_id(), recognized_kind, call->token_pos());
1183 ReplaceCall(call, invoke); 1201 ReplaceCall(call, invoke);
1184 } 1202 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 } 1463 }
1446 1464
1447 1465
1448 // TODO(srdjan): Use ICData to check if always true or false. 1466 // TODO(srdjan): Use ICData to check if always true or false.
1449 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { 1467 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
1450 ASSERT(Token::IsTypeTestOperator(call->token_kind())); 1468 ASSERT(Token::IsTypeTestOperator(call->token_kind()));
1451 Definition* left = call->ArgumentAt(0); 1469 Definition* left = call->ArgumentAt(0);
1452 Definition* instantiator_type_args = NULL; 1470 Definition* instantiator_type_args = NULL;
1453 Definition* function_type_args = NULL; 1471 Definition* function_type_args = NULL;
1454 AbstractType& type = AbstractType::ZoneHandle(Z); 1472 AbstractType& type = AbstractType::ZoneHandle(Z);
1473 ASSERT(call->type_args_len() == 0);
1455 if (call->ArgumentCount() == 2) { 1474 if (call->ArgumentCount() == 2) {
1456 instantiator_type_args = flow_graph()->constant_null(); 1475 instantiator_type_args = flow_graph()->constant_null();
1457 function_type_args = flow_graph()->constant_null(); 1476 function_type_args = flow_graph()->constant_null();
1458 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); 1477 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
1459 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); 1478 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
1460 } else { 1479 } else {
1461 instantiator_type_args = call->ArgumentAt(1); 1480 instantiator_type_args = call->ArgumentAt(1);
1462 function_type_args = call->ArgumentAt(2); 1481 function_type_args = call->ArgumentAt(2);
1463 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); 1482 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
1464 } 1483 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 args->Add(arg); 1527 args->Add(arg);
1509 1528
1510 const Library& dart_internal = 1529 const Library& dart_internal =
1511 Library::Handle(Z, Library::InternalLibrary()); 1530 Library::Handle(Z, Library::InternalLibrary());
1512 const String& target_name = Symbols::_classRangeCheck(); 1531 const String& target_name = Symbols::_classRangeCheck();
1513 const Function& target = Function::ZoneHandle( 1532 const Function& target = Function::ZoneHandle(
1514 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1533 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1515 ASSERT(!target.IsNull()); 1534 ASSERT(!target.IsNull());
1516 ASSERT(target.IsRecognized() && target.always_inline()); 1535 ASSERT(target.IsRecognized() && target.always_inline());
1517 1536
1537 const intptr_t kTypeArgsLen = 0;
1518 StaticCallInstr* new_call = 1538 StaticCallInstr* new_call =
1519 new (Z) StaticCallInstr(call->token_pos(), target, 1539 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1520 Object::null_array(), // argument_names 1540 Object::null_array(), // argument_names
1521 args, call->deopt_id()); 1541 args, call->deopt_id());
1522 Environment* copy = call->env()->DeepCopy( 1542 Environment* copy = call->env()->DeepCopy(
1523 Z, call->env()->Length() - call->ArgumentCount()); 1543 Z, call->env()->Length() - call->ArgumentCount());
1524 for (intptr_t i = 0; i < args->length(); ++i) { 1544 for (intptr_t i = 0; i < args->length(); ++i) {
1525 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1545 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1526 } 1546 }
1527 call->RemoveEnvironment(); 1547 call->RemoveEnvironment();
1528 ReplaceCall(call, new_call); 1548 ReplaceCall(call, new_call);
1529 copy->DeepCopyTo(Z, new_call); 1549 copy->DeepCopyTo(Z, new_call);
(...skipping 27 matching lines...) Expand all
1557 call->token_pos(), new (Z) Value(left), 1577 call->token_pos(), new (Z) Value(left),
1558 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args), 1578 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
1559 type, call->deopt_id()); 1579 type, call->deopt_id());
1560 ReplaceCall(call, instance_of); 1580 ReplaceCall(call, instance_of);
1561 } 1581 }
1562 1582
1563 1583
1564 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). 1584 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
1565 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 1585 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
1566 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 1586 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
1587 ASSERT(call->type_args_len() == 0);
1567 Definition* left = call->ArgumentAt(0); 1588 Definition* left = call->ArgumentAt(0);
1568 Definition* instantiator_type_args = call->ArgumentAt(1); 1589 Definition* instantiator_type_args = call->ArgumentAt(1);
1569 Definition* function_type_args = call->ArgumentAt(2); 1590 Definition* function_type_args = call->ArgumentAt(2);
1570 const AbstractType& type = 1591 const AbstractType& type =
1571 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 1592 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
1572 ASSERT(!type.IsMalformedOrMalbounded()); 1593 ASSERT(!type.IsMalformedOrMalbounded());
1573 1594
1574 if (TypeCheckAsClassEquality(type)) { 1595 if (TypeCheckAsClassEquality(type)) {
1575 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); 1596 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
1576 InsertBefore(call, left_cid, NULL, FlowGraph::kValue); 1597 InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
(...skipping 23 matching lines...) Expand all
1600 args->Add(arg); 1621 args->Add(arg);
1601 1622
1602 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1623 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1603 const String& target_name = Symbols::_classIdEqualsAssert(); 1624 const String& target_name = Symbols::_classIdEqualsAssert();
1604 const Function& target = Function::ZoneHandle( 1625 const Function& target = Function::ZoneHandle(
1605 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1626 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1606 ASSERT(!target.IsNull()); 1627 ASSERT(!target.IsNull());
1607 ASSERT(target.IsRecognized()); 1628 ASSERT(target.IsRecognized());
1608 ASSERT(target.always_inline()); 1629 ASSERT(target.always_inline());
1609 1630
1631 const intptr_t kTypeArgsLen = 0;
1610 StaticCallInstr* new_call = 1632 StaticCallInstr* new_call =
1611 new (Z) StaticCallInstr(call->token_pos(), target, 1633 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1612 Object::null_array(), // argument_names 1634 Object::null_array(), // argument_names
1613 args, call->deopt_id()); 1635 args, call->deopt_id());
1614 Environment* copy = 1636 Environment* copy =
1615 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); 1637 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
1616 for (intptr_t i = 0; i < args->length(); ++i) { 1638 for (intptr_t i = 0; i < args->length(); ++i) {
1617 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1639 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1618 } 1640 }
1619 call->RemoveEnvironment(); 1641 call->RemoveEnvironment();
1620 ReplaceCall(call, new_call); 1642 ReplaceCall(call, new_call);
1621 copy->DeepCopyTo(Z, new_call); 1643 copy->DeepCopyTo(Z, new_call);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 args->Add(arg); 1685 args->Add(arg);
1664 1686
1665 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1687 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1666 const String& target_name = Symbols::_classRangeAssert(); 1688 const String& target_name = Symbols::_classRangeAssert();
1667 const Function& target = Function::ZoneHandle( 1689 const Function& target = Function::ZoneHandle(
1668 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1690 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1669 ASSERT(!target.IsNull()); 1691 ASSERT(!target.IsNull());
1670 ASSERT(target.IsRecognized()); 1692 ASSERT(target.IsRecognized());
1671 ASSERT(target.always_inline()); 1693 ASSERT(target.always_inline());
1672 1694
1695 const intptr_t kTypeArgsLen = 0;
1673 StaticCallInstr* new_call = 1696 StaticCallInstr* new_call =
1674 new (Z) StaticCallInstr(call->token_pos(), target, 1697 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1675 Object::null_array(), // argument_names 1698 Object::null_array(), // argument_names
1676 args, call->deopt_id()); 1699 args, call->deopt_id());
1677 Environment* copy = call->env()->DeepCopy( 1700 Environment* copy = call->env()->DeepCopy(
1678 Z, call->env()->Length() - call->ArgumentCount()); 1701 Z, call->env()->Length() - call->ArgumentCount());
1679 for (intptr_t i = 0; i < args->length(); ++i) { 1702 for (intptr_t i = 0; i < args->length(); ++i) {
1680 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1703 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1681 } 1704 }
1682 call->RemoveEnvironment(); 1705 call->RemoveEnvironment();
1683 ReplaceCall(call, new_call); 1706 ReplaceCall(call, new_call);
1684 copy->DeepCopyTo(Z, new_call); 1707 copy->DeepCopyTo(Z, new_call);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) { 1747 bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
1725 if (!use_speculative_inlining_) return false; 1748 if (!use_speculative_inlining_) return false;
1726 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { 1749 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
1727 if ((*inlining_black_list_)[i] == call_deopt_id) return false; 1750 if ((*inlining_black_list_)[i] == call_deopt_id) return false;
1728 } 1751 }
1729 return true; 1752 return true;
1730 } 1753 }
1731 1754
1732 1755
1733 static bool HasLikelySmiOperand(InstanceCallInstr* instr) { 1756 static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
1757 if (instr->type_args_len() > 0) {
1758 return false; // TODO(regis): Is it even possible? Replace with assert.
1759 }
1734 // Phis with at least one known smi are // guessed to be likely smi as well. 1760 // Phis with at least one known smi are // guessed to be likely smi as well.
1735 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) { 1761 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
1736 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi(); 1762 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi();
1737 if (phi != NULL) { 1763 if (phi != NULL) {
1738 for (intptr_t j = 0; j < phi->InputCount(); ++j) { 1764 for (intptr_t j = 0; j < phi->InputCount(); ++j) {
1739 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true; 1765 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true;
1740 } 1766 }
1741 } 1767 }
1742 } 1768 }
1743 // If all of the inputs are known smis or the result of CheckedSmiOp, 1769 // If all of the inputs are known smis or the result of CheckedSmiOp,
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 break; 1920 break;
1895 } 1921 }
1896 1922
1897 // No IC data checks. Try resolve target using the propagated cid. 1923 // No IC data checks. Try resolve target using the propagated cid.
1898 const intptr_t receiver_cid = 1924 const intptr_t receiver_cid =
1899 instr->PushArgumentAt(0)->value()->Type()->ToCid(); 1925 instr->PushArgumentAt(0)->value()->Type()->ToCid();
1900 if (receiver_cid != kDynamicCid) { 1926 if (receiver_cid != kDynamicCid) {
1901 const Class& receiver_class = 1927 const Class& receiver_class =
1902 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 1928 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
1903 1929
1904 const Array& args_desc_array = 1930 ArgumentsDescriptor args_desc(instr->GetArgumentsDescriptor(Z));
1905 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(),
1906 instr->argument_names()));
1907 ArgumentsDescriptor args_desc(args_desc_array);
1908 Function& function = Function::Handle( 1931 Function& function = Function::Handle(
1909 Z, Resolver::ResolveDynamicForReceiverClass( 1932 Z, Resolver::ResolveDynamicForReceiverClass(
1910 receiver_class, instr->function_name(), args_desc)); 1933 receiver_class, instr->function_name(), args_desc));
1911 if (!function.IsNull()) { 1934 if (!function.IsNull()) {
1912 CallTargets* targets = new (Z) CallTargets(); 1935 CallTargets* targets = new (Z) CallTargets();
1913 Function& target = Function::ZoneHandle(Z, function.raw()); 1936 Function& target = Function::ZoneHandle(Z, function.raw());
1914 targets->Add(CidRangeTarget(receiver_class.id(), receiver_class.id(), 1937 targets->Add(CidRangeTarget(receiver_class.id(), receiver_class.id(),
1915 &target, /*count = */ 1)); 1938 &target, /*count = */ 1));
1916 PolymorphicInstanceCallInstr* call = 1939 PolymorphicInstanceCallInstr* call =
1917 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 1940 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
(...skipping 26 matching lines...) Expand all
1944 if (!receiver_class.IsNull()) { 1967 if (!receiver_class.IsNull()) {
1945 GrowableArray<intptr_t> class_ids(6); 1968 GrowableArray<intptr_t> class_ids(6);
1946 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { 1969 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
1947 // First check if all subclasses end up calling the same method. 1970 // First check if all subclasses end up calling the same method.
1948 // If this is the case we will replace instance call with a direct 1971 // If this is the case we will replace instance call with a direct
1949 // static call. 1972 // static call.
1950 // Otherwise we will try to create ICData that contains all possible 1973 // Otherwise we will try to create ICData that contains all possible
1951 // targets with appropriate checks. 1974 // targets with appropriate checks.
1952 Function& single_target = Function::Handle(Z); 1975 Function& single_target = Function::Handle(Z);
1953 ICData& ic_data = ICData::Handle(Z); 1976 ICData& ic_data = ICData::Handle(Z);
1954 1977 const Array& args_desc_array = instr->GetArgumentsDescriptor(Z);
1955 const Array& args_desc_array =
1956 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(),
1957 instr->argument_names()));
1958 ArgumentsDescriptor args_desc(args_desc_array); 1978 ArgumentsDescriptor args_desc(args_desc_array);
1959
1960 Function& target = Function::Handle(Z); 1979 Function& target = Function::Handle(Z);
1961 Class& cls = Class::Handle(Z); 1980 Class& cls = Class::Handle(Z);
1962 for (intptr_t i = 0; i < class_ids.length(); i++) { 1981 for (intptr_t i = 0; i < class_ids.length(); i++) {
1963 const intptr_t cid = class_ids[i]; 1982 const intptr_t cid = class_ids[i];
1964 cls = isolate()->class_table()->At(cid); 1983 cls = isolate()->class_table()->At(cid);
1965 target = Resolver::ResolveDynamicForReceiverClass( 1984 target = Resolver::ResolveDynamicForReceiverClass(
1966 cls, instr->function_name(), args_desc); 1985 cls, instr->function_name(), args_desc);
1967 1986
1968 if (target.IsNull()) { 1987 if (target.IsNull()) {
1969 // Can't resolve the target. It might be a noSuchMethod, 1988 // Can't resolve the target. It might be a noSuchMethod,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2025 2044
2026 // We have computed that there is only a single target for this call 2045 // We have computed that there is only a single target for this call
2027 // within the whole hierarchy. Replace InstanceCall with StaticCall. 2046 // within the whole hierarchy. Replace InstanceCall with StaticCall.
2028 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z) 2047 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z)
2029 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount()); 2048 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount());
2030 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { 2049 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
2031 args->Add(instr->PushArgumentAt(i)); 2050 args->Add(instr->PushArgumentAt(i));
2032 } 2051 }
2033 StaticCallInstr* call = new (Z) StaticCallInstr( 2052 StaticCallInstr* call = new (Z) StaticCallInstr(
2034 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), 2053 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()),
2035 instr->argument_names(), args, instr->deopt_id()); 2054 instr->type_args_len(), instr->argument_names(), args,
2055 instr->deopt_id());
2036 instr->ReplaceWith(call, current_iterator()); 2056 instr->ReplaceWith(call, current_iterator());
2037 return; 2057 return;
2038 } else if ((ic_data.raw() != ICData::null()) && 2058 } else if ((ic_data.raw() != ICData::null()) &&
2039 !ic_data.NumberOfChecksIs(0)) { 2059 !ic_data.NumberOfChecksIs(0)) {
2040 CallTargets* targets = CallTargets::Create(Z, ic_data); 2060 CallTargets* targets = CallTargets::Create(Z, ic_data);
2041 PolymorphicInstanceCallInstr* call = 2061 PolymorphicInstanceCallInstr* call =
2042 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 2062 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
2043 /* with_checks = */ true, 2063 /* with_checks = */ true,
2044 /* complete = */ true); 2064 /* complete = */ true);
2045 instr->ReplaceWith(call, current_iterator()); 2065 instr->ReplaceWith(call, current_iterator());
(...skipping 20 matching lines...) Expand all
2066 2086
2067 2087
2068 void AotOptimizer::VisitPolymorphicInstanceCall( 2088 void AotOptimizer::VisitPolymorphicInstanceCall(
2069 PolymorphicInstanceCallInstr* call) { 2089 PolymorphicInstanceCallInstr* call) {
2070 if (call->with_checks()) { 2090 if (call->with_checks()) {
2071 const intptr_t receiver_cid = 2091 const intptr_t receiver_cid =
2072 call->PushArgumentAt(0)->value()->Type()->ToCid(); 2092 call->PushArgumentAt(0)->value()->Type()->ToCid();
2073 if (receiver_cid != kDynamicCid) { 2093 if (receiver_cid != kDynamicCid) {
2074 const Class& receiver_class = 2094 const Class& receiver_class =
2075 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 2095 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
2076 2096 ArgumentsDescriptor args_desc(
2077 const Array& args_desc_array = Array::Handle( 2097 call->instance_call()->GetArgumentsDescriptor(Z));
2078 Z, ArgumentsDescriptor::New(call->ArgumentCount(),
2079 call->instance_call()->argument_names()));
2080 ArgumentsDescriptor args_desc(args_desc_array);
2081 const Function& function = Function::Handle( 2098 const Function& function = Function::Handle(
2082 Z, Resolver::ResolveDynamicForReceiverClass( 2099 Z, Resolver::ResolveDynamicForReceiverClass(
2083 receiver_class, call->instance_call()->function_name(), 2100 receiver_class, call->instance_call()->function_name(),
2084 args_desc)); 2101 args_desc));
2085 if (!function.IsNull()) { 2102 if (!function.IsNull()) {
2086 call->set_with_checks(false); 2103 call->set_with_checks(false);
2087 } 2104 }
2088 } 2105 }
2089 } 2106 }
2090 } 2107 }
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2255 FlowGraph::kEffect); 2272 FlowGraph::kEffect);
2256 current_iterator()->RemoveCurrentFromGraph(); 2273 current_iterator()->RemoveCurrentFromGraph();
2257 } 2274 }
2258 } 2275 }
2259 } 2276 }
2260 } 2277 }
2261 2278
2262 #endif // DART_PRECOMPILER 2279 #endif // DART_PRECOMPILER
2263 2280
2264 } // namespace dart 2281 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698