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