| 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 inliner_->precompiler_->TryApplyFeedback( | 826 inliner_->precompiler_->TryApplyFeedback( |
| 824 parsed_function->function(), callee_graph); | 827 parsed_function->function(), callee_graph); |
| 825 } | 828 } |
| 826 } | 829 } |
| 827 #endif | 830 #endif |
| 828 | 831 |
| 829 // The parameter stubs are a copy of the actual arguments providing | 832 // The parameter stubs are a copy of the actual arguments providing |
| 830 // concrete information about the values, for example constant values, | 833 // concrete information about the values, for example constant values, |
| 831 // without linking between the caller and callee graphs. | 834 // without linking between the caller and callee graphs. |
| 832 // TODO(zerny): Put more information in the stubs, eg, type information. | 835 // TODO(zerny): Put more information in the stubs, eg, type information. |
| 836 const intptr_t first_param_index = call_data->first_param_index; |
| 837 const intptr_t num_params = |
| 838 first_param_index + function.NumParameters(); |
| 833 ZoneGrowableArray<Definition*>* param_stubs = | 839 ZoneGrowableArray<Definition*>* param_stubs = |
| 834 new (Z) ZoneGrowableArray<Definition*>(function.NumParameters()); | 840 new (Z) ZoneGrowableArray<Definition*>(num_params); |
| 835 | 841 |
| 842 // Create a ConstantInstr as Definition for the type arguments, if any. |
| 843 Definition* type_args_stub = NULL; |
| 844 if (first_param_index > 0) { |
| 845 type_args_stub = |
| 846 CreateParameterStub(0, (*arguments)[0], callee_graph); |
| 847 } |
| 836 // Create a parameter stub for each fixed positional parameter. | 848 // Create a parameter stub for each fixed positional parameter. |
| 837 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { | 849 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { |
| 838 param_stubs->Add( | 850 param_stubs->Add(CreateParameterStub( |
| 839 CreateParameterStub(i, (*arguments)[i], callee_graph)); | 851 i, (*arguments)[first_param_index + i], callee_graph)); |
| 840 } | 852 } |
| 841 | 853 |
| 842 // If the callee has optional parameters, rebuild the argument and stub | 854 // If the callee has optional parameters, rebuild the argument and stub |
| 843 // arrays so that actual arguments are in one-to-one with the formal | 855 // arrays so that actual arguments are in one-to-one with the formal |
| 844 // parameters. | 856 // parameters. |
| 845 if (function.HasOptionalParameters()) { | 857 if (function.HasOptionalParameters()) { |
| 846 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); | 858 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); |
| 847 if (!AdjustForOptionalParameters(*parsed_function, argument_names, | 859 if (!AdjustForOptionalParameters(*parsed_function, first_param_index, |
| 848 arguments, param_stubs, | 860 argument_names, arguments, |
| 849 callee_graph)) { | 861 param_stubs, callee_graph)) { |
| 850 function.set_is_inlinable(false); | 862 function.set_is_inlinable(false); |
| 851 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); | 863 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); |
| 852 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller, | 864 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller, |
| 853 &function, call_data->call); | 865 &function, call_data->call); |
| 854 return false; | 866 return false; |
| 855 } | 867 } |
| 856 } | 868 } |
| 857 | 869 |
| 858 // After treating optional parameters the actual/formal count must | 870 // After treating optional parameters the actual/formal count must |
| 859 // match. | 871 // match. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 880 } | 892 } |
| 881 } | 893 } |
| 882 | 894 |
| 883 BlockScheduler block_scheduler(callee_graph); | 895 BlockScheduler block_scheduler(callee_graph); |
| 884 block_scheduler.AssignEdgeWeights(); | 896 block_scheduler.AssignEdgeWeights(); |
| 885 | 897 |
| 886 { | 898 { |
| 887 CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer); | 899 CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer); |
| 888 // Compute SSA on the callee graph, catching bailouts. | 900 // Compute SSA on the callee graph, catching bailouts. |
| 889 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), | 901 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), |
| 890 param_stubs); | 902 param_stubs, type_args_stub); |
| 891 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | 903 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 892 } | 904 } |
| 893 | 905 |
| 894 { | 906 { |
| 895 CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer); | 907 CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer); |
| 896 // TODO(fschneider): Improve suppression of speculative inlining. | 908 // TODO(fschneider): Improve suppression of speculative inlining. |
| 897 // Deopt-ids overlap between caller and callee. | 909 // Deopt-ids overlap between caller and callee. |
| 898 if (FLAG_precompiled_mode) { | 910 if (FLAG_precompiled_mode) { |
| 899 #ifdef DART_PRECOMPILER | 911 #ifdef DART_PRECOMPILER |
| 900 AotOptimizer optimizer(inliner_->precompiler_, callee_graph, | 912 AotOptimizer optimizer(inliner_->precompiler_, callee_graph, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 } | 1026 } |
| 1015 // When inlined, we add the deferred prefixes of the callee to the | 1027 // When inlined, we add the deferred prefixes of the callee to the |
| 1016 // caller's list of deferred prefixes. | 1028 // caller's list of deferred prefixes. |
| 1017 caller_graph()->AddToDeferredPrefixes( | 1029 caller_graph()->AddToDeferredPrefixes( |
| 1018 callee_graph->deferred_prefixes()); | 1030 callee_graph->deferred_prefixes()); |
| 1019 | 1031 |
| 1020 FlowGraphInliner::SetInliningId( | 1032 FlowGraphInliner::SetInliningId( |
| 1021 callee_graph, | 1033 callee_graph, |
| 1022 inliner_->NextInlineId(callee_graph->function(), | 1034 inliner_->NextInlineId(callee_graph->function(), |
| 1023 call_data->call->token_pos(), | 1035 call_data->call->token_pos(), |
| 1024 call_data->caller_inlining_id_)); | 1036 call_data->caller_inlining_id)); |
| 1025 TRACE_INLINING(THR_Print(" Success\n")); | 1037 TRACE_INLINING(THR_Print(" Success\n")); |
| 1026 TRACE_INLINING(THR_Print(" with size %" Pd "\n", | 1038 TRACE_INLINING(THR_Print(" with size %" Pd "\n", |
| 1027 function.optimized_instruction_count())); | 1039 function.optimized_instruction_count())); |
| 1028 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call); | 1040 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call); |
| 1029 return true; | 1041 return true; |
| 1030 } else { | 1042 } else { |
| 1031 error = thread()->sticky_error(); | 1043 error = thread()->sticky_error(); |
| 1032 thread()->clear_sticky_error(); | 1044 thread()->clear_sticky_error(); |
| 1033 | 1045 |
| 1034 if (error.IsLanguageError() && | 1046 if (error.IsLanguageError() && |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 FlowGraph* callee_graph = call_data->callee_graph; | 1139 FlowGraph* callee_graph = call_data->callee_graph; |
| 1128 TargetEntryInstr* callee_entry = | 1140 TargetEntryInstr* callee_entry = |
| 1129 callee_graph->graph_entry()->normal_entry(); | 1141 callee_graph->graph_entry()->normal_entry(); |
| 1130 // Plug result in the caller graph. | 1142 // Plug result in the caller graph. |
| 1131 InlineExitCollector* exit_collector = call_data->exit_collector; | 1143 InlineExitCollector* exit_collector = call_data->exit_collector; |
| 1132 exit_collector->PrepareGraphs(callee_graph); | 1144 exit_collector->PrepareGraphs(callee_graph); |
| 1133 exit_collector->ReplaceCall(callee_entry); | 1145 exit_collector->ReplaceCall(callee_entry); |
| 1134 | 1146 |
| 1135 // Replace each stub with the actual argument or the caller's constant. | 1147 // Replace each stub with the actual argument or the caller's constant. |
| 1136 // Nulls denote optional parameters for which no actual was given. | 1148 // Nulls denote optional parameters for which no actual was given. |
| 1149 const intptr_t first_param_index = call_data->first_param_index; |
| 1137 GrowableArray<Value*>* arguments = call_data->arguments; | 1150 GrowableArray<Value*>* arguments = call_data->arguments; |
| 1138 for (intptr_t i = 0; i < arguments->length(); ++i) { | 1151 for (intptr_t i = 0; i < arguments->length() - first_param_index; ++i) { |
| 1139 Definition* stub = (*call_data->parameter_stubs)[i]; | 1152 Definition* stub = (*call_data->parameter_stubs)[i]; |
| 1140 Value* actual = (*arguments)[i]; | 1153 Value* actual = (*arguments)[first_param_index + i]; |
| 1141 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); | 1154 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); |
| 1142 } | 1155 } |
| 1143 | 1156 |
| 1144 // Remove push arguments of the call. | 1157 // Remove push arguments of the call. |
| 1145 Definition* call = call_data->call; | 1158 Definition* call = call_data->call; |
| 1146 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 1159 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 1147 PushArgumentInstr* push = call->PushArgumentAt(i); | 1160 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 1148 push->ReplaceUsesWith(push->value()->definition()); | 1161 push->ReplaceUsesWith(push->value()->definition()); |
| 1149 push->RemoveFromGraph(); | 1162 push->RemoveFromGraph(); |
| 1150 } | 1163 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1222 } | 1235 } |
| 1223 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(), | 1236 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(), |
| 1224 &call->function(), call); | 1237 &call->function(), call); |
| 1225 continue; | 1238 continue; |
| 1226 } | 1239 } |
| 1227 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1240 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1228 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1241 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1229 arguments.Add(call->PushArgumentAt(i)->value()); | 1242 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1230 } | 1243 } |
| 1231 InlinedCallData call_data( | 1244 InlinedCallData call_data( |
| 1232 call, &arguments, call_info[call_idx].caller(), | 1245 call, call->FirstParamIndex(), &arguments, |
| 1246 call_info[call_idx].caller(), |
| 1233 call_info[call_idx].caller_graph->inlining_id()); | 1247 call_info[call_idx].caller_graph->inlining_id()); |
| 1234 if (TryInlining(call->function(), call->argument_names(), &call_data)) { | 1248 if (TryInlining(call->function(), call->argument_names(), &call_data)) { |
| 1235 InlineCall(&call_data); | 1249 InlineCall(&call_data); |
| 1236 } | 1250 } |
| 1237 } | 1251 } |
| 1238 } | 1252 } |
| 1239 | 1253 |
| 1240 void InlineClosureCalls() { | 1254 void InlineClosureCalls() { |
| 1241 const GrowableArray<CallSites::ClosureCallInfo>& call_info = | 1255 const GrowableArray<CallSites::ClosureCallInfo>& call_info = |
| 1242 inlining_call_sites_->closure_calls(); | 1256 inlining_call_sites_->closure_calls(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1268 call->ArgumentCount() < target.num_fixed_parameters()) { | 1282 call->ArgumentCount() < target.num_fixed_parameters()) { |
| 1269 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n")); | 1283 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n")); |
| 1270 continue; | 1284 continue; |
| 1271 } | 1285 } |
| 1272 | 1286 |
| 1273 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1287 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1274 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1288 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1275 arguments.Add(call->PushArgumentAt(i)->value()); | 1289 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1276 } | 1290 } |
| 1277 InlinedCallData call_data( | 1291 InlinedCallData call_data( |
| 1278 call, &arguments, call_info[call_idx].caller(), | 1292 call, call->FirstParamIndex(), &arguments, |
| 1293 call_info[call_idx].caller(), |
| 1279 call_info[call_idx].caller_graph->inlining_id()); | 1294 call_info[call_idx].caller_graph->inlining_id()); |
| 1280 if (TryInlining(target, call->argument_names(), &call_data)) { | 1295 if (TryInlining(target, call->argument_names(), &call_data)) { |
| 1281 InlineCall(&call_data); | 1296 InlineCall(&call_data); |
| 1282 } | 1297 } |
| 1283 } | 1298 } |
| 1284 } | 1299 } |
| 1285 | 1300 |
| 1286 void InlineInstanceCalls() { | 1301 void InlineInstanceCalls() { |
| 1287 const GrowableArray<CallSites::InstanceCallInfo>& call_info = | 1302 const GrowableArray<CallSites::InstanceCallInfo>& call_info = |
| 1288 inlining_call_sites_->instance_calls(); | 1303 inlining_call_sites_->instance_calls(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1299 } | 1314 } |
| 1300 const Function& cl = call_info[call_idx].caller(); | 1315 const Function& cl = call_info[call_idx].caller(); |
| 1301 intptr_t caller_inlining_id = | 1316 intptr_t caller_inlining_id = |
| 1302 call_info[call_idx].caller_graph->inlining_id(); | 1317 call_info[call_idx].caller_graph->inlining_id(); |
| 1303 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); | 1318 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); |
| 1304 inliner.Inline(); | 1319 inliner.Inline(); |
| 1305 } | 1320 } |
| 1306 } | 1321 } |
| 1307 | 1322 |
| 1308 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, | 1323 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, |
| 1324 intptr_t first_param_index, |
| 1309 const Array& argument_names, | 1325 const Array& argument_names, |
| 1310 GrowableArray<Value*>* arguments, | 1326 GrowableArray<Value*>* arguments, |
| 1311 ZoneGrowableArray<Definition*>* param_stubs, | 1327 ZoneGrowableArray<Definition*>* param_stubs, |
| 1312 FlowGraph* callee_graph) { | 1328 FlowGraph* callee_graph) { |
| 1313 const Function& function = parsed_function.function(); | 1329 const Function& function = parsed_function.function(); |
| 1314 // The language and this code does not support both optional positional | 1330 // The language and this code does not support both optional positional |
| 1315 // and optional named parameters for the same function. | 1331 // and optional named parameters for the same function. |
| 1316 ASSERT(!function.HasOptionalPositionalParameters() || | 1332 ASSERT(!function.HasOptionalPositionalParameters() || |
| 1317 !function.HasOptionalNamedParameters()); | 1333 !function.HasOptionalNamedParameters()); |
| 1318 | 1334 |
| 1319 // TODO(regis): Consider type arguments in arguments. | 1335 // TODO(regis): Consider type arguments in arguments. |
| 1320 intptr_t arg_count = arguments->length(); | 1336 intptr_t arg_count = arguments->length(); |
| 1321 intptr_t param_count = function.NumParameters(); | 1337 intptr_t param_count = function.NumParameters(); |
| 1322 intptr_t fixed_param_count = function.num_fixed_parameters(); | 1338 intptr_t fixed_param_count = function.num_fixed_parameters(); |
| 1323 ASSERT(fixed_param_count <= arg_count); | 1339 ASSERT(fixed_param_count <= arg_count - first_param_index); |
| 1324 ASSERT(arg_count <= param_count); | 1340 ASSERT(arg_count - first_param_index <= param_count); |
| 1325 | 1341 |
| 1326 if (function.HasOptionalPositionalParameters()) { | 1342 if (function.HasOptionalPositionalParameters()) { |
| 1327 // Create a stub for each optional positional parameters with an actual. | 1343 // Create a stub for each optional positional parameters with an actual. |
| 1328 for (intptr_t i = fixed_param_count; i < arg_count; ++i) { | 1344 for (intptr_t i = first_param_index + fixed_param_count; i < arg_count; |
| 1345 ++i) { |
| 1329 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); | 1346 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); |
| 1330 } | 1347 } |
| 1331 ASSERT(function.NumOptionalPositionalParameters() == | 1348 ASSERT(function.NumOptionalPositionalParameters() == |
| 1332 (param_count - fixed_param_count)); | 1349 (param_count - fixed_param_count)); |
| 1333 // For each optional positional parameter without an actual, add its | 1350 // For each optional positional parameter without an actual, add its |
| 1334 // default value. | 1351 // default value. |
| 1335 for (intptr_t i = arg_count; i < param_count; ++i) { | 1352 for (intptr_t i = arg_count - first_param_index; i < param_count; ++i) { |
| 1336 const Instance& object = | 1353 const Instance& object = |
| 1337 parsed_function.DefaultParameterValueAt(i - fixed_param_count); | 1354 parsed_function.DefaultParameterValueAt(i - fixed_param_count); |
| 1338 ConstantInstr* constant = new (Z) ConstantInstr(object); | 1355 ConstantInstr* constant = new (Z) ConstantInstr(object); |
| 1339 arguments->Add(NULL); | 1356 arguments->Add(NULL); |
| 1340 param_stubs->Add(constant); | 1357 param_stubs->Add(constant); |
| 1341 } | 1358 } |
| 1342 return true; | 1359 return true; |
| 1343 } | 1360 } |
| 1344 | 1361 |
| 1345 ASSERT(function.HasOptionalNamedParameters()); | 1362 ASSERT(function.HasOptionalNamedParameters()); |
| 1346 | 1363 |
| 1347 // Passed arguments must match fixed parameters plus named arguments. | 1364 // Passed arguments (not counting optional type args) must match fixed |
| 1365 // parameters plus named arguments. |
| 1348 intptr_t argument_names_count = | 1366 intptr_t argument_names_count = |
| 1349 (argument_names.IsNull()) ? 0 : argument_names.Length(); | 1367 (argument_names.IsNull()) ? 0 : argument_names.Length(); |
| 1350 ASSERT(arg_count == (fixed_param_count + argument_names_count)); | 1368 ASSERT((arg_count - first_param_index) == |
| 1369 (fixed_param_count + argument_names_count)); |
| 1351 | 1370 |
| 1352 // Fast path when no optional named parameters are given. | 1371 // Fast path when no optional named parameters are given. |
| 1353 if (argument_names_count == 0) { | 1372 if (argument_names_count == 0) { |
| 1354 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) { | 1373 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) { |
| 1355 arguments->Add(NULL); | 1374 arguments->Add(NULL); |
| 1356 param_stubs->Add(GetDefaultValue(i, parsed_function)); | 1375 param_stubs->Add(GetDefaultValue(i, parsed_function)); |
| 1357 } | 1376 } |
| 1358 return true; | 1377 return true; |
| 1359 } | 1378 } |
| 1360 | 1379 |
| 1361 // Otherwise, build a collection of name/argument pairs. | 1380 // Otherwise, build a collection of name/argument pairs. |
| 1362 GrowableArray<NamedArgument> named_args(argument_names_count); | 1381 GrowableArray<NamedArgument> named_args(argument_names_count); |
| 1363 for (intptr_t i = 0; i < argument_names.Length(); ++i) { | 1382 for (intptr_t i = 0; i < argument_names.Length(); ++i) { |
| 1364 String& arg_name = String::Handle(caller_graph_->zone()); | 1383 String& arg_name = String::Handle(caller_graph_->zone()); |
| 1365 arg_name ^= argument_names.At(i); | 1384 arg_name ^= argument_names.At(i); |
| 1366 named_args.Add( | 1385 named_args.Add(NamedArgument( |
| 1367 NamedArgument(&arg_name, (*arguments)[i + fixed_param_count])); | 1386 &arg_name, (*arguments)[first_param_index + fixed_param_count + i])); |
| 1368 } | 1387 } |
| 1369 | 1388 |
| 1370 // Truncate the arguments array to just fixed parameters. | 1389 // Truncate the arguments array to just type args and fixed parameters. |
| 1371 arguments->TruncateTo(fixed_param_count); | 1390 arguments->TruncateTo(first_param_index + fixed_param_count); |
| 1372 | 1391 |
| 1373 // For each optional named parameter, add the actual argument or its | 1392 // For each optional named parameter, add the actual argument or its |
| 1374 // default if no argument is passed. | 1393 // default if no argument is passed. |
| 1375 intptr_t match_count = 0; | 1394 intptr_t match_count = 0; |
| 1376 for (intptr_t i = fixed_param_count; i < param_count; ++i) { | 1395 for (intptr_t i = fixed_param_count; i < param_count; ++i) { |
| 1377 String& param_name = String::Handle(function.ParameterNameAt(i)); | 1396 String& param_name = String::Handle(function.ParameterNameAt(i)); |
| 1378 // Search for and add the named argument. | 1397 // Search for and add the named argument. |
| 1379 Value* arg = NULL; | 1398 Value* arg = NULL; |
| 1380 for (intptr_t j = 0; j < named_args.length(); ++j) { | 1399 for (intptr_t j = 0; j < named_args.length(); ++j) { |
| 1381 if (param_name.Equals(*named_args[j].name)) { | 1400 if (param_name.Equals(*named_args[j].name)) { |
| 1382 arg = named_args[j].value; | 1401 arg = named_args[j].value; |
| 1383 match_count++; | 1402 match_count++; |
| 1384 break; | 1403 break; |
| 1385 } | 1404 } |
| 1386 } | 1405 } |
| 1387 arguments->Add(arg); | 1406 arguments->Add(arg); |
| 1388 // Create a stub for the argument or use the parameter's default value. | 1407 // Create a stub for the argument or use the parameter's default value. |
| 1389 if (arg != NULL) { | 1408 if (arg != NULL) { |
| 1390 param_stubs->Add(CreateParameterStub(i, arg, callee_graph)); | 1409 param_stubs->Add( |
| 1410 CreateParameterStub(first_param_index + i, arg, callee_graph)); |
| 1391 } else { | 1411 } else { |
| 1392 param_stubs->Add( | 1412 param_stubs->Add( |
| 1393 GetDefaultValue(i - fixed_param_count, parsed_function)); | 1413 GetDefaultValue(i - fixed_param_count, parsed_function)); |
| 1394 } | 1414 } |
| 1395 } | 1415 } |
| 1396 return argument_names_count == match_count; | 1416 return argument_names_count == match_count; |
| 1397 } | 1417 } |
| 1398 | 1418 |
| 1399 FlowGraphInliner* inliner_; | 1419 FlowGraphInliner* inliner_; |
| 1400 FlowGraph* caller_graph_; | 1420 FlowGraph* caller_graph_; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 target_info.IsSingleCid() && | 1543 target_info.IsSingleCid() && |
| 1524 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { | 1544 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { |
| 1525 owner_->inlined_ = true; | 1545 owner_->inlined_ = true; |
| 1526 return true; | 1546 return true; |
| 1527 } | 1547 } |
| 1528 | 1548 |
| 1529 GrowableArray<Value*> arguments(call_->ArgumentCount()); | 1549 GrowableArray<Value*> arguments(call_->ArgumentCount()); |
| 1530 for (int i = 0; i < call_->ArgumentCount(); ++i) { | 1550 for (int i = 0; i < call_->ArgumentCount(); ++i) { |
| 1531 arguments.Add(call_->PushArgumentAt(i)->value()); | 1551 arguments.Add(call_->PushArgumentAt(i)->value()); |
| 1532 } | 1552 } |
| 1533 InlinedCallData call_data(call_, &arguments, caller_function_, | 1553 InlinedCallData call_data(call_, call_->instance_call()->FirstParamIndex(), |
| 1534 caller_inlining_id_); | 1554 &arguments, caller_function_, caller_inlining_id_); |
| 1535 Function& target = Function::ZoneHandle(zone(), target_info.target->raw()); | 1555 Function& target = Function::ZoneHandle(zone(), target_info.target->raw()); |
| 1536 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), | 1556 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), |
| 1537 &call_data)) { | 1557 &call_data)) { |
| 1538 return false; | 1558 return false; |
| 1539 } | 1559 } |
| 1540 | 1560 |
| 1541 FlowGraph* callee_graph = call_data.callee_graph; | 1561 FlowGraph* callee_graph = call_data.callee_graph; |
| 1542 call_data.exit_collector->PrepareGraphs(callee_graph); | 1562 call_data.exit_collector->PrepareGraphs(callee_graph); |
| 1543 inlined_entries_.Add(callee_graph->graph_entry()); | 1563 inlined_entries_.Add(callee_graph->graph_entry()); |
| 1544 exit_collector_->Union(call_data.exit_collector); | 1564 exit_collector_->Union(call_data.exit_collector); |
| (...skipping 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3743 } | 3763 } |
| 3744 | 3764 |
| 3745 default: | 3765 default: |
| 3746 return false; | 3766 return false; |
| 3747 } | 3767 } |
| 3748 } | 3768 } |
| 3749 | 3769 |
| 3750 | 3770 |
| 3751 } // namespace dart | 3771 } // namespace dart |
| 3752 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 3772 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |