| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_inliner.h" | 5 #include "vm/flow_graph_inliner.h" |
| 6 | 6 |
| 7 #include "vm/block_scheduler.h" | 7 #include "vm/block_scheduler.h" |
| 8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 class CallSites : public ValueObject { | 185 class CallSites : public ValueObject { |
| 186 public: | 186 public: |
| 187 explicit CallSites(FlowGraph* flow_graph) | 187 explicit CallSites(FlowGraph* flow_graph) |
| 188 : static_calls_(), | 188 : static_calls_(), |
| 189 closure_calls_(), | 189 closure_calls_(), |
| 190 instance_calls_() { } | 190 instance_calls_() { } |
| 191 | 191 |
| 192 struct InstanceCallInfo { | 192 struct InstanceCallInfo { |
| 193 PolymorphicInstanceCallInstr* call; | 193 PolymorphicInstanceCallInstr* call; |
| 194 double ratio; | 194 double ratio; |
| 195 const Function* caller; | 195 const FlowGraph* caller_graph; |
| 196 InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg, | 196 InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg, |
| 197 FlowGraph* flow_graph) | 197 FlowGraph* flow_graph) |
| 198 : call(call_arg), | 198 : call(call_arg), |
| 199 ratio(0.0), | 199 ratio(0.0), |
| 200 caller(&flow_graph->function()) {} | 200 caller_graph(flow_graph) {} |
| 201 const Function& caller() const { return caller_graph->function(); } |
| 201 }; | 202 }; |
| 202 | 203 |
| 203 struct StaticCallInfo { | 204 struct StaticCallInfo { |
| 204 StaticCallInstr* call; | 205 StaticCallInstr* call; |
| 205 double ratio; | 206 double ratio; |
| 206 const Function* caller; | 207 FlowGraph* caller_graph; |
| 207 StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph) | 208 StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph) |
| 208 : call(value), | 209 : call(value), |
| 209 ratio(0.0), | 210 ratio(0.0), |
| 210 caller(&flow_graph->function()) {} | 211 caller_graph(flow_graph) {} |
| 212 const Function& caller() const { return caller_graph->function(); } |
| 211 }; | 213 }; |
| 212 | 214 |
| 213 struct ClosureCallInfo { | 215 struct ClosureCallInfo { |
| 214 ClosureCallInstr* call; | 216 ClosureCallInstr* call; |
| 215 const Function* caller; | 217 FlowGraph* caller_graph; |
| 216 ClosureCallInfo(ClosureCallInstr* value, FlowGraph* flow_graph) | 218 ClosureCallInfo(ClosureCallInstr* value, FlowGraph* flow_graph) |
| 217 : call(value), | 219 : call(value), |
| 218 caller(&flow_graph->function()) {} | 220 caller_graph(flow_graph) {} |
| 221 const Function& caller() const { return caller_graph->function(); } |
| 219 }; | 222 }; |
| 220 | 223 |
| 221 const GrowableArray<InstanceCallInfo>& instance_calls() const { | 224 const GrowableArray<InstanceCallInfo>& instance_calls() const { |
| 222 return instance_calls_; | 225 return instance_calls_; |
| 223 } | 226 } |
| 224 | 227 |
| 225 const GrowableArray<StaticCallInfo>& static_calls() const { | 228 const GrowableArray<StaticCallInfo>& static_calls() const { |
| 226 return static_calls_; | 229 return static_calls_; |
| 227 } | 230 } |
| 228 | 231 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 GrowableArray<ClosureCallInfo> closure_calls_; | 400 GrowableArray<ClosureCallInfo> closure_calls_; |
| 398 GrowableArray<InstanceCallInfo> instance_calls_; | 401 GrowableArray<InstanceCallInfo> instance_calls_; |
| 399 | 402 |
| 400 DISALLOW_COPY_AND_ASSIGN(CallSites); | 403 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 401 }; | 404 }; |
| 402 | 405 |
| 403 | 406 |
| 404 struct InlinedCallData { | 407 struct InlinedCallData { |
| 405 InlinedCallData(Definition* call, | 408 InlinedCallData(Definition* call, |
| 406 GrowableArray<Value*>* arguments, | 409 GrowableArray<Value*>* arguments, |
| 407 const Function& caller) | 410 const Function& caller, |
| 411 intptr_t caller_inlining_id) |
| 408 : call(call), | 412 : call(call), |
| 409 arguments(arguments), | 413 arguments(arguments), |
| 410 callee_graph(NULL), | 414 callee_graph(NULL), |
| 411 parameter_stubs(NULL), | 415 parameter_stubs(NULL), |
| 412 exit_collector(NULL), | 416 exit_collector(NULL), |
| 413 caller(caller) { } | 417 caller(caller), |
| 418 caller_inlining_id_(caller_inlining_id) { } |
| 414 | 419 |
| 415 Definition* call; | 420 Definition* call; |
| 416 GrowableArray<Value*>* arguments; | 421 GrowableArray<Value*>* arguments; |
| 417 FlowGraph* callee_graph; | 422 FlowGraph* callee_graph; |
| 418 ZoneGrowableArray<Definition*>* parameter_stubs; | 423 ZoneGrowableArray<Definition*>* parameter_stubs; |
| 419 InlineExitCollector* exit_collector; | 424 InlineExitCollector* exit_collector; |
| 420 const Function& caller; | 425 const Function& caller; |
| 426 const intptr_t caller_inlining_id_; |
| 421 }; | 427 }; |
| 422 | 428 |
| 423 | 429 |
| 424 class CallSiteInliner; | 430 class CallSiteInliner; |
| 425 | 431 |
| 426 class PolymorphicInliner : public ValueObject { | 432 class PolymorphicInliner : public ValueObject { |
| 427 public: | 433 public: |
| 428 PolymorphicInliner(CallSiteInliner* owner, | 434 PolymorphicInliner(CallSiteInliner* owner, |
| 429 PolymorphicInstanceCallInstr* call, | 435 PolymorphicInstanceCallInstr* call, |
| 430 const Function& caller_function); | 436 const Function& caller_function, |
| 437 intptr_t caller_inlining_id); |
| 431 | 438 |
| 432 void Inline(); | 439 void Inline(); |
| 433 | 440 |
| 434 private: | 441 private: |
| 435 bool CheckInlinedDuplicate(const Function& target); | 442 bool CheckInlinedDuplicate(const Function& target); |
| 436 bool CheckNonInlinedDuplicate(const Function& target); | 443 bool CheckNonInlinedDuplicate(const Function& target); |
| 437 | 444 |
| 438 bool TryInliningPoly(intptr_t receiver_cid, const Function& target); | 445 bool TryInliningPoly(intptr_t receiver_cid, const Function& target); |
| 439 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target); | 446 bool TryInlineRecognizedMethod(intptr_t receiver_cid, const Function& target); |
| 440 | 447 |
| 441 TargetEntryInstr* BuildDecisionGraph(); | 448 TargetEntryInstr* BuildDecisionGraph(); |
| 442 | 449 |
| 443 Isolate* isolate() const; | 450 Isolate* isolate() const; |
| 444 Zone* zone() const; | 451 Zone* zone() const; |
| 445 | 452 |
| 446 CallSiteInliner* const owner_; | 453 CallSiteInliner* const owner_; |
| 447 PolymorphicInstanceCallInstr* const call_; | 454 PolymorphicInstanceCallInstr* const call_; |
| 448 const intptr_t num_variants_; | 455 const intptr_t num_variants_; |
| 449 GrowableArray<CidTarget> variants_; | 456 GrowableArray<CidTarget> variants_; |
| 450 | 457 |
| 451 GrowableArray<CidTarget> inlined_variants_; | 458 GrowableArray<CidTarget> inlined_variants_; |
| 452 GrowableArray<CidTarget> non_inlined_variants_; | 459 GrowableArray<CidTarget> non_inlined_variants_; |
| 453 GrowableArray<BlockEntryInstr*> inlined_entries_; | 460 GrowableArray<BlockEntryInstr*> inlined_entries_; |
| 454 InlineExitCollector* exit_collector_; | 461 InlineExitCollector* exit_collector_; |
| 455 | 462 |
| 456 const Function& caller_function_; | 463 const Function& caller_function_; |
| 464 const intptr_t caller_inlining_id_; |
| 457 }; | 465 }; |
| 458 | 466 |
| 459 | 467 |
| 460 static bool HasAnnotation(const Function& function, const char* annotation) { | 468 static bool HasAnnotation(const Function& function, const char* annotation) { |
| 461 const Class& owner = Class::Handle(function.Owner()); | 469 const Class& owner = Class::Handle(function.Owner()); |
| 462 const Library& library = Library::Handle(owner.library()); | 470 const Library& library = Library::Handle(owner.library()); |
| 463 const Array& metadata = | 471 const Array& metadata = |
| 464 Array::Cast(Object::Handle(library.GetMetadata(function))); | 472 Array::Cast(Object::Handle(library.GetMetadata(function))); |
| 465 | 473 |
| 466 if (metadata.Length() > 0) { | 474 if (metadata.Length() > 0) { |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 // When inlined, we add the guarded fields of the callee to the caller's | 853 // When inlined, we add the guarded fields of the callee to the caller's |
| 846 // list of guarded fields. | 854 // list of guarded fields. |
| 847 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { | 855 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { |
| 848 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), | 856 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), |
| 849 (*callee_graph->guarded_fields())[i]); | 857 (*callee_graph->guarded_fields())[i]); |
| 850 } | 858 } |
| 851 // When inlined, we add the deferred prefixes of the callee to the | 859 // When inlined, we add the deferred prefixes of the callee to the |
| 852 // caller's list of deferred prefixes. | 860 // caller's list of deferred prefixes. |
| 853 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); | 861 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); |
| 854 | 862 |
| 855 FlowGraphInliner::SetInliningId(*callee_graph, | 863 FlowGraphInliner::SetInliningId(callee_graph, |
| 856 inliner_->NextInlineId(callee_graph->function())); | 864 inliner_->NextInlineId(callee_graph->function(), |
| 865 call_data->caller_inlining_id_)); |
| 857 // We allocate a ZoneHandle for the unoptimized code so that it cannot be | 866 // We allocate a ZoneHandle for the unoptimized code so that it cannot be |
| 858 // disconnected from its function during the rest of compilation. | 867 // disconnected from its function during the rest of compilation. |
| 859 Code::ZoneHandle(unoptimized_code.raw()); | 868 Code::ZoneHandle(unoptimized_code.raw()); |
| 860 TRACE_INLINING(ISL_Print(" Success\n")); | 869 TRACE_INLINING(ISL_Print(" Success\n")); |
| 861 PRINT_INLINING_TREE(NULL, | 870 PRINT_INLINING_TREE(NULL, |
| 862 &call_data->caller, &function, call); | 871 &call_data->caller, &function, call); |
| 863 return true; | 872 return true; |
| 864 } else { | 873 } else { |
| 865 Error& error = Error::Handle(); | 874 Error& error = Error::Handle(); |
| 866 error = isolate()->object_store()->sticky_error(); | 875 error = isolate()->object_store()->sticky_error(); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 } | 1056 } |
| 1048 const Function& target = call->function(); | 1057 const Function& target = call->function(); |
| 1049 if (!inliner_->AlwaysInline(target) && | 1058 if (!inliner_->AlwaysInline(target) && |
| 1050 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { | 1059 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { |
| 1051 TRACE_INLINING(ISL_Print( | 1060 TRACE_INLINING(ISL_Print( |
| 1052 " => %s (deopt count %d)\n Bailout: cold %f\n", | 1061 " => %s (deopt count %d)\n Bailout: cold %f\n", |
| 1053 target.ToCString(), | 1062 target.ToCString(), |
| 1054 target.deoptimization_counter(), | 1063 target.deoptimization_counter(), |
| 1055 call_info[call_idx].ratio)); | 1064 call_info[call_idx].ratio)); |
| 1056 PRINT_INLINING_TREE("Too cold", | 1065 PRINT_INLINING_TREE("Too cold", |
| 1057 call_info[call_idx].caller, &call->function(), call); | 1066 &call_info[call_idx].caller(), &call->function(), call); |
| 1058 continue; | 1067 continue; |
| 1059 } | 1068 } |
| 1060 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1069 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1061 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1070 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1062 arguments.Add(call->PushArgumentAt(i)->value()); | 1071 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1063 } | 1072 } |
| 1064 InlinedCallData call_data(call, &arguments, *call_info[call_idx].caller); | 1073 InlinedCallData call_data( |
| 1074 call, &arguments, call_info[call_idx].caller(), |
| 1075 call_info[call_idx].caller_graph->inlining_id()); |
| 1065 if (TryInlining(call->function(), call->argument_names(), &call_data)) { | 1076 if (TryInlining(call->function(), call->argument_names(), &call_data)) { |
| 1066 InlineCall(&call_data); | 1077 InlineCall(&call_data); |
| 1067 } | 1078 } |
| 1068 } | 1079 } |
| 1069 } | 1080 } |
| 1070 | 1081 |
| 1071 void InlineClosureCalls() { | 1082 void InlineClosureCalls() { |
| 1072 const GrowableArray<CallSites::ClosureCallInfo>& call_info = | 1083 const GrowableArray<CallSites::ClosureCallInfo>& call_info = |
| 1073 inlining_call_sites_->closure_calls(); | 1084 inlining_call_sites_->closure_calls(); |
| 1074 TRACE_INLINING(ISL_Print(" Closure Calls (%" Pd ")\n", | 1085 TRACE_INLINING(ISL_Print(" Closure Calls (%" Pd ")\n", |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1093 } | 1104 } |
| 1094 | 1105 |
| 1095 if (target.IsNull()) { | 1106 if (target.IsNull()) { |
| 1096 TRACE_INLINING(ISL_Print(" Bailout: non-closure operator\n")); | 1107 TRACE_INLINING(ISL_Print(" Bailout: non-closure operator\n")); |
| 1097 continue; | 1108 continue; |
| 1098 } | 1109 } |
| 1099 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1110 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1100 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1111 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1101 arguments.Add(call->PushArgumentAt(i)->value()); | 1112 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1102 } | 1113 } |
| 1103 InlinedCallData call_data(call, &arguments, *call_info[call_idx].caller); | 1114 InlinedCallData call_data( |
| 1115 call, &arguments, call_info[call_idx].caller(), |
| 1116 call_info[call_idx].caller_graph->inlining_id()); |
| 1104 if (TryInlining(target, | 1117 if (TryInlining(target, |
| 1105 call->argument_names(), | 1118 call->argument_names(), |
| 1106 &call_data)) { | 1119 &call_data)) { |
| 1107 InlineCall(&call_data); | 1120 InlineCall(&call_data); |
| 1108 } | 1121 } |
| 1109 } | 1122 } |
| 1110 } | 1123 } |
| 1111 | 1124 |
| 1112 void InlineInstanceCalls() { | 1125 void InlineInstanceCalls() { |
| 1113 const GrowableArray<CallSites::InstanceCallInfo>& call_info = | 1126 const GrowableArray<CallSites::InstanceCallInfo>& call_info = |
| 1114 inlining_call_sites_->instance_calls(); | 1127 inlining_call_sites_->instance_calls(); |
| 1115 TRACE_INLINING(ISL_Print(" Polymorphic Instance Calls (%" Pd ")\n", | 1128 TRACE_INLINING(ISL_Print(" Polymorphic Instance Calls (%" Pd ")\n", |
| 1116 call_info.length())); | 1129 call_info.length())); |
| 1117 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { | 1130 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { |
| 1118 PolymorphicInstanceCallInstr* call = call_info[call_idx].call; | 1131 PolymorphicInstanceCallInstr* call = call_info[call_idx].call; |
| 1119 if (call->with_checks()) { | 1132 if (call->with_checks()) { |
| 1120 const Function& cl = *call_info[call_idx].caller; | 1133 const Function& cl = call_info[call_idx].caller(); |
| 1121 PolymorphicInliner inliner(this, call, cl); | 1134 intptr_t caller_inlining_id = |
| 1135 call_info[call_idx].caller_graph->inlining_id(); |
| 1136 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); |
| 1122 inliner.Inline(); | 1137 inliner.Inline(); |
| 1123 continue; | 1138 continue; |
| 1124 } | 1139 } |
| 1125 | 1140 |
| 1126 const ICData& ic_data = call->ic_data(); | 1141 const ICData& ic_data = call->ic_data(); |
| 1127 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 1142 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 1128 if (!inliner_->AlwaysInline(target) && | 1143 if (!inliner_->AlwaysInline(target) && |
| 1129 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { | 1144 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { |
| 1130 TRACE_INLINING(ISL_Print( | 1145 TRACE_INLINING(ISL_Print( |
| 1131 " => %s (deopt count %d)\n Bailout: cold %f\n", | 1146 " => %s (deopt count %d)\n Bailout: cold %f\n", |
| 1132 target.ToCString(), | 1147 target.ToCString(), |
| 1133 target.deoptimization_counter(), | 1148 target.deoptimization_counter(), |
| 1134 call_info[call_idx].ratio)); | 1149 call_info[call_idx].ratio)); |
| 1135 PRINT_INLINING_TREE("Too cold", | 1150 PRINT_INLINING_TREE("Too cold", |
| 1136 call_info[call_idx].caller, &target, call); | 1151 &call_info[call_idx].caller(), &target, call); |
| 1137 continue; | 1152 continue; |
| 1138 } | 1153 } |
| 1139 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1154 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1140 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) { | 1155 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) { |
| 1141 arguments.Add(call->PushArgumentAt(arg_i)->value()); | 1156 arguments.Add(call->PushArgumentAt(arg_i)->value()); |
| 1142 } | 1157 } |
| 1143 InlinedCallData call_data(call, &arguments, *call_info[call_idx].caller); | 1158 InlinedCallData call_data( |
| 1159 call, &arguments, call_info[call_idx].caller(), |
| 1160 call_info[call_idx].caller_graph->inlining_id()); |
| 1144 if (TryInlining(target, | 1161 if (TryInlining(target, |
| 1145 call->instance_call()->argument_names(), | 1162 call->instance_call()->argument_names(), |
| 1146 &call_data)) { | 1163 &call_data)) { |
| 1147 InlineCall(&call_data); | 1164 InlineCall(&call_data); |
| 1148 } | 1165 } |
| 1149 } | 1166 } |
| 1150 } | 1167 } |
| 1151 | 1168 |
| 1152 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, | 1169 bool AdjustForOptionalParameters(const ParsedFunction& parsed_function, |
| 1153 const Array& argument_names, | 1170 const Array& argument_names, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 CallSites* inlining_call_sites_; | 1270 CallSites* inlining_call_sites_; |
| 1254 GrowableArray<ParsedFunction*> function_cache_; | 1271 GrowableArray<ParsedFunction*> function_cache_; |
| 1255 GrowableArray<InlinedInfo> inlined_info_; | 1272 GrowableArray<InlinedInfo> inlined_info_; |
| 1256 | 1273 |
| 1257 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); | 1274 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); |
| 1258 }; | 1275 }; |
| 1259 | 1276 |
| 1260 | 1277 |
| 1261 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, | 1278 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, |
| 1262 PolymorphicInstanceCallInstr* call, | 1279 PolymorphicInstanceCallInstr* call, |
| 1263 const Function& caller_function) | 1280 const Function& caller_function, |
| 1281 intptr_t caller_inlining_id) |
| 1264 : owner_(owner), | 1282 : owner_(owner), |
| 1265 call_(call), | 1283 call_(call), |
| 1266 num_variants_(call->ic_data().NumberOfChecks()), | 1284 num_variants_(call->ic_data().NumberOfChecks()), |
| 1267 variants_(num_variants_), | 1285 variants_(num_variants_), |
| 1268 inlined_variants_(num_variants_), | 1286 inlined_variants_(num_variants_), |
| 1269 non_inlined_variants_(num_variants_), | 1287 non_inlined_variants_(num_variants_), |
| 1270 inlined_entries_(num_variants_), | 1288 inlined_entries_(num_variants_), |
| 1271 exit_collector_(new(Z) | 1289 exit_collector_(new(Z) |
| 1272 InlineExitCollector(owner->caller_graph(), call)), | 1290 InlineExitCollector(owner->caller_graph(), call)), |
| 1273 caller_function_(caller_function) { | 1291 caller_function_(caller_function), |
| 1292 caller_inlining_id_(caller_inlining_id) { |
| 1274 } | 1293 } |
| 1275 | 1294 |
| 1276 | 1295 |
| 1277 Isolate* PolymorphicInliner::isolate() const { | 1296 Isolate* PolymorphicInliner::isolate() const { |
| 1278 return owner_->caller_graph()->isolate(); | 1297 return owner_->caller_graph()->isolate(); |
| 1279 } | 1298 } |
| 1280 | 1299 |
| 1281 | 1300 |
| 1282 Zone* PolymorphicInliner::zone() const { | 1301 Zone* PolymorphicInliner::zone() const { |
| 1283 return owner_->caller_graph()->zone(); | 1302 return owner_->caller_graph()->zone(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 const Function& target) { | 1380 const Function& target) { |
| 1362 if (TryInlineRecognizedMethod(receiver_cid, target)) { | 1381 if (TryInlineRecognizedMethod(receiver_cid, target)) { |
| 1363 owner_->inlined_ = true; | 1382 owner_->inlined_ = true; |
| 1364 return true; | 1383 return true; |
| 1365 } | 1384 } |
| 1366 | 1385 |
| 1367 GrowableArray<Value*> arguments(call_->ArgumentCount()); | 1386 GrowableArray<Value*> arguments(call_->ArgumentCount()); |
| 1368 for (int i = 0; i < call_->ArgumentCount(); ++i) { | 1387 for (int i = 0; i < call_->ArgumentCount(); ++i) { |
| 1369 arguments.Add(call_->PushArgumentAt(i)->value()); | 1388 arguments.Add(call_->PushArgumentAt(i)->value()); |
| 1370 } | 1389 } |
| 1371 InlinedCallData call_data(call_, &arguments, caller_function_); | 1390 InlinedCallData call_data(call_, &arguments, |
| 1391 caller_function_, |
| 1392 caller_inlining_id_); |
| 1372 if (!owner_->TryInlining(target, | 1393 if (!owner_->TryInlining(target, |
| 1373 call_->instance_call()->argument_names(), | 1394 call_->instance_call()->argument_names(), |
| 1374 &call_data)) { | 1395 &call_data)) { |
| 1375 return false; | 1396 return false; |
| 1376 } | 1397 } |
| 1377 | 1398 |
| 1378 FlowGraph* callee_graph = call_data.callee_graph; | 1399 FlowGraph* callee_graph = call_data.callee_graph; |
| 1379 call_data.exit_collector->PrepareGraphs(callee_graph); | 1400 call_data.exit_collector->PrepareGraphs(callee_graph); |
| 1380 inlined_entries_.Add(callee_graph->graph_entry()); | 1401 inlined_entries_.Add(callee_graph->graph_entry()); |
| 1381 exit_collector_->Union(call_data.exit_collector); | 1402 exit_collector_->Union(call_data.exit_collector); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1739 | 1760 |
| 1740 | 1761 |
| 1741 static bool ShouldTraceInlining(FlowGraph* flow_graph) { | 1762 static bool ShouldTraceInlining(FlowGraph* flow_graph) { |
| 1742 const Function& top = flow_graph->parsed_function().function(); | 1763 const Function& top = flow_graph->parsed_function().function(); |
| 1743 return FLAG_trace_inlining && FlowGraphPrinter::ShouldPrint(top); | 1764 return FLAG_trace_inlining && FlowGraphPrinter::ShouldPrint(top); |
| 1744 } | 1765 } |
| 1745 | 1766 |
| 1746 | 1767 |
| 1747 FlowGraphInliner::FlowGraphInliner( | 1768 FlowGraphInliner::FlowGraphInliner( |
| 1748 FlowGraph* flow_graph, | 1769 FlowGraph* flow_graph, |
| 1749 GrowableArray<const Function*>* inline_id_to_function) | 1770 GrowableArray<const Function*>* inline_id_to_function, |
| 1771 GrowableArray<intptr_t>* caller_inline_id) |
| 1750 : flow_graph_(flow_graph), | 1772 : flow_graph_(flow_graph), |
| 1751 inline_id_to_function_(inline_id_to_function), | 1773 inline_id_to_function_(inline_id_to_function), |
| 1774 caller_inline_id_(caller_inline_id), |
| 1752 trace_inlining_(ShouldTraceInlining(flow_graph)) { | 1775 trace_inlining_(ShouldTraceInlining(flow_graph)) { |
| 1753 } | 1776 } |
| 1754 | 1777 |
| 1755 | 1778 |
| 1756 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) { | 1779 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) { |
| 1757 const Function& function = flow_graph->function(); | 1780 const Function& function = flow_graph->function(); |
| 1758 if (force || (function.optimized_instruction_count() == 0)) { | 1781 if (force || (function.optimized_instruction_count() == 0)) { |
| 1759 GraphInfoCollector info; | 1782 GraphInfoCollector info; |
| 1760 info.Collect(*flow_graph); | 1783 info.Collect(*flow_graph); |
| 1761 | 1784 |
| 1762 function.set_optimized_instruction_count( | 1785 function.set_optimized_instruction_count( |
| 1763 ClampUint16(info.instruction_count())); | 1786 ClampUint16(info.instruction_count())); |
| 1764 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); | 1787 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); |
| 1765 } | 1788 } |
| 1766 } | 1789 } |
| 1767 | 1790 |
| 1768 | 1791 |
| 1769 // TODO(srdjan): This is only needed when disassembling and/or profiling. | 1792 // TODO(srdjan): This is only needed when disassembling and/or profiling. |
| 1770 void FlowGraphInliner::SetInliningId(const FlowGraph& flow_graph, | 1793 // Sets inlining id for all instructions of this flow-graph, as well for the |
| 1794 // FlowGraph itself. |
| 1795 void FlowGraphInliner::SetInliningId(FlowGraph* flow_graph, |
| 1771 intptr_t inlining_id) { | 1796 intptr_t inlining_id) { |
| 1772 for (BlockIterator block_it = flow_graph.postorder_iterator(); | 1797 ASSERT(flow_graph->inlining_id() < 0); |
| 1798 flow_graph->set_inlining_id(inlining_id); |
| 1799 for (BlockIterator block_it = flow_graph->postorder_iterator(); |
| 1773 !block_it.Done(); | 1800 !block_it.Done(); |
| 1774 block_it.Advance()) { | 1801 block_it.Advance()) { |
| 1775 for (ForwardInstructionIterator it(block_it.Current()); | 1802 for (ForwardInstructionIterator it(block_it.Current()); |
| 1776 !it.Done(); | 1803 !it.Done(); |
| 1777 it.Advance()) { | 1804 it.Advance()) { |
| 1778 Instruction* current = it.Current(); | 1805 Instruction* current = it.Current(); |
| 1779 // Do not overwrite owner function. | 1806 // Do not overwrite owner function. |
| 1780 ASSERT(!current->has_inlining_id()); | 1807 ASSERT(!current->has_inlining_id()); |
| 1781 current->set_inlining_id(inlining_id); | 1808 current->set_inlining_id(inlining_id); |
| 1782 } | 1809 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 ISL_Print("After Inlining of %s\n", flow_graph_-> | 1866 ISL_Print("After Inlining of %s\n", flow_graph_-> |
| 1840 function().ToFullyQualifiedCString()); | 1867 function().ToFullyQualifiedCString()); |
| 1841 FlowGraphPrinter printer(*flow_graph_); | 1868 FlowGraphPrinter printer(*flow_graph_); |
| 1842 printer.PrintBlocks(); | 1869 printer.PrintBlocks(); |
| 1843 } | 1870 } |
| 1844 } | 1871 } |
| 1845 } | 1872 } |
| 1846 } | 1873 } |
| 1847 | 1874 |
| 1848 | 1875 |
| 1849 intptr_t FlowGraphInliner::NextInlineId(const Function& function) { | 1876 intptr_t FlowGraphInliner::NextInlineId(const Function& function, |
| 1877 intptr_t parent_id) { |
| 1850 const intptr_t id = inline_id_to_function_->length(); | 1878 const intptr_t id = inline_id_to_function_->length(); |
| 1851 inline_id_to_function_->Add(&function); | 1879 inline_id_to_function_->Add(&function); |
| 1880 caller_inline_id_->Add(parent_id); |
| 1852 return id; | 1881 return id; |
| 1853 } | 1882 } |
| 1854 | 1883 |
| 1855 | 1884 |
| 1856 } // namespace dart | 1885 } // namespace dart |
| OLD | NEW |