OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |