| 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 instance_calls_() { } | 185 instance_calls_() { } |
| 186 | 186 |
| 187 struct InstanceCallInfo { | 187 struct InstanceCallInfo { |
| 188 PolymorphicInstanceCallInstr* call; | 188 PolymorphicInstanceCallInstr* call; |
| 189 double ratio; | 189 double ratio; |
| 190 const Function* caller; | 190 const Function* caller; |
| 191 InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg, | 191 InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg, |
| 192 FlowGraph* flow_graph) | 192 FlowGraph* flow_graph) |
| 193 : call(call_arg), | 193 : call(call_arg), |
| 194 ratio(0.0), | 194 ratio(0.0), |
| 195 caller(&flow_graph->parsed_function().function()) {} | 195 caller(&flow_graph->parsed_function()->function()) {} |
| 196 }; | 196 }; |
| 197 | 197 |
| 198 struct StaticCallInfo { | 198 struct StaticCallInfo { |
| 199 StaticCallInstr* call; | 199 StaticCallInstr* call; |
| 200 double ratio; | 200 double ratio; |
| 201 const Function* caller; | 201 const Function* caller; |
| 202 StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph) | 202 StaticCallInfo(StaticCallInstr* value, FlowGraph* flow_graph) |
| 203 : call(value), | 203 : call(value), |
| 204 ratio(0.0), | 204 ratio(0.0), |
| 205 caller(&flow_graph->parsed_function().function()) {} | 205 caller(&flow_graph->parsed_function()->function()) {} |
| 206 }; | 206 }; |
| 207 | 207 |
| 208 struct ClosureCallInfo { | 208 struct ClosureCallInfo { |
| 209 ClosureCallInstr* call; | 209 ClosureCallInstr* call; |
| 210 const Function* caller; | 210 const Function* caller; |
| 211 ClosureCallInfo(ClosureCallInstr* value, FlowGraph* flow_graph) | 211 ClosureCallInfo(ClosureCallInstr* value, FlowGraph* flow_graph) |
| 212 : call(value), | 212 : call(value), |
| 213 caller(&flow_graph->parsed_function().function()) {} | 213 caller(&flow_graph->parsed_function()->function()) {} |
| 214 }; | 214 }; |
| 215 | 215 |
| 216 const GrowableArray<InstanceCallInfo>& instance_calls() const { | 216 const GrowableArray<InstanceCallInfo>& instance_calls() const { |
| 217 return instance_calls_; | 217 return instance_calls_; |
| 218 } | 218 } |
| 219 | 219 |
| 220 const GrowableArray<StaticCallInfo>& static_calls() const { | 220 const GrowableArray<StaticCallInfo>& static_calls() const { |
| 221 return static_calls_; | 221 return static_calls_; |
| 222 } | 222 } |
| 223 | 223 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 const double ratio = (max_count == 0) ? | 279 const double ratio = (max_count == 0) ? |
| 280 0.0 : static_cast<double>(static_call_counts[i]) / max_count; | 280 0.0 : static_cast<double>(static_call_counts[i]) / max_count; |
| 281 static_calls_[i + static_call_start_ix].ratio = ratio; | 281 static_calls_[i + static_call_start_ix].ratio = ratio; |
| 282 } | 282 } |
| 283 } | 283 } |
| 284 | 284 |
| 285 static void RecordAllNotInlinedFunction( | 285 static void RecordAllNotInlinedFunction( |
| 286 FlowGraph* graph, | 286 FlowGraph* graph, |
| 287 intptr_t depth, | 287 intptr_t depth, |
| 288 GrowableArray<InlinedInfo>* inlined_info) { | 288 GrowableArray<InlinedInfo>* inlined_info) { |
| 289 const Function* caller = &graph->parsed_function().function(); | 289 const Function* caller = &graph->parsed_function()->function(); |
| 290 Function& target = Function::ZoneHandle(); | 290 Function& target = Function::ZoneHandle(); |
| 291 for (BlockIterator block_it = graph->postorder_iterator(); | 291 for (BlockIterator block_it = graph->postorder_iterator(); |
| 292 !block_it.Done(); | 292 !block_it.Done(); |
| 293 block_it.Advance()) { | 293 block_it.Advance()) { |
| 294 for (ForwardInstructionIterator it(block_it.Current()); | 294 for (ForwardInstructionIterator it(block_it.Current()); |
| 295 !it.Done(); | 295 !it.Done(); |
| 296 it.Advance()) { | 296 it.Advance()) { |
| 297 Instruction* current = it.Current(); | 297 Instruction* current = it.Current(); |
| 298 Definition* call = NULL; | 298 Definition* call = NULL; |
| 299 if (current->IsPolymorphicInstanceCall()) { | 299 if (current->IsPolymorphicInstanceCall()) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 PolymorphicInstanceCallInstr* instance_call = | 346 PolymorphicInstanceCallInstr* instance_call = |
| 347 current->AsPolymorphicInstanceCall(); | 347 current->AsPolymorphicInstanceCall(); |
| 348 if (!inline_only_recognized_methods || | 348 if (!inline_only_recognized_methods || |
| 349 instance_call->HasSingleRecognizedTarget() || | 349 instance_call->HasSingleRecognizedTarget() || |
| 350 instance_call->HasOnlyDispatcherTargets()) { | 350 instance_call->HasOnlyDispatcherTargets()) { |
| 351 instance_calls_.Add(InstanceCallInfo(instance_call, graph)); | 351 instance_calls_.Add(InstanceCallInfo(instance_call, graph)); |
| 352 } else { | 352 } else { |
| 353 // Method not inlined because inlining too deep and method | 353 // Method not inlined because inlining too deep and method |
| 354 // not recognized. | 354 // not recognized. |
| 355 if (FLAG_print_inlining_tree) { | 355 if (FLAG_print_inlining_tree) { |
| 356 const Function* caller = &graph->parsed_function().function(); | 356 const Function* caller = &graph->parsed_function()->function(); |
| 357 const Function* target = | 357 const Function* target = |
| 358 &Function::ZoneHandle( | 358 &Function::ZoneHandle( |
| 359 instance_call->ic_data().GetTargetAt(0)); | 359 instance_call->ic_data().GetTargetAt(0)); |
| 360 inlined_info->Add(InlinedInfo( | 360 inlined_info->Add(InlinedInfo( |
| 361 caller, target, depth + 1, instance_call, "Too deep")); | 361 caller, target, depth + 1, instance_call, "Too deep")); |
| 362 } | 362 } |
| 363 } | 363 } |
| 364 } else if (current->IsStaticCall()) { | 364 } else if (current->IsStaticCall()) { |
| 365 StaticCallInstr* static_call = current->AsStaticCall(); | 365 StaticCallInstr* static_call = current->AsStaticCall(); |
| 366 if (!inline_only_recognized_methods || | 366 if (!inline_only_recognized_methods || |
| 367 static_call->function().IsRecognized()) { | 367 static_call->function().IsRecognized()) { |
| 368 static_calls_.Add(StaticCallInfo(static_call, graph)); | 368 static_calls_.Add(StaticCallInfo(static_call, graph)); |
| 369 } else { | 369 } else { |
| 370 // Method not inlined because inlining too deep and method | 370 // Method not inlined because inlining too deep and method |
| 371 // not recognized. | 371 // not recognized. |
| 372 if (FLAG_print_inlining_tree) { | 372 if (FLAG_print_inlining_tree) { |
| 373 const Function* caller = &graph->parsed_function().function(); | 373 const Function* caller = &graph->parsed_function()->function(); |
| 374 const Function* target = &static_call->function(); | 374 const Function* target = &static_call->function(); |
| 375 inlined_info->Add(InlinedInfo( | 375 inlined_info->Add(InlinedInfo( |
| 376 caller, target, depth + 1, static_call, "Too deep")); | 376 caller, target, depth + 1, static_call, "Too deep")); |
| 377 } | 377 } |
| 378 } | 378 } |
| 379 } else if (current->IsClosureCall()) { | 379 } else if (current->IsClosureCall()) { |
| 380 if (!inline_only_recognized_methods) { | 380 if (!inline_only_recognized_methods) { |
| 381 ClosureCallInstr* closure_call = current->AsClosureCall(); | 381 ClosureCallInstr* closure_call = current->AsClosureCall(); |
| 382 closure_calls_.Add(ClosureCallInfo(closure_call, graph)); | 382 closure_calls_.Add(ClosureCallInfo(closure_call, graph)); |
| 383 } | 383 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 } | 514 } |
| 515 if (FlowGraphInliner::AlwaysInline(callee)) { | 515 if (FlowGraphInliner::AlwaysInline(callee)) { |
| 516 return true; | 516 return true; |
| 517 } | 517 } |
| 518 return false; | 518 return false; |
| 519 } | 519 } |
| 520 | 520 |
| 521 void InlineCalls() { | 521 void InlineCalls() { |
| 522 // If inlining depth is less then one abort. | 522 // If inlining depth is less then one abort. |
| 523 if (FLAG_inlining_depth_threshold < 1) return; | 523 if (FLAG_inlining_depth_threshold < 1) return; |
| 524 if (caller_graph_->parsed_function().function().deoptimization_counter() >= | 524 if (caller_graph_->parsed_function()->function().deoptimization_counter() >= |
| 525 FLAG_deoptimization_counter_inlining_threshold) { | 525 FLAG_deoptimization_counter_inlining_threshold) { |
| 526 return; | 526 return; |
| 527 } | 527 } |
| 528 // Create two call site collections to swap between. | 528 // Create two call site collections to swap between. |
| 529 CallSites sites1(caller_graph_); | 529 CallSites sites1(caller_graph_); |
| 530 CallSites sites2(caller_graph_); | 530 CallSites sites2(caller_graph_); |
| 531 CallSites* call_sites_temp = NULL; | 531 CallSites* call_sites_temp = NULL; |
| 532 collected_call_sites_ = &sites1; | 532 collected_call_sites_ = &sites1; |
| 533 inlining_call_sites_ = &sites2; | 533 inlining_call_sites_ = &sites2; |
| 534 // Collect initial call sites. | 534 // Collect initial call sites. |
| (...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 exit_collector_->ReplaceCall(entry); | 1699 exit_collector_->ReplaceCall(entry); |
| 1700 } | 1700 } |
| 1701 | 1701 |
| 1702 | 1702 |
| 1703 static uint16_t ClampUint16(intptr_t v) { | 1703 static uint16_t ClampUint16(intptr_t v) { |
| 1704 return (v > 0xFFFF) ? 0xFFFF : static_cast<uint16_t>(v); | 1704 return (v > 0xFFFF) ? 0xFFFF : static_cast<uint16_t>(v); |
| 1705 } | 1705 } |
| 1706 | 1706 |
| 1707 | 1707 |
| 1708 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) { | 1708 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) { |
| 1709 const Function& function = flow_graph->parsed_function().function(); | 1709 const Function& function = flow_graph->parsed_function()->function(); |
| 1710 if (force || (function.optimized_instruction_count() == 0)) { | 1710 if (force || (function.optimized_instruction_count() == 0)) { |
| 1711 GraphInfoCollector info; | 1711 GraphInfoCollector info; |
| 1712 info.Collect(*flow_graph); | 1712 info.Collect(*flow_graph); |
| 1713 | 1713 |
| 1714 function.set_optimized_instruction_count( | 1714 function.set_optimized_instruction_count( |
| 1715 ClampUint16(info.instruction_count())); | 1715 ClampUint16(info.instruction_count())); |
| 1716 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); | 1716 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); |
| 1717 } | 1717 } |
| 1718 } | 1718 } |
| 1719 | 1719 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1736 } | 1736 } |
| 1737 return MethodRecognizer::AlwaysInline(function); | 1737 return MethodRecognizer::AlwaysInline(function); |
| 1738 } | 1738 } |
| 1739 | 1739 |
| 1740 | 1740 |
| 1741 void FlowGraphInliner::Inline() { | 1741 void FlowGraphInliner::Inline() { |
| 1742 // Collect graph info and store it on the function. | 1742 // Collect graph info and store it on the function. |
| 1743 // We might later use it for an early bailout from the inlining. | 1743 // We might later use it for an early bailout from the inlining. |
| 1744 CollectGraphInfo(flow_graph_); | 1744 CollectGraphInfo(flow_graph_); |
| 1745 | 1745 |
| 1746 const Function& top = flow_graph_->parsed_function().function(); | 1746 const Function& top = flow_graph_->parsed_function()->function(); |
| 1747 if ((FLAG_inlining_filter != NULL) && | 1747 if ((FLAG_inlining_filter != NULL) && |
| 1748 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { | 1748 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { |
| 1749 return; | 1749 return; |
| 1750 } | 1750 } |
| 1751 | 1751 |
| 1752 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); | 1752 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); |
| 1753 | 1753 |
| 1754 if (FLAG_trace_inlining && | 1754 if (FLAG_trace_inlining && |
| 1755 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | 1755 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
| 1756 OS::Print("Before Inlining of %s\n", flow_graph_-> | 1756 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 1757 parsed_function().function().ToFullyQualifiedCString()); | 1757 parsed_function()->function().ToFullyQualifiedCString()); |
| 1758 FlowGraphPrinter printer(*flow_graph_); | 1758 FlowGraphPrinter printer(*flow_graph_); |
| 1759 printer.PrintBlocks(); | 1759 printer.PrintBlocks(); |
| 1760 } | 1760 } |
| 1761 | 1761 |
| 1762 CallSiteInliner inliner(flow_graph_); | 1762 CallSiteInliner inliner(flow_graph_); |
| 1763 inliner.InlineCalls(); | 1763 inliner.InlineCalls(); |
| 1764 if (FLAG_print_inlining_tree) { | 1764 if (FLAG_print_inlining_tree) { |
| 1765 inliner.PrintInlinedInfo(top); | 1765 inliner.PrintInlinedInfo(top); |
| 1766 } | 1766 } |
| 1767 | 1767 |
| 1768 if (inliner.inlined()) { | 1768 if (inliner.inlined()) { |
| 1769 flow_graph_->DiscoverBlocks(); | 1769 flow_graph_->DiscoverBlocks(); |
| 1770 if (FLAG_trace_inlining) { | 1770 if (FLAG_trace_inlining) { |
| 1771 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); | 1771 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
| 1772 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 1772 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
| 1773 OS::Print("After Inlining of %s\n", flow_graph_-> | 1773 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1774 parsed_function().function().ToFullyQualifiedCString()); | 1774 parsed_function()->function().ToFullyQualifiedCString()); |
| 1775 FlowGraphPrinter printer(*flow_graph_); | 1775 FlowGraphPrinter printer(*flow_graph_); |
| 1776 printer.PrintBlocks(); | 1776 printer.PrintBlocks(); |
| 1777 } | 1777 } |
| 1778 } | 1778 } |
| 1779 } | 1779 } |
| 1780 } | 1780 } |
| 1781 | 1781 |
| 1782 } // namespace dart | 1782 } // namespace dart |
| OLD | NEW |