| 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 |