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

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: fix dartk and sync 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 =
Vyacheslav Egorov (Google) 2017/05/13 22:20:13 This pattern is repeated - maybe call instruction
regis 2017/05/18 21:02:12 Done.
117 Z, 117 Array::Handle(Z, call->GetArgumentsDescriptor());
118 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
119 ArgumentsDescriptor args_desc(args_desc_array); 118 ArgumentsDescriptor args_desc(args_desc_array);
120 const Function& function = 119 const Function& function =
121 Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass( 120 Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass(
122 cls, call->function_name(), args_desc)); 121 cls, call->function_name(), args_desc));
123 ASSERT(!function.IsNull()); 122 ASSERT(!function.IsNull());
124 123 const intptr_t kTypeArgsLen = 0;
124 ASSERT(call->type_args_len() == kTypeArgsLen);
125 ZoneGrowableArray<PushArgumentInstr*>* args = 125 ZoneGrowableArray<PushArgumentInstr*>* args =
126 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount()); 126 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount());
127 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 127 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
128 args->Add(call->PushArgumentAt(i)); 128 args->Add(call->PushArgumentAt(i));
129 } 129 }
130 StaticCallInstr* static_call = new (Z) StaticCallInstr( 130 StaticCallInstr* static_call = new (Z) StaticCallInstr(
131 call->token_pos(), Function::ZoneHandle(Z, function.raw()), 131 call->token_pos(), Function::ZoneHandle(Z, function.raw()), kTypeArgsLen,
132 call->argument_names(), args, call->deopt_id()); 132 call->argument_names(), args, call->deopt_id());
133 static_call->set_result_cid(kTypeCid); 133 static_call->set_result_cid(kTypeCid);
134 call->ReplaceWith(static_call, current_iterator()); 134 call->ReplaceWith(static_call, current_iterator());
135 return true; 135 return true;
136 } 136 }
137 137
138 138
139 // Optimize instance calls using cid. This is called after optimizer 139 // Optimize instance calls using cid. This is called after optimizer
140 // converted instance calls to instructions. Any remaining 140 // converted instance calls to instructions. Any remaining
141 // instance calls are either megamorphic calls, cannot be optimized or 141 // instance calls are either megamorphic calls, cannot be optimized or
(...skipping 29 matching lines...) Expand all
171 171
172 172
173 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { 173 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
174 ASSERT(call->HasICData()); 174 ASSERT(call->HasICData());
175 if (call->ic_data()->NumberOfUsedChecks() > 0) { 175 if (call->ic_data()->NumberOfUsedChecks() > 0) {
176 // This occurs when an instance call has too many checks, will be converted 176 // This occurs when an instance call has too many checks, will be converted
177 // to megamorphic call. 177 // to megamorphic call.
178 return false; 178 return false;
179 } 179 }
180 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); 180 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
181 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); 181 const intptr_t receiver_idx = call->FirstParamIndex();
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 22 matching lines...) Expand all
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 =
226 Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(), 229 Array::Handle(Z, call->GetArgumentsDescriptor());
227 call->argument_names()));
228 ArgumentsDescriptor args_desc(args_desc_array); 230 ArgumentsDescriptor args_desc(args_desc_array);
229 const Function& function = Function::Handle( 231 const Function& function = Function::Handle(
230 Z, Resolver::ResolveDynamicForReceiverClass( 232 Z, Resolver::ResolveDynamicForReceiverClass(
231 receiver_class, call->function_name(), args_desc)); 233 receiver_class, call->function_name(), args_desc));
232 if (function.IsNull()) { 234 if (function.IsNull()) {
233 return false; 235 return false;
234 } 236 }
235 237
236 // Create new ICData, do not modify the one attached to the instruction 238 // Create new ICData, do not modify the one attached to the instruction
237 // since it is attached to the assembly instruction itself. 239 // since it is attached to the assembly instruction itself.
238 // TODO(srdjan): Prevent modification of ICData object that is 240 // TODO(srdjan): Prevent modification of ICData object that is
239 // referenced in assembly code. 241 // referenced in assembly code.
240 const ICData& ic_data = ICData::ZoneHandle( 242 const ICData& ic_data = ICData::ZoneHandle(
241 Z, ICData::NewFrom(*call->ic_data(), class_ids.length())); 243 Z, ICData::NewFrom(*call->ic_data(), class_ids.length()));
242 if (class_ids.length() > 1) { 244 if (class_ids.length() > 1) {
243 ic_data.AddCheck(class_ids, function); 245 ic_data.AddCheck(class_ids, function);
244 } else { 246 } else {
245 ASSERT(class_ids.length() == 1); 247 ASSERT(class_ids.length() == 1);
246 ic_data.AddReceiverCheck(class_ids[0], function); 248 ic_data.AddReceiverCheck(class_ids[0], function);
247 } 249 }
248 call->set_ic_data(&ic_data); 250 call->set_ic_data(&ic_data);
249 return true; 251 return true;
250 } 252 }
251 253
252 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { 254 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
253 // Check if the target is unique. 255 // Check if the target is unique.
254 Function& target_function = Function::Handle(Z); 256 Function& target_function = Function::Handle(Z);
255 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); 257 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
256 // Calls with named arguments must be resolved/checked at runtime. 258 // Calls passing named arguments and calls to a function taking named
259 // arguments must be resolved/checked at runtime.
260 // Calls passing a type argument vector and calls to a generic function must
261 // be resolved/checked at runtime.
257 if (!target_function.IsNull() && 262 if (!target_function.IsNull() &&
258 !target_function.HasOptionalNamedParameters() && 263 !target_function.HasOptionalNamedParameters() &&
259 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, 264 !target_function.IsGeneric() &&
260 /* error_message = */ NULL)) { 265 target_function.AreValidArgumentCounts(
266 call->type_args_len(), call->ArgumentCountWithoutTypeArgs(),
267 call->argument_names().IsNull() ? 0
268 : call->argument_names().Length(),
269 /* error_message = */ NULL)) {
261 const Class& cls = Class::Handle(Z, target_function.Owner()); 270 const Class& cls = Class::Handle(Z, target_function.Owner());
262 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) { 271 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
263 const ICData& ic_data = 272 const ICData& ic_data =
264 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1)); 273 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1));
265 ic_data.AddReceiverCheck(cls.id(), target_function); 274 ic_data.AddReceiverCheck(cls.id(), target_function);
266 call->set_ic_data(&ic_data); 275 call->set_ic_data(&ic_data);
267 if (has_unique_no_such_method_) { 276 if (has_unique_no_such_method_) {
268 call->set_has_unique_selector(true); 277 call->set_has_unique_selector(true);
269 // Add redefinition of the receiver to prevent code motion across 278 // Add redefinition of the receiver to prevent code motion across
270 // this call. 279 // this call.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 } 615 }
607 616
608 617
609 // Recognize a.runtimeType == b.runtimeType and fold it into 618 // Recognize a.runtimeType == b.runtimeType and fold it into
610 // Object._haveSameRuntimeType(a, b). 619 // Object._haveSameRuntimeType(a, b).
611 // Note: this optimization is not speculative. 620 // Note: this optimization is not speculative.
612 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) { 621 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
613 const ICData& ic_data = *call->ic_data(); 622 const ICData& ic_data = *call->ic_data();
614 ASSERT(ic_data.NumArgsTested() == 2); 623 ASSERT(ic_data.NumArgsTested() == 2);
615 624
625 ASSERT(call->type_args_len() == 0);
616 ASSERT(call->ArgumentCount() == 2); 626 ASSERT(call->ArgumentCount() == 2);
617 Definition* left = call->ArgumentAt(0); 627 Definition* left = call->ArgumentAt(0);
618 Definition* right = call->ArgumentAt(1); 628 Definition* right = call->ArgumentAt(1);
619 629
620 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() && 630 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
621 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) { 631 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
622 const Class& cls = Class::Handle(Z, I->object_store()->object_class()); 632 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
623 const Function& have_same_runtime_type = Function::ZoneHandle( 633 const Function& have_same_runtime_type = Function::ZoneHandle(
624 Z, 634 Z,
625 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); 635 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
626 ASSERT(!have_same_runtime_type.IsNull()); 636 ASSERT(!have_same_runtime_type.IsNull());
627 637
628 ZoneGrowableArray<PushArgumentInstr*>* args = 638 ZoneGrowableArray<PushArgumentInstr*>* args =
629 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); 639 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
630 PushArgumentInstr* arg = 640 PushArgumentInstr* arg =
631 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0))); 641 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0)));
632 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 642 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
633 args->Add(arg); 643 args->Add(arg);
634 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0))); 644 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0)));
635 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 645 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
636 args->Add(arg); 646 args->Add(arg);
637 StaticCallInstr* static_call = 647 const intptr_t kTypeArgsLen = 0;
638 new (Z) StaticCallInstr(call->token_pos(), have_same_runtime_type, 648 ASSERT(call->type_args_len() == kTypeArgsLen);
639 Object::null_array(), // argument_names 649 StaticCallInstr* static_call = new (Z)
640 args, call->deopt_id()); 650 StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen,
651 Object::null_array(), // argument_names
652 args, call->deopt_id());
641 static_call->set_result_cid(kBoolCid); 653 static_call->set_result_cid(kBoolCid);
642 ReplaceCall(call, static_call); 654 ReplaceCall(call, static_call);
643 return true; 655 return true;
644 } 656 }
645 657
646 return false; 658 return false;
647 } 659 }
648 660
649 661
650 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 662 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
651 Token::Kind op_kind) { 663 Token::Kind op_kind) {
652 const ICData& ic_data = *call->ic_data(); 664 const ICData& ic_data = *call->ic_data();
653 ASSERT(ic_data.NumArgsTested() == 2); 665 ASSERT(ic_data.NumArgsTested() == 2);
654 666
667 ASSERT(call->type_args_len() == 0);
655 ASSERT(call->ArgumentCount() == 2); 668 ASSERT(call->ArgumentCount() == 2);
656 Definition* const left = call->ArgumentAt(0); 669 Definition* const left = call->ArgumentAt(0);
657 Definition* const right = call->ArgumentAt(1); 670 Definition* const right = call->ArgumentAt(1);
658 671
659 intptr_t cid = kIllegalCid; 672 intptr_t cid = kIllegalCid;
660 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 673 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
661 return TryStringLengthOneEquality(call, op_kind); 674 return TryStringLengthOneEquality(call, op_kind);
662 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 675 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
663 InsertBefore(call, 676 InsertBefore(call,
664 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 677 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 ReplaceCall(call, comp); 740 ReplaceCall(call, comp);
728 return true; 741 return true;
729 } 742 }
730 743
731 744
732 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 745 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
733 Token::Kind op_kind) { 746 Token::Kind op_kind) {
734 const ICData& ic_data = *call->ic_data(); 747 const ICData& ic_data = *call->ic_data();
735 ASSERT(ic_data.NumArgsTested() == 2); 748 ASSERT(ic_data.NumArgsTested() == 2);
736 749
750 ASSERT(call->type_args_len() == 0);
737 ASSERT(call->ArgumentCount() == 2); 751 ASSERT(call->ArgumentCount() == 2);
738 Definition* left = call->ArgumentAt(0); 752 Definition* left = call->ArgumentAt(0);
739 Definition* right = call->ArgumentAt(1); 753 Definition* right = call->ArgumentAt(1);
740 754
741 intptr_t cid = kIllegalCid; 755 intptr_t cid = kIllegalCid;
742 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 756 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
743 InsertBefore(call, 757 InsertBefore(call,
744 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 758 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
745 call->token_pos()), 759 call->token_pos()),
746 call->env(), FlowGraph::kEffect); 760 call->env(), FlowGraph::kEffect);
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 } 890 }
877 operands_type = kSmiCid; 891 operands_type = kSmiCid;
878 } else { 892 } else {
879 return false; 893 return false;
880 } 894 }
881 break; 895 break;
882 default: 896 default:
883 UNREACHABLE(); 897 UNREACHABLE();
884 } 898 }
885 899
900 ASSERT(call->type_args_len() == 0);
886 ASSERT(call->ArgumentCount() == 2); 901 ASSERT(call->ArgumentCount() == 2);
887 Definition* left = call->ArgumentAt(0); 902 Definition* left = call->ArgumentAt(0);
888 Definition* right = call->ArgumentAt(1); 903 Definition* right = call->ArgumentAt(1);
889 if (operands_type == kDoubleCid) { 904 if (operands_type == kDoubleCid) {
890 if (!CanUnboxDouble()) { 905 if (!CanUnboxDouble()) {
891 return false; 906 return false;
892 } 907 }
893 // Check that either left or right are not a smi. Result of a 908 // Check that either left or right are not a smi. Result of a
894 // binary operation with two smis is a smi not a double, except '/' which 909 // binary operation with two smis is a smi not a double, except '/' which
895 // returns a double for two smis. 910 // returns a double for two smis.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 BinarySmiOpInstr* bin_op = new (Z) BinarySmiOpInstr( 979 BinarySmiOpInstr* bin_op = new (Z) BinarySmiOpInstr(
965 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 980 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
966 ReplaceCall(call, bin_op); 981 ReplaceCall(call, bin_op);
967 } 982 }
968 return true; 983 return true;
969 } 984 }
970 985
971 986
972 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 987 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
973 Token::Kind op_kind) { 988 Token::Kind op_kind) {
989 ASSERT(call->type_args_len() == 0);
974 ASSERT(call->ArgumentCount() == 1); 990 ASSERT(call->ArgumentCount() == 1);
975 Definition* input = call->ArgumentAt(0); 991 Definition* input = call->ArgumentAt(0);
976 Definition* unary_op = NULL; 992 Definition* unary_op = NULL;
977 if (HasOnlyOneSmi(*call->ic_data())) { 993 if (HasOnlyOneSmi(*call->ic_data())) {
978 InsertBefore(call, 994 InsertBefore(call,
979 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(), 995 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(),
980 call->token_pos()), 996 call->token_pos()),
981 call->env(), FlowGraph::kEffect); 997 call->env(), FlowGraph::kEffect);
982 unary_op = new (Z) 998 unary_op = new (Z)
983 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); 999 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 } 1066 }
1051 return true; 1067 return true;
1052 } 1068 }
1053 1069
1054 1070
1055 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 1071 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1056 Token::Kind op_kind) { 1072 Token::Kind op_kind) {
1057 if (!ShouldInlineSimd()) { 1073 if (!ShouldInlineSimd()) {
1058 return false; 1074 return false;
1059 } 1075 }
1076 ASSERT(call->type_args_len() == 0);
1060 ASSERT(call->ArgumentCount() == 2); 1077 ASSERT(call->ArgumentCount() == 2);
1061 Definition* const left = call->ArgumentAt(0); 1078 Definition* const left = call->ArgumentAt(0);
1062 Definition* const right = call->ArgumentAt(1); 1079 Definition* const right = call->ArgumentAt(1);
1063 // Type check left and right. 1080 // Type check left and right.
1064 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1081 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1065 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1082 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1066 // Replace call. 1083 // Replace call.
1067 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( 1084 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr(
1068 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1085 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1069 ReplaceCall(call, float32x4_bin_op); 1086 ReplaceCall(call, float32x4_bin_op);
1070 1087
1071 return true; 1088 return true;
1072 } 1089 }
1073 1090
1074 1091
1075 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, 1092 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
1076 Token::Kind op_kind) { 1093 Token::Kind op_kind) {
1077 if (!ShouldInlineSimd()) { 1094 if (!ShouldInlineSimd()) {
1078 return false; 1095 return false;
1079 } 1096 }
1097 ASSERT(call->type_args_len() == 0);
1080 ASSERT(call->ArgumentCount() == 2); 1098 ASSERT(call->ArgumentCount() == 2);
1081 Definition* const left = call->ArgumentAt(0); 1099 Definition* const left = call->ArgumentAt(0);
1082 Definition* const right = call->ArgumentAt(1); 1100 Definition* const right = call->ArgumentAt(1);
1083 // Type check left and right. 1101 // Type check left and right.
1084 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1102 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1085 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1103 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1086 // Replace call. 1104 // Replace call.
1087 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( 1105 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr(
1088 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1106 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1089 ReplaceCall(call, int32x4_bin_op); 1107 ReplaceCall(call, int32x4_bin_op);
1090 return true; 1108 return true;
1091 } 1109 }
1092 1110
1093 1111
1094 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, 1112 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
1095 Token::Kind op_kind) { 1113 Token::Kind op_kind) {
1096 if (!ShouldInlineSimd()) { 1114 if (!ShouldInlineSimd()) {
1097 return false; 1115 return false;
1098 } 1116 }
1117 ASSERT(call->type_args_len() == 0);
1099 ASSERT(call->ArgumentCount() == 2); 1118 ASSERT(call->ArgumentCount() == 2);
1100 Definition* const left = call->ArgumentAt(0); 1119 Definition* const left = call->ArgumentAt(0);
1101 Definition* const right = call->ArgumentAt(1); 1120 Definition* const right = call->ArgumentAt(1);
1102 // Type check left and right. 1121 // Type check left and right.
1103 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1122 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1104 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1123 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1105 // Replace call. 1124 // Replace call.
1106 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( 1125 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr(
1107 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1126 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1108 ReplaceCall(call, float64x2_bin_op); 1127 ReplaceCall(call, float64x2_bin_op);
(...skipping 22 matching lines...) Expand all
1131 // inlining in FlowGraphInliner. 1150 // inlining in FlowGraphInliner.
1132 return false; 1151 return false;
1133 } 1152 }
1134 return InlineImplicitInstanceGetter(call); 1153 return InlineImplicitInstanceGetter(call);
1135 } 1154 }
1136 1155
1137 1156
1138 void AotOptimizer::ReplaceWithMathCFunction( 1157 void AotOptimizer::ReplaceWithMathCFunction(
1139 InstanceCallInstr* call, 1158 InstanceCallInstr* call,
1140 MethodRecognizer::Kind recognized_kind) { 1159 MethodRecognizer::Kind recognized_kind) {
1160 ASSERT(call->type_args_len() == 0);
1141 AddReceiverCheck(call); 1161 AddReceiverCheck(call);
1142 ZoneGrowableArray<Value*>* args = 1162 ZoneGrowableArray<Value*>* args =
1143 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 1163 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
1144 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 1164 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
1145 args->Add(new (Z) Value(call->ArgumentAt(i))); 1165 args->Add(new (Z) Value(call->ArgumentAt(i)));
1146 } 1166 }
1147 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr( 1167 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr(
1148 args, call->deopt_id(), recognized_kind, call->token_pos()); 1168 args, call->deopt_id(), recognized_kind, call->token_pos());
1149 ReplaceCall(call, invoke); 1169 ReplaceCall(call, invoke);
1150 } 1170 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 } 1431 }
1412 1432
1413 1433
1414 // TODO(srdjan): Use ICData to check if always true or false. 1434 // TODO(srdjan): Use ICData to check if always true or false.
1415 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { 1435 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
1416 ASSERT(Token::IsTypeTestOperator(call->token_kind())); 1436 ASSERT(Token::IsTypeTestOperator(call->token_kind()));
1417 Definition* left = call->ArgumentAt(0); 1437 Definition* left = call->ArgumentAt(0);
1418 Definition* instantiator_type_args = NULL; 1438 Definition* instantiator_type_args = NULL;
1419 Definition* function_type_args = NULL; 1439 Definition* function_type_args = NULL;
1420 AbstractType& type = AbstractType::ZoneHandle(Z); 1440 AbstractType& type = AbstractType::ZoneHandle(Z);
1441 ASSERT(call->type_args_len() == 0);
1421 if (call->ArgumentCount() == 2) { 1442 if (call->ArgumentCount() == 2) {
1422 instantiator_type_args = flow_graph()->constant_null(); 1443 instantiator_type_args = flow_graph()->constant_null();
1423 function_type_args = flow_graph()->constant_null(); 1444 function_type_args = flow_graph()->constant_null();
1424 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); 1445 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
1425 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); 1446 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
1426 } else { 1447 } else {
1427 instantiator_type_args = call->ArgumentAt(1); 1448 instantiator_type_args = call->ArgumentAt(1);
1428 function_type_args = call->ArgumentAt(2); 1449 function_type_args = call->ArgumentAt(2);
1429 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); 1450 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
1430 } 1451 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 args->Add(arg); 1495 args->Add(arg);
1475 1496
1476 const Library& dart_internal = 1497 const Library& dart_internal =
1477 Library::Handle(Z, Library::InternalLibrary()); 1498 Library::Handle(Z, Library::InternalLibrary());
1478 const String& target_name = Symbols::_classRangeCheck(); 1499 const String& target_name = Symbols::_classRangeCheck();
1479 const Function& target = Function::ZoneHandle( 1500 const Function& target = Function::ZoneHandle(
1480 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1501 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1481 ASSERT(!target.IsNull()); 1502 ASSERT(!target.IsNull());
1482 ASSERT(target.IsRecognized() && target.always_inline()); 1503 ASSERT(target.IsRecognized() && target.always_inline());
1483 1504
1505 const intptr_t kTypeArgsLen = 0;
1484 StaticCallInstr* new_call = 1506 StaticCallInstr* new_call =
1485 new (Z) StaticCallInstr(call->token_pos(), target, 1507 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1486 Object::null_array(), // argument_names 1508 Object::null_array(), // argument_names
1487 args, call->deopt_id()); 1509 args, call->deopt_id());
1488 Environment* copy = call->env()->DeepCopy( 1510 Environment* copy = call->env()->DeepCopy(
1489 Z, call->env()->Length() - call->ArgumentCount()); 1511 Z, call->env()->Length() - call->ArgumentCount());
1490 for (intptr_t i = 0; i < args->length(); ++i) { 1512 for (intptr_t i = 0; i < args->length(); ++i) {
1491 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1513 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1492 } 1514 }
1493 call->RemoveEnvironment(); 1515 call->RemoveEnvironment();
1494 ReplaceCall(call, new_call); 1516 ReplaceCall(call, new_call);
1495 copy->DeepCopyTo(Z, new_call); 1517 copy->DeepCopyTo(Z, new_call);
(...skipping 27 matching lines...) Expand all
1523 call->token_pos(), new (Z) Value(left), 1545 call->token_pos(), new (Z) Value(left),
1524 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args), 1546 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
1525 type, call->deopt_id()); 1547 type, call->deopt_id());
1526 ReplaceCall(call, instance_of); 1548 ReplaceCall(call, instance_of);
1527 } 1549 }
1528 1550
1529 1551
1530 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). 1552 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
1531 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 1553 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
1532 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 1554 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
1555 ASSERT(call->type_args_len() == 0);
1533 Definition* left = call->ArgumentAt(0); 1556 Definition* left = call->ArgumentAt(0);
1534 Definition* instantiator_type_args = call->ArgumentAt(1); 1557 Definition* instantiator_type_args = call->ArgumentAt(1);
1535 Definition* function_type_args = call->ArgumentAt(2); 1558 Definition* function_type_args = call->ArgumentAt(2);
1536 const AbstractType& type = 1559 const AbstractType& type =
1537 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 1560 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
1538 ASSERT(!type.IsMalformedOrMalbounded()); 1561 ASSERT(!type.IsMalformedOrMalbounded());
1539 1562
1540 if (TypeCheckAsClassEquality(type)) { 1563 if (TypeCheckAsClassEquality(type)) {
1541 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); 1564 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
1542 InsertBefore(call, left_cid, NULL, FlowGraph::kValue); 1565 InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
(...skipping 23 matching lines...) Expand all
1566 args->Add(arg); 1589 args->Add(arg);
1567 1590
1568 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1591 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1569 const String& target_name = Symbols::_classIdEqualsAssert(); 1592 const String& target_name = Symbols::_classIdEqualsAssert();
1570 const Function& target = Function::ZoneHandle( 1593 const Function& target = Function::ZoneHandle(
1571 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1594 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1572 ASSERT(!target.IsNull()); 1595 ASSERT(!target.IsNull());
1573 ASSERT(target.IsRecognized()); 1596 ASSERT(target.IsRecognized());
1574 ASSERT(target.always_inline()); 1597 ASSERT(target.always_inline());
1575 1598
1599 const intptr_t kTypeArgsLen = 0;
1576 StaticCallInstr* new_call = 1600 StaticCallInstr* new_call =
1577 new (Z) StaticCallInstr(call->token_pos(), target, 1601 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1578 Object::null_array(), // argument_names 1602 Object::null_array(), // argument_names
1579 args, call->deopt_id()); 1603 args, call->deopt_id());
1580 Environment* copy = 1604 Environment* copy =
1581 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); 1605 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
1582 for (intptr_t i = 0; i < args->length(); ++i) { 1606 for (intptr_t i = 0; i < args->length(); ++i) {
1583 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1607 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1584 } 1608 }
1585 call->RemoveEnvironment(); 1609 call->RemoveEnvironment();
1586 ReplaceCall(call, new_call); 1610 ReplaceCall(call, new_call);
1587 copy->DeepCopyTo(Z, new_call); 1611 copy->DeepCopyTo(Z, new_call);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 args->Add(arg); 1653 args->Add(arg);
1630 1654
1631 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1655 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1632 const String& target_name = Symbols::_classRangeAssert(); 1656 const String& target_name = Symbols::_classRangeAssert();
1633 const Function& target = Function::ZoneHandle( 1657 const Function& target = Function::ZoneHandle(
1634 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1658 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1635 ASSERT(!target.IsNull()); 1659 ASSERT(!target.IsNull());
1636 ASSERT(target.IsRecognized()); 1660 ASSERT(target.IsRecognized());
1637 ASSERT(target.always_inline()); 1661 ASSERT(target.always_inline());
1638 1662
1663 const intptr_t kTypeArgsLen = 0;
1639 StaticCallInstr* new_call = 1664 StaticCallInstr* new_call =
1640 new (Z) StaticCallInstr(call->token_pos(), target, 1665 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1641 Object::null_array(), // argument_names 1666 Object::null_array(), // argument_names
1642 args, call->deopt_id()); 1667 args, call->deopt_id());
1643 Environment* copy = call->env()->DeepCopy( 1668 Environment* copy = call->env()->DeepCopy(
1644 Z, call->env()->Length() - call->ArgumentCount()); 1669 Z, call->env()->Length() - call->ArgumentCount());
1645 for (intptr_t i = 0; i < args->length(); ++i) { 1670 for (intptr_t i = 0; i < args->length(); ++i) {
1646 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1671 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1647 } 1672 }
1648 call->RemoveEnvironment(); 1673 call->RemoveEnvironment();
1649 ReplaceCall(call, new_call); 1674 ReplaceCall(call, new_call);
1650 copy->DeepCopyTo(Z, new_call); 1675 copy->DeepCopyTo(Z, new_call);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1690 bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) { 1715 bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
1691 if (!use_speculative_inlining_) return false; 1716 if (!use_speculative_inlining_) return false;
1692 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { 1717 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
1693 if ((*inlining_black_list_)[i] == call_deopt_id) return false; 1718 if ((*inlining_black_list_)[i] == call_deopt_id) return false;
1694 } 1719 }
1695 return true; 1720 return true;
1696 } 1721 }
1697 1722
1698 1723
1699 static bool HasLikelySmiOperand(InstanceCallInstr* instr) { 1724 static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
1725 if (instr->type_args_len() > 0) {
Vyacheslav Egorov (Google) 2017/05/13 22:20:13 Should not be possible. These are operators, no wa
regis 2017/05/18 21:02:12 What I thought. Replaced by assert.
1726 return false; // TODO(regis): Is it even possible? Replace with assert.
1727 }
1700 // Phis with at least one known smi are // guessed to be likely smi as well. 1728 // Phis with at least one known smi are // guessed to be likely smi as well.
1701 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) { 1729 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
1702 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi(); 1730 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi();
1703 if (phi != NULL) { 1731 if (phi != NULL) {
1704 for (intptr_t j = 0; j < phi->InputCount(); ++j) { 1732 for (intptr_t j = 0; j < phi->InputCount(); ++j) {
1705 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true; 1733 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true;
1706 } 1734 }
1707 } 1735 }
1708 } 1736 }
1709 // If all of the inputs are known smis or the result of CheckedSmiOp, 1737 // If all of the inputs are known smis or the result of CheckedSmiOp,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 break; 1890 break;
1863 } 1891 }
1864 1892
1865 // No IC data checks. Try resolve target using the propagated cid. 1893 // No IC data checks. Try resolve target using the propagated cid.
1866 const intptr_t receiver_cid = 1894 const intptr_t receiver_cid =
1867 instr->PushArgumentAt(0)->value()->Type()->ToCid(); 1895 instr->PushArgumentAt(0)->value()->Type()->ToCid();
1868 if (receiver_cid != kDynamicCid) { 1896 if (receiver_cid != kDynamicCid) {
1869 const Class& receiver_class = 1897 const Class& receiver_class =
1870 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 1898 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
1871 1899
1872 const Array& args_desc_array = 1900 ArgumentsDescriptor args_desc(
1873 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), 1901 Array::Handle(Z, instr->GetArgumentsDescriptor()));
1874 instr->argument_names()));
1875 ArgumentsDescriptor args_desc(args_desc_array);
1876 Function& function = Function::Handle( 1902 Function& function = Function::Handle(
1877 Z, Resolver::ResolveDynamicForReceiverClass( 1903 Z, Resolver::ResolveDynamicForReceiverClass(
1878 receiver_class, instr->function_name(), args_desc)); 1904 receiver_class, instr->function_name(), args_desc));
1879 if (!function.IsNull()) { 1905 if (!function.IsNull()) {
1880 CallTargets* targets = new (Z) CallTargets(Z); 1906 CallTargets* targets = new (Z) CallTargets(Z);
1881 Function& target = Function::ZoneHandle(Z, function.raw()); 1907 Function& target = Function::ZoneHandle(Z, function.raw());
1882 targets->Add(new (Z) TargetInfo(receiver_class.id(), receiver_class.id(), 1908 targets->Add(new (Z) TargetInfo(receiver_class.id(), receiver_class.id(),
1883 &target, /*count = */ 1)); 1909 &target, /*count = */ 1));
1884 PolymorphicInstanceCallInstr* call = 1910 PolymorphicInstanceCallInstr* call =
1885 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 1911 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
(...skipping 26 matching lines...) Expand all
1912 if (!receiver_class.IsNull()) { 1938 if (!receiver_class.IsNull()) {
1913 GrowableArray<intptr_t> class_ids(6); 1939 GrowableArray<intptr_t> class_ids(6);
1914 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { 1940 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
1915 // First check if all subclasses end up calling the same method. 1941 // First check if all subclasses end up calling the same method.
1916 // If this is the case we will replace instance call with a direct 1942 // If this is the case we will replace instance call with a direct
1917 // static call. 1943 // static call.
1918 // Otherwise we will try to create ICData that contains all possible 1944 // Otherwise we will try to create ICData that contains all possible
1919 // targets with appropriate checks. 1945 // targets with appropriate checks.
1920 Function& single_target = Function::Handle(Z); 1946 Function& single_target = Function::Handle(Z);
1921 ICData& ic_data = ICData::Handle(Z); 1947 ICData& ic_data = ICData::Handle(Z);
1922
1923 const Array& args_desc_array = 1948 const Array& args_desc_array =
1924 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), 1949 Array::Handle(Z, instr->GetArgumentsDescriptor());
1925 instr->argument_names()));
1926 ArgumentsDescriptor args_desc(args_desc_array); 1950 ArgumentsDescriptor args_desc(args_desc_array);
1927
1928 Function& target = Function::Handle(Z); 1951 Function& target = Function::Handle(Z);
1929 Class& cls = Class::Handle(Z); 1952 Class& cls = Class::Handle(Z);
1930 for (intptr_t i = 0; i < class_ids.length(); i++) { 1953 for (intptr_t i = 0; i < class_ids.length(); i++) {
1931 const intptr_t cid = class_ids[i]; 1954 const intptr_t cid = class_ids[i];
1932 cls = isolate()->class_table()->At(cid); 1955 cls = isolate()->class_table()->At(cid);
1933 target = Resolver::ResolveDynamicForReceiverClass( 1956 target = Resolver::ResolveDynamicForReceiverClass(
1934 cls, instr->function_name(), args_desc); 1957 cls, instr->function_name(), args_desc);
1935 1958
1936 if (target.IsNull()) { 1959 if (target.IsNull()) {
1937 // Can't resolve the target. It might be a noSuchMethod, 1960 // Can't resolve the target. It might be a noSuchMethod,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 2016
1994 // We have computed that there is only a single target for this call 2017 // We have computed that there is only a single target for this call
1995 // within the whole hierarchy. Replace InstanceCall with StaticCall. 2018 // within the whole hierarchy. Replace InstanceCall with StaticCall.
1996 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z) 2019 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z)
1997 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount()); 2020 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount());
1998 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { 2021 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
1999 args->Add(instr->PushArgumentAt(i)); 2022 args->Add(instr->PushArgumentAt(i));
2000 } 2023 }
2001 StaticCallInstr* call = new (Z) StaticCallInstr( 2024 StaticCallInstr* call = new (Z) StaticCallInstr(
2002 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), 2025 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()),
2003 instr->argument_names(), args, instr->deopt_id()); 2026 instr->type_args_len(), instr->argument_names(), args,
2027 instr->deopt_id());
2004 instr->ReplaceWith(call, current_iterator()); 2028 instr->ReplaceWith(call, current_iterator());
2005 return; 2029 return;
2006 } else if ((ic_data.raw() != ICData::null()) && 2030 } else if ((ic_data.raw() != ICData::null()) &&
2007 !ic_data.NumberOfChecksIs(0)) { 2031 !ic_data.NumberOfChecksIs(0)) {
2008 CallTargets* targets = CallTargets::Create(Z, ic_data); 2032 CallTargets* targets = CallTargets::Create(Z, ic_data);
2009 PolymorphicInstanceCallInstr* call = 2033 PolymorphicInstanceCallInstr* call =
2010 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 2034 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
2011 /* with_checks = */ true, 2035 /* with_checks = */ true,
2012 /* complete = */ true); 2036 /* complete = */ true);
2013 instr->ReplaceWith(call, current_iterator()); 2037 instr->ReplaceWith(call, current_iterator());
(...skipping 20 matching lines...) Expand all
2034 2058
2035 2059
2036 void AotOptimizer::VisitPolymorphicInstanceCall( 2060 void AotOptimizer::VisitPolymorphicInstanceCall(
2037 PolymorphicInstanceCallInstr* call) { 2061 PolymorphicInstanceCallInstr* call) {
2038 if (call->with_checks()) { 2062 if (call->with_checks()) {
2039 const intptr_t receiver_cid = 2063 const intptr_t receiver_cid =
2040 call->PushArgumentAt(0)->value()->Type()->ToCid(); 2064 call->PushArgumentAt(0)->value()->Type()->ToCid();
2041 if (receiver_cid != kDynamicCid) { 2065 if (receiver_cid != kDynamicCid) {
2042 const Class& receiver_class = 2066 const Class& receiver_class =
2043 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 2067 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
2044 2068 ArgumentsDescriptor args_desc(
2045 const Array& args_desc_array = Array::Handle( 2069 Array::Handle(Z, call->instance_call()->GetArgumentsDescriptor()));
2046 Z, ArgumentsDescriptor::New(call->ArgumentCount(),
2047 call->instance_call()->argument_names()));
2048 ArgumentsDescriptor args_desc(args_desc_array);
2049 const Function& function = Function::Handle( 2070 const Function& function = Function::Handle(
2050 Z, Resolver::ResolveDynamicForReceiverClass( 2071 Z, Resolver::ResolveDynamicForReceiverClass(
2051 receiver_class, call->instance_call()->function_name(), 2072 receiver_class, call->instance_call()->function_name(),
2052 args_desc)); 2073 args_desc));
2053 if (!function.IsNull()) { 2074 if (!function.IsNull()) {
2054 call->set_with_checks(false); 2075 call->set_with_checks(false);
2055 } 2076 }
2056 } 2077 }
2057 } 2078 }
2058 } 2079 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 FlowGraph::kEffect); 2243 FlowGraph::kEffect);
2223 current_iterator()->RemoveCurrentFromGraph(); 2244 current_iterator()->RemoveCurrentFromGraph();
2224 } 2245 }
2225 } 2246 }
2226 } 2247 }
2227 } 2248 }
2228 2249
2229 #endif // DART_PRECOMPILER 2250 #endif // DART_PRECOMPILER
2230 2251
2231 } // namespace dart 2252 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698