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

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: work in progress Created 3 years, 6 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698