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

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

Issue 2894953002: Support inlining of calls where type arguments are passed to generic functions. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 #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
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
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
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
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
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
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
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698