| 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 CallSites(FlowGraph* flow_graph, | 181 explicit CallSites(FlowGraph* flow_graph) |
| 182 const GrowableArray<intptr_t>& skip_static_call_deopt_ids) | |
| 183 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. | 182 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. |
| 184 static_calls_(), | 183 static_calls_(), |
| 185 closure_calls_(), | 184 closure_calls_(), |
| 186 instance_calls_(), | 185 instance_calls_(), |
| 187 skip_static_call_deopt_ids_(skip_static_call_deopt_ids) { } | 186 skip_static_call_deopt_ids_() { } |
| 188 | 187 |
| 189 GrowableArray<StaticCallInstr*>* static_calls() { | 188 GrowableArray<StaticCallInstr*>* static_calls() { |
| 190 return &static_calls_; | 189 return &static_calls_; |
| 191 } | 190 } |
| 192 | 191 |
| 193 GrowableArray<ClosureCallInstr*>* closure_calls() { | 192 GrowableArray<ClosureCallInstr*>* closure_calls() { |
| 194 return &closure_calls_; | 193 return &closure_calls_; |
| 195 } | 194 } |
| 196 | 195 |
| 197 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { | 196 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { |
| 198 return &instance_calls_; | 197 return &instance_calls_; |
| 199 } | 198 } |
| 200 | 199 |
| 201 bool HasCalls() const { | 200 bool HasCalls() const { |
| 202 return !(static_calls_.is_empty() && | 201 return !(static_calls_.is_empty() && |
| 203 closure_calls_.is_empty() && | 202 closure_calls_.is_empty() && |
| 204 instance_calls_.is_empty()); | 203 instance_calls_.is_empty()); |
| 205 } | 204 } |
| 206 | 205 |
| 207 void Clear() { | 206 void Clear() { |
| 208 static_calls_.Clear(); | 207 static_calls_.Clear(); |
| 209 closure_calls_.Clear(); | 208 closure_calls_.Clear(); |
| 210 instance_calls_.Clear(); | 209 instance_calls_.Clear(); |
| 210 skip_static_call_deopt_ids_.Clear(); |
| 211 } | 211 } |
| 212 | 212 |
| 213 void FindCallSites(FlowGraph* graph) { | 213 void FindCallSites(FlowGraph* graph) { |
| 214 ASSERT(graph != NULL); |
| 215 const Function& function = graph->parsed_function().function(); |
| 216 ASSERT(function.HasCode()); |
| 217 const Code& code = Code::Handle(function.CurrentCode()); |
| 218 skip_static_call_deopt_ids_.Clear(); |
| 219 code.ExtractUncalledStaticCallDeoptIds(&skip_static_call_deopt_ids_); |
| 214 for (BlockIterator block_it = graph->postorder_iterator(); | 220 for (BlockIterator block_it = graph->postorder_iterator(); |
| 215 !block_it.Done(); | 221 !block_it.Done(); |
| 216 block_it.Advance()) { | 222 block_it.Advance()) { |
| 217 for (ForwardInstructionIterator it(block_it.Current()); | 223 for (ForwardInstructionIterator it(block_it.Current()); |
| 218 !it.Done(); | 224 !it.Done(); |
| 219 it.Advance()) { | 225 it.Advance()) { |
| 220 it.Current()->Accept(this); | 226 it.Current()->Accept(this); |
| 221 } | 227 } |
| 222 } | 228 } |
| 223 } | 229 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 239 return; | 245 return; |
| 240 } | 246 } |
| 241 } | 247 } |
| 242 static_calls_.Add(call); | 248 static_calls_.Add(call); |
| 243 } | 249 } |
| 244 | 250 |
| 245 private: | 251 private: |
| 246 GrowableArray<StaticCallInstr*> static_calls_; | 252 GrowableArray<StaticCallInstr*> static_calls_; |
| 247 GrowableArray<ClosureCallInstr*> closure_calls_; | 253 GrowableArray<ClosureCallInstr*> closure_calls_; |
| 248 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; | 254 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; |
| 249 const GrowableArray<intptr_t>& skip_static_call_deopt_ids_; | 255 GrowableArray<intptr_t> skip_static_call_deopt_ids_; |
| 250 | 256 |
| 251 DISALLOW_COPY_AND_ASSIGN(CallSites); | 257 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 252 }; | 258 }; |
| 253 | 259 |
| 254 | 260 |
| 255 class CallSiteInliner : public ValueObject { | 261 class CallSiteInliner : public ValueObject { |
| 256 public: | 262 public: |
| 257 explicit CallSiteInliner(FlowGraph* flow_graph) | 263 explicit CallSiteInliner(FlowGraph* flow_graph) |
| 258 : caller_graph_(flow_graph), | 264 : caller_graph_(flow_graph), |
| 259 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), | 265 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 282 } | 288 } |
| 283 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && | 289 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && |
| 284 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { | 290 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { |
| 285 return true; | 291 return true; |
| 286 } | 292 } |
| 287 return false; | 293 return false; |
| 288 } | 294 } |
| 289 | 295 |
| 290 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently | 296 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently |
| 291 // max. size observed is 11 (dart2js). | 297 // max. size observed is 11 (dart2js). |
| 292 void InlineCalls(const GrowableArray<intptr_t>& skip_static_call_deopt_ids) { | 298 void InlineCalls() { |
| 293 // If inlining depth is less then one abort. | 299 // If inlining depth is less then one abort. |
| 294 if (FLAG_inlining_depth_threshold < 1) return; | 300 if (FLAG_inlining_depth_threshold < 1) return; |
| 295 // Create two call site collections to swap between. | 301 // Create two call site collections to swap between. |
| 296 CallSites sites1(caller_graph_, skip_static_call_deopt_ids); | 302 CallSites sites1(caller_graph_); |
| 297 CallSites sites2(caller_graph_, skip_static_call_deopt_ids); | 303 CallSites sites2(caller_graph_); |
| 298 CallSites* call_sites_temp = NULL; | 304 CallSites* call_sites_temp = NULL; |
| 299 collected_call_sites_ = &sites1; | 305 collected_call_sites_ = &sites1; |
| 300 inlining_call_sites_ = &sites2; | 306 inlining_call_sites_ = &sites2; |
| 301 // Collect initial call sites. | 307 // Collect initial call sites. |
| 302 collected_call_sites_->FindCallSites(caller_graph_); | 308 collected_call_sites_->FindCallSites(caller_graph_); |
| 303 while (collected_call_sites_->HasCalls()) { | 309 while (collected_call_sites_->HasCalls()) { |
| 304 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); | 310 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); |
| 305 // Swap collected and inlining arrays and clear the new collecting array. | 311 // Swap collected and inlining arrays and clear the new collecting array. |
| 306 call_sites_temp = collected_call_sites_; | 312 call_sites_temp = collected_call_sites_; |
| 307 collected_call_sites_ = inlining_call_sites_; | 313 collected_call_sites_ = inlining_call_sites_; |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 flow_graph_->parsed_function().function().ToCString())); | 783 flow_graph_->parsed_function().function().ToCString())); |
| 778 | 784 |
| 779 if (FLAG_trace_inlining && FLAG_print_flow_graph) { | 785 if (FLAG_trace_inlining && FLAG_print_flow_graph) { |
| 780 OS::Print("Before Inlining of %s\n", flow_graph_-> | 786 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 781 parsed_function().function().ToFullyQualifiedCString()); | 787 parsed_function().function().ToFullyQualifiedCString()); |
| 782 FlowGraphPrinter printer(*flow_graph_); | 788 FlowGraphPrinter printer(*flow_graph_); |
| 783 printer.PrintBlocks(); | 789 printer.PrintBlocks(); |
| 784 } | 790 } |
| 785 | 791 |
| 786 CallSiteInliner inliner(flow_graph_); | 792 CallSiteInliner inliner(flow_graph_); |
| 787 inliner.InlineCalls(uncalled_static_static_call_deopt_ids_); | 793 inliner.InlineCalls(); |
| 788 | 794 |
| 789 if (inliner.inlined()) { | 795 if (inliner.inlined()) { |
| 790 flow_graph_->RepairGraphAfterInlining(); | 796 flow_graph_->RepairGraphAfterInlining(); |
| 791 if (FLAG_trace_inlining) { | 797 if (FLAG_trace_inlining) { |
| 792 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); | 798 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
| 793 if (FLAG_print_flow_graph) { | 799 if (FLAG_print_flow_graph) { |
| 794 OS::Print("After Inlining of %s\n", flow_graph_-> | 800 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 795 parsed_function().function().ToFullyQualifiedCString()); | 801 parsed_function().function().ToFullyQualifiedCString()); |
| 796 FlowGraphPrinter printer(*flow_graph_); | 802 FlowGraphPrinter printer(*flow_graph_); |
| 797 printer.PrintBlocks(); | 803 printer.PrintBlocks(); |
| 798 } | 804 } |
| 799 } | 805 } |
| 800 } | 806 } |
| 801 } | 807 } |
| 802 | 808 |
| 803 } // namespace dart | 809 } // namespace dart |
| OLD | NEW |