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

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, 5 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.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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 inliner_->precompiler_->TryApplyFeedback( 825 inliner_->precompiler_->TryApplyFeedback(
823 parsed_function->function(), callee_graph); 826 parsed_function->function(), callee_graph);
824 } 827 }
825 } 828 }
826 #endif 829 #endif
827 830
828 // The parameter stubs are a copy of the actual arguments providing 831 // The parameter stubs are a copy of the actual arguments providing
829 // concrete information about the values, for example constant values, 832 // concrete information about the values, for example constant values,
830 // without linking between the caller and callee graphs. 833 // without linking between the caller and callee graphs.
831 // TODO(zerny): Put more information in the stubs, eg, type information. 834 // TODO(zerny): Put more information in the stubs, eg, type information.
835 const intptr_t first_actual_param_index = call_data->first_param_index;
836 const intptr_t inlined_type_args_param =
837 (FLAG_reify_generic_functions && function.IsGeneric()) ? 1 : 0;
838 const intptr_t num_inlined_params =
839 inlined_type_args_param + function.NumParameters();
832 ZoneGrowableArray<Definition*>* param_stubs = 840 ZoneGrowableArray<Definition*>* param_stubs =
833 new (Z) ZoneGrowableArray<Definition*>(function.NumParameters()); 841 new (Z) ZoneGrowableArray<Definition*>(num_inlined_params);
834 842
843 // Create a ConstantInstr as Definition for the type arguments, if any.
844 if (first_actual_param_index > 0) {
845 // A type argument vector is explicitly passed.
846 param_stubs->Add(
847 CreateParameterStub(-1, (*arguments)[0], callee_graph));
848 } else if (inlined_type_args_param > 0) {
849 // No type argument vector is passed to the generic function,
850 // pass a null vector, which is the same as a vector of dynamic types.
851 param_stubs->Add(callee_graph->GetConstant(Object::ZoneHandle()));
852 }
835 // Create a parameter stub for each fixed positional parameter. 853 // Create a parameter stub for each fixed positional parameter.
836 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { 854 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
837 param_stubs->Add( 855 param_stubs->Add(CreateParameterStub(
838 CreateParameterStub(i, (*arguments)[i], callee_graph)); 856 i, (*arguments)[first_actual_param_index + i], callee_graph));
839 } 857 }
840 858
841 // If the callee has optional parameters, rebuild the argument and stub 859 // If the callee has optional parameters, rebuild the argument and stub
842 // arrays so that actual arguments are in one-to-one with the formal 860 // arrays so that actual arguments are in one-to-one with the formal
843 // parameters. 861 // parameters.
844 if (function.HasOptionalParameters()) { 862 if (function.HasOptionalParameters()) {
845 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); 863 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n"));
846 if (!AdjustForOptionalParameters(*parsed_function, argument_names, 864 if (!AdjustForOptionalParameters(
847 arguments, param_stubs, 865 *parsed_function, first_actual_param_index, argument_names,
848 callee_graph)) { 866 arguments, param_stubs, callee_graph)) {
849 function.set_is_inlinable(false); 867 function.set_is_inlinable(false);
850 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); 868 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n"));
851 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller, 869 PRINT_INLINING_TREE("Optional arg mismatch", &call_data->caller,
852 &function, call_data->call); 870 &function, call_data->call);
853 return false; 871 return false;
854 } 872 }
855 } 873 }
856 874
857 // After treating optional parameters the actual/formal count must 875 // After treating optional parameters the actual/formal count must
858 // match. 876 // match.
859 // TODO(regis): Consider type arguments in arguments. 877 ASSERT(arguments->length() ==
860 if (arguments->length() != function.NumParameters()) { 878 first_actual_param_index + function.NumParameters());
861 ASSERT(function.IsGeneric()); 879 ASSERT(param_stubs->length() ==
862 ASSERT(arguments->length() == function.NumParameters() + 1); 880 inlined_type_args_param + callee_graph->parameter_count());
863 TRACE_INLINING(
864 THR_Print(" Bailout: unsupported type arguments\n"));
865 PRINT_INLINING_TREE("Unsupported type arguments", &call_data->caller,
866 &function, call_data->call);
867 return false;
868 }
869 ASSERT(param_stubs->length() == callee_graph->parameter_count());
870 881
871 // Update try-index of the callee graph. 882 // Update try-index of the callee graph.
872 BlockEntryInstr* call_block = call_data->call->GetBlock(); 883 BlockEntryInstr* call_block = call_data->call->GetBlock();
873 if (call_block->InsideTryBlock()) { 884 if (call_block->InsideTryBlock()) {
874 intptr_t try_index = call_block->try_index(); 885 intptr_t try_index = call_block->try_index();
875 for (BlockIterator it = callee_graph->reverse_postorder_iterator(); 886 for (BlockIterator it = callee_graph->reverse_postorder_iterator();
876 !it.Done(); it.Advance()) { 887 !it.Done(); it.Advance()) {
877 BlockEntryInstr* block = it.Current(); 888 BlockEntryInstr* block = it.Current();
878 block->set_try_index(try_index); 889 block->set_try_index(try_index);
879 } 890 }
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 } 1024 }
1014 // When inlined, we add the deferred prefixes of the callee to the 1025 // When inlined, we add the deferred prefixes of the callee to the
1015 // caller's list of deferred prefixes. 1026 // caller's list of deferred prefixes.
1016 caller_graph()->AddToDeferredPrefixes( 1027 caller_graph()->AddToDeferredPrefixes(
1017 callee_graph->deferred_prefixes()); 1028 callee_graph->deferred_prefixes());
1018 1029
1019 FlowGraphInliner::SetInliningId( 1030 FlowGraphInliner::SetInliningId(
1020 callee_graph, 1031 callee_graph,
1021 inliner_->NextInlineId(callee_graph->function(), 1032 inliner_->NextInlineId(callee_graph->function(),
1022 call_data->call->token_pos(), 1033 call_data->call->token_pos(),
1023 call_data->caller_inlining_id_)); 1034 call_data->caller_inlining_id));
1024 TRACE_INLINING(THR_Print(" Success\n")); 1035 TRACE_INLINING(THR_Print(" Success\n"));
1025 TRACE_INLINING(THR_Print(" with size %" Pd "\n", 1036 TRACE_INLINING(THR_Print(" with size %" Pd "\n",
1026 function.optimized_instruction_count())); 1037 function.optimized_instruction_count()));
1027 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call); 1038 PRINT_INLINING_TREE(NULL, &call_data->caller, &function, call);
1028 return true; 1039 return true;
1029 } else { 1040 } else {
1030 error = thread()->sticky_error(); 1041 error = thread()->sticky_error();
1031 thread()->clear_sticky_error(); 1042 thread()->clear_sticky_error();
1032 1043
1033 if (error.IsLanguageError() && 1044 if (error.IsLanguageError() &&
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 FlowGraph* callee_graph = call_data->callee_graph; 1137 FlowGraph* callee_graph = call_data->callee_graph;
1127 TargetEntryInstr* callee_entry = 1138 TargetEntryInstr* callee_entry =
1128 callee_graph->graph_entry()->normal_entry(); 1139 callee_graph->graph_entry()->normal_entry();
1129 // Plug result in the caller graph. 1140 // Plug result in the caller graph.
1130 InlineExitCollector* exit_collector = call_data->exit_collector; 1141 InlineExitCollector* exit_collector = call_data->exit_collector;
1131 exit_collector->PrepareGraphs(callee_graph); 1142 exit_collector->PrepareGraphs(callee_graph);
1132 exit_collector->ReplaceCall(callee_entry); 1143 exit_collector->ReplaceCall(callee_entry);
1133 1144
1134 // Replace each stub with the actual argument or the caller's constant. 1145 // Replace each stub with the actual argument or the caller's constant.
1135 // Nulls denote optional parameters for which no actual was given. 1146 // Nulls denote optional parameters for which no actual was given.
1147 const intptr_t first_param_index = call_data->first_param_index;
1148 // When first_param_index > 0, the stub and actual argument processed in the
1149 // first loop iteration represent a passed-in type argument vector.
1136 GrowableArray<Value*>* arguments = call_data->arguments; 1150 GrowableArray<Value*>* arguments = call_data->arguments;
1151 intptr_t first_arg_stub_index = 0;
1152 if (arguments->length() != call_data->parameter_stubs->length()) {
1153 ASSERT(arguments->length() == call_data->parameter_stubs->length() - 1);
1154 ASSERT(first_param_index == 0);
1155 // The first parameter stub accepts an optional type argument vector, but
1156 // none was provided in arguments.
1157 first_arg_stub_index = 1;
1158 }
1137 for (intptr_t i = 0; i < arguments->length(); ++i) { 1159 for (intptr_t i = 0; i < arguments->length(); ++i) {
1138 Definition* stub = (*call_data->parameter_stubs)[i]; 1160 Definition* stub =
1161 (*call_data->parameter_stubs)[first_arg_stub_index + i];
1139 Value* actual = (*arguments)[i]; 1162 Value* actual = (*arguments)[i];
1140 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); 1163 if (actual != NULL) {
1164 stub->ReplaceUsesWith(actual->definition());
1165 }
1141 } 1166 }
1142 1167
1143 // Remove push arguments of the call. 1168 // Remove push arguments of the call.
1144 Definition* call = call_data->call; 1169 Definition* call = call_data->call;
1145 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 1170 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
1146 PushArgumentInstr* push = call->PushArgumentAt(i); 1171 PushArgumentInstr* push = call->PushArgumentAt(i);
1147 push->ReplaceUsesWith(push->value()->definition()); 1172 push->ReplaceUsesWith(push->value()->definition());
1148 push->RemoveFromGraph(); 1173 push->RemoveFromGraph();
1149 } 1174 }
1150 1175
1151 // Replace remaining constants with uses by constants in the caller's 1176 // Replace remaining constants with uses by constants in the caller's
1152 // initial definitions. 1177 // initial definitions.
1153 GrowableArray<Definition*>* defns = 1178 GrowableArray<Definition*>* defns =
1154 callee_graph->graph_entry()->initial_definitions(); 1179 callee_graph->graph_entry()->initial_definitions();
1155 for (intptr_t i = 0; i < defns->length(); ++i) { 1180 for (intptr_t i = 0; i < defns->length(); ++i) {
1156 ConstantInstr* constant = (*defns)[i]->AsConstant(); 1181 ConstantInstr* constant = (*defns)[i]->AsConstant();
1157 if ((constant != NULL) && constant->HasUses()) { 1182 if ((constant != NULL) && constant->HasUses()) {
1158 constant->ReplaceUsesWith( 1183 constant->ReplaceUsesWith(
1159 caller_graph_->GetConstant(constant->value())); 1184 caller_graph_->GetConstant(constant->value()));
1160 } 1185 }
1161 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); 1186 SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter();
1162 if ((context != NULL) && context->HasUses()) { 1187 if ((param != NULL) && param->HasUses()) {
1163 ASSERT(call->IsClosureCall()); 1188 if (param->kind() == SpecialParameterInstr::kContext) {
1164 LoadFieldInstr* context_load = new (Z) LoadFieldInstr( 1189 ASSERT(call->IsClosureCall());
1165 new Value((*arguments)[0]->definition()), Closure::context_offset(), 1190 LoadFieldInstr* context_load = new (Z) LoadFieldInstr(
1166 AbstractType::ZoneHandle(zone(), AbstractType::null()), 1191 new Value((*arguments)[first_param_index]->definition()),
1167 call_data->call->token_pos()); 1192 Closure::context_offset(),
1168 context_load->set_is_immutable(true); 1193 AbstractType::ZoneHandle(zone(), AbstractType::null()),
1169 context_load->set_ssa_temp_index(caller_graph_->alloc_ssa_temp_index()); 1194 call_data->call->token_pos());
1170 context_load->InsertBefore(callee_entry->next()); 1195 context_load->set_is_immutable(true);
1171 context->ReplaceUsesWith(context_load); 1196 context_load->set_ssa_temp_index(
1197 caller_graph_->alloc_ssa_temp_index());
1198 context_load->InsertBefore(callee_entry->next());
1199 param->ReplaceUsesWith(context_load);
1200 } else {
1201 ASSERT(param->kind() == SpecialParameterInstr::kTypeArgs);
1202 Definition* type_args;
1203 if (first_param_index > 0) {
1204 type_args = (*arguments)[0]->definition();
1205 } else {
1206 type_args = callee_graph->constant_null();
1207 }
1208 param->ReplaceUsesWith(type_args);
1209 }
1172 } 1210 }
1173 } 1211 }
1174 1212
1175 // Check that inlining maintains use lists. 1213 // Check that inlining maintains use lists.
1176 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists()); 1214 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists());
1177 } 1215 }
1178 1216
1179 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) { 1217 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) {
1180 intptr_t count = 0; 1218 intptr_t count = 0;
1181 for (intptr_t i = 0; i < arguments.length(); i++) { 1219 for (intptr_t i = 0; i < arguments.length(); i++) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 } 1259 }
1222 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(), 1260 PRINT_INLINING_TREE("Too cold", &call_info[call_idx].caller(),
1223 &call->function(), call); 1261 &call->function(), call);
1224 continue; 1262 continue;
1225 } 1263 }
1226 GrowableArray<Value*> arguments(call->ArgumentCount()); 1264 GrowableArray<Value*> arguments(call->ArgumentCount());
1227 for (int i = 0; i < call->ArgumentCount(); ++i) { 1265 for (int i = 0; i < call->ArgumentCount(); ++i) {
1228 arguments.Add(call->PushArgumentAt(i)->value()); 1266 arguments.Add(call->PushArgumentAt(i)->value());
1229 } 1267 }
1230 InlinedCallData call_data( 1268 InlinedCallData call_data(
1231 call, &arguments, call_info[call_idx].caller(), 1269 call, call->FirstParamIndex(), &arguments,
1270 call_info[call_idx].caller(),
1232 call_info[call_idx].caller_graph->inlining_id()); 1271 call_info[call_idx].caller_graph->inlining_id());
1233 if (TryInlining(call->function(), call->argument_names(), &call_data)) { 1272 if (TryInlining(call->function(), call->argument_names(), &call_data)) {
1234 InlineCall(&call_data); 1273 InlineCall(&call_data);
1235 } 1274 }
1236 } 1275 }
1237 } 1276 }
1238 1277
1239 void InlineClosureCalls() { 1278 void InlineClosureCalls() {
1240 const GrowableArray<CallSites::ClosureCallInfo>& call_info = 1279 const GrowableArray<CallSites::ClosureCallInfo>& call_info =
1241 inlining_call_sites_->closure_calls(); 1280 inlining_call_sites_->closure_calls();
(...skipping 25 matching lines...) Expand all
1267 call->ArgumentCount() < target.num_fixed_parameters()) { 1306 call->ArgumentCount() < target.num_fixed_parameters()) {
1268 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n")); 1307 TRACE_INLINING(THR_Print(" Bailout: wrong parameter count\n"));
1269 continue; 1308 continue;
1270 } 1309 }
1271 1310
1272 GrowableArray<Value*> arguments(call->ArgumentCount()); 1311 GrowableArray<Value*> arguments(call->ArgumentCount());
1273 for (int i = 0; i < call->ArgumentCount(); ++i) { 1312 for (int i = 0; i < call->ArgumentCount(); ++i) {
1274 arguments.Add(call->PushArgumentAt(i)->value()); 1313 arguments.Add(call->PushArgumentAt(i)->value());
1275 } 1314 }
1276 InlinedCallData call_data( 1315 InlinedCallData call_data(
1277 call, &arguments, call_info[call_idx].caller(), 1316 call, call->FirstParamIndex(), &arguments,
1317 call_info[call_idx].caller(),
1278 call_info[call_idx].caller_graph->inlining_id()); 1318 call_info[call_idx].caller_graph->inlining_id());
1279 if (TryInlining(target, call->argument_names(), &call_data)) { 1319 if (TryInlining(target, call->argument_names(), &call_data)) {
1280 InlineCall(&call_data); 1320 InlineCall(&call_data);
1281 } 1321 }
1282 } 1322 }
1283 } 1323 }
1284 1324
1285 void InlineInstanceCalls() { 1325 void InlineInstanceCalls() {
1286 const GrowableArray<CallSites::InstanceCallInfo>& call_info = 1326 const GrowableArray<CallSites::InstanceCallInfo>& call_info =
1287 inlining_call_sites_->instance_calls(); 1327 inlining_call_sites_->instance_calls();
(...skipping 10 matching lines...) Expand all
1298 } 1338 }
1299 const Function& cl = call_info[call_idx].caller(); 1339 const Function& cl = call_info[call_idx].caller();
1300 intptr_t caller_inlining_id = 1340 intptr_t caller_inlining_id =
1301 call_info[call_idx].caller_graph->inlining_id(); 1341 call_info[call_idx].caller_graph->inlining_id();
1302 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); 1342 PolymorphicInliner inliner(this, call, cl, caller_inlining_id);
1303 inliner.Inline(); 1343 inliner.Inline();
1304 } 1344 }
1305 } 1345 }
1306 1346
1307 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, 1347 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function,
1348 intptr_t first_param_index,
1308 const Array& argument_names, 1349 const Array& argument_names,
1309 GrowableArray<Value*>* arguments, 1350 GrowableArray<Value*>* arguments,
1310 ZoneGrowableArray<Definition*>* param_stubs, 1351 ZoneGrowableArray<Definition*>* param_stubs,
1311 FlowGraph* callee_graph) { 1352 FlowGraph* callee_graph) {
1312 const Function& function = parsed_function.function(); 1353 const Function& function = parsed_function.function();
1313 // The language and this code does not support both optional positional 1354 // The language and this code does not support both optional positional
1314 // and optional named parameters for the same function. 1355 // and optional named parameters for the same function.
1315 ASSERT(!function.HasOptionalPositionalParameters() || 1356 ASSERT(!function.HasOptionalPositionalParameters() ||
1316 !function.HasOptionalNamedParameters()); 1357 !function.HasOptionalNamedParameters());
1317 1358
1318 // TODO(regis): Consider type arguments in arguments.
1319 intptr_t arg_count = arguments->length(); 1359 intptr_t arg_count = arguments->length();
1320 intptr_t param_count = function.NumParameters(); 1360 intptr_t param_count = function.NumParameters();
1321 intptr_t fixed_param_count = function.num_fixed_parameters(); 1361 intptr_t fixed_param_count = function.num_fixed_parameters();
1322 ASSERT(fixed_param_count <= arg_count); 1362 ASSERT(fixed_param_count <= arg_count - first_param_index);
1323 ASSERT(arg_count <= param_count); 1363 ASSERT(arg_count - first_param_index <= param_count);
1324 1364
1325 if (function.HasOptionalPositionalParameters()) { 1365 if (function.HasOptionalPositionalParameters()) {
1326 // Create a stub for each optional positional parameters with an actual. 1366 // Create a stub for each optional positional parameters with an actual.
1327 for (intptr_t i = fixed_param_count; i < arg_count; ++i) { 1367 for (intptr_t i = first_param_index + fixed_param_count; i < arg_count;
1368 ++i) {
1328 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); 1369 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph));
1329 } 1370 }
1330 ASSERT(function.NumOptionalPositionalParameters() == 1371 ASSERT(function.NumOptionalPositionalParameters() ==
1331 (param_count - fixed_param_count)); 1372 (param_count - fixed_param_count));
1332 // For each optional positional parameter without an actual, add its 1373 // For each optional positional parameter without an actual, add its
1333 // default value. 1374 // default value.
1334 for (intptr_t i = arg_count; i < param_count; ++i) { 1375 for (intptr_t i = arg_count - first_param_index; i < param_count; ++i) {
1335 const Instance& object = 1376 const Instance& object =
1336 parsed_function.DefaultParameterValueAt(i - fixed_param_count); 1377 parsed_function.DefaultParameterValueAt(i - fixed_param_count);
1337 ConstantInstr* constant = new (Z) ConstantInstr(object); 1378 ConstantInstr* constant = new (Z) ConstantInstr(object);
1338 arguments->Add(NULL); 1379 arguments->Add(NULL);
1339 param_stubs->Add(constant); 1380 param_stubs->Add(constant);
1340 } 1381 }
1341 return true; 1382 return true;
1342 } 1383 }
1343 1384
1344 ASSERT(function.HasOptionalNamedParameters()); 1385 ASSERT(function.HasOptionalNamedParameters());
1345 1386
1346 // Passed arguments must match fixed parameters plus named arguments. 1387 // Passed arguments (not counting optional type args) must match fixed
1388 // parameters plus named arguments.
1347 intptr_t argument_names_count = 1389 intptr_t argument_names_count =
1348 (argument_names.IsNull()) ? 0 : argument_names.Length(); 1390 (argument_names.IsNull()) ? 0 : argument_names.Length();
1349 ASSERT(arg_count == (fixed_param_count + argument_names_count)); 1391 ASSERT((arg_count - first_param_index) ==
1392 (fixed_param_count + argument_names_count));
1350 1393
1351 // Fast path when no optional named parameters are given. 1394 // Fast path when no optional named parameters are given.
1352 if (argument_names_count == 0) { 1395 if (argument_names_count == 0) {
1353 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) { 1396 for (intptr_t i = 0; i < param_count - fixed_param_count; ++i) {
1354 arguments->Add(NULL); 1397 arguments->Add(NULL);
1355 param_stubs->Add(GetDefaultValue(i, parsed_function)); 1398 param_stubs->Add(GetDefaultValue(i, parsed_function));
1356 } 1399 }
1357 return true; 1400 return true;
1358 } 1401 }
1359 1402
1360 // Otherwise, build a collection of name/argument pairs. 1403 // Otherwise, build a collection of name/argument pairs.
1361 GrowableArray<NamedArgument> named_args(argument_names_count); 1404 GrowableArray<NamedArgument> named_args(argument_names_count);
1362 for (intptr_t i = 0; i < argument_names.Length(); ++i) { 1405 for (intptr_t i = 0; i < argument_names.Length(); ++i) {
1363 String& arg_name = String::Handle(caller_graph_->zone()); 1406 String& arg_name = String::Handle(caller_graph_->zone());
1364 arg_name ^= argument_names.At(i); 1407 arg_name ^= argument_names.At(i);
1365 named_args.Add( 1408 named_args.Add(NamedArgument(
1366 NamedArgument(&arg_name, (*arguments)[i + fixed_param_count])); 1409 &arg_name, (*arguments)[first_param_index + fixed_param_count + i]));
1367 } 1410 }
1368 1411
1369 // Truncate the arguments array to just fixed parameters. 1412 // Truncate the arguments array to just type args and fixed parameters.
1370 arguments->TruncateTo(fixed_param_count); 1413 arguments->TruncateTo(first_param_index + fixed_param_count);
1371 1414
1372 // For each optional named parameter, add the actual argument or its 1415 // For each optional named parameter, add the actual argument or its
1373 // default if no argument is passed. 1416 // default if no argument is passed.
1374 intptr_t match_count = 0; 1417 intptr_t match_count = 0;
1375 for (intptr_t i = fixed_param_count; i < param_count; ++i) { 1418 for (intptr_t i = fixed_param_count; i < param_count; ++i) {
1376 String& param_name = String::Handle(function.ParameterNameAt(i)); 1419 String& param_name = String::Handle(function.ParameterNameAt(i));
1377 // Search for and add the named argument. 1420 // Search for and add the named argument.
1378 Value* arg = NULL; 1421 Value* arg = NULL;
1379 for (intptr_t j = 0; j < named_args.length(); ++j) { 1422 for (intptr_t j = 0; j < named_args.length(); ++j) {
1380 if (param_name.Equals(*named_args[j].name)) { 1423 if (param_name.Equals(*named_args[j].name)) {
1381 arg = named_args[j].value; 1424 arg = named_args[j].value;
1382 match_count++; 1425 match_count++;
1383 break; 1426 break;
1384 } 1427 }
1385 } 1428 }
1386 arguments->Add(arg); 1429 arguments->Add(arg);
1387 // Create a stub for the argument or use the parameter's default value. 1430 // Create a stub for the argument or use the parameter's default value.
1388 if (arg != NULL) { 1431 if (arg != NULL) {
1389 param_stubs->Add(CreateParameterStub(i, arg, callee_graph)); 1432 param_stubs->Add(
1433 CreateParameterStub(first_param_index + i, arg, callee_graph));
1390 } else { 1434 } else {
1391 param_stubs->Add( 1435 param_stubs->Add(
1392 GetDefaultValue(i - fixed_param_count, parsed_function)); 1436 GetDefaultValue(i - fixed_param_count, parsed_function));
1393 } 1437 }
1394 } 1438 }
1395 return argument_names_count == match_count; 1439 return argument_names_count == match_count;
1396 } 1440 }
1397 1441
1398 FlowGraphInliner* inliner_; 1442 FlowGraphInliner* inliner_;
1399 FlowGraph* caller_graph_; 1443 FlowGraph* caller_graph_;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 target_info.IsSingleCid() && 1566 target_info.IsSingleCid() &&
1523 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) { 1567 TryInlineRecognizedMethod(target_info.cid_start, *target_info.target)) {
1524 owner_->inlined_ = true; 1568 owner_->inlined_ = true;
1525 return true; 1569 return true;
1526 } 1570 }
1527 1571
1528 GrowableArray<Value*> arguments(call_->ArgumentCount()); 1572 GrowableArray<Value*> arguments(call_->ArgumentCount());
1529 for (int i = 0; i < call_->ArgumentCount(); ++i) { 1573 for (int i = 0; i < call_->ArgumentCount(); ++i) {
1530 arguments.Add(call_->PushArgumentAt(i)->value()); 1574 arguments.Add(call_->PushArgumentAt(i)->value());
1531 } 1575 }
1532 InlinedCallData call_data(call_, &arguments, caller_function_, 1576 InlinedCallData call_data(call_, call_->instance_call()->FirstParamIndex(),
1533 caller_inlining_id_); 1577 &arguments, caller_function_, caller_inlining_id_);
1534 Function& target = Function::ZoneHandle(zone(), target_info.target->raw()); 1578 Function& target = Function::ZoneHandle(zone(), target_info.target->raw());
1535 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(), 1579 if (!owner_->TryInlining(target, call_->instance_call()->argument_names(),
1536 &call_data)) { 1580 &call_data)) {
1537 return false; 1581 return false;
1538 } 1582 }
1539 1583
1540 FlowGraph* callee_graph = call_data.callee_graph; 1584 FlowGraph* callee_graph = call_data.callee_graph;
1541 call_data.exit_collector->PrepareGraphs(callee_graph); 1585 call_data.exit_collector->PrepareGraphs(callee_graph);
1542 inlined_entries_.Add(callee_graph->graph_entry()); 1586 inlined_entries_.Add(callee_graph->graph_entry());
1543 exit_collector_->Union(call_data.exit_collector); 1587 exit_collector_->Union(call_data.exit_collector);
1544 1588
1545 // Replace parameter stubs and constants. Replace the receiver argument 1589 // Replace parameter stubs and constants. Replace the receiver argument
Vyacheslav Egorov (Google) 2017/06/28 14:56:02 I think that parameter stubs replacement that happ
regis 2017/06/28 21:03:59 That was it! Thanks! I moved this code into a shar
1546 // with a redefinition to prevent code from the inlined body from being 1590 // with a redefinition to prevent code from the inlined body from being
1547 // hoisted above the inlined entry. 1591 // hoisted above the inlined entry.
1548 ASSERT(arguments.length() > 0); 1592 ASSERT(arguments.length() > 0);
1549 Value* actual = arguments[0]; 1593 Value* actual = arguments[0];
1550 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z)); 1594 RedefinitionInstr* redefinition = new (Z) RedefinitionInstr(actual->Copy(Z));
1551 redefinition->set_ssa_temp_index( 1595 redefinition->set_ssa_temp_index(
1552 owner_->caller_graph()->alloc_ssa_temp_index()); 1596 owner_->caller_graph()->alloc_ssa_temp_index());
1553 if (target_info.IsSingleCid()) { 1597 if (target_info.IsSingleCid()) {
1554 redefinition->UpdateType(CompileType::FromCid(target_info.cid_start)); 1598 redefinition->UpdateType(CompileType::FromCid(target_info.cid_start));
1555 } 1599 }
1556 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry()); 1600 redefinition->InsertAfter(callee_graph->graph_entry()->normal_entry());
1557 Definition* stub = (*call_data.parameter_stubs)[0]; 1601 Definition* stub = (*call_data.parameter_stubs)[0];
1558 stub->ReplaceUsesWith(redefinition); 1602 stub->ReplaceUsesWith(redefinition);
1559 1603
1560 for (intptr_t i = 1; i < arguments.length(); ++i) { 1604 for (intptr_t i = 1; i < arguments.length(); ++i) {
1561 actual = arguments[i]; 1605 actual = arguments[i];
1562 if (actual != NULL) { 1606 if (actual != NULL) {
1563 stub = (*call_data.parameter_stubs)[i]; 1607 stub = (*call_data.parameter_stubs)[i];
1564 stub->ReplaceUsesWith(actual->definition()); 1608 stub->ReplaceUsesWith(actual->definition());
1565 } 1609 }
1566 } 1610 }
1567 GrowableArray<Definition*>* defns = 1611 GrowableArray<Definition*>* defns =
1568 callee_graph->graph_entry()->initial_definitions(); 1612 callee_graph->graph_entry()->initial_definitions();
1569 for (intptr_t i = 0; i < defns->length(); ++i) { 1613 for (intptr_t i = 0; i < defns->length(); ++i) {
1570 ConstantInstr* constant = (*defns)[i]->AsConstant(); 1614 ConstantInstr* constant = (*defns)[i]->AsConstant();
1571 if ((constant != NULL) && constant->HasUses()) { 1615 if ((constant != NULL) && constant->HasUses()) {
1572 constant->ReplaceUsesWith( 1616 constant->ReplaceUsesWith(
1573 owner_->caller_graph()->GetConstant(constant->value())); 1617 owner_->caller_graph()->GetConstant(constant->value()));
1574 } 1618 }
1575 CurrentContextInstr* context = (*defns)[i]->AsCurrentContext(); 1619 SpecialParameterInstr* param = (*defns)[i]->AsSpecialParameter();
1576 if ((context != NULL) && context->HasUses()) { 1620 if ((param != NULL) && param->HasUses()) {
1577 ASSERT(call_data.call->IsClosureCall()); 1621 if (param->kind() == SpecialParameterInstr::kContext) {
1578 LoadFieldInstr* context_load = new (Z) 1622 ASSERT(call_data.call->IsClosureCall());
1579 LoadFieldInstr(new Value(redefinition), Closure::context_offset(), 1623 LoadFieldInstr* context_load = new (Z) LoadFieldInstr(
1580 AbstractType::ZoneHandle(zone(), AbstractType::null()), 1624 new Value(redefinition), Closure::context_offset(),
1581 call_data.call->token_pos()); 1625 AbstractType::ZoneHandle(zone(), AbstractType::null()),
1582 context_load->set_is_immutable(true); 1626 call_data.call->token_pos());
1583 context_load->set_ssa_temp_index( 1627 context_load->set_is_immutable(true);
1584 owner_->caller_graph()->alloc_ssa_temp_index()); 1628 context_load->set_ssa_temp_index(
1585 context_load->InsertAfter(redefinition); 1629 owner_->caller_graph()->alloc_ssa_temp_index());
1586 context->ReplaceUsesWith(context_load); 1630 context_load->InsertAfter(redefinition);
1631 param->ReplaceUsesWith(context_load);
1632 } else {
1633 ASSERT(param->kind() == SpecialParameterInstr::kTypeArgs);
1634 UNIMPLEMENTED(); // TODO(regis): Why am I not hitting this? No uses?
1635 }
1587 } 1636 }
1588 } 1637 }
1589 return true; 1638 return true;
1590 } 1639 }
1591 1640
1592 1641
1593 static Instruction* AppendInstruction(Instruction* first, Instruction* second) { 1642 static Instruction* AppendInstruction(Instruction* first, Instruction* second) {
1594 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) { 1643 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) {
1595 Value* input = second->InputAt(i); 1644 Value* input = second->InputAt(i);
1596 input->definition()->AddInputUse(input); 1645 input->definition()->AddInputUse(input);
(...skipping 2170 matching lines...) Expand 10 before | Expand all | Expand 10 after
3767 } 3816 }
3768 3817
3769 default: 3818 default:
3770 return false; 3819 return false;
3771 } 3820 }
3772 } 3821 }
3773 3822
3774 3823
3775 } // namespace dart 3824 } // namespace dart
3776 #endif // !defined(DART_PRECOMPILED_RUNTIME) 3825 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698