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

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 review comments 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
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/assembler_dbc_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(
117 Z,
118 ArgumentsDescriptor::New(call->ArgumentCount(), call->argument_names()));
119 ArgumentsDescriptor args_desc(args_desc_array);
120 const Function& function = 116 const Function& function =
121 Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass( 117 Function::Handle(Z, call->ResolveForReceiverClass(cls));
122 cls, call->function_name(), args_desc));
123 ASSERT(!function.IsNull()); 118 ASSERT(!function.IsNull());
124 119 const intptr_t kTypeArgsLen = 0;
120 ASSERT(call->type_args_len() == kTypeArgsLen);
125 ZoneGrowableArray<PushArgumentInstr*>* args = 121 ZoneGrowableArray<PushArgumentInstr*>* args =
126 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount()); 122 new (Z) ZoneGrowableArray<PushArgumentInstr*>(call->ArgumentCount());
127 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 123 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
128 args->Add(call->PushArgumentAt(i)); 124 args->Add(call->PushArgumentAt(i));
129 } 125 }
130 StaticCallInstr* static_call = new (Z) StaticCallInstr( 126 StaticCallInstr* static_call = new (Z) StaticCallInstr(
131 call->token_pos(), Function::ZoneHandle(Z, function.raw()), 127 call->token_pos(), Function::ZoneHandle(Z, function.raw()), kTypeArgsLen,
132 call->argument_names(), args, call->deopt_id()); 128 call->argument_names(), args, call->deopt_id());
133 static_call->set_result_cid(kTypeCid); 129 static_call->set_result_cid(kTypeCid);
134 call->ReplaceWith(static_call, current_iterator()); 130 call->ReplaceWith(static_call, current_iterator());
135 return true; 131 return true;
136 } 132 }
137 133
138 134
139 // Optimize instance calls using cid. This is called after optimizer 135 // Optimize instance calls using cid. This is called after optimizer
140 // converted instance calls to instructions. Any remaining 136 // converted instance calls to instructions. Any remaining
141 // instance calls are either megamorphic calls, cannot be optimized or 137 // instance calls are either megamorphic calls, cannot be optimized or
(...skipping 29 matching lines...) Expand all
171 167
172 168
173 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) { 169 bool AotOptimizer::TryCreateICData(InstanceCallInstr* call) {
174 ASSERT(call->HasICData()); 170 ASSERT(call->HasICData());
175 if (call->ic_data()->NumberOfUsedChecks() > 0) { 171 if (call->ic_data()->NumberOfUsedChecks() > 0) {
176 // This occurs when an instance call has too many checks, will be converted 172 // This occurs when an instance call has too many checks, will be converted
177 // to megamorphic call. 173 // to megamorphic call.
178 return false; 174 return false;
179 } 175 }
180 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested()); 176 GrowableArray<intptr_t> class_ids(call->ic_data()->NumArgsTested());
181 ASSERT(call->ic_data()->NumArgsTested() <= call->ArgumentCount()); 177 const intptr_t receiver_idx = call->FirstParamIndex();
178 ASSERT(call->ic_data()->NumArgsTested() <=
179 call->ArgumentCountWithoutTypeArgs());
182 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) { 180 for (intptr_t i = 0; i < call->ic_data()->NumArgsTested(); i++) {
183 class_ids.Add(call->PushArgumentAt(i)->value()->Type()->ToCid()); 181 class_ids.Add(
182 call->PushArgumentAt(receiver_idx + i)->value()->Type()->ToCid());
184 } 183 }
185 184
186 const Token::Kind op_kind = call->token_kind(); 185 const Token::Kind op_kind = call->token_kind();
187 if (FLAG_guess_icdata_cid) { 186 if (FLAG_guess_icdata_cid) {
188 if (Token::IsBinaryBitwiseOperator(op_kind)) { 187 if (Token::IsBinaryBitwiseOperator(op_kind)) {
189 class_ids[0] = kSmiCid; 188 class_ids[0] = kSmiCid;
190 class_ids[1] = kSmiCid; 189 class_ids[1] = kSmiCid;
191 } 190 }
192 if (Token::IsRelationalOperator(op_kind) || 191 if (Token::IsRelationalOperator(op_kind) ||
193 Token::IsEqualityOperator(op_kind) || 192 Token::IsEqualityOperator(op_kind) ||
(...skipping 21 matching lines...) Expand all
215 214
216 if (all_cids_known) { 215 if (all_cids_known) {
217 const Class& receiver_class = 216 const Class& receiver_class =
218 Class::Handle(Z, isolate()->class_table()->At(class_ids[0])); 217 Class::Handle(Z, isolate()->class_table()->At(class_ids[0]));
219 if (!receiver_class.is_finalized()) { 218 if (!receiver_class.is_finalized()) {
220 // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can 219 // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can
221 // cause class finalization, since callee's receiver class may not be 220 // cause class finalization, since callee's receiver class may not be
222 // finalized yet. 221 // finalized yet.
223 return false; 222 return false;
224 } 223 }
225 const Array& args_desc_array = 224 const Function& function =
226 Array::Handle(Z, ArgumentsDescriptor::New(call->ArgumentCount(), 225 Function::Handle(Z, call->ResolveForReceiverClass(receiver_class));
227 call->argument_names()));
228 ArgumentsDescriptor args_desc(args_desc_array);
229 const Function& function = Function::Handle(
230 Z, Resolver::ResolveDynamicForReceiverClass(
231 receiver_class, call->function_name(), args_desc));
232 if (function.IsNull()) { 226 if (function.IsNull()) {
233 return false; 227 return false;
234 } 228 }
235 229
236 // Create new ICData, do not modify the one attached to the instruction 230 // Create new ICData, do not modify the one attached to the instruction
237 // since it is attached to the assembly instruction itself. 231 // since it is attached to the assembly instruction itself.
238 // TODO(srdjan): Prevent modification of ICData object that is 232 // TODO(srdjan): Prevent modification of ICData object that is
239 // referenced in assembly code. 233 // referenced in assembly code.
240 const ICData& ic_data = ICData::ZoneHandle( 234 const ICData& ic_data = ICData::ZoneHandle(
241 Z, ICData::NewFrom(*call->ic_data(), class_ids.length())); 235 Z, ICData::NewFrom(*call->ic_data(), class_ids.length()));
242 if (class_ids.length() > 1) { 236 if (class_ids.length() > 1) {
243 ic_data.AddCheck(class_ids, function); 237 ic_data.AddCheck(class_ids, function);
244 } else { 238 } else {
245 ASSERT(class_ids.length() == 1); 239 ASSERT(class_ids.length() == 1);
246 ic_data.AddReceiverCheck(class_ids[0], function); 240 ic_data.AddReceiverCheck(class_ids[0], function);
247 } 241 }
248 call->set_ic_data(&ic_data); 242 call->set_ic_data(&ic_data);
249 return true; 243 return true;
250 } 244 }
251 245
252 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) { 246 if (isolate()->object_store()->unique_dynamic_targets() != Array::null()) {
253 // Check if the target is unique. 247 // Check if the target is unique.
254 Function& target_function = Function::Handle(Z); 248 Function& target_function = Function::Handle(Z);
255 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function); 249 GetUniqueDynamicTarget(isolate(), call->function_name(), &target_function);
256 // Calls with named arguments must be resolved/checked at runtime. 250 // Calls passing named arguments and calls to a function taking named
251 // arguments must be resolved/checked at runtime.
252 // Calls passing a type argument vector and calls to a generic function must
253 // be resolved/checked at runtime.
257 if (!target_function.IsNull() && 254 if (!target_function.IsNull() &&
258 !target_function.HasOptionalNamedParameters() && 255 !target_function.HasOptionalNamedParameters() &&
259 target_function.AreValidArgumentCounts(call->ArgumentCount(), 0, 256 !target_function.IsGeneric() &&
260 /* error_message = */ NULL)) { 257 target_function.AreValidArgumentCounts(
258 call->type_args_len(), call->ArgumentCountWithoutTypeArgs(),
259 call->argument_names().IsNull() ? 0
260 : call->argument_names().Length(),
261 /* error_message = */ NULL)) {
261 const Class& cls = Class::Handle(Z, target_function.Owner()); 262 const Class& cls = Class::Handle(Z, target_function.Owner());
262 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) { 263 if (!CHA::IsImplemented(cls) && !CHA::HasSubclasses(cls)) {
263 const ICData& ic_data = 264 const ICData& ic_data =
264 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1)); 265 ICData::ZoneHandle(Z, ICData::NewFrom(*call->ic_data(), 1));
265 ic_data.AddReceiverCheck(cls.id(), target_function); 266 ic_data.AddReceiverCheck(cls.id(), target_function);
266 call->set_ic_data(&ic_data); 267 call->set_ic_data(&ic_data);
267 if (has_unique_no_such_method_) { 268 if (has_unique_no_such_method_) {
268 call->set_has_unique_selector(true); 269 call->set_has_unique_selector(true);
269 // Add redefinition of the receiver to prevent code motion across 270 // Add redefinition of the receiver to prevent code motion across
270 // this call. 271 // this call.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 } 607 }
607 608
608 609
609 // Recognize a.runtimeType == b.runtimeType and fold it into 610 // Recognize a.runtimeType == b.runtimeType and fold it into
610 // Object._haveSameRuntimeType(a, b). 611 // Object._haveSameRuntimeType(a, b).
611 // Note: this optimization is not speculative. 612 // Note: this optimization is not speculative.
612 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) { 613 bool AotOptimizer::TryReplaceWithHaveSameRuntimeType(InstanceCallInstr* call) {
613 const ICData& ic_data = *call->ic_data(); 614 const ICData& ic_data = *call->ic_data();
614 ASSERT(ic_data.NumArgsTested() == 2); 615 ASSERT(ic_data.NumArgsTested() == 2);
615 616
617 ASSERT(call->type_args_len() == 0);
616 ASSERT(call->ArgumentCount() == 2); 618 ASSERT(call->ArgumentCount() == 2);
617 Definition* left = call->ArgumentAt(0); 619 Definition* left = call->ArgumentAt(0);
618 Definition* right = call->ArgumentAt(1); 620 Definition* right = call->ArgumentAt(1);
619 621
620 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() && 622 if (IsGetRuntimeType(left) && left->input_use_list()->IsSingleUse() &&
621 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) { 623 IsGetRuntimeType(right) && right->input_use_list()->IsSingleUse()) {
622 const Class& cls = Class::Handle(Z, I->object_store()->object_class()); 624 const Class& cls = Class::Handle(Z, I->object_store()->object_class());
623 const Function& have_same_runtime_type = Function::ZoneHandle( 625 const Function& have_same_runtime_type = Function::ZoneHandle(
624 Z, 626 Z,
625 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType())); 627 cls.LookupStaticFunctionAllowPrivate(Symbols::HaveSameRuntimeType()));
626 ASSERT(!have_same_runtime_type.IsNull()); 628 ASSERT(!have_same_runtime_type.IsNull());
627 629
628 ZoneGrowableArray<PushArgumentInstr*>* args = 630 ZoneGrowableArray<PushArgumentInstr*>* args =
629 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2); 631 new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
630 PushArgumentInstr* arg = 632 PushArgumentInstr* arg =
631 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0))); 633 new (Z) PushArgumentInstr(new (Z) Value(left->ArgumentAt(0)));
632 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 634 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
633 args->Add(arg); 635 args->Add(arg);
634 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0))); 636 arg = new (Z) PushArgumentInstr(new (Z) Value(right->ArgumentAt(0)));
635 InsertBefore(call, arg, NULL, FlowGraph::kEffect); 637 InsertBefore(call, arg, NULL, FlowGraph::kEffect);
636 args->Add(arg); 638 args->Add(arg);
637 StaticCallInstr* static_call = 639 const intptr_t kTypeArgsLen = 0;
638 new (Z) StaticCallInstr(call->token_pos(), have_same_runtime_type, 640 ASSERT(call->type_args_len() == kTypeArgsLen);
639 Object::null_array(), // argument_names 641 StaticCallInstr* static_call = new (Z)
640 args, call->deopt_id()); 642 StaticCallInstr(call->token_pos(), have_same_runtime_type, kTypeArgsLen,
643 Object::null_array(), // argument_names
644 args, call->deopt_id());
641 static_call->set_result_cid(kBoolCid); 645 static_call->set_result_cid(kBoolCid);
642 ReplaceCall(call, static_call); 646 ReplaceCall(call, static_call);
643 return true; 647 return true;
644 } 648 }
645 649
646 return false; 650 return false;
647 } 651 }
648 652
649 653
650 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call, 654 bool AotOptimizer::TryReplaceWithEqualityOp(InstanceCallInstr* call,
651 Token::Kind op_kind) { 655 Token::Kind op_kind) {
652 const ICData& ic_data = *call->ic_data(); 656 const ICData& ic_data = *call->ic_data();
653 ASSERT(ic_data.NumArgsTested() == 2); 657 ASSERT(ic_data.NumArgsTested() == 2);
654 658
659 ASSERT(call->type_args_len() == 0);
655 ASSERT(call->ArgumentCount() == 2); 660 ASSERT(call->ArgumentCount() == 2);
656 Definition* const left = call->ArgumentAt(0); 661 Definition* const left = call->ArgumentAt(0);
657 Definition* const right = call->ArgumentAt(1); 662 Definition* const right = call->ArgumentAt(1);
658 663
659 intptr_t cid = kIllegalCid; 664 intptr_t cid = kIllegalCid;
660 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) { 665 if (HasOnlyTwoOf(ic_data, kOneByteStringCid)) {
661 return TryStringLengthOneEquality(call, op_kind); 666 return TryStringLengthOneEquality(call, op_kind);
662 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) { 667 } else if (HasOnlyTwoOf(ic_data, kSmiCid)) {
663 InsertBefore(call, 668 InsertBefore(call,
664 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 669 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); 732 ReplaceCall(call, comp);
728 return true; 733 return true;
729 } 734 }
730 735
731 736
732 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call, 737 bool AotOptimizer::TryReplaceWithRelationalOp(InstanceCallInstr* call,
733 Token::Kind op_kind) { 738 Token::Kind op_kind) {
734 const ICData& ic_data = *call->ic_data(); 739 const ICData& ic_data = *call->ic_data();
735 ASSERT(ic_data.NumArgsTested() == 2); 740 ASSERT(ic_data.NumArgsTested() == 2);
736 741
742 ASSERT(call->type_args_len() == 0);
737 ASSERT(call->ArgumentCount() == 2); 743 ASSERT(call->ArgumentCount() == 2);
738 Definition* left = call->ArgumentAt(0); 744 Definition* left = call->ArgumentAt(0);
739 Definition* right = call->ArgumentAt(1); 745 Definition* right = call->ArgumentAt(1);
740 746
741 intptr_t cid = kIllegalCid; 747 intptr_t cid = kIllegalCid;
742 if (HasOnlyTwoOf(ic_data, kSmiCid)) { 748 if (HasOnlyTwoOf(ic_data, kSmiCid)) {
743 InsertBefore(call, 749 InsertBefore(call,
744 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(), 750 new (Z) CheckSmiInstr(new (Z) Value(left), call->deopt_id(),
745 call->token_pos()), 751 call->token_pos()),
746 call->env(), FlowGraph::kEffect); 752 call->env(), FlowGraph::kEffect);
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 } 882 }
877 operands_type = kSmiCid; 883 operands_type = kSmiCid;
878 } else { 884 } else {
879 return false; 885 return false;
880 } 886 }
881 break; 887 break;
882 default: 888 default:
883 UNREACHABLE(); 889 UNREACHABLE();
884 } 890 }
885 891
892 ASSERT(call->type_args_len() == 0);
886 ASSERT(call->ArgumentCount() == 2); 893 ASSERT(call->ArgumentCount() == 2);
887 Definition* left = call->ArgumentAt(0); 894 Definition* left = call->ArgumentAt(0);
888 Definition* right = call->ArgumentAt(1); 895 Definition* right = call->ArgumentAt(1);
889 if (operands_type == kDoubleCid) { 896 if (operands_type == kDoubleCid) {
890 if (!CanUnboxDouble()) { 897 if (!CanUnboxDouble()) {
891 return false; 898 return false;
892 } 899 }
893 // Check that either left or right are not a smi. Result of a 900 // 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 901 // binary operation with two smis is a smi not a double, except '/' which
895 // returns a double for two smis. 902 // 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( 971 BinarySmiOpInstr* bin_op = new (Z) BinarySmiOpInstr(
965 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 972 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
966 ReplaceCall(call, bin_op); 973 ReplaceCall(call, bin_op);
967 } 974 }
968 return true; 975 return true;
969 } 976 }
970 977
971 978
972 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call, 979 bool AotOptimizer::TryReplaceWithUnaryOp(InstanceCallInstr* call,
973 Token::Kind op_kind) { 980 Token::Kind op_kind) {
981 ASSERT(call->type_args_len() == 0);
974 ASSERT(call->ArgumentCount() == 1); 982 ASSERT(call->ArgumentCount() == 1);
975 Definition* input = call->ArgumentAt(0); 983 Definition* input = call->ArgumentAt(0);
976 Definition* unary_op = NULL; 984 Definition* unary_op = NULL;
977 if (HasOnlyOneSmi(*call->ic_data())) { 985 if (HasOnlyOneSmi(*call->ic_data())) {
978 InsertBefore(call, 986 InsertBefore(call,
979 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(), 987 new (Z) CheckSmiInstr(new (Z) Value(input), call->deopt_id(),
980 call->token_pos()), 988 call->token_pos()),
981 call->env(), FlowGraph::kEffect); 989 call->env(), FlowGraph::kEffect);
982 unary_op = new (Z) 990 unary_op = new (Z)
983 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id()); 991 UnarySmiOpInstr(op_kind, new (Z) Value(input), call->deopt_id());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 } 1058 }
1051 return true; 1059 return true;
1052 } 1060 }
1053 1061
1054 1062
1055 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 1063 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1056 Token::Kind op_kind) { 1064 Token::Kind op_kind) {
1057 if (!ShouldInlineSimd()) { 1065 if (!ShouldInlineSimd()) {
1058 return false; 1066 return false;
1059 } 1067 }
1068 ASSERT(call->type_args_len() == 0);
1060 ASSERT(call->ArgumentCount() == 2); 1069 ASSERT(call->ArgumentCount() == 2);
1061 Definition* const left = call->ArgumentAt(0); 1070 Definition* const left = call->ArgumentAt(0);
1062 Definition* const right = call->ArgumentAt(1); 1071 Definition* const right = call->ArgumentAt(1);
1063 // Type check left and right. 1072 // Type check left and right.
1064 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1073 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1065 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1074 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1066 // Replace call. 1075 // Replace call.
1067 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr( 1076 BinaryFloat32x4OpInstr* float32x4_bin_op = new (Z) BinaryFloat32x4OpInstr(
1068 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1077 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1069 ReplaceCall(call, float32x4_bin_op); 1078 ReplaceCall(call, float32x4_bin_op);
1070 1079
1071 return true; 1080 return true;
1072 } 1081 }
1073 1082
1074 1083
1075 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, 1084 bool AotOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call,
1076 Token::Kind op_kind) { 1085 Token::Kind op_kind) {
1077 if (!ShouldInlineSimd()) { 1086 if (!ShouldInlineSimd()) {
1078 return false; 1087 return false;
1079 } 1088 }
1089 ASSERT(call->type_args_len() == 0);
1080 ASSERT(call->ArgumentCount() == 2); 1090 ASSERT(call->ArgumentCount() == 2);
1081 Definition* const left = call->ArgumentAt(0); 1091 Definition* const left = call->ArgumentAt(0);
1082 Definition* const right = call->ArgumentAt(1); 1092 Definition* const right = call->ArgumentAt(1);
1083 // Type check left and right. 1093 // Type check left and right.
1084 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1094 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1085 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1095 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1086 // Replace call. 1096 // Replace call.
1087 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr( 1097 BinaryInt32x4OpInstr* int32x4_bin_op = new (Z) BinaryInt32x4OpInstr(
1088 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1098 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1089 ReplaceCall(call, int32x4_bin_op); 1099 ReplaceCall(call, int32x4_bin_op);
1090 return true; 1100 return true;
1091 } 1101 }
1092 1102
1093 1103
1094 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call, 1104 bool AotOptimizer::InlineFloat64x2BinaryOp(InstanceCallInstr* call,
1095 Token::Kind op_kind) { 1105 Token::Kind op_kind) {
1096 if (!ShouldInlineSimd()) { 1106 if (!ShouldInlineSimd()) {
1097 return false; 1107 return false;
1098 } 1108 }
1109 ASSERT(call->type_args_len() == 0);
1099 ASSERT(call->ArgumentCount() == 2); 1110 ASSERT(call->ArgumentCount() == 2);
1100 Definition* const left = call->ArgumentAt(0); 1111 Definition* const left = call->ArgumentAt(0);
1101 Definition* const right = call->ArgumentAt(1); 1112 Definition* const right = call->ArgumentAt(1);
1102 // Type check left and right. 1113 // Type check left and right.
1103 AddChecksForArgNr(call, left, /* arg_number = */ 0); 1114 AddChecksForArgNr(call, left, /* arg_number = */ 0);
1104 AddChecksForArgNr(call, right, /* arg_number = */ 1); 1115 AddChecksForArgNr(call, right, /* arg_number = */ 1);
1105 // Replace call. 1116 // Replace call.
1106 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr( 1117 BinaryFloat64x2OpInstr* float64x2_bin_op = new (Z) BinaryFloat64x2OpInstr(
1107 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id()); 1118 op_kind, new (Z) Value(left), new (Z) Value(right), call->deopt_id());
1108 ReplaceCall(call, float64x2_bin_op); 1119 ReplaceCall(call, float64x2_bin_op);
(...skipping 22 matching lines...) Expand all
1131 // inlining in FlowGraphInliner. 1142 // inlining in FlowGraphInliner.
1132 return false; 1143 return false;
1133 } 1144 }
1134 return InlineImplicitInstanceGetter(call); 1145 return InlineImplicitInstanceGetter(call);
1135 } 1146 }
1136 1147
1137 1148
1138 void AotOptimizer::ReplaceWithMathCFunction( 1149 void AotOptimizer::ReplaceWithMathCFunction(
1139 InstanceCallInstr* call, 1150 InstanceCallInstr* call,
1140 MethodRecognizer::Kind recognized_kind) { 1151 MethodRecognizer::Kind recognized_kind) {
1152 ASSERT(call->type_args_len() == 0);
1141 AddReceiverCheck(call); 1153 AddReceiverCheck(call);
1142 ZoneGrowableArray<Value*>* args = 1154 ZoneGrowableArray<Value*>* args =
1143 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount()); 1155 new (Z) ZoneGrowableArray<Value*>(call->ArgumentCount());
1144 for (intptr_t i = 0; i < call->ArgumentCount(); i++) { 1156 for (intptr_t i = 0; i < call->ArgumentCount(); i++) {
1145 args->Add(new (Z) Value(call->ArgumentAt(i))); 1157 args->Add(new (Z) Value(call->ArgumentAt(i)));
1146 } 1158 }
1147 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr( 1159 InvokeMathCFunctionInstr* invoke = new (Z) InvokeMathCFunctionInstr(
1148 args, call->deopt_id(), recognized_kind, call->token_pos()); 1160 args, call->deopt_id(), recognized_kind, call->token_pos());
1149 ReplaceCall(call, invoke); 1161 ReplaceCall(call, invoke);
1150 } 1162 }
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 } 1423 }
1412 1424
1413 1425
1414 // TODO(srdjan): Use ICData to check if always true or false. 1426 // TODO(srdjan): Use ICData to check if always true or false.
1415 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) { 1427 void AotOptimizer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
1416 ASSERT(Token::IsTypeTestOperator(call->token_kind())); 1428 ASSERT(Token::IsTypeTestOperator(call->token_kind()));
1417 Definition* left = call->ArgumentAt(0); 1429 Definition* left = call->ArgumentAt(0);
1418 Definition* instantiator_type_args = NULL; 1430 Definition* instantiator_type_args = NULL;
1419 Definition* function_type_args = NULL; 1431 Definition* function_type_args = NULL;
1420 AbstractType& type = AbstractType::ZoneHandle(Z); 1432 AbstractType& type = AbstractType::ZoneHandle(Z);
1433 ASSERT(call->type_args_len() == 0);
1421 if (call->ArgumentCount() == 2) { 1434 if (call->ArgumentCount() == 2) {
1422 instantiator_type_args = flow_graph()->constant_null(); 1435 instantiator_type_args = flow_graph()->constant_null();
1423 function_type_args = flow_graph()->constant_null(); 1436 function_type_args = flow_graph()->constant_null();
1424 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf())); 1437 ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
1425 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw(); 1438 type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
1426 } else { 1439 } else {
1427 instantiator_type_args = call->ArgumentAt(1); 1440 instantiator_type_args = call->ArgumentAt(1);
1428 function_type_args = call->ArgumentAt(2); 1441 function_type_args = call->ArgumentAt(2);
1429 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw(); 1442 type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
1430 } 1443 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 args->Add(arg); 1487 args->Add(arg);
1475 1488
1476 const Library& dart_internal = 1489 const Library& dart_internal =
1477 Library::Handle(Z, Library::InternalLibrary()); 1490 Library::Handle(Z, Library::InternalLibrary());
1478 const String& target_name = Symbols::_classRangeCheck(); 1491 const String& target_name = Symbols::_classRangeCheck();
1479 const Function& target = Function::ZoneHandle( 1492 const Function& target = Function::ZoneHandle(
1480 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1493 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1481 ASSERT(!target.IsNull()); 1494 ASSERT(!target.IsNull());
1482 ASSERT(target.IsRecognized() && target.always_inline()); 1495 ASSERT(target.IsRecognized() && target.always_inline());
1483 1496
1497 const intptr_t kTypeArgsLen = 0;
1484 StaticCallInstr* new_call = 1498 StaticCallInstr* new_call =
1485 new (Z) StaticCallInstr(call->token_pos(), target, 1499 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1486 Object::null_array(), // argument_names 1500 Object::null_array(), // argument_names
1487 args, call->deopt_id()); 1501 args, call->deopt_id());
1488 Environment* copy = call->env()->DeepCopy( 1502 Environment* copy = call->env()->DeepCopy(
1489 Z, call->env()->Length() - call->ArgumentCount()); 1503 Z, call->env()->Length() - call->ArgumentCount());
1490 for (intptr_t i = 0; i < args->length(); ++i) { 1504 for (intptr_t i = 0; i < args->length(); ++i) {
1491 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1505 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1492 } 1506 }
1493 call->RemoveEnvironment(); 1507 call->RemoveEnvironment();
1494 ReplaceCall(call, new_call); 1508 ReplaceCall(call, new_call);
1495 copy->DeepCopyTo(Z, new_call); 1509 copy->DeepCopyTo(Z, new_call);
(...skipping 27 matching lines...) Expand all
1523 call->token_pos(), new (Z) Value(left), 1537 call->token_pos(), new (Z) Value(left),
1524 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args), 1538 new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
1525 type, call->deopt_id()); 1539 type, call->deopt_id());
1526 ReplaceCall(call, instance_of); 1540 ReplaceCall(call, instance_of);
1527 } 1541 }
1528 1542
1529 1543
1530 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids). 1544 // TODO(srdjan): Apply optimizations as in ReplaceWithInstanceOf (TestCids).
1531 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) { 1545 void AotOptimizer::ReplaceWithTypeCast(InstanceCallInstr* call) {
1532 ASSERT(Token::IsTypeCastOperator(call->token_kind())); 1546 ASSERT(Token::IsTypeCastOperator(call->token_kind()));
1547 ASSERT(call->type_args_len() == 0);
1533 Definition* left = call->ArgumentAt(0); 1548 Definition* left = call->ArgumentAt(0);
1534 Definition* instantiator_type_args = call->ArgumentAt(1); 1549 Definition* instantiator_type_args = call->ArgumentAt(1);
1535 Definition* function_type_args = call->ArgumentAt(2); 1550 Definition* function_type_args = call->ArgumentAt(2);
1536 const AbstractType& type = 1551 const AbstractType& type =
1537 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()); 1552 AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
1538 ASSERT(!type.IsMalformedOrMalbounded()); 1553 ASSERT(!type.IsMalformedOrMalbounded());
1539 1554
1540 if (TypeCheckAsClassEquality(type)) { 1555 if (TypeCheckAsClassEquality(type)) {
1541 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left)); 1556 LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
1542 InsertBefore(call, left_cid, NULL, FlowGraph::kValue); 1557 InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
(...skipping 23 matching lines...) Expand all
1566 args->Add(arg); 1581 args->Add(arg);
1567 1582
1568 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1583 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1569 const String& target_name = Symbols::_classIdEqualsAssert(); 1584 const String& target_name = Symbols::_classIdEqualsAssert();
1570 const Function& target = Function::ZoneHandle( 1585 const Function& target = Function::ZoneHandle(
1571 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1586 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1572 ASSERT(!target.IsNull()); 1587 ASSERT(!target.IsNull());
1573 ASSERT(target.IsRecognized()); 1588 ASSERT(target.IsRecognized());
1574 ASSERT(target.always_inline()); 1589 ASSERT(target.always_inline());
1575 1590
1591 const intptr_t kTypeArgsLen = 0;
1576 StaticCallInstr* new_call = 1592 StaticCallInstr* new_call =
1577 new (Z) StaticCallInstr(call->token_pos(), target, 1593 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1578 Object::null_array(), // argument_names 1594 Object::null_array(), // argument_names
1579 args, call->deopt_id()); 1595 args, call->deopt_id());
1580 Environment* copy = 1596 Environment* copy =
1581 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount()); 1597 call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
1582 for (intptr_t i = 0; i < args->length(); ++i) { 1598 for (intptr_t i = 0; i < args->length(); ++i) {
1583 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1599 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1584 } 1600 }
1585 call->RemoveEnvironment(); 1601 call->RemoveEnvironment();
1586 ReplaceCall(call, new_call); 1602 ReplaceCall(call, new_call);
1587 copy->DeepCopyTo(Z, new_call); 1603 copy->DeepCopyTo(Z, new_call);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 args->Add(arg); 1645 args->Add(arg);
1630 1646
1631 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary()); 1647 const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
1632 const String& target_name = Symbols::_classRangeAssert(); 1648 const String& target_name = Symbols::_classRangeAssert();
1633 const Function& target = Function::ZoneHandle( 1649 const Function& target = Function::ZoneHandle(
1634 Z, dart_internal.LookupFunctionAllowPrivate(target_name)); 1650 Z, dart_internal.LookupFunctionAllowPrivate(target_name));
1635 ASSERT(!target.IsNull()); 1651 ASSERT(!target.IsNull());
1636 ASSERT(target.IsRecognized()); 1652 ASSERT(target.IsRecognized());
1637 ASSERT(target.always_inline()); 1653 ASSERT(target.always_inline());
1638 1654
1655 const intptr_t kTypeArgsLen = 0;
1639 StaticCallInstr* new_call = 1656 StaticCallInstr* new_call =
1640 new (Z) StaticCallInstr(call->token_pos(), target, 1657 new (Z) StaticCallInstr(call->token_pos(), target, kTypeArgsLen,
1641 Object::null_array(), // argument_names 1658 Object::null_array(), // argument_names
1642 args, call->deopt_id()); 1659 args, call->deopt_id());
1643 Environment* copy = call->env()->DeepCopy( 1660 Environment* copy = call->env()->DeepCopy(
1644 Z, call->env()->Length() - call->ArgumentCount()); 1661 Z, call->env()->Length() - call->ArgumentCount());
1645 for (intptr_t i = 0; i < args->length(); ++i) { 1662 for (intptr_t i = 0; i < args->length(); ++i) {
1646 copy->PushValue(new (Z) Value((*args)[i]->value()->definition())); 1663 copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
1647 } 1664 }
1648 call->RemoveEnvironment(); 1665 call->RemoveEnvironment();
1649 ReplaceCall(call, new_call); 1666 ReplaceCall(call, new_call);
1650 copy->DeepCopyTo(Z, new_call); 1667 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) { 1707 bool AotOptimizer::IsAllowedForInlining(intptr_t call_deopt_id) {
1691 if (!use_speculative_inlining_) return false; 1708 if (!use_speculative_inlining_) return false;
1692 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) { 1709 for (intptr_t i = 0; i < inlining_black_list_->length(); ++i) {
1693 if ((*inlining_black_list_)[i] == call_deopt_id) return false; 1710 if ((*inlining_black_list_)[i] == call_deopt_id) return false;
1694 } 1711 }
1695 return true; 1712 return true;
1696 } 1713 }
1697 1714
1698 1715
1699 static bool HasLikelySmiOperand(InstanceCallInstr* instr) { 1716 static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
1717 ASSERT(instr->type_args_len() == 0);
1700 // Phis with at least one known smi are // guessed to be likely smi as well. 1718 // 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) { 1719 for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
1702 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi(); 1720 PhiInstr* phi = instr->ArgumentAt(i)->AsPhi();
1703 if (phi != NULL) { 1721 if (phi != NULL) {
1704 for (intptr_t j = 0; j < phi->InputCount(); ++j) { 1722 for (intptr_t j = 0; j < phi->InputCount(); ++j) {
1705 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true; 1723 if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true;
1706 } 1724 }
1707 } 1725 }
1708 } 1726 }
1709 // If all of the inputs are known smis or the result of CheckedSmiOp, 1727 // If all of the inputs are known smis or the result of CheckedSmiOp,
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1861 default: 1879 default:
1862 break; 1880 break;
1863 } 1881 }
1864 1882
1865 // No IC data checks. Try resolve target using the propagated cid. 1883 // No IC data checks. Try resolve target using the propagated cid.
1866 const intptr_t receiver_cid = 1884 const intptr_t receiver_cid =
1867 instr->PushArgumentAt(0)->value()->Type()->ToCid(); 1885 instr->PushArgumentAt(0)->value()->Type()->ToCid();
1868 if (receiver_cid != kDynamicCid) { 1886 if (receiver_cid != kDynamicCid) {
1869 const Class& receiver_class = 1887 const Class& receiver_class =
1870 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 1888 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
1871 1889 const Function& function =
1872 const Array& args_desc_array = 1890 Function::Handle(Z, instr->ResolveForReceiverClass(receiver_class));
1873 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(),
1874 instr->argument_names()));
1875 ArgumentsDescriptor args_desc(args_desc_array);
1876 Function& function = Function::Handle(
1877 Z, Resolver::ResolveDynamicForReceiverClass(
1878 receiver_class, instr->function_name(), args_desc));
1879 if (!function.IsNull()) { 1891 if (!function.IsNull()) {
1880 CallTargets* targets = new (Z) CallTargets(Z); 1892 CallTargets* targets = new (Z) CallTargets(Z);
1881 Function& target = Function::ZoneHandle(Z, function.raw()); 1893 Function& target = Function::ZoneHandle(Z, function.raw());
1882 targets->Add(new (Z) TargetInfo(receiver_class.id(), receiver_class.id(), 1894 targets->Add(new (Z) TargetInfo(receiver_class.id(), receiver_class.id(),
1883 &target, /*count = */ 1)); 1895 &target, /*count = */ 1));
1884 PolymorphicInstanceCallInstr* call = 1896 PolymorphicInstanceCallInstr* call =
1885 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 1897 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
1886 /* with_checks = */ false, 1898 /* with_checks = */ false,
1887 /* complete = */ true); 1899 /* complete = */ true);
1888 instr->ReplaceWith(call, current_iterator()); 1900 instr->ReplaceWith(call, current_iterator());
(...skipping 23 matching lines...) Expand all
1912 if (!receiver_class.IsNull()) { 1924 if (!receiver_class.IsNull()) {
1913 GrowableArray<intptr_t> class_ids(6); 1925 GrowableArray<intptr_t> class_ids(6);
1914 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) { 1926 if (thread()->cha()->ConcreteSubclasses(receiver_class, &class_ids)) {
1915 // First check if all subclasses end up calling the same method. 1927 // 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 1928 // If this is the case we will replace instance call with a direct
1917 // static call. 1929 // static call.
1918 // Otherwise we will try to create ICData that contains all possible 1930 // Otherwise we will try to create ICData that contains all possible
1919 // targets with appropriate checks. 1931 // targets with appropriate checks.
1920 Function& single_target = Function::Handle(Z); 1932 Function& single_target = Function::Handle(Z);
1921 ICData& ic_data = ICData::Handle(Z); 1933 ICData& ic_data = ICData::Handle(Z);
1922
1923 const Array& args_desc_array = 1934 const Array& args_desc_array =
1924 Array::Handle(Z, ArgumentsDescriptor::New(instr->ArgumentCount(), 1935 Array::Handle(Z, instr->GetArgumentsDescriptor());
1925 instr->argument_names()));
1926 ArgumentsDescriptor args_desc(args_desc_array);
1927
1928 Function& target = Function::Handle(Z); 1936 Function& target = Function::Handle(Z);
1929 Class& cls = Class::Handle(Z); 1937 Class& cls = Class::Handle(Z);
1930 for (intptr_t i = 0; i < class_ids.length(); i++) { 1938 for (intptr_t i = 0; i < class_ids.length(); i++) {
1931 const intptr_t cid = class_ids[i]; 1939 const intptr_t cid = class_ids[i];
1932 cls = isolate()->class_table()->At(cid); 1940 cls = isolate()->class_table()->At(cid);
1933 target = Resolver::ResolveDynamicForReceiverClass( 1941 target = instr->ResolveForReceiverClass(cls);
1934 cls, instr->function_name(), args_desc);
1935
1936 if (target.IsNull()) { 1942 if (target.IsNull()) {
1937 // Can't resolve the target. It might be a noSuchMethod, 1943 // Can't resolve the target. It might be a noSuchMethod,
1938 // call through getter or closurization. 1944 // call through getter or closurization.
1939 single_target = Function::null(); 1945 single_target = Function::null();
1940 ic_data = ICData::null(); 1946 ic_data = ICData::null();
1941 break; 1947 break;
1942 } else if (ic_data.IsNull()) { 1948 } else if (ic_data.IsNull()) {
1943 // First we are trying to compute a single target for all subclasses. 1949 // First we are trying to compute a single target for all subclasses.
1944 if (single_target.IsNull()) { 1950 if (single_target.IsNull()) {
1945 ASSERT(i == 0); 1951 ASSERT(i == 0);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 1999
1994 // We have computed that there is only a single target for this call 2000 // We have computed that there is only a single target for this call
1995 // within the whole hierarchy. Replace InstanceCall with StaticCall. 2001 // within the whole hierarchy. Replace InstanceCall with StaticCall.
1996 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z) 2002 ZoneGrowableArray<PushArgumentInstr*>* args = new (Z)
1997 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount()); 2003 ZoneGrowableArray<PushArgumentInstr*>(instr->ArgumentCount());
1998 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) { 2004 for (intptr_t i = 0; i < instr->ArgumentCount(); i++) {
1999 args->Add(instr->PushArgumentAt(i)); 2005 args->Add(instr->PushArgumentAt(i));
2000 } 2006 }
2001 StaticCallInstr* call = new (Z) StaticCallInstr( 2007 StaticCallInstr* call = new (Z) StaticCallInstr(
2002 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()), 2008 instr->token_pos(), Function::ZoneHandle(Z, single_target.raw()),
2003 instr->argument_names(), args, instr->deopt_id()); 2009 instr->type_args_len(), instr->argument_names(), args,
2010 instr->deopt_id());
2004 instr->ReplaceWith(call, current_iterator()); 2011 instr->ReplaceWith(call, current_iterator());
2005 return; 2012 return;
2006 } else if ((ic_data.raw() != ICData::null()) && 2013 } else if ((ic_data.raw() != ICData::null()) &&
2007 !ic_data.NumberOfChecksIs(0)) { 2014 !ic_data.NumberOfChecksIs(0)) {
2008 CallTargets* targets = CallTargets::Create(Z, ic_data); 2015 CallTargets* targets = CallTargets::Create(Z, ic_data);
2009 PolymorphicInstanceCallInstr* call = 2016 PolymorphicInstanceCallInstr* call =
2010 new (Z) PolymorphicInstanceCallInstr(instr, *targets, 2017 new (Z) PolymorphicInstanceCallInstr(instr, *targets,
2011 /* with_checks = */ true, 2018 /* with_checks = */ true,
2012 /* complete = */ true); 2019 /* complete = */ true);
2013 instr->ReplaceWith(call, current_iterator()); 2020 instr->ReplaceWith(call, current_iterator());
(...skipping 20 matching lines...) Expand all
2034 2041
2035 2042
2036 void AotOptimizer::VisitPolymorphicInstanceCall( 2043 void AotOptimizer::VisitPolymorphicInstanceCall(
2037 PolymorphicInstanceCallInstr* call) { 2044 PolymorphicInstanceCallInstr* call) {
2038 if (call->with_checks()) { 2045 if (call->with_checks()) {
2039 const intptr_t receiver_cid = 2046 const intptr_t receiver_cid =
2040 call->PushArgumentAt(0)->value()->Type()->ToCid(); 2047 call->PushArgumentAt(0)->value()->Type()->ToCid();
2041 if (receiver_cid != kDynamicCid) { 2048 if (receiver_cid != kDynamicCid) {
2042 const Class& receiver_class = 2049 const Class& receiver_class =
2043 Class::Handle(Z, isolate()->class_table()->At(receiver_cid)); 2050 Class::Handle(Z, isolate()->class_table()->At(receiver_cid));
2044
2045 const Array& args_desc_array = Array::Handle(
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( 2051 const Function& function = Function::Handle(
2050 Z, Resolver::ResolveDynamicForReceiverClass( 2052 Z, call->instance_call()->ResolveForReceiverClass(receiver_class));
2051 receiver_class, call->instance_call()->function_name(),
2052 args_desc));
2053 if (!function.IsNull()) { 2053 if (!function.IsNull()) {
2054 call->set_with_checks(false); 2054 call->set_with_checks(false);
2055 } 2055 }
2056 } 2056 }
2057 } 2057 }
2058 } 2058 }
2059 2059
2060 2060
2061 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { 2061 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) {
2062 if (!IsAllowedForInlining(call->deopt_id())) { 2062 if (!IsAllowedForInlining(call->deopt_id())) {
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 FlowGraph::kEffect); 2222 FlowGraph::kEffect);
2223 current_iterator()->RemoveCurrentFromGraph(); 2223 current_iterator()->RemoveCurrentFromGraph();
2224 } 2224 }
2225 } 2225 }
2226 } 2226 }
2227 } 2227 }
2228 2228
2229 #endif // DART_PRECOMPILER 2229 #endif // DART_PRECOMPILER
2230 2230
2231 } // namespace dart 2231 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/lib/mirrors.cc ('k') | runtime/vm/assembler_dbc_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698