Chromium Code Reviews| 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 #if !defined(DART_PRECOMPILED_RUNTIME) | 4 #if !defined(DART_PRECOMPILED_RUNTIME) |
| 5 #include "vm/flow_graph_inliner.h" | 5 #include "vm/flow_graph_inliner.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/precompiler.h" | 8 #include "vm/precompiler.h" |
| 9 #include "vm/block_scheduler.h" | 9 #include "vm/block_scheduler.h" |
| 10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 GrowableArray<StaticCallInfo> static_calls_; | 425 GrowableArray<StaticCallInfo> static_calls_; |
| 426 GrowableArray<ClosureCallInfo> closure_calls_; | 426 GrowableArray<ClosureCallInfo> closure_calls_; |
| 427 GrowableArray<InstanceCallInfo> instance_calls_; | 427 GrowableArray<InstanceCallInfo> instance_calls_; |
| 428 | 428 |
| 429 DISALLOW_COPY_AND_ASSIGN(CallSites); | 429 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 430 }; | 430 }; |
| 431 | 431 |
| 432 | 432 |
| 433 struct InlinedCallData { | 433 struct InlinedCallData { |
| 434 InlinedCallData(Definition* call, | 434 InlinedCallData(Definition* call, |
| 435 intptr_t first_param_index, // 1 if type args are passed. | |
| 435 GrowableArray<Value*>* arguments, | 436 GrowableArray<Value*>* arguments, |
| 436 const Function& caller, | 437 const Function& caller, |
| 437 intptr_t caller_inlining_id) | 438 intptr_t caller_inlining_id) |
| 438 : call(call), | 439 : call(call), |
| 440 first_param_index(first_param_index), | |
| 439 arguments(arguments), | 441 arguments(arguments), |
| 440 callee_graph(NULL), | 442 callee_graph(NULL), |
| 441 parameter_stubs(NULL), | 443 parameter_stubs(NULL), |
| 442 exit_collector(NULL), | 444 exit_collector(NULL), |
| 443 caller(caller), | 445 caller(caller), |
| 444 caller_inlining_id_(caller_inlining_id) {} | 446 caller_inlining_id(caller_inlining_id) {} |
| 445 | 447 |
| 446 Definition* call; | 448 Definition* call; |
| 449 const intptr_t first_param_index; | |
| 447 GrowableArray<Value*>* arguments; | 450 GrowableArray<Value*>* arguments; |
| 448 FlowGraph* callee_graph; | 451 FlowGraph* callee_graph; |
| 449 ZoneGrowableArray<Definition*>* parameter_stubs; | 452 ZoneGrowableArray<Definition*>* parameter_stubs; |
| 450 InlineExitCollector* exit_collector; | 453 InlineExitCollector* exit_collector; |
| 451 const Function& caller; | 454 const Function& caller; |
| 452 const intptr_t caller_inlining_id_; | 455 const intptr_t caller_inlining_id; |
| 453 }; | 456 }; |
| 454 | 457 |
| 455 | 458 |
| 456 class CallSiteInliner; | 459 class CallSiteInliner; |
| 457 | 460 |
| 458 class PolymorphicInliner : public ValueObject { | 461 class PolymorphicInliner : public ValueObject { |
| 459 public: | 462 public: |
| 460 PolymorphicInliner(CallSiteInliner* owner, | 463 PolymorphicInliner(CallSiteInliner* owner, |
| 461 PolymorphicInstanceCallInstr* call, | 464 PolymorphicInstanceCallInstr* call, |
| 462 const Function& caller_function, | 465 const Function& caller_function, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 return true; | 569 return true; |
| 567 } | 570 } |
| 568 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && | 571 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && |
| 569 (instr_count <= FLAG_inlining_constant_arguments_min_size_threshold)) { | 572 (instr_count <= FLAG_inlining_constant_arguments_min_size_threshold)) { |
| 570 return true; | 573 return true; |
| 571 } | 574 } |
| 572 return false; | 575 return false; |
| 573 } | 576 } |
| 574 | 577 |
| 575 void InlineCalls() { | 578 void InlineCalls() { |
| 576 // If inlining depth is less then one abort. | 579 // If inlining depth is less than one abort. |
| 577 if (inlining_depth_threshold_ < 1) return; | 580 if (inlining_depth_threshold_ < 1) return; |
| 578 if (caller_graph_->function().deoptimization_counter() >= | 581 if (caller_graph_->function().deoptimization_counter() >= |
| 579 FLAG_deoptimization_counter_inlining_threshold) { | 582 FLAG_deoptimization_counter_inlining_threshold) { |
| 580 return; | 583 return; |
| 581 } | 584 } |
| 582 // Create two call site collections to swap between. | 585 // Create two call site collections to swap between. |
| 583 CallSites sites1(caller_graph_, inlining_depth_threshold_); | 586 CallSites sites1(caller_graph_, inlining_depth_threshold_); |
| 584 CallSites sites2(caller_graph_, inlining_depth_threshold_); | 587 CallSites sites2(caller_graph_, inlining_depth_threshold_); |
| 585 CallSites* call_sites_temp = NULL; | 588 CallSites* call_sites_temp = NULL; |
| 586 collected_call_sites_ = &sites1; | 589 collected_call_sites_ = &sites1; |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 inliner_->precompiler_->TryApplyFeedback( | 828 inliner_->precompiler_->TryApplyFeedback( |
| 826 parsed_function->function(), callee_graph); | 829 parsed_function->function(), callee_graph); |
| 827 } | 830 } |
| 828 } | 831 } |
| 829 #endif | 832 #endif |
| 830 | 833 |
| 831 // The parameter stubs are a copy of the actual arguments providing | 834 // The parameter stubs are a copy of the actual arguments providing |
| 832 // concrete information about the values, for example constant values, | 835 // concrete information about the values, for example constant values, |
| 833 // without linking between the caller and callee graphs. | 836 // without linking between the caller and callee graphs. |
| 834 // TODO(zerny): Put more information in the stubs, eg, type information. | 837 // TODO(zerny): Put more information in the stubs, eg, type information. |
| 838 const intptr_t first_actual_param_index = call_data->first_param_index; | |
| 839 const intptr_t inlined_type_args_param = | |
| 840 (FLAG_reify_generic_functions && function.IsGeneric()) ? 1 : 0; | |
| 841 const intptr_t num_inlined_params = | |
| 842 inlined_type_args_param + function.NumParameters(); | |
| 835 ZoneGrowableArray<Definition*>* param_stubs = | 843 ZoneGrowableArray<Definition*>* param_stubs = |
| 836 new (Z) ZoneGrowableArray<Definition*>(function.NumParameters()); | 844 new (Z) ZoneGrowableArray<Definition*>(num_inlined_params); |
| 837 | 845 |
| 846 // Create a ConstantInstr as Definition for the type arguments, if any. | |
| 847 if (first_actual_param_index > 0) { | |
| 848 // A type argument vector is explicitly passed. | |
| 849 param_stubs->Add( | |
| 850 CreateParameterStub(-1, (*arguments)[0], callee_graph)); | |
| 851 } else if (inlined_type_args_param > 0) { | |
| 852 // No type argument vector is passed to the generic function, | |
| 853 // pass a null vector, which is the same as a vector of dynamic types. | |
| 854 param_stubs->Add(callee_graph->GetConstant(Object::ZoneHandle())); | |
| 855 } | |
| 838 // Create a parameter stub for each fixed positional parameter. | 856 // Create a parameter stub for each fixed positional parameter. |
| 839 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { | 857 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { |
| 840 param_stubs->Add( | 858 param_stubs->Add(CreateParameterStub( |
| 841 CreateParameterStub(i, (*arguments)[i], callee_graph)); | 859 i, (*arguments)[first_actual_param_index + i], callee_graph)); |
| 842 } | 860 } |
| 843 | 861 |
| 844 // If the callee has optional parameters, rebuild the argument and stub | 862 // If the callee has optional parameters, rebuild the argument and stub |
| 845 // arrays so that actual arguments are in one-to-one with the formal | 863 // arrays so that actual arguments are in one-to-one with the formal |
| 846 // parameters. | 864 // parameters. |
| 847 if (function.HasOptionalParameters()) { | 865 if (function.HasOptionalParameters()) { |
| 848 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); | 866 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); |
| 849 if (!AdjustForOptionalParameters(*parsed_function, argument_names, | 867 if (!AdjustForOptionalParameters( |
| 850 arguments, param_stubs, | 868 *parsed_function, first_actual_param_index, argument_names, |
| 851 callee_graph)) { | 869 arguments, param_stubs, callee_graph)) { |
| 852 function.set_is_inlinable(false); | 870 function.set_is_inlinable(false); |
| 853 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); | 871 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); |
| 854 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller, | 872 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller, |
| 855 &function, call_data->call); | 873 &function, call_data->call); |
| 856 return false; | 874 return false; |
| 857 } | 875 } |
| 858 } | 876 } |
| 859 | 877 |
| 860 // After treating optional parameters the actual/formal count must | 878 // After treating optional parameters the actual/formal count must |
| 861 // match. | 879 // match. |
| 862 // TODO(regis): Consider type arguments in arguments. | 880 ASSERT(arguments->length() == |
| 863 if (arguments->length() != function.NumParameters()) { | 881 first_actual_param_index + function.NumParameters()); |
| 864 ASSERT(function.IsGeneric()); | 882 ASSERT(param_stubs->length() == |
| 865 ASSERT(arguments->length() == function.NumParameters() + 1); | 883 inlined_type_args_param + callee_graph->parameter_count()); |
| 866 TRACE_INLINING( | |
| 867 THR_Print(" Bailout: unsupported type arguments\n")); | |
| 868 PRINT_INLINING_TREE("Unsupported type arguments", &call_data->caller, | |
| 869 &function, call_data->call); | |
| 870 return false; | |
| 871 } | |
| 872 ASSERT(param_stubs->length() == callee_graph->parameter_count()); | |
| 873 | 884 |
| 874 // Update try-index of the callee graph. | 885 // Update try-index of the callee graph. |
| 875 BlockEntryInstr* call_block = call_data->call->GetBlock(); | 886 BlockEntryInstr* call_block = call_data->call->GetBlock(); |
| 876 if (call_block->InsideTryBlock()) { | 887 if (call_block->InsideTryBlock()) { |
| 877 intptr_t try_index = call_block->try_index(); | 888 intptr_t try_index = call_block->try_index(); |
| 878 for (BlockIterator it = callee_graph->reverse_postorder_iterator(); | 889 for (BlockIterator it = callee_graph->reverse_postorder_iterator(); |
| 879 !it.Done(); it.Advance()) { | 890 !it.Done(); it.Advance()) { |
| 880 BlockEntryInstr* block = it.Current(); | 891 BlockEntryInstr* block = it.Current(); |
| 881 block->set_try_index(try_index); | 892 block->set_try_index(try_index); |
| 882 } | 893 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1016 } | 1027 } |
| 1017 // When inlined, we add the deferred prefixes of the callee to the | 1028 // When inlined, we add the deferred prefixes of the callee to the |
| 1018 // caller's list of deferred prefixes. | 1029 // caller's list of deferred prefixes. |
| 1019 caller_graph()->AddToDeferredPrefixes( | 1030 caller_graph()->AddToDeferredPrefixes( |
| 1020 callee_graph->deferred_prefixes()); | 1031 callee_graph->deferred_prefixes()); |
| 1021 | 1032 |
| 1022 FlowGraphInliner::SetInliningId( | 1033 FlowGraphInliner::SetInliningId( |
| 1023 callee_graph, | 1034 callee_graph, |
| 1024 inliner_->NextInlineId(callee_graph->function(), | 1035 inliner_->NextInlineId(callee_graph->function(), |
| 1025 call_data->call->token_pos(), | 1036 call_data->call->token_pos(), |
| 1026 call_data->caller_inlining_id_)); | 1037 call_data->caller_inlining_id)); |
| 1027 TRACE_INLINING(THR_Print(" Success\n")); | 1038 TRACE_INLINING(THR_Print(" Success\n")); |
| 1028 TRACE_INLINING(THR_Print(" with size %" Pd "\n", | 1039 TRACE_INLINING(THR_Print(" with size %" Pd "\n", |
| 1029 function.optimized_instruction_count())); | 1040 function.optimized_instruction_count())); |
| 1030 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call); | 1041 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call); |
| 1031 return true; | 1042 return true; |
| 1032 } else { | 1043 } else { |
| 1033 error = thread()->sticky_error(); | 1044 error = thread()->sticky_error(); |
| 1034 thread()->clear_sticky_error(); | 1045 thread()->clear_sticky_error(); |
| 1035 | 1046 |
| 1036 if (error.IsLanguageError() && | 1047 if (error.IsLanguageError() && |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1129 FlowGraph* callee_graph = call_data->callee_graph; | 1140 FlowGraph* callee_graph = call_data->callee_graph; |
| 1130 TargetEntryInstr* callee_entry = | 1141 TargetEntryInstr* callee_entry = |
| 1131 callee_graph->graph_entry()->normal_entry(); | 1142 callee_graph->graph_entry()->normal_entry(); |
| 1132 // Plug result in the caller graph. | 1143 // Plug result in the caller graph. |
| 1133 InlineExitCollector* exit_collector = call_data->exit_collector; | 1144 InlineExitCollector* exit_collector = call_data->exit_collector; |
| 1134 exit_collector->PrepareGraphs(callee_graph); | 1145 exit_collector->PrepareGraphs(callee_graph); |
| 1135 exit_collector->ReplaceCall(callee_entry); | 1146 exit_collector->ReplaceCall(callee_entry); |
| 1136 | 1147 |
| 1137 // Replace each stub with the actual argument or the caller's constant. | 1148 // Replace each stub with the actual argument or the caller's constant. |
| 1138 // Nulls denote optional parameters for which no actual was given. | 1149 // Nulls denote optional parameters for which no actual was given. |
| 1150 const intptr_t first_param_index = call_data->first_param_index; | |
| 1151 // When first_param_index > 0, the stub and actual argument processed in the | |
| 1152 // first loop iteration represent a passed-in type argument vector. | |
| 1139 GrowableArray<Value*>* arguments = call_data->arguments; | 1153 GrowableArray<Value*>* arguments = call_data->arguments; |
| 1140 for (intptr_t i = 0; i < arguments->length(); ++i) { | 1154 for (intptr_t i = 0; i < arguments->length(); ++i) { |
|
Vyacheslav Egorov (Google)
2017/06/12 10:52:11
Hi Regis!
I briefly looked at the crash: it seems
regis
2017/06/12 20:37:34
Thanks a lot Slava!
Indeed, these arrays are out o
| |
| 1141 Definition* stub = (*call_data->parameter_stubs)[i]; | 1155 Definition* stub = (*call_data->parameter_stubs)[i]; |
| 1142 Value* actual = (*arguments)[i]; | 1156 Value* actual = (*arguments)[i]; |
| 1143 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); | 1157 if (actual != NULL) { |
| 1158 stub->ReplaceUsesWith(actual->definition()); | |
| 1159 } | |
| 1144 } | 1160 } |
| 1145 | 1161 |
| 1146 // Remove push arguments of the call. | 1162 // Remove push arguments of the call. |
| 1147 Definition* call = call_data->call; | 1163 Definition* call = call_data->call; |
| 1148 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 1164 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 1149 PushArgumentInstr* push = call->PushArgumentAt(i); | 1165 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 1150 push->ReplaceUsesWith(push->value()->definition()); | 1166 push->ReplaceUsesWith(push->value()->definition()); |
| 1151 push->RemoveFromGraph(); | 1167 push->RemoveFromGraph(); |
| 1152 } | 1168 } |
| 1153 | 1169 |
| 1154 // Replace remaining constants with uses by constants in the caller's | 1170 // Replace remaining constants with uses by constants in the caller's |
| 1155 // initial definitions. | 1171 // initial definitions. |
| 1156 GrowableArray<Definition*>* defns = | 1172 GrowableArray<Definition*>* defns = |
| 1157 callee_graph->graph_entry()->initial_definitions(); | 1173 callee_graph->graph_entry()->initial_definitions(); |
| 1158 for (intptr_t i = 0; i < defns->length(); ++i) { | 1174 for (intptr_t i = 0; i < defns->length(); ++i) { |
| 1159 ConstantInstr* constant = (*defns)[i]->AsConstant(); | 1175 ConstantInstr* constant = (*defns)[i]->AsConstant(); |
| 1160 if ((constant != NULL) && constant->HasUses()) { | 1176 if ((constant != NULL) && constant->HasUses()) { |
| 1161 constant->ReplaceUsesWith( | 1177 constant->ReplaceUsesWith( |
| 1162 caller_graph_->GetConstant(constant->value())); | 1178 caller_graph_->GetConstant(constant->value())); |
| 1163 } | 1179 } |
| 1164 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); | 1180 SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter(); |
| 1165 if ((context != NULL) && context->HasUses()) { | 1181 if ((param != NULL) && param->HasUses()) { |
| 1166 ASSERT(call->IsClosureCall()); | 1182 if (param->kind() == SpecialParameterInstr::kContext) { |
| 1167 LoadFieldInstr* context_load = new (Z) LoadFieldInstr( | 1183 ASSERT(call->IsClosureCall()); |
| 1168 new Value((*arguments)[0]->definition()), Closure::context_offset(), | 1184 LoadFieldInstr* context_load = new (Z) LoadFieldInstr( |
| 1169 AbstractType::ZoneHandle(zone(), AbstractType::null()), | 1185 new Value((*arguments)[first_param_index]->definition()), |
| 1170 call_data->call->token_pos()); | 1186 Closure::context_offset(), |
| 1171 context_load->set_is_immutable(true); | 1187 AbstractType::ZoneHandle(zone(), AbstractType::null()), |
| 1172 context_load->set_ssa_temp_index(caller_graph_->alloc_ssa_temp_index()); | 1188 call_data->call->token_pos()); |
| 1173 context_load->InsertBefore(callee_entry->next()); | 1189 context_load->set_is_immutable(true); |
| 1174 context->ReplaceUsesWith(context_load); | 1190 context_load->set_ssa_temp_index( |
| 1191 caller_graph_->alloc_ssa_temp_index()); | |
| 1192 context_load->InsertBefore(callee_entry->next()); | |
| 1193 param->ReplaceUsesWith(context_load); | |
| 1194 } else { | |
| 1195 ASSERT(param->kind() == SpecialParameterInstr::kTypeArgs); | |
| 1196 Definition* type_args; | |
| 1197 if (first_param_index > 0) { | |
| 1198 type_args = (*arguments)[0]->definition(); | |
| 1199 } else { | |
| 1200 type_args = callee_graph->constant_null(); | |
| 1201 } | |
| 1202 param->ReplaceUsesWith(type_args); | |
| 1203 } | |
| 1175 } | 1204 } |
| 1176 } | 1205 } |
| 1177 | 1206 |
| 1178 // Check that inlining maintains use lists. | 1207 // Check that inlining maintains use lists. |
| 1179 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists()); | 1208 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists()); |
| 1180 } | 1209 } |
| 1181 | 1210 |
| 1182 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) { | 1211 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) { |
| 1183 intptr_t count = 0; | 1212 intptr_t count = 0; |
| 1184 for (intptr_t i = 0; i < arguments.length(); i++) { | 1213 for (intptr_t i = 0; i < arguments.length(); i++) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1224 } | 1253 } |
| 1225 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(), | 1254 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(), |
| 1226 &call->function(), call); | 1255 &call->function(), call); |
| 1227 continue; | 1256 continue; |
| 1228 } | 1257 } |
| 1229 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1258 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1230 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1259 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1231 arguments.Add(call->PushArgumentAt(i)->value()); | 1260 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1232 } | 1261 } |
| 1233 InlinedCallData call_data( | 1262 InlinedCallData call_data( |
| 1234 call, &arguments, call_info[call_idx].caller(), | 1263 call, call->FirstParamIndex(), &arguments, |
| 1264 call_info[call_idx].caller(), | |
| 1235 call_info[call_idx].caller_graph->inlining_id()); | 1265 call_info[call_idx].caller_graph->inlining_id()); |
| 1236 if (TryInlining(call->function(), call->argument_names(), &call_data)) { | 1266 if (TryInlining(call->function(), call->argument_names(), &call_data)) { |
| 1237 InlineCall(&call_data); | 1267 InlineCall(&call_data); |
| 1238 } | 1268 } |
| 1239 } | 1269 } |
| 1240 } | 1270 } |
| 1241 | 1271 |
| 1242 void InlineClosureCalls() { | 1272 void InlineClosureCalls() { |
| 1243 const GrowableArray<CallSites::ClosureCallInfo>& call_info = | 1273 const GrowableArray<CallSites::ClosureCallInfo>& call_info = |
| 1244 inlining_call_sites_->closure_calls(); | 1274 inlining_call_sites_->closure_calls(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1270 call->ArgumentCount() < target.num_fixed_parameters()) { | 1300 call->ArgumentCount() < target.num_fixed_parameters()) { |
| 1271 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n")); | 1301 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n")); |
| 1272 continue; | 1302 continue; |
| 1273 } | 1303 } |
| 1274 | 1304 |
| 1275 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1305 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1276 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1306 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1277 arguments.Add(call->PushArgumentAt(i)->value()); | 1307 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1278 } | 1308 } |
| 1279 InlinedCallData call_data( | 1309 InlinedCallData call_data( |
| 1280 call, &arguments, call_info[call_idx].caller(), | 1310 call, call->FirstParamIndex(), &arguments, |
| 1311 call_info[call_idx].caller(), | |
| 1281 call_info[call_idx].caller_graph->inlining_id()); | 1312 call_info[call_idx].caller_graph->inlining_id()); |
| 1282 if (TryInlining(target, call->argument_names(), &call_data)) { | 1313 if (TryInlining(target, call->argument_names(), &call_data)) { |
| 1283 InlineCall(&call_data); | 1314 InlineCall(&call_data); |
| 1284 } | 1315 } |
| 1285 } | 1316 } |
| 1286 } | 1317 } |
| 1287 | 1318 |
| 1288 void InlineInstanceCalls() { | 1319 void InlineInstanceCalls() { |
| 1289 const GrowableArray<CallSites::InstanceCallInfo>& call_info = | 1320 const GrowableArray<CallSites::InstanceCallInfo>& call_info = |
| 1290 inlining_call_sites_->instance_calls(); | 1321 inlining_call_sites_->instance_calls(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1301 } | 1332 } |
| 1302 const Function& cl = call_info[call_idx].caller(); | 1333 const Function& cl = call_info[call_idx].caller(); |
| 1303 intptr_t caller_inlining_id = | 1334 intptr_t caller_inlining_id = |
| 1304 call_info[call_idx].caller_graph->inlining_id(); | 1335 call_info[call_idx].caller_graph->inlining_id(); |
| 1305 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); | 1336 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); |
| 1306 inliner.Inline(); | 1337 inliner.Inline(); |
| 1307 } | 1338 } |
| 1308 } | 1339 } |
| 1309 | 1340 |
| 1310 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, | 1341 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, |
| 1342 intptr_t first_param_index, | |
| 1311 const Array& argument_names, | 1343 const Array& argument_names, |
| 1312 GrowableArray<Value*>* arguments, | 1344 GrowableArray<Value*>* arguments, |
| 1313 ZoneGrowableArray<Definition*>* param_stubs, | 1345 ZoneGrowableArray<Definition*>* param_stubs, |
| 1314 FlowGraph* callee_graph) { | 1346 FlowGraph* callee_graph) { |
| 1315 const Function& function = parsed_function.function(); | 1347 const Function& function = parsed_function.function(); |
| 1316 // The language and this code does not support both optional positional | 1348 // The language and this code does not support both optional positional |
| 1317 // and optional named parameters for the same function. | 1349 // and optional named parameters for the same function. |
| 1318 ASSERT(!function.HasOptionalPositionalParameters() || | 1350 ASSERT(!function.HasOptionalPositionalParameters() || |
| 1319 !function.HasOptionalNamedParameters()); | 1351 !function.HasOptionalNamedParameters()); |
| 1320 | 1352 |
| 1321 // TODO(regis): Consider type arguments in arguments. | |
| 1322 intptr_t arg_count = arguments->length(); | 1353 intptr_t arg_count = arguments->length(); |
| 1323 intptr_t param_count = function.NumParameters(); | 1354 intptr_t param_count = function.NumParameters(); |
| 1324 intptr_t fixed_param_count = function.num_fixed_parameters(); | 1355 intptr_t fixed_param_count = function.num_fixed_parameters(); |
| 1325 ASSERT(fixed_param_count <= arg_count); | 1356 ASSERT(fixed_param_count <= arg_count - first_param_index); |
| 1326 ASSERT(arg_count <= param_count); | 1357 ASSERT(arg_count - first_param_index <= param_count); |
| 1327 | 1358 |
| 1328 if (function.HasOptionalPositionalParameters()) { | 1359 if (function.HasOptionalPositionalParameters()) { |
| 1329 // Create a stub for each optional positional parameters with an actual. | 1360 // Create a stub for each optional positional parameters with an actual. |
| 1330 for (intptr_t i = fixed_param_count; i < arg_count; ++i) { | 1361 for (intptr_t i = first_param_index + fixed_param_count; i < arg_count; |
| 1362 ++i) { | |
| 1331 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); | 1363 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); |
| 1332 } | 1364 } |
| 1333 ASSERT(function.NumOptionalPositionalParameters() == | 1365 ASSERT(function.NumOptionalPositionalParameters() == |
| 1334 (param_count - fixed_param_count)); | 1366 (param_count - fixed_param_count)); |
| 1335 // For each optional positional parameter without an actual, add its | 1367 // For each optional positional parameter without an actual, add its |
| 1336 // default value. | 1368 // default value. |
| 1337 for (intptr_t i = arg_count; i < param_count; ++i) { | 1369 for (intptr_t i = arg_count - first_param_index; i < param_count; ++i) { |
| 1338 const Instance& object = | 1370 const Instance& object = |
| 1339 parsed_function.DefaultParameterValueAt(i - fixed_param_count); | 1371 parsed_function.DefaultParameterValueAt(i - fixed_param_count); |
| 1340 ConstantInstr* constant = new (Z) ConstantInstr(object); | 1372 ConstantInstr* constant = new (Z) ConstantInstr(object); |
| 1341 arguments->Add(NULL); | 1373 arguments->Add(NULL); |
| 1342 param_stubs->Add(constant); | 1374 param_stubs->Add(constant); |
| 1343 } | 1375 } |
| 1344 return true; | 1376 return true; |
| 1345 } | 1377 } |
| 1346 | 1378 |
| 1347 ASSERT(function.HasOptionalNamedParameters()); | 1379 ASSERT(function.HasOptionalNamedParameters()); |
| 1348 | 1380 |
| 1349 // Passed arguments must match fixed parameters plus named arguments. | 1381 // Passed arguments (not counting optional type args) must match fixed |
| 1382 // parameters plus named arguments. | |
| 1350 intptr_t argument_names_count = | 1383 intptr_t argument_names_count = |
| 1351 (argument_names.IsNull()) ? 0 : argument_names.Length(); | 1384 (argument_names.IsNull()) ? 0 : argument_names.Length(); |
| 1352 ASSERT(arg_count == (fixed_param_count + argument_names_count)); | 1385 ASSERT((arg_count - first_param_index) == |
| 1386 (fixed_param_count + argument_names_count)); | |
| 1353 | 1387 |
| 1354 // Fast path when no optional named parameters are given. | 1388 // Fast path when no optional named parameters are given. |
| 1355 if (argument_names_count == 0) { | 1389 if (argument_names_count == 0) { |
| 1356 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) { | 1390 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) { |
| 1357 arguments->Add(NULL); | 1391 arguments->Add(NULL); |
| 1358 param_stubs->Add(GetDefaultValue(i, parsed_function)); | 1392 param_stubs->Add(GetDefaultValue(i, parsed_function)); |
| 1359 } | 1393 } |
| 1360 return true; | 1394 return true; |
| 1361 } | 1395 } |
| 1362 | 1396 |
| 1363 // Otherwise, build a collection of name/argument pairs. | 1397 // Otherwise, build a collection of name/argument pairs. |
| 1364 GrowableArray<NamedArgument> named_args(argument_names_count); | 1398 GrowableArray<NamedArgument> named_args(argument_names_count); |
| 1365 for (intptr_t i = 0; i < argument_names.Length(); ++i) { | 1399 for (intptr_t i = 0; i < argument_names.Length(); ++i) { |
| 1366 String& arg_name = String::Handle(caller_graph_->zone()); | 1400 String& arg_name = String::Handle(caller_graph_->zone()); |
| 1367 arg_name ^= argument_names.At(i); | 1401 arg_name ^= argument_names.At(i); |
| 1368 named_args.Add( | 1402 named_args.Add(NamedArgument( |
| 1369 NamedArgument(&arg_name, (*arguments)[i + fixed_param_count])); | 1403 &arg_name, (*arguments)[first_param_index + fixed_param_count + i])); |
| 1370 } | 1404 } |
| 1371 | 1405 |
| 1372 // Truncate the arguments array to just fixed parameters. | 1406 // Truncate the arguments array to just type args and fixed parameters. |
| 1373 arguments->TruncateTo(fixed_param_count); | 1407 arguments->TruncateTo(first_param_index + fixed_param_count); |
| 1374 | 1408 |
| 1375 // For each optional named parameter, add the actual argument or its | 1409 // For each optional named parameter, add the actual argument or its |
| 1376 // default if no argument is passed. | 1410 // default if no argument is passed. |
| 1377 intptr_t match_count = 0; | 1411 intptr_t match_count = 0; |
| 1378 for (intptr_t i = fixed_param_count; i < param_count; ++i) { | 1412 for (intptr_t i = fixed_param_count; i < param_count; ++i) { |
| 1379 String& param_name = String::Handle(function.ParameterNameAt(i)); | 1413 String& param_name = String::Handle(function.ParameterNameAt(i)); |
| 1380 // Search for and add the named argument. | 1414 // Search for and add the named argument. |
| 1381 Value* arg = NULL; | 1415 Value* arg = NULL; |
| 1382 for (intptr_t j = 0; j < named_args.length(); ++j) { | 1416 for (intptr_t j = 0; j < named_args.length(); ++j) { |
| 1383 if (param_name.Equals(*named_args[j].name)) { | 1417 if (param_name.Equals(*named_args[j].name)) { |
| 1384 arg = named_args[j].value; | 1418 arg = named_args[j].value; |
| 1385 match_count++; | 1419 match_count++; |
| 1386 break; | 1420 break; |
| 1387 } | 1421 } |
| 1388 } | 1422 } |
| 1389 arguments->Add(arg); | 1423 arguments->Add(arg); |
| 1390 // Create a stub for the argument or use the parameter's default value. | 1424 // Create a stub for the argument or use the parameter's default value. |
| 1391 if (arg != NULL) { | 1425 if (arg != NULL) { |
| 1392 param_stubs->Add(CreateParameterStub(i, arg, callee_graph)); | 1426 param_stubs->Add( |
| 1427 CreateParameterStub(first_param_index + i, arg, callee_graph)); | |
| 1393 } else { | 1428 } else { |
| 1394 param_stubs->Add( | 1429 param_stubs->Add( |
| 1395 GetDefaultValue(i - fixed_param_count, parsed_function)); | 1430 GetDefaultValue(i - fixed_param_count, parsed_function)); |
| 1396 } | 1431 } |
| 1397 } | 1432 } |
| 1398 return argument_names_count == match_count; | 1433 return argument_names_count == match_count; |
| 1399 } | 1434 } |
| 1400 | 1435 |
| 1401 FlowGraphInliner* inliner_; | 1436 FlowGraphInliner* inliner_; |
| 1402 FlowGraph* caller_graph_; | 1437 FlowGraph* caller_graph_; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1525 target_info.IsSingleCid() && | 1560 target_info.IsSingleCid() && |
| 1526 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { | 1561 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { |
| 1527 owner_->inlined_ = true; | 1562 owner_->inlined_ = true; |
| 1528 return true; | 1563 return true; |
| 1529 } | 1564 } |
| 1530 | 1565 |
| 1531 GrowableArray<Value*> arguments(call_->ArgumentCount()); | 1566 GrowableArray<Value*> arguments(call_->ArgumentCount()); |
| 1532 for (int i = 0; i < call_->ArgumentCount(); ++i) { | 1567 for (int i = 0; i < call_->ArgumentCount(); ++i) { |
| 1533 arguments.Add(call_->PushArgumentAt(i)->value()); | 1568 arguments.Add(call_->PushArgumentAt(i)->value()); |
| 1534 } | 1569 } |
| 1535 InlinedCallData call_data(call_, &arguments, caller_function_, | 1570 InlinedCallData call_data(call_, call_->instance_call()->FirstParamIndex(), |
| 1536 caller_inlining_id_); | 1571 &arguments, caller_function_, caller_inlining_id_); |
| 1537 Function& target = Function::ZoneHandle(zone(), target_info.target->raw()); | 1572 Function& target = Function::ZoneHandle(zone(), target_info.target->raw()); |
| 1538 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), | 1573 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), |
| 1539 &call_data)) { | 1574 &call_data)) { |
| 1540 return false; | 1575 return false; |
| 1541 } | 1576 } |
| 1542 | 1577 |
| 1543 FlowGraph* callee_graph = call_data.callee_graph; | 1578 FlowGraph* callee_graph = call_data.callee_graph; |
| 1544 call_data.exit_collector->PrepareGraphs(callee_graph); | 1579 call_data.exit_collector->PrepareGraphs(callee_graph); |
| 1545 inlined_entries_.Add(callee_graph->graph_entry()); | 1580 inlined_entries_.Add(callee_graph->graph_entry()); |
| 1546 exit_collector_->Union(call_data.exit_collector); | 1581 exit_collector_->Union(call_data.exit_collector); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1568 } | 1603 } |
| 1569 } | 1604 } |
| 1570 GrowableArray<Definition*>* defns = | 1605 GrowableArray<Definition*>* defns = |
| 1571 callee_graph->graph_entry()->initial_definitions(); | 1606 callee_graph->graph_entry()->initial_definitions(); |
| 1572 for (intptr_t i = 0; i < defns->length(); ++i) { | 1607 for (intptr_t i = 0; i < defns->length(); ++i) { |
| 1573 ConstantInstr* constant = (*defns)[i]->AsConstant(); | 1608 ConstantInstr* constant = (*defns)[i]->AsConstant(); |
| 1574 if ((constant != NULL) && constant->HasUses()) { | 1609 if ((constant != NULL) && constant->HasUses()) { |
| 1575 constant->ReplaceUsesWith( | 1610 constant->ReplaceUsesWith( |
| 1576 owner_->caller_graph()->GetConstant(constant->value())); | 1611 owner_->caller_graph()->GetConstant(constant->value())); |
| 1577 } | 1612 } |
| 1578 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); | 1613 SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter(); |
| 1579 if ((context != NULL) && context->HasUses()) { | 1614 if ((param != NULL) && param->HasUses()) { |
| 1580 ASSERT(call_data.call->IsClosureCall()); | 1615 if (param->kind() == SpecialParameterInstr::kContext) { |
| 1581 LoadFieldInstr* context_load = new (Z) | 1616 ASSERT(call_data.call->IsClosureCall()); |
| 1582 LoadFieldInstr(new Value(redefinition), Closure::context_offset(), | 1617 LoadFieldInstr* context_load = new (Z) LoadFieldInstr( |
| 1583 AbstractType::ZoneHandle(zone(), AbstractType::null()), | 1618 new Value(redefinition), Closure::context_offset(), |
| 1584 call_data.call->token_pos()); | 1619 AbstractType::ZoneHandle(zone(), AbstractType::null()), |
| 1585 context_load->set_is_immutable(true); | 1620 call_data.call->token_pos()); |
| 1586 context_load->set_ssa_temp_index( | 1621 context_load->set_is_immutable(true); |
| 1587 owner_->caller_graph()->alloc_ssa_temp_index()); | 1622 context_load->set_ssa_temp_index( |
| 1588 context_load->InsertAfter(redefinition); | 1623 owner_->caller_graph()->alloc_ssa_temp_index()); |
| 1589 context->ReplaceUsesWith(context_load); | 1624 context_load->InsertAfter(redefinition); |
| 1625 param->ReplaceUsesWith(context_load); | |
| 1626 } else { | |
| 1627 ASSERT(param->kind() == SpecialParameterInstr::kTypeArgs); | |
| 1628 UNIMPLEMENTED(); // TODO(regis): Why am I not hitting this? No uses? | |
| 1629 } | |
| 1590 } | 1630 } |
| 1591 } | 1631 } |
| 1592 return true; | 1632 return true; |
| 1593 } | 1633 } |
| 1594 | 1634 |
| 1595 | 1635 |
| 1596 static Instruction* AppendInstruction(Instruction* first, Instruction* second) { | 1636 static Instruction* AppendInstruction(Instruction* first, Instruction* second) { |
| 1597 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) { | 1637 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) { |
| 1598 Value* input = second->InputAt(i); | 1638 Value* input = second->InputAt(i); |
| 1599 input->definition()->AddInputUse(input); | 1639 input->definition()->AddInputUse(input); |
| (...skipping 2170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3770 } | 3810 } |
| 3771 | 3811 |
| 3772 default: | 3812 default: |
| 3773 return false; | 3813 return false; |
| 3774 } | 3814 } |
| 3775 } | 3815 } |
| 3776 | 3816 |
| 3777 | 3817 |
| 3778 } // namespace dart | 3818 } // namespace dart |
| 3779 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 3819 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |