| 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/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 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 }; | 179 }; |
| 180 | 180 |
| 181 | 181 |
| 182 // A collection of call sites to consider for inlining. | 182 // A collection of call sites to consider for inlining. |
| 183 class CallSites : public FlowGraphVisitor { | 183 class CallSites : public FlowGraphVisitor { |
| 184 public: | 184 public: |
| 185 explicit CallSites(FlowGraph* flow_graph) | 185 explicit CallSites(FlowGraph* flow_graph) |
| 186 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. | 186 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. |
| 187 static_calls_(), | 187 static_calls_(), |
| 188 closure_calls_(), | 188 closure_calls_(), |
| 189 instance_calls_(), | 189 instance_calls_() { } |
| 190 skip_static_call_deopt_ids_() { } | |
| 191 | 190 |
| 192 const GrowableArray<StaticCallInstr*>& static_calls() const { | 191 const GrowableArray<StaticCallInstr*>& static_calls() const { |
| 193 return static_calls_; | 192 return static_calls_; |
| 194 } | 193 } |
| 195 | 194 |
| 196 const GrowableArray<ClosureCallInstr*>& closure_calls() const { | 195 const GrowableArray<ClosureCallInstr*>& closure_calls() const { |
| 197 return closure_calls_; | 196 return closure_calls_; |
| 198 } | 197 } |
| 199 | 198 |
| 200 struct InstanceCallInfo { | 199 struct InstanceCallInfo { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 211 bool HasCalls() const { | 210 bool HasCalls() const { |
| 212 return !(static_calls_.is_empty() && | 211 return !(static_calls_.is_empty() && |
| 213 closure_calls_.is_empty() && | 212 closure_calls_.is_empty() && |
| 214 instance_calls_.is_empty()); | 213 instance_calls_.is_empty()); |
| 215 } | 214 } |
| 216 | 215 |
| 217 void Clear() { | 216 void Clear() { |
| 218 static_calls_.Clear(); | 217 static_calls_.Clear(); |
| 219 closure_calls_.Clear(); | 218 closure_calls_.Clear(); |
| 220 instance_calls_.Clear(); | 219 instance_calls_.Clear(); |
| 221 skip_static_call_deopt_ids_.Clear(); | |
| 222 } | 220 } |
| 223 | 221 |
| 224 void FindCallSites(FlowGraph* graph) { | 222 void FindCallSites(FlowGraph* graph) { |
| 225 ASSERT(graph != NULL); | 223 ASSERT(graph != NULL); |
| 226 const Function& function = graph->parsed_function().function(); | |
| 227 ASSERT(function.HasCode()); | |
| 228 const Code& code = Code::Handle(function.unoptimized_code()); | |
| 229 | |
| 230 skip_static_call_deopt_ids_.Clear(); | |
| 231 code.ExtractUncalledStaticCallDeoptIds(&skip_static_call_deopt_ids_); | |
| 232 | 224 |
| 233 const intptr_t instance_call_start_ix = instance_calls_.length(); | 225 const intptr_t instance_call_start_ix = instance_calls_.length(); |
| 234 for (BlockIterator block_it = graph->postorder_iterator(); | 226 for (BlockIterator block_it = graph->postorder_iterator(); |
| 235 !block_it.Done(); | 227 !block_it.Done(); |
| 236 block_it.Advance()) { | 228 block_it.Advance()) { |
| 237 for (ForwardInstructionIterator it(block_it.Current()); | 229 for (ForwardInstructionIterator it(block_it.Current()); |
| 238 !it.Done(); | 230 !it.Done(); |
| 239 it.Advance()) { | 231 it.Advance()) { |
| 240 it.Current()->Accept(this); | 232 it.Current()->Accept(this); |
| 241 } | 233 } |
| 242 } | 234 } |
| 243 // Compute instance call site ratio. | 235 // Compute instance call site ratio. |
| 244 const intptr_t num_instance_calls = | 236 const intptr_t num_instance_calls = |
| 245 instance_calls_.length() - instance_call_start_ix; | 237 instance_calls_.length() - instance_call_start_ix; |
| 246 intptr_t max_count = 0; | 238 intptr_t max_count = 0; |
| 247 GrowableArray<intptr_t> call_counts(num_instance_calls); | 239 GrowableArray<intptr_t> call_counts(num_instance_calls); |
| 248 for (intptr_t i = 0; i < num_instance_calls; ++i) { | 240 for (intptr_t i = 0; i < num_instance_calls; ++i) { |
| 249 const intptr_t aggregate_count = | 241 const intptr_t aggregate_count = |
| 250 instance_calls_[i + instance_call_start_ix]. | 242 instance_calls_[i + instance_call_start_ix]. |
| 251 call->ic_data().AggregateCount(); | 243 call->ic_data().AggregateCount(); |
| 252 call_counts.Add(aggregate_count); | 244 call_counts.Add(aggregate_count); |
| 253 if (aggregate_count > max_count) max_count = aggregate_count; | 245 if (aggregate_count > max_count) max_count = aggregate_count; |
| 254 } | 246 } |
| 255 | 247 |
| 256 | |
| 257 for (intptr_t i = 0; i < num_instance_calls; ++i) { | 248 for (intptr_t i = 0; i < num_instance_calls; ++i) { |
| 258 const double ratio = static_cast<double>(call_counts[i]) / max_count; | 249 const double ratio = static_cast<double>(call_counts[i]) / max_count; |
| 259 instance_calls_[i + instance_call_start_ix].ratio = ratio; | 250 instance_calls_[i + instance_call_start_ix].ratio = ratio; |
| 260 } | 251 } |
| 261 } | 252 } |
| 262 | 253 |
| 263 void VisitClosureCall(ClosureCallInstr* call) { | 254 void VisitClosureCall(ClosureCallInstr* call) { |
| 264 closure_calls_.Add(call); | 255 closure_calls_.Add(call); |
| 265 } | 256 } |
| 266 | 257 |
| 267 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { | 258 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { |
| 268 instance_calls_.Add(InstanceCallInfo(call)); | 259 instance_calls_.Add(InstanceCallInfo(call)); |
| 269 } | 260 } |
| 270 | 261 |
| 271 void VisitStaticCall(StaticCallInstr* call) { | 262 void VisitStaticCall(StaticCallInstr* call) { |
| 272 if (!call->function().IsInlineable()) return; | 263 if (!call->function().IsInlineable()) return; |
| 273 const intptr_t call_deopt_id = call->deopt_id(); | |
| 274 for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) { | |
| 275 if (call_deopt_id == skip_static_call_deopt_ids_[i]) { | |
| 276 // Do not inline this call. | |
| 277 return; | |
| 278 } | |
| 279 } | |
| 280 static_calls_.Add(call); | 264 static_calls_.Add(call); |
| 281 } | 265 } |
| 282 | 266 |
| 283 private: | 267 private: |
| 284 GrowableArray<StaticCallInstr*> static_calls_; | 268 GrowableArray<StaticCallInstr*> static_calls_; |
| 285 GrowableArray<ClosureCallInstr*> closure_calls_; | 269 GrowableArray<ClosureCallInstr*> closure_calls_; |
| 286 GrowableArray<InstanceCallInfo> instance_calls_; | 270 GrowableArray<InstanceCallInfo> instance_calls_; |
| 287 GrowableArray<intptr_t> skip_static_call_deopt_ids_; | |
| 288 | 271 |
| 289 DISALLOW_COPY_AND_ASSIGN(CallSites); | 272 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 290 }; | 273 }; |
| 291 | 274 |
| 292 | 275 |
| 293 struct InlinedCallData { | 276 struct InlinedCallData { |
| 294 InlinedCallData(Definition* call, GrowableArray<Value*>* arguments) | 277 InlinedCallData(Definition* call, GrowableArray<Value*>* arguments) |
| 295 : call(call), | 278 : call(call), |
| 296 arguments(arguments), | 279 arguments(arguments), |
| 297 callee_graph(NULL), | 280 callee_graph(NULL), |
| (...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 OS::Print("After Inlining of %s\n", flow_graph_-> | 1326 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1344 parsed_function().function().ToFullyQualifiedCString()); | 1327 parsed_function().function().ToFullyQualifiedCString()); |
| 1345 FlowGraphPrinter printer(*flow_graph_); | 1328 FlowGraphPrinter printer(*flow_graph_); |
| 1346 printer.PrintBlocks(); | 1329 printer.PrintBlocks(); |
| 1347 } | 1330 } |
| 1348 } | 1331 } |
| 1349 } | 1332 } |
| 1350 } | 1333 } |
| 1351 | 1334 |
| 1352 } // namespace dart | 1335 } // namespace dart |
| OLD | NEW |