| 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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 return true; | 467 return true; |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 } | 470 } |
| 471 return false; | 471 return false; |
| 472 } | 472 } |
| 473 | 473 |
| 474 | 474 |
| 475 class CallSiteInliner : public ValueObject { | 475 class CallSiteInliner : public ValueObject { |
| 476 public: | 476 public: |
| 477 explicit CallSiteInliner(FlowGraph* flow_graph) | 477 explicit CallSiteInliner(FlowGraphInliner* inliner) |
| 478 : caller_graph_(flow_graph), | 478 : inliner_(inliner), |
| 479 caller_graph_(inliner->flow_graph()), |
| 479 inlined_(false), | 480 inlined_(false), |
| 480 initial_size_(flow_graph->InstructionCount()), | 481 initial_size_(inliner->flow_graph()->InstructionCount()), |
| 481 inlined_size_(0), | 482 inlined_size_(0), |
| 482 inlined_recursive_call_(false), | 483 inlined_recursive_call_(false), |
| 483 inlining_depth_(1), | 484 inlining_depth_(1), |
| 484 inlining_recursion_depth_(0), | 485 inlining_recursion_depth_(0), |
| 485 collected_call_sites_(NULL), | 486 collected_call_sites_(NULL), |
| 486 inlining_call_sites_(NULL), | 487 inlining_call_sites_(NULL), |
| 487 function_cache_(), | 488 function_cache_(), |
| 488 inlined_info_() { } | 489 inlined_info_() { } |
| 489 | 490 |
| 490 FlowGraph* caller_graph() const { return caller_graph_; } | 491 FlowGraph* caller_graph() const { return caller_graph_; } |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 "const args: %" Pd "\n", | 805 "const args: %" Pd "\n", |
| 805 size, | 806 size, |
| 806 call_site_count, | 807 call_site_count, |
| 807 constants_count)); | 808 constants_count)); |
| 808 PRINT_INLINING_TREE("Heuristic fail", | 809 PRINT_INLINING_TREE("Heuristic fail", |
| 809 &call_data->caller, &function, call_data->call); | 810 &call_data->caller, &function, call_data->call); |
| 810 return false; | 811 return false; |
| 811 } | 812 } |
| 812 | 813 |
| 813 // Inline dispatcher methods regardless of the current depth. | 814 // Inline dispatcher methods regardless of the current depth. |
| 814 intptr_t depth = | 815 const intptr_t depth = |
| 815 (function.IsInvokeFieldDispatcher() || | 816 (function.IsInvokeFieldDispatcher() || |
| 816 function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_; | 817 function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_; |
| 817 collected_call_sites_->FindCallSites(callee_graph, depth, &inlined_info_); | 818 collected_call_sites_->FindCallSites(callee_graph, depth, &inlined_info_); |
| 818 | 819 |
| 819 // Add the function to the cache. | 820 // Add the function to the cache. |
| 820 if (!in_cache) { | 821 if (!in_cache) { |
| 821 function_cache_.Add(parsed_function); | 822 function_cache_.Add(parsed_function); |
| 822 } | 823 } |
| 823 | 824 |
| 824 // Build succeeded so we restore the bailout jump. | 825 // Build succeeded so we restore the bailout jump. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 836 // When inlined, we add the guarded fields of the callee to the caller's | 837 // When inlined, we add the guarded fields of the callee to the caller's |
| 837 // list of guarded fields. | 838 // list of guarded fields. |
| 838 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { | 839 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { |
| 839 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), | 840 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), |
| 840 (*callee_graph->guarded_fields())[i]); | 841 (*callee_graph->guarded_fields())[i]); |
| 841 } | 842 } |
| 842 // When inlined, we add the deferred prefixes of the callee to the | 843 // When inlined, we add the deferred prefixes of the callee to the |
| 843 // caller's list of deferred prefixes. | 844 // caller's list of deferred prefixes. |
| 844 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); | 845 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); |
| 845 | 846 |
| 847 FlowGraphInliner::SetInliningId(*callee_graph, |
| 848 inliner_->NextInlineId(callee_graph->parsed_function()->function())); |
| 846 // We allocate a ZoneHandle for the unoptimized code so that it cannot be | 849 // We allocate a ZoneHandle for the unoptimized code so that it cannot be |
| 847 // disconnected from its function during the rest of compilation. | 850 // disconnected from its function during the rest of compilation. |
| 848 Code::ZoneHandle(unoptimized_code.raw()); | 851 Code::ZoneHandle(unoptimized_code.raw()); |
| 849 TRACE_INLINING(OS::Print(" Success\n")); | 852 TRACE_INLINING(OS::Print(" Success\n")); |
| 850 PRINT_INLINING_TREE(NULL, | 853 PRINT_INLINING_TREE(NULL, |
| 851 &call_data->caller, &function, call); | 854 &call_data->caller, &function, call); |
| 852 return true; | 855 return true; |
| 853 } else { | 856 } else { |
| 854 Error& error = Error::Handle(); | 857 Error& error = Error::Handle(); |
| 855 error = isolate()->object_store()->sticky_error(); | 858 error = isolate()->object_store()->sticky_error(); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 if (arg != NULL) { | 1226 if (arg != NULL) { |
| 1224 param_stubs->Add(CreateParameterStub(i, arg, callee_graph)); | 1227 param_stubs->Add(CreateParameterStub(i, arg, callee_graph)); |
| 1225 } else { | 1228 } else { |
| 1226 param_stubs->Add( | 1229 param_stubs->Add( |
| 1227 GetDefaultValue(i - fixed_param_count, parsed_function)); | 1230 GetDefaultValue(i - fixed_param_count, parsed_function)); |
| 1228 } | 1231 } |
| 1229 } | 1232 } |
| 1230 return argument_names_count == match_count; | 1233 return argument_names_count == match_count; |
| 1231 } | 1234 } |
| 1232 | 1235 |
| 1236 FlowGraphInliner* inliner_; |
| 1233 FlowGraph* caller_graph_; | 1237 FlowGraph* caller_graph_; |
| 1234 bool inlined_; | 1238 bool inlined_; |
| 1235 const intptr_t initial_size_; | 1239 const intptr_t initial_size_; |
| 1236 intptr_t inlined_size_; | 1240 intptr_t inlined_size_; |
| 1237 bool inlined_recursive_call_; | 1241 bool inlined_recursive_call_; |
| 1238 intptr_t inlining_depth_; | 1242 intptr_t inlining_depth_; |
| 1239 intptr_t inlining_recursion_depth_; | 1243 intptr_t inlining_recursion_depth_; |
| 1240 CallSites* collected_call_sites_; | 1244 CallSites* collected_call_sites_; |
| 1241 CallSites* inlining_call_sites_; | 1245 CallSites* inlining_call_sites_; |
| 1242 GrowableArray<ParsedFunction*> function_cache_; | 1246 GrowableArray<ParsedFunction*> function_cache_; |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 GraphInfoCollector info; | 1727 GraphInfoCollector info; |
| 1724 info.Collect(*flow_graph); | 1728 info.Collect(*flow_graph); |
| 1725 | 1729 |
| 1726 function.set_optimized_instruction_count( | 1730 function.set_optimized_instruction_count( |
| 1727 ClampUint16(info.instruction_count())); | 1731 ClampUint16(info.instruction_count())); |
| 1728 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); | 1732 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); |
| 1729 } | 1733 } |
| 1730 } | 1734 } |
| 1731 | 1735 |
| 1732 | 1736 |
| 1737 // TODO(srdjan): This is only needed when disassembling and/or profiling. |
| 1738 void FlowGraphInliner::SetInliningId(const FlowGraph& flow_graph, |
| 1739 intptr_t inlining_id) { |
| 1740 for (BlockIterator block_it = flow_graph.postorder_iterator(); |
| 1741 !block_it.Done(); |
| 1742 block_it.Advance()) { |
| 1743 for (ForwardInstructionIterator it(block_it.Current()); |
| 1744 !it.Done(); |
| 1745 it.Advance()) { |
| 1746 Instruction* current = it.Current(); |
| 1747 // Do not overwrite owner function. |
| 1748 ASSERT(!current->has_inlining_id()); |
| 1749 current->set_inlining_id(inlining_id); |
| 1750 } |
| 1751 } |
| 1752 } |
| 1753 |
| 1754 |
| 1733 bool FlowGraphInliner::AlwaysInline(const Function& function) { | 1755 bool FlowGraphInliner::AlwaysInline(const Function& function) { |
| 1734 const char* kAlwaysInlineAnnotation = "AlwaysInline"; | 1756 const char* kAlwaysInlineAnnotation = "AlwaysInline"; |
| 1735 if (FLAG_enable_inlining_annotations && | 1757 if (FLAG_enable_inlining_annotations && |
| 1736 HasAnnotation(function, kAlwaysInlineAnnotation)) { | 1758 HasAnnotation(function, kAlwaysInlineAnnotation)) { |
| 1737 TRACE_INLINING(OS::Print("AlwaysInline annotation for %s\n", | 1759 TRACE_INLINING(OS::Print("AlwaysInline annotation for %s\n", |
| 1738 function.ToCString())); | 1760 function.ToCString())); |
| 1739 return true; | 1761 return true; |
| 1740 } | 1762 } |
| 1741 | 1763 |
| 1742 if (function.IsImplicitGetterFunction() || function.IsGetterFunction() || | 1764 if (function.IsImplicitGetterFunction() || function.IsGetterFunction() || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1764 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); | 1786 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); |
| 1765 | 1787 |
| 1766 if (FLAG_trace_inlining && | 1788 if (FLAG_trace_inlining && |
| 1767 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | 1789 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
| 1768 OS::Print("Before Inlining of %s\n", flow_graph_-> | 1790 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 1769 parsed_function()->function().ToFullyQualifiedCString()); | 1791 parsed_function()->function().ToFullyQualifiedCString()); |
| 1770 FlowGraphPrinter printer(*flow_graph_); | 1792 FlowGraphPrinter printer(*flow_graph_); |
| 1771 printer.PrintBlocks(); | 1793 printer.PrintBlocks(); |
| 1772 } | 1794 } |
| 1773 | 1795 |
| 1774 CallSiteInliner inliner(flow_graph_); | 1796 CallSiteInliner inliner(this); |
| 1775 inliner.InlineCalls(); | 1797 inliner.InlineCalls(); |
| 1776 if (FLAG_print_inlining_tree) { | 1798 if (FLAG_print_inlining_tree) { |
| 1777 inliner.PrintInlinedInfo(top); | 1799 inliner.PrintInlinedInfo(top); |
| 1778 } | 1800 } |
| 1779 | 1801 |
| 1780 if (inliner.inlined()) { | 1802 if (inliner.inlined()) { |
| 1781 flow_graph_->DiscoverBlocks(); | 1803 flow_graph_->DiscoverBlocks(); |
| 1782 if (FLAG_trace_inlining) { | 1804 if (FLAG_trace_inlining) { |
| 1783 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); | 1805 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
| 1784 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 1806 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
| 1785 OS::Print("After Inlining of %s\n", flow_graph_-> | 1807 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1786 parsed_function()->function().ToFullyQualifiedCString()); | 1808 parsed_function()->function().ToFullyQualifiedCString()); |
| 1787 FlowGraphPrinter printer(*flow_graph_); | 1809 FlowGraphPrinter printer(*flow_graph_); |
| 1788 printer.PrintBlocks(); | 1810 printer.PrintBlocks(); |
| 1789 } | 1811 } |
| 1790 } | 1812 } |
| 1791 } | 1813 } |
| 1792 } | 1814 } |
| 1793 | 1815 |
| 1816 |
| 1817 intptr_t FlowGraphInliner::NextInlineId(const Function& function) { |
| 1818 const intptr_t id = inline_id_to_function_->length(); |
| 1819 inline_id_to_function_->Add(&function); |
| 1820 return id; |
| 1821 } |
| 1822 |
| 1823 |
| 1794 } // namespace dart | 1824 } // namespace dart |
| OLD | NEW |