OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/precompiler.h" | 5 #include "vm/precompiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/branch_optimizer.h" | 9 #include "vm/branch_optimizer.h" |
10 #include "vm/cha.h" | 10 #include "vm/cha.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 "In precompilation collects all dynamic function names in order to" | 52 "In precompilation collects all dynamic function names in order to" |
53 " identify unique targets"); | 53 " identify unique targets"); |
54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); | 54 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); |
55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); | 55 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); |
56 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, | 56 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, |
57 "Max number of attempts with speculative inlining (precompilation only)"); | 57 "Max number of attempts with speculative inlining (precompilation only)"); |
58 | 58 |
59 DECLARE_FLAG(bool, allocation_sinking); | 59 DECLARE_FLAG(bool, allocation_sinking); |
60 DECLARE_FLAG(bool, common_subexpression_elimination); | 60 DECLARE_FLAG(bool, common_subexpression_elimination); |
61 DECLARE_FLAG(bool, constant_propagation); | 61 DECLARE_FLAG(bool, constant_propagation); |
62 DECLARE_FLAG(bool, disassemble); | |
63 DECLARE_FLAG(bool, disassemble_optimized); | |
64 DECLARE_FLAG(bool, loop_invariant_code_motion); | 62 DECLARE_FLAG(bool, loop_invariant_code_motion); |
65 DECLARE_FLAG(bool, print_flow_graph); | 63 DECLARE_FLAG(bool, print_flow_graph); |
66 DECLARE_FLAG(bool, print_flow_graph_optimized); | 64 DECLARE_FLAG(bool, print_flow_graph_optimized); |
67 DECLARE_FLAG(bool, range_analysis); | 65 DECLARE_FLAG(bool, range_analysis); |
68 DECLARE_FLAG(bool, trace_compiler); | 66 DECLARE_FLAG(bool, trace_compiler); |
69 DECLARE_FLAG(bool, trace_optimizing_compiler); | 67 DECLARE_FLAG(bool, trace_optimizing_compiler); |
70 DECLARE_FLAG(bool, trace_bailout); | 68 DECLARE_FLAG(bool, trace_bailout); |
71 DECLARE_FLAG(bool, use_inlining); | 69 DECLARE_FLAG(bool, use_inlining); |
72 DECLARE_FLAG(bool, verify_compiler); | 70 DECLARE_FLAG(bool, verify_compiler); |
73 DECLARE_FLAG(bool, precompilation); | 71 DECLARE_FLAG(bool, precompilation); |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 } | 735 } |
738 UNREACHABLE(); | 736 UNREACHABLE(); |
739 return Object::null(); | 737 return Object::null(); |
740 } | 738 } |
741 | 739 |
742 | 740 |
743 RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) { | 741 RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) { |
744 LongJumpScope jump; | 742 LongJumpScope jump; |
745 if (setjmp(*jump.Set()) == 0) { | 743 if (setjmp(*jump.Set()) == 0) { |
746 Thread* const thread = Thread::Current(); | 744 Thread* const thread = Thread::Current(); |
747 if (FLAG_trace_compiler) { | 745 if (FLAG_support_ast_printer && FLAG_trace_compiler) { |
748 THR_Print("compiling expression: "); | 746 THR_Print("compiling expression: "); |
749 AstPrinter::PrintNode(fragment); | 747 AstPrinter::PrintNode(fragment); |
750 } | 748 } |
751 | 749 |
752 // Create a dummy function object for the code generator. | 750 // Create a dummy function object for the code generator. |
753 // The function needs to be associated with a named Class: the interface | 751 // The function needs to be associated with a named Class: the interface |
754 // Function fits the bill. | 752 // Function fits the bill. |
755 const char* kEvalConst = "eval_const"; | 753 const char* kEvalConst = "eval_const"; |
756 const Function& func = Function::ZoneHandle(Function::New( | 754 const Function& func = Function::ZoneHandle(Function::New( |
757 String::Handle(Symbols::New(kEvalConst)), | 755 String::Handle(Symbols::New(kEvalConst)), |
(...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 // If optimized_result_code is not NULL then it is caller's responsibility | 1618 // If optimized_result_code is not NULL then it is caller's responsibility |
1621 // to install code. | 1619 // to install code. |
1622 bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { | 1620 bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { |
1623 ASSERT(FLAG_precompilation); | 1621 ASSERT(FLAG_precompilation); |
1624 const Function& function = parsed_function()->function(); | 1622 const Function& function = parsed_function()->function(); |
1625 if (optimized() && !function.IsOptimizable()) { | 1623 if (optimized() && !function.IsOptimizable()) { |
1626 return false; | 1624 return false; |
1627 } | 1625 } |
1628 bool is_compiled = false; | 1626 bool is_compiled = false; |
1629 Zone* const zone = thread()->zone(); | 1627 Zone* const zone = thread()->zone(); |
| 1628 #ifndef PRODUCT |
1630 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); | 1629 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); |
| 1630 #endif // !PRODUCT |
1631 CSTAT_TIMER_SCOPE(thread(), codegen_timer); | 1631 CSTAT_TIMER_SCOPE(thread(), codegen_timer); |
1632 HANDLESCOPE(thread()); | 1632 HANDLESCOPE(thread()); |
1633 | 1633 |
1634 // We may reattempt compilation if the function needs to be assembled using | 1634 // We may reattempt compilation if the function needs to be assembled using |
1635 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 1635 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
1636 // done is set to false, and use_far_branches is set to true if there is a | 1636 // done is set to false, and use_far_branches is set to true if there is a |
1637 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 1637 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
1638 // while loop, done is set to true. use_far_branches is always false on ia32 | 1638 // while loop, done is set to true. use_far_branches is always false on ia32 |
1639 // and x64. | 1639 // and x64. |
1640 bool done = false; | 1640 bool done = false; |
(...skipping 14 matching lines...) Expand all Loading... |
1655 // Class hierarchy analysis is registered with the isolate in the | 1655 // Class hierarchy analysis is registered with the isolate in the |
1656 // constructor and unregisters itself upon destruction. | 1656 // constructor and unregisters itself upon destruction. |
1657 CHA cha(thread()); | 1657 CHA cha(thread()); |
1658 | 1658 |
1659 // TimerScope needs an isolate to be properly terminated in case of a | 1659 // TimerScope needs an isolate to be properly terminated in case of a |
1660 // LongJump. | 1660 // LongJump. |
1661 { | 1661 { |
1662 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer); | 1662 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer); |
1663 ZoneGrowableArray<const ICData*>* ic_data_array = | 1663 ZoneGrowableArray<const ICData*>* ic_data_array = |
1664 new(zone) ZoneGrowableArray<const ICData*>(); | 1664 new(zone) ZoneGrowableArray<const ICData*>(); |
| 1665 #ifndef PRODUCT |
1665 TimelineDurationScope tds(thread(), | 1666 TimelineDurationScope tds(thread(), |
1666 compiler_timeline, | 1667 compiler_timeline, |
1667 "BuildFlowGraph"); | 1668 "BuildFlowGraph"); |
| 1669 #endif // !PRODUCT |
1668 flow_graph = pipeline->BuildFlowGraph(zone, | 1670 flow_graph = pipeline->BuildFlowGraph(zone, |
1669 parsed_function(), | 1671 parsed_function(), |
1670 *ic_data_array, | 1672 *ic_data_array, |
1671 Compiler::kNoOSRDeoptId); | 1673 Compiler::kNoOSRDeoptId); |
1672 } | 1674 } |
1673 | 1675 |
1674 const bool print_flow_graph = | 1676 const bool print_flow_graph = |
1675 (FLAG_print_flow_graph || | 1677 (FLAG_print_flow_graph || |
1676 (optimized() && FLAG_print_flow_graph_optimized)) && | 1678 (optimized() && FLAG_print_flow_graph_optimized)) && |
1677 FlowGraphPrinter::ShouldPrint(function); | 1679 FlowGraphPrinter::ShouldPrint(function); |
1678 | 1680 |
1679 if (print_flow_graph) { | 1681 if (print_flow_graph) { |
1680 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 1682 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
1681 } | 1683 } |
1682 | 1684 |
1683 if (optimized()) { | 1685 if (optimized()) { |
| 1686 #ifndef PRODUCT |
1684 TimelineDurationScope tds(thread(), | 1687 TimelineDurationScope tds(thread(), |
1685 compiler_timeline, | 1688 compiler_timeline, |
1686 "ComputeSSA"); | 1689 "ComputeSSA"); |
| 1690 #endif // !PRODUCT |
1687 CSTAT_TIMER_SCOPE(thread(), ssa_timer); | 1691 CSTAT_TIMER_SCOPE(thread(), ssa_timer); |
1688 // Transform to SSA (virtual register 0 and no inlining arguments). | 1692 // Transform to SSA (virtual register 0 and no inlining arguments). |
1689 flow_graph->ComputeSSA(0, NULL); | 1693 flow_graph->ComputeSSA(0, NULL); |
1690 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1694 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1691 if (print_flow_graph) { | 1695 if (print_flow_graph) { |
1692 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 1696 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
1693 } | 1697 } |
1694 } | 1698 } |
1695 | 1699 |
1696 // Maps inline_id_to_function[inline_id] -> function. Top scope | 1700 // Maps inline_id_to_function[inline_id] -> function. Top scope |
1697 // function has inline_id 0. The map is populated by the inliner. | 1701 // function has inline_id 0. The map is populated by the inliner. |
1698 GrowableArray<const Function*> inline_id_to_function; | 1702 GrowableArray<const Function*> inline_id_to_function; |
1699 // For a given inlining-id(index) specifies the caller's inlining-id. | 1703 // For a given inlining-id(index) specifies the caller's inlining-id. |
1700 GrowableArray<intptr_t> caller_inline_id; | 1704 GrowableArray<intptr_t> caller_inline_id; |
1701 // Collect all instance fields that are loaded in the graph and | 1705 // Collect all instance fields that are loaded in the graph and |
1702 // have non-generic type feedback attached to them that can | 1706 // have non-generic type feedback attached to them that can |
1703 // potentially affect optimizations. | 1707 // potentially affect optimizations. |
1704 if (optimized()) { | 1708 if (optimized()) { |
| 1709 #ifndef PRODUCT |
1705 TimelineDurationScope tds(thread(), | 1710 TimelineDurationScope tds(thread(), |
1706 compiler_timeline, | 1711 compiler_timeline, |
1707 "OptimizationPasses"); | 1712 "OptimizationPasses"); |
| 1713 #endif // !PRODUCT |
1708 inline_id_to_function.Add(&function); | 1714 inline_id_to_function.Add(&function); |
1709 // Top scope function has no caller (-1). | 1715 // Top scope function has no caller (-1). |
1710 caller_inline_id.Add(-1); | 1716 caller_inline_id.Add(-1); |
1711 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 1717 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
1712 | 1718 |
1713 FlowGraphOptimizer optimizer(flow_graph, | 1719 FlowGraphOptimizer optimizer(flow_graph, |
1714 use_speculative_inlining, | 1720 use_speculative_inlining, |
1715 &inlining_black_list); | 1721 &inlining_black_list); |
1716 optimizer.PopulateWithICData(); | 1722 optimizer.PopulateWithICData(); |
1717 | 1723 |
1718 optimizer.ApplyClassIds(); | 1724 optimizer.ApplyClassIds(); |
1719 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1725 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1720 | 1726 |
1721 FlowGraphTypePropagator::Propagate(flow_graph); | 1727 FlowGraphTypePropagator::Propagate(flow_graph); |
1722 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1728 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1723 | 1729 |
1724 optimizer.ApplyICData(); | 1730 optimizer.ApplyICData(); |
1725 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1731 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1726 | 1732 |
1727 // Optimize (a << b) & c patterns, merge operations. | 1733 // Optimize (a << b) & c patterns, merge operations. |
1728 // Run early in order to have more opportunity to optimize left shifts. | 1734 // Run early in order to have more opportunity to optimize left shifts. |
1729 optimizer.TryOptimizePatterns(); | 1735 optimizer.TryOptimizePatterns(); |
1730 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1736 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1731 | 1737 |
1732 FlowGraphInliner::SetInliningId(flow_graph, 0); | 1738 FlowGraphInliner::SetInliningId(flow_graph, 0); |
1733 | 1739 |
1734 // Inlining (mutates the flow graph) | 1740 // Inlining (mutates the flow graph) |
1735 if (FLAG_use_inlining) { | 1741 if (FLAG_use_inlining) { |
| 1742 #ifndef PRODUCT |
1736 TimelineDurationScope tds2(thread(), | 1743 TimelineDurationScope tds2(thread(), |
1737 compiler_timeline, | 1744 compiler_timeline, |
1738 "Inlining"); | 1745 "Inlining"); |
| 1746 #endif // !PRODUCT |
1739 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); | 1747 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); |
1740 // Propagate types to create more inlining opportunities. | 1748 // Propagate types to create more inlining opportunities. |
1741 FlowGraphTypePropagator::Propagate(flow_graph); | 1749 FlowGraphTypePropagator::Propagate(flow_graph); |
1742 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1750 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1743 | 1751 |
1744 // Use propagated class-ids to create more inlining opportunities. | 1752 // Use propagated class-ids to create more inlining opportunities. |
1745 optimizer.ApplyClassIds(); | 1753 optimizer.ApplyClassIds(); |
1746 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1754 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1747 | 1755 |
1748 FlowGraphInliner inliner(flow_graph, | 1756 FlowGraphInliner inliner(flow_graph, |
1749 &inline_id_to_function, | 1757 &inline_id_to_function, |
1750 &caller_inline_id, | 1758 &caller_inline_id, |
1751 use_speculative_inlining, | 1759 use_speculative_inlining, |
1752 &inlining_black_list); | 1760 &inlining_black_list); |
1753 inliner.Inline(); | 1761 inliner.Inline(); |
1754 // Use lists are maintained and validated by the inliner. | 1762 // Use lists are maintained and validated by the inliner. |
1755 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1763 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1756 } | 1764 } |
1757 | 1765 |
1758 // Propagate types and eliminate more type tests. | 1766 // Propagate types and eliminate more type tests. |
1759 FlowGraphTypePropagator::Propagate(flow_graph); | 1767 FlowGraphTypePropagator::Propagate(flow_graph); |
1760 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1768 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1761 | 1769 |
1762 { | 1770 { |
| 1771 #ifndef PRODUCT |
1763 TimelineDurationScope tds2(thread(), | 1772 TimelineDurationScope tds2(thread(), |
1764 compiler_timeline, | 1773 compiler_timeline, |
1765 "ApplyClassIds"); | 1774 "ApplyClassIds"); |
| 1775 #endif // !PRODUCT |
1766 // Use propagated class-ids to optimize further. | 1776 // Use propagated class-ids to optimize further. |
1767 optimizer.ApplyClassIds(); | 1777 optimizer.ApplyClassIds(); |
1768 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1778 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1769 } | 1779 } |
1770 | 1780 |
1771 // Propagate types for potentially newly added instructions by | 1781 // Propagate types for potentially newly added instructions by |
1772 // ApplyClassIds(). Must occur before canonicalization. | 1782 // ApplyClassIds(). Must occur before canonicalization. |
1773 FlowGraphTypePropagator::Propagate(flow_graph); | 1783 FlowGraphTypePropagator::Propagate(flow_graph); |
1774 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1784 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1775 | 1785 |
1776 // Do optimizations that depend on the propagated type information. | 1786 // Do optimizations that depend on the propagated type information. |
1777 if (optimizer.Canonicalize()) { | 1787 if (optimizer.Canonicalize()) { |
1778 // Invoke Canonicalize twice in order to fully canonicalize patterns | 1788 // Invoke Canonicalize twice in order to fully canonicalize patterns |
1779 // like "if (a & const == 0) { }". | 1789 // like "if (a & const == 0) { }". |
1780 optimizer.Canonicalize(); | 1790 optimizer.Canonicalize(); |
1781 } | 1791 } |
1782 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1792 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1783 | 1793 |
1784 { | 1794 { |
| 1795 #ifndef PRODUCT |
1785 TimelineDurationScope tds2(thread(), | 1796 TimelineDurationScope tds2(thread(), |
1786 compiler_timeline, | 1797 compiler_timeline, |
1787 "BranchSimplifier"); | 1798 "BranchSimplifier"); |
| 1799 #endif // !PRODUCT |
1788 BranchSimplifier::Simplify(flow_graph); | 1800 BranchSimplifier::Simplify(flow_graph); |
1789 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1801 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1790 | 1802 |
1791 IfConverter::Simplify(flow_graph); | 1803 IfConverter::Simplify(flow_graph); |
1792 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1804 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1793 } | 1805 } |
1794 | 1806 |
1795 if (FLAG_constant_propagation) { | 1807 if (FLAG_constant_propagation) { |
| 1808 #ifndef PRODUCT |
1796 TimelineDurationScope tds2(thread(), | 1809 TimelineDurationScope tds2(thread(), |
1797 compiler_timeline, | 1810 compiler_timeline, |
1798 "ConstantPropagation"); | 1811 "ConstantPropagation"); |
| 1812 #endif // !PRODUCT |
1799 ConstantPropagator::Optimize(flow_graph); | 1813 ConstantPropagator::Optimize(flow_graph); |
1800 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1814 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1801 // A canonicalization pass to remove e.g. smi checks on smi constants. | 1815 // A canonicalization pass to remove e.g. smi checks on smi constants. |
1802 optimizer.Canonicalize(); | 1816 optimizer.Canonicalize(); |
1803 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1817 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1804 // Canonicalization introduced more opportunities for constant | 1818 // Canonicalization introduced more opportunities for constant |
1805 // propagation. | 1819 // propagation. |
1806 ConstantPropagator::Optimize(flow_graph); | 1820 ConstantPropagator::Optimize(flow_graph); |
1807 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1821 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1808 } | 1822 } |
1809 | 1823 |
1810 // Optimistically convert loop phis that have a single non-smi input | 1824 // Optimistically convert loop phis that have a single non-smi input |
1811 // coming from the loop pre-header into smi-phis. | 1825 // coming from the loop pre-header into smi-phis. |
1812 if (FLAG_loop_invariant_code_motion) { | 1826 if (FLAG_loop_invariant_code_motion) { |
1813 LICM licm(flow_graph); | 1827 LICM licm(flow_graph); |
1814 licm.OptimisticallySpecializeSmiPhis(); | 1828 licm.OptimisticallySpecializeSmiPhis(); |
1815 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1829 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1816 } | 1830 } |
1817 | 1831 |
1818 // Propagate types and eliminate even more type tests. | 1832 // Propagate types and eliminate even more type tests. |
1819 // Recompute types after constant propagation to infer more precise | 1833 // Recompute types after constant propagation to infer more precise |
1820 // types for uses that were previously reached by now eliminated phis. | 1834 // types for uses that were previously reached by now eliminated phis. |
1821 FlowGraphTypePropagator::Propagate(flow_graph); | 1835 FlowGraphTypePropagator::Propagate(flow_graph); |
1822 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1836 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1823 | 1837 |
1824 { | 1838 { |
| 1839 #ifndef PRODUCT |
1825 TimelineDurationScope tds2(thread(), | 1840 TimelineDurationScope tds2(thread(), |
1826 compiler_timeline, | 1841 compiler_timeline, |
1827 "SelectRepresentations"); | 1842 "SelectRepresentations"); |
| 1843 #endif // !PRODUCT |
1828 // Where beneficial convert Smi operations into Int32 operations. | 1844 // Where beneficial convert Smi operations into Int32 operations. |
1829 // Only meanigful for 32bit platforms right now. | 1845 // Only meanigful for 32bit platforms right now. |
1830 optimizer.WidenSmiToInt32(); | 1846 optimizer.WidenSmiToInt32(); |
1831 | 1847 |
1832 // Unbox doubles. Performed after constant propagation to minimize | 1848 // Unbox doubles. Performed after constant propagation to minimize |
1833 // interference from phis merging double values and tagged | 1849 // interference from phis merging double values and tagged |
1834 // values coming from dead paths. | 1850 // values coming from dead paths. |
1835 optimizer.SelectRepresentations(); | 1851 optimizer.SelectRepresentations(); |
1836 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1852 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1837 } | 1853 } |
1838 | 1854 |
1839 { | 1855 { |
| 1856 #ifndef PRODUCT |
1840 TimelineDurationScope tds2(thread(), | 1857 TimelineDurationScope tds2(thread(), |
1841 compiler_timeline, | 1858 compiler_timeline, |
1842 "CommonSubexpressionElinination"); | 1859 "CommonSubexpressionElinination"); |
| 1860 #endif // !PRODUCT |
1843 if (FLAG_common_subexpression_elimination || | 1861 if (FLAG_common_subexpression_elimination || |
1844 FLAG_loop_invariant_code_motion) { | 1862 FLAG_loop_invariant_code_motion) { |
1845 flow_graph->ComputeBlockEffects(); | 1863 flow_graph->ComputeBlockEffects(); |
1846 } | 1864 } |
1847 | 1865 |
1848 if (FLAG_common_subexpression_elimination) { | 1866 if (FLAG_common_subexpression_elimination) { |
1849 if (DominatorBasedCSE::Optimize(flow_graph)) { | 1867 if (DominatorBasedCSE::Optimize(flow_graph)) { |
1850 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1868 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1851 optimizer.Canonicalize(); | 1869 optimizer.Canonicalize(); |
1852 // Do another round of CSE to take secondary effects into account: | 1870 // Do another round of CSE to take secondary effects into account: |
(...skipping 17 matching lines...) Expand all Loading... |
1870 flow_graph->RemoveRedefinitions(); | 1888 flow_graph->RemoveRedefinitions(); |
1871 } | 1889 } |
1872 | 1890 |
1873 // Optimize (a << b) & c patterns, merge operations. | 1891 // Optimize (a << b) & c patterns, merge operations. |
1874 // Run after CSE in order to have more opportunity to merge | 1892 // Run after CSE in order to have more opportunity to merge |
1875 // instructions that have same inputs. | 1893 // instructions that have same inputs. |
1876 optimizer.TryOptimizePatterns(); | 1894 optimizer.TryOptimizePatterns(); |
1877 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1895 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1878 | 1896 |
1879 { | 1897 { |
| 1898 #ifndef PRODUCT |
1880 TimelineDurationScope tds2(thread(), | 1899 TimelineDurationScope tds2(thread(), |
1881 compiler_timeline, | 1900 compiler_timeline, |
1882 "DeadStoreElimination"); | 1901 "DeadStoreElimination"); |
| 1902 #endif // !PRODUCT |
1883 DeadStoreElimination::Optimize(flow_graph); | 1903 DeadStoreElimination::Optimize(flow_graph); |
1884 } | 1904 } |
1885 | 1905 |
1886 if (FLAG_range_analysis) { | 1906 if (FLAG_range_analysis) { |
| 1907 #ifndef PRODUCT |
1887 TimelineDurationScope tds2(thread(), | 1908 TimelineDurationScope tds2(thread(), |
1888 compiler_timeline, | 1909 compiler_timeline, |
1889 "RangeAnalysis"); | 1910 "RangeAnalysis"); |
| 1911 #endif // !PRODUCT |
1890 // Propagate types after store-load-forwarding. Some phis may have | 1912 // Propagate types after store-load-forwarding. Some phis may have |
1891 // become smi phis that can be processed by range analysis. | 1913 // become smi phis that can be processed by range analysis. |
1892 FlowGraphTypePropagator::Propagate(flow_graph); | 1914 FlowGraphTypePropagator::Propagate(flow_graph); |
1893 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1915 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1894 | 1916 |
1895 // We have to perform range analysis after LICM because it | 1917 // We have to perform range analysis after LICM because it |
1896 // optimistically moves CheckSmi through phis into loop preheaders | 1918 // optimistically moves CheckSmi through phis into loop preheaders |
1897 // making some phis smi. | 1919 // making some phis smi. |
1898 optimizer.InferIntRanges(); | 1920 optimizer.InferIntRanges(); |
1899 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1921 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1900 } | 1922 } |
1901 | 1923 |
1902 if (FLAG_constant_propagation) { | 1924 if (FLAG_constant_propagation) { |
| 1925 #ifndef PRODUCT |
1903 TimelineDurationScope tds2(thread(), | 1926 TimelineDurationScope tds2(thread(), |
1904 compiler_timeline, | 1927 compiler_timeline, |
1905 "ConstantPropagator::OptimizeBranches"); | 1928 "ConstantPropagator::OptimizeBranches"); |
| 1929 #endif // !PRODUCT |
1906 // Constant propagation can use information from range analysis to | 1930 // Constant propagation can use information from range analysis to |
1907 // find unreachable branch targets and eliminate branches that have | 1931 // find unreachable branch targets and eliminate branches that have |
1908 // the same true- and false-target. | 1932 // the same true- and false-target. |
1909 ConstantPropagator::OptimizeBranches(flow_graph); | 1933 ConstantPropagator::OptimizeBranches(flow_graph); |
1910 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1934 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1911 } | 1935 } |
1912 | 1936 |
1913 // Recompute types after code movement was done to ensure correct | 1937 // Recompute types after code movement was done to ensure correct |
1914 // reaching types for hoisted values. | 1938 // reaching types for hoisted values. |
1915 FlowGraphTypePropagator::Propagate(flow_graph); | 1939 FlowGraphTypePropagator::Propagate(flow_graph); |
1916 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1940 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1917 | 1941 |
1918 { | 1942 { |
| 1943 #ifndef PRODUCT |
1919 TimelineDurationScope tds2(thread(), | 1944 TimelineDurationScope tds2(thread(), |
1920 compiler_timeline, | 1945 compiler_timeline, |
1921 "TryCatchAnalyzer::Optimize"); | 1946 "TryCatchAnalyzer::Optimize"); |
| 1947 #endif // !PRODUCT |
1922 // Optimize try-blocks. | 1948 // Optimize try-blocks. |
1923 TryCatchAnalyzer::Optimize(flow_graph); | 1949 TryCatchAnalyzer::Optimize(flow_graph); |
1924 } | 1950 } |
1925 | 1951 |
1926 // Detach environments from the instructions that can't deoptimize. | 1952 // Detach environments from the instructions that can't deoptimize. |
1927 // Do it before we attempt to perform allocation sinking to minimize | 1953 // Do it before we attempt to perform allocation sinking to minimize |
1928 // amount of materializations it has to perform. | 1954 // amount of materializations it has to perform. |
1929 optimizer.EliminateEnvironments(); | 1955 optimizer.EliminateEnvironments(); |
1930 | 1956 |
1931 { | 1957 { |
| 1958 #ifndef PRODUCT |
1932 TimelineDurationScope tds2(thread(), | 1959 TimelineDurationScope tds2(thread(), |
1933 compiler_timeline, | 1960 compiler_timeline, |
1934 "EliminateDeadPhis"); | 1961 "EliminateDeadPhis"); |
| 1962 #endif // !PRODUCT |
1935 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 1963 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
1936 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1964 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1937 } | 1965 } |
1938 | 1966 |
1939 if (optimizer.Canonicalize()) { | 1967 if (optimizer.Canonicalize()) { |
1940 optimizer.Canonicalize(); | 1968 optimizer.Canonicalize(); |
1941 } | 1969 } |
1942 | 1970 |
1943 // Attempt to sink allocations of temporary non-escaping objects to | 1971 // Attempt to sink allocations of temporary non-escaping objects to |
1944 // the deoptimization path. | 1972 // the deoptimization path. |
1945 AllocationSinking* sinking = NULL; | 1973 AllocationSinking* sinking = NULL; |
1946 if (FLAG_allocation_sinking && | 1974 if (FLAG_allocation_sinking && |
1947 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 1975 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| 1976 #ifndef PRODUCT |
1948 TimelineDurationScope tds2(thread(), | 1977 TimelineDurationScope tds2(thread(), |
1949 compiler_timeline, | 1978 compiler_timeline, |
1950 "AllocationSinking::Optimize"); | 1979 "AllocationSinking::Optimize"); |
| 1980 #endif // !PRODUCT |
1951 // TODO(fschneider): Support allocation sinking with try-catch. | 1981 // TODO(fschneider): Support allocation sinking with try-catch. |
1952 sinking = new AllocationSinking(flow_graph); | 1982 sinking = new AllocationSinking(flow_graph); |
1953 sinking->Optimize(); | 1983 sinking->Optimize(); |
1954 } | 1984 } |
1955 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1985 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1956 | 1986 |
1957 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 1987 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
1958 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1988 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1959 | 1989 |
1960 FlowGraphTypePropagator::Propagate(flow_graph); | 1990 FlowGraphTypePropagator::Propagate(flow_graph); |
1961 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 1991 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1962 | 1992 |
1963 { | 1993 { |
| 1994 #ifndef PRODUCT |
1964 TimelineDurationScope tds2(thread(), | 1995 TimelineDurationScope tds2(thread(), |
1965 compiler_timeline, | 1996 compiler_timeline, |
1966 "SelectRepresentations"); | 1997 "SelectRepresentations"); |
| 1998 #endif // !PRODUCT |
1967 // Ensure that all phis inserted by optimization passes have | 1999 // Ensure that all phis inserted by optimization passes have |
1968 // consistent representations. | 2000 // consistent representations. |
1969 optimizer.SelectRepresentations(); | 2001 optimizer.SelectRepresentations(); |
1970 } | 2002 } |
1971 | 2003 |
1972 if (optimizer.Canonicalize()) { | 2004 if (optimizer.Canonicalize()) { |
1973 // To fully remove redundant boxing (e.g. BoxDouble used only in | 2005 // To fully remove redundant boxing (e.g. BoxDouble used only in |
1974 // environments and UnboxDouble instructions) instruction we | 2006 // environments and UnboxDouble instructions) instruction we |
1975 // first need to replace all their uses and then fold them away. | 2007 // first need to replace all their uses and then fold them away. |
1976 // For now we just repeat Canonicalize twice to do that. | 2008 // For now we just repeat Canonicalize twice to do that. |
1977 // TODO(vegorov): implement a separate representation folding pass. | 2009 // TODO(vegorov): implement a separate representation folding pass. |
1978 optimizer.Canonicalize(); | 2010 optimizer.Canonicalize(); |
1979 } | 2011 } |
1980 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 2012 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
1981 | 2013 |
1982 if (sinking != NULL) { | 2014 if (sinking != NULL) { |
| 2015 #ifndef PRODUCT |
1983 TimelineDurationScope tds2( | 2016 TimelineDurationScope tds2( |
1984 thread(), | 2017 thread(), |
1985 compiler_timeline, | 2018 compiler_timeline, |
1986 "AllocationSinking::DetachMaterializations"); | 2019 "AllocationSinking::DetachMaterializations"); |
| 2020 #endif // !PRODUCT |
1987 // Remove all MaterializeObject instructions inserted by allocation | 2021 // Remove all MaterializeObject instructions inserted by allocation |
1988 // sinking from the flow graph and let them float on the side | 2022 // sinking from the flow graph and let them float on the side |
1989 // referenced only from environments. Register allocator will consider | 2023 // referenced only from environments. Register allocator will consider |
1990 // them as part of a deoptimization environment. | 2024 // them as part of a deoptimization environment. |
1991 sinking->DetachMaterializations(); | 2025 sinking->DetachMaterializations(); |
1992 } | 2026 } |
1993 | 2027 |
1994 // Compute and store graph informations (call & instruction counts) | 2028 // Compute and store graph informations (call & instruction counts) |
1995 // to be later used by the inliner. | 2029 // to be later used by the inliner. |
1996 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | 2030 FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
1997 | 2031 |
1998 { | 2032 { |
| 2033 #ifndef PRODUCT |
1999 TimelineDurationScope tds2(thread(), | 2034 TimelineDurationScope tds2(thread(), |
2000 compiler_timeline, | 2035 compiler_timeline, |
2001 "AllocateRegisters"); | 2036 "AllocateRegisters"); |
| 2037 #endif // !PRODUCT |
2002 // Perform register allocation on the SSA graph. | 2038 // Perform register allocation on the SSA graph. |
2003 FlowGraphAllocator allocator(*flow_graph); | 2039 FlowGraphAllocator allocator(*flow_graph); |
2004 allocator.AllocateRegisters(); | 2040 allocator.AllocateRegisters(); |
2005 } | 2041 } |
2006 | 2042 |
2007 if (print_flow_graph) { | 2043 if (print_flow_graph) { |
2008 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 2044 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
2009 } | 2045 } |
2010 } | 2046 } |
2011 | 2047 |
2012 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 2048 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
2013 Assembler assembler(use_far_branches); | 2049 Assembler assembler(use_far_branches); |
2014 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 2050 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
2015 *parsed_function(), optimized(), | 2051 *parsed_function(), optimized(), |
2016 inline_id_to_function, | 2052 inline_id_to_function, |
2017 caller_inline_id); | 2053 caller_inline_id); |
2018 { | 2054 { |
2019 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); | 2055 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); |
| 2056 #ifndef PRODUCT |
2020 TimelineDurationScope tds(thread(), | 2057 TimelineDurationScope tds(thread(), |
2021 compiler_timeline, | 2058 compiler_timeline, |
2022 "CompileGraph"); | 2059 "CompileGraph"); |
| 2060 #endif // !PRODUCT |
2023 graph_compiler.CompileGraph(); | 2061 graph_compiler.CompileGraph(); |
2024 pipeline->FinalizeCompilation(); | 2062 pipeline->FinalizeCompilation(); |
2025 } | 2063 } |
2026 { | 2064 { |
| 2065 #ifndef PRODUCT |
2027 TimelineDurationScope tds(thread(), | 2066 TimelineDurationScope tds(thread(), |
2028 compiler_timeline, | 2067 compiler_timeline, |
2029 "FinalizeCompilation"); | 2068 "FinalizeCompilation"); |
| 2069 #endif // !PRODUCT |
2030 ASSERT(thread()->IsMutatorThread()); | 2070 ASSERT(thread()->IsMutatorThread()); |
2031 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); | 2071 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); |
2032 } | 2072 } |
2033 // Mark that this isolate now has compiled code. | 2073 // Mark that this isolate now has compiled code. |
2034 isolate()->set_has_compiled_code(true); | 2074 isolate()->set_has_compiled_code(true); |
2035 // Exit the loop and the function with the correct result value. | 2075 // Exit the loop and the function with the correct result value. |
2036 is_compiled = true; | 2076 is_compiled = true; |
2037 done = true; | 2077 done = true; |
2038 } else { | 2078 } else { |
2039 // We bailed out or we encountered an error. | 2079 // We bailed out or we encountered an error. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2190 CompilationPipeline::New(thread->zone(), function); | 2230 CompilationPipeline::New(thread->zone(), function); |
2191 | 2231 |
2192 ASSERT(FLAG_precompilation); | 2232 ASSERT(FLAG_precompilation); |
2193 const bool optimized = function.IsOptimizable(); // False for natives. | 2233 const bool optimized = function.IsOptimizable(); // False for natives. |
2194 return PrecompileFunctionHelper(pipeline, function, optimized); | 2234 return PrecompileFunctionHelper(pipeline, function, optimized); |
2195 } | 2235 } |
2196 | 2236 |
2197 #endif // DART_PRECOMPILER | 2237 #endif // DART_PRECOMPILER |
2198 | 2238 |
2199 } // namespace dart | 2239 } // namespace dart |
OLD | NEW |