| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/flow_graph.h" | 9 #include "vm/flow_graph.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 171 |
| 172 private: | 172 private: |
| 173 intptr_t call_site_count_; | 173 intptr_t call_site_count_; |
| 174 intptr_t instruction_count_; | 174 intptr_t instruction_count_; |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 | 177 |
| 178 // A collection of call sites to consider for inlining. | 178 // A collection of call sites to consider for inlining. |
| 179 class CallSites : public FlowGraphVisitor { | 179 class CallSites : public FlowGraphVisitor { |
| 180 public: | 180 public: |
| 181 explicit CallSites(FlowGraph* flow_graph) | 181 CallSites(FlowGraph* flow_graph, |
| 182 const GrowableArray<intptr_t>& skip_static_call_deopt_ids) |
| 182 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. | 183 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. |
| 183 static_calls_(), | 184 static_calls_(), |
| 184 closure_calls_(), | 185 closure_calls_(), |
| 185 instance_calls_() { } | 186 instance_calls_(), |
| 187 skip_static_call_deopt_ids_(skip_static_call_deopt_ids) { } |
| 186 | 188 |
| 187 GrowableArray<StaticCallInstr*>* static_calls() { | 189 GrowableArray<StaticCallInstr*>* static_calls() { |
| 188 return &static_calls_; | 190 return &static_calls_; |
| 189 } | 191 } |
| 190 | 192 |
| 191 GrowableArray<ClosureCallInstr*>* closure_calls() { | 193 GrowableArray<ClosureCallInstr*>* closure_calls() { |
| 192 return &closure_calls_; | 194 return &closure_calls_; |
| 193 } | 195 } |
| 194 | 196 |
| 195 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { | 197 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 222 | 224 |
| 223 void VisitClosureCall(ClosureCallInstr* call) { | 225 void VisitClosureCall(ClosureCallInstr* call) { |
| 224 closure_calls_.Add(call); | 226 closure_calls_.Add(call); |
| 225 } | 227 } |
| 226 | 228 |
| 227 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { | 229 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { |
| 228 instance_calls_.Add(call); | 230 instance_calls_.Add(call); |
| 229 } | 231 } |
| 230 | 232 |
| 231 void VisitStaticCall(StaticCallInstr* call) { | 233 void VisitStaticCall(StaticCallInstr* call) { |
| 232 if (call->function().IsInlineable()) static_calls_.Add(call); | 234 if (!call->function().IsInlineable()) return; |
| 235 const intptr_t call_deopt_id = call->deopt_id(); |
| 236 for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) { |
| 237 if (call_deopt_id == skip_static_call_deopt_ids_[i]) { |
| 238 // Do not inline this call. |
| 239 return; |
| 240 } |
| 241 } |
| 242 static_calls_.Add(call); |
| 233 } | 243 } |
| 234 | 244 |
| 235 private: | 245 private: |
| 236 GrowableArray<StaticCallInstr*> static_calls_; | 246 GrowableArray<StaticCallInstr*> static_calls_; |
| 237 GrowableArray<ClosureCallInstr*> closure_calls_; | 247 GrowableArray<ClosureCallInstr*> closure_calls_; |
| 238 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; | 248 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; |
| 249 const GrowableArray<intptr_t>& skip_static_call_deopt_ids_; |
| 239 | 250 |
| 240 DISALLOW_COPY_AND_ASSIGN(CallSites); | 251 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 241 }; | 252 }; |
| 242 | 253 |
| 243 | 254 |
| 244 class CallSiteInliner : public ValueObject { | 255 class CallSiteInliner : public ValueObject { |
| 245 public: | 256 public: |
| 246 explicit CallSiteInliner(FlowGraph* flow_graph) | 257 explicit CallSiteInliner(FlowGraph* flow_graph) |
| 247 : caller_graph_(flow_graph), | 258 : caller_graph_(flow_graph), |
| 248 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), | 259 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 269 (instr_count <= FLAG_inlining_in_loop_size_threshold)) { | 280 (instr_count <= FLAG_inlining_in_loop_size_threshold)) { |
| 270 return true; | 281 return true; |
| 271 } | 282 } |
| 272 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && | 283 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && |
| 273 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { | 284 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { |
| 274 return true; | 285 return true; |
| 275 } | 286 } |
| 276 return false; | 287 return false; |
| 277 } | 288 } |
| 278 | 289 |
| 279 void InlineCalls() { | 290 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently |
| 291 // max. size observed is 11 (dart2js). |
| 292 void InlineCalls(const GrowableArray<intptr_t>& skip_static_call_deopt_ids) { |
| 280 // If inlining depth is less then one abort. | 293 // If inlining depth is less then one abort. |
| 281 if (FLAG_inlining_depth_threshold < 1) return; | 294 if (FLAG_inlining_depth_threshold < 1) return; |
| 282 // Create two call site collections to swap between. | 295 // Create two call site collections to swap between. |
| 283 CallSites sites1(caller_graph_); | 296 CallSites sites1(caller_graph_, skip_static_call_deopt_ids); |
| 284 CallSites sites2(caller_graph_); | 297 CallSites sites2(caller_graph_, skip_static_call_deopt_ids); |
| 285 CallSites* call_sites_temp = NULL; | 298 CallSites* call_sites_temp = NULL; |
| 286 collected_call_sites_ = &sites1; | 299 collected_call_sites_ = &sites1; |
| 287 inlining_call_sites_ = &sites2; | 300 inlining_call_sites_ = &sites2; |
| 288 // Collect initial call sites. | 301 // Collect initial call sites. |
| 289 collected_call_sites_->FindCallSites(caller_graph_); | 302 collected_call_sites_->FindCallSites(caller_graph_); |
| 290 while (collected_call_sites_->HasCalls()) { | 303 while (collected_call_sites_->HasCalls()) { |
| 291 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); | 304 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); |
| 292 // Swap collected and inlining arrays and clear the new collecting array. | 305 // Swap collected and inlining arrays and clear the new collecting array. |
| 293 call_sites_temp = collected_call_sites_; | 306 call_sites_temp = collected_call_sites_; |
| 294 collected_call_sites_ = inlining_call_sites_; | 307 collected_call_sites_ = inlining_call_sites_; |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 flow_graph_->parsed_function().function().ToCString())); | 777 flow_graph_->parsed_function().function().ToCString())); |
| 765 | 778 |
| 766 if (FLAG_trace_inlining && FLAG_print_flow_graph) { | 779 if (FLAG_trace_inlining && FLAG_print_flow_graph) { |
| 767 OS::Print("Before Inlining of %s\n", flow_graph_-> | 780 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 768 parsed_function().function().ToFullyQualifiedCString()); | 781 parsed_function().function().ToFullyQualifiedCString()); |
| 769 FlowGraphPrinter printer(*flow_graph_); | 782 FlowGraphPrinter printer(*flow_graph_); |
| 770 printer.PrintBlocks(); | 783 printer.PrintBlocks(); |
| 771 } | 784 } |
| 772 | 785 |
| 773 CallSiteInliner inliner(flow_graph_); | 786 CallSiteInliner inliner(flow_graph_); |
| 774 inliner.InlineCalls(); | 787 inliner.InlineCalls(uncalled_static_static_call_deopt_ids_); |
| 775 | 788 |
| 776 if (inliner.inlined()) { | 789 if (inliner.inlined()) { |
| 777 flow_graph_->RepairGraphAfterInlining(); | 790 flow_graph_->RepairGraphAfterInlining(); |
| 778 if (FLAG_trace_inlining) { | 791 if (FLAG_trace_inlining) { |
| 779 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); | 792 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
| 780 if (FLAG_print_flow_graph) { | 793 if (FLAG_print_flow_graph) { |
| 781 OS::Print("After Inlining of %s\n", flow_graph_-> | 794 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 782 parsed_function().function().ToFullyQualifiedCString()); | 795 parsed_function().function().ToFullyQualifiedCString()); |
| 783 FlowGraphPrinter printer(*flow_graph_); | 796 FlowGraphPrinter printer(*flow_graph_); |
| 784 printer.PrintBlocks(); | 797 printer.PrintBlocks(); |
| 785 } | 798 } |
| 786 } | 799 } |
| 787 } | 800 } |
| 788 } | 801 } |
| 789 | 802 |
| 790 } // namespace dart | 803 } // namespace dart |
| OLD | NEW |