| 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 explicit CallSites(FlowGraph* flow_graph) |
| 182 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. | 182 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. |
| 183 static_calls_(), | 183 static_calls_(), |
| 184 closure_calls_(), | 184 closure_calls_(), |
| 185 instance_calls_() { } | 185 instance_calls_(), |
| 186 skip_static_call_deopt_ids_() { } |
| 186 | 187 |
| 187 GrowableArray<StaticCallInstr*>* static_calls() { | 188 GrowableArray<StaticCallInstr*>* static_calls() { |
| 188 return &static_calls_; | 189 return &static_calls_; |
| 189 } | 190 } |
| 190 | 191 |
| 191 GrowableArray<ClosureCallInstr*>* closure_calls() { | 192 GrowableArray<ClosureCallInstr*>* closure_calls() { |
| 192 return &closure_calls_; | 193 return &closure_calls_; |
| 193 } | 194 } |
| 194 | 195 |
| 195 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { | 196 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { |
| 196 return &instance_calls_; | 197 return &instance_calls_; |
| 197 } | 198 } |
| 198 | 199 |
| 199 bool HasCalls() const { | 200 bool HasCalls() const { |
| 200 return !(static_calls_.is_empty() && | 201 return !(static_calls_.is_empty() && |
| 201 closure_calls_.is_empty() && | 202 closure_calls_.is_empty() && |
| 202 instance_calls_.is_empty()); | 203 instance_calls_.is_empty()); |
| 203 } | 204 } |
| 204 | 205 |
| 205 void Clear() { | 206 void Clear() { |
| 206 static_calls_.Clear(); | 207 static_calls_.Clear(); |
| 207 closure_calls_.Clear(); | 208 closure_calls_.Clear(); |
| 208 instance_calls_.Clear(); | 209 instance_calls_.Clear(); |
| 210 skip_static_call_deopt_ids_.Clear(); |
| 209 } | 211 } |
| 210 | 212 |
| 211 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_); |
| 212 for (BlockIterator block_it = graph->postorder_iterator(); | 220 for (BlockIterator block_it = graph->postorder_iterator(); |
| 213 !block_it.Done(); | 221 !block_it.Done(); |
| 214 block_it.Advance()) { | 222 block_it.Advance()) { |
| 215 for (ForwardInstructionIterator it(block_it.Current()); | 223 for (ForwardInstructionIterator it(block_it.Current()); |
| 216 !it.Done(); | 224 !it.Done(); |
| 217 it.Advance()) { | 225 it.Advance()) { |
| 218 it.Current()->Accept(this); | 226 it.Current()->Accept(this); |
| 219 } | 227 } |
| 220 } | 228 } |
| 221 } | 229 } |
| 222 | 230 |
| 223 void VisitClosureCall(ClosureCallInstr* call) { | 231 void VisitClosureCall(ClosureCallInstr* call) { |
| 224 closure_calls_.Add(call); | 232 closure_calls_.Add(call); |
| 225 } | 233 } |
| 226 | 234 |
| 227 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { | 235 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { |
| 228 instance_calls_.Add(call); | 236 instance_calls_.Add(call); |
| 229 } | 237 } |
| 230 | 238 |
| 231 void VisitStaticCall(StaticCallInstr* call) { | 239 void VisitStaticCall(StaticCallInstr* call) { |
| 232 if (call->function().IsInlineable()) static_calls_.Add(call); | 240 if (!call->function().IsInlineable()) return; |
| 241 const intptr_t call_deopt_id = call->deopt_id(); |
| 242 for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) { |
| 243 if (call_deopt_id == skip_static_call_deopt_ids_[i]) { |
| 244 // Do not inline this call. |
| 245 return; |
| 246 } |
| 247 } |
| 248 static_calls_.Add(call); |
| 233 } | 249 } |
| 234 | 250 |
| 235 private: | 251 private: |
| 236 GrowableArray<StaticCallInstr*> static_calls_; | 252 GrowableArray<StaticCallInstr*> static_calls_; |
| 237 GrowableArray<ClosureCallInstr*> closure_calls_; | 253 GrowableArray<ClosureCallInstr*> closure_calls_; |
| 238 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; | 254 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; |
| 255 GrowableArray<intptr_t> skip_static_call_deopt_ids_; |
| 239 | 256 |
| 240 DISALLOW_COPY_AND_ASSIGN(CallSites); | 257 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 241 }; | 258 }; |
| 242 | 259 |
| 243 | 260 |
| 244 class CallSiteInliner : public ValueObject { | 261 class CallSiteInliner : public ValueObject { |
| 245 public: | 262 public: |
| 246 explicit CallSiteInliner(FlowGraph* flow_graph) | 263 explicit CallSiteInliner(FlowGraph* flow_graph) |
| 247 : caller_graph_(flow_graph), | 264 : caller_graph_(flow_graph), |
| 248 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), | 265 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)) { | 286 (instr_count <= FLAG_inlining_in_loop_size_threshold)) { |
| 270 return true; | 287 return true; |
| 271 } | 288 } |
| 272 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && | 289 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && |
| 273 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { | 290 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { |
| 274 return true; | 291 return true; |
| 275 } | 292 } |
| 276 return false; | 293 return false; |
| 277 } | 294 } |
| 278 | 295 |
| 296 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently |
| 297 // max. size observed is 11 (dart2js). |
| 279 void InlineCalls() { | 298 void InlineCalls() { |
| 280 // If inlining depth is less then one abort. | 299 // If inlining depth is less then one abort. |
| 281 if (FLAG_inlining_depth_threshold < 1) return; | 300 if (FLAG_inlining_depth_threshold < 1) return; |
| 282 // Create two call site collections to swap between. | 301 // Create two call site collections to swap between. |
| 283 CallSites sites1(caller_graph_); | 302 CallSites sites1(caller_graph_); |
| 284 CallSites sites2(caller_graph_); | 303 CallSites sites2(caller_graph_); |
| 285 CallSites* call_sites_temp = NULL; | 304 CallSites* call_sites_temp = NULL; |
| 286 collected_call_sites_ = &sites1; | 305 collected_call_sites_ = &sites1; |
| 287 inlining_call_sites_ = &sites2; | 306 inlining_call_sites_ = &sites2; |
| 288 // Collect initial call sites. | 307 // Collect initial call sites. |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 781 OS::Print("After Inlining of %s\n", flow_graph_-> | 800 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 782 parsed_function().function().ToFullyQualifiedCString()); | 801 parsed_function().function().ToFullyQualifiedCString()); |
| 783 FlowGraphPrinter printer(*flow_graph_); | 802 FlowGraphPrinter printer(*flow_graph_); |
| 784 printer.PrintBlocks(); | 803 printer.PrintBlocks(); |
| 785 } | 804 } |
| 786 } | 805 } |
| 787 } | 806 } |
| 788 } | 807 } |
| 789 | 808 |
| 790 } // namespace dart | 809 } // namespace dart |
| OLD | NEW |