Mercurial > hg > truffle
comparison src/share/vm/opto/compile.cpp @ 7473:d092d1b31229
8005071: Incremental inlining for JSR 292
Summary: post parse inlining driven by number of live nodes.
Reviewed-by: twisti, kvn, jrose
author | roland |
---|---|
date | Sun, 23 Dec 2012 17:08:22 +0100 |
parents | ad5dd04754ee |
children | 5b8548391bf3 |
comparison
equal
deleted
inserted
replaced
7445:cd962e15c08e | 7473:d092d1b31229 |
---|---|
134 return lo; // inexact match | 134 return lo; // inexact match |
135 } | 135 } |
136 | 136 |
137 void Compile::register_intrinsic(CallGenerator* cg) { | 137 void Compile::register_intrinsic(CallGenerator* cg) { |
138 if (_intrinsics == NULL) { | 138 if (_intrinsics == NULL) { |
139 _intrinsics = new GrowableArray<CallGenerator*>(60); | 139 _intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL); |
140 } | 140 } |
141 // This code is stolen from ciObjectFactory::insert. | 141 // This code is stolen from ciObjectFactory::insert. |
142 // Really, GrowableArray should have methods for | 142 // Really, GrowableArray should have methods for |
143 // insert_at, remove_at, and binary_search. | 143 // insert_at, remove_at, and binary_search. |
144 int len = _intrinsics->length(); | 144 int len = _intrinsics->length(); |
363 record_dead_node(node_idx); | 363 record_dead_node(node_idx); |
364 } | 364 } |
365 } | 365 } |
366 } | 366 } |
367 | 367 |
368 void Compile::remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines, Unique_Node_List &useful) { | |
369 int shift = 0; | |
370 for (int i = 0; i < inlines->length(); i++) { | |
371 CallGenerator* cg = inlines->at(i); | |
372 CallNode* call = cg->call_node(); | |
373 if (shift > 0) { | |
374 inlines->at_put(i-shift, cg); | |
375 } | |
376 if (!useful.member(call)) { | |
377 shift++; | |
378 } | |
379 } | |
380 inlines->trunc_to(inlines->length()-shift); | |
381 } | |
382 | |
368 // Disconnect all useless nodes by disconnecting those at the boundary. | 383 // Disconnect all useless nodes by disconnecting those at the boundary. |
369 void Compile::remove_useless_nodes(Unique_Node_List &useful) { | 384 void Compile::remove_useless_nodes(Unique_Node_List &useful) { |
370 uint next = 0; | 385 uint next = 0; |
371 while (next < useful.size()) { | 386 while (next < useful.size()) { |
372 Node *n = useful.at(next++); | 387 Node *n = useful.at(next++); |
392 Node* n = C->macro_node(i); | 407 Node* n = C->macro_node(i); |
393 if (!useful.member(n)) { | 408 if (!useful.member(n)) { |
394 remove_macro_node(n); | 409 remove_macro_node(n); |
395 } | 410 } |
396 } | 411 } |
412 // clean up the late inline lists | |
413 remove_useless_late_inlines(&_string_late_inlines, useful); | |
414 remove_useless_late_inlines(&_late_inlines, useful); | |
397 debug_only(verify_graph_edges(true/*check for no_dead_code*/);) | 415 debug_only(verify_graph_edges(true/*check for no_dead_code*/);) |
398 } | 416 } |
399 | 417 |
400 //------------------------------frame_size_in_words----------------------------- | 418 //------------------------------frame_size_in_words----------------------------- |
401 // frame_slots in units of words | 419 // frame_slots in units of words |
609 #ifndef PRODUCT | 627 #ifndef PRODUCT |
610 _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), | 628 _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), |
611 _printer(IdealGraphPrinter::printer()), | 629 _printer(IdealGraphPrinter::printer()), |
612 #endif | 630 #endif |
613 _congraph(NULL), | 631 _congraph(NULL), |
632 _late_inlines(comp_arena(), 2, 0, NULL), | |
633 _string_late_inlines(comp_arena(), 2, 0, NULL), | |
634 _late_inlines_pos(0), | |
635 _number_of_mh_late_inlines(0), | |
636 _inlining_progress(false), | |
637 _inlining_incrementally(false), | |
614 _print_inlining_list(NULL), | 638 _print_inlining_list(NULL), |
615 _print_inlining(0) { | 639 _print_inlining(0) { |
616 C = this; | 640 C = this; |
617 | 641 |
618 CompileWrapper cw(this); | 642 CompileWrapper cw(this); |
735 // to whatever caller is dynamically above us on the stack. | 759 // to whatever caller is dynamically above us on the stack. |
736 // This is done by a special, unique RethrowNode bound to root. | 760 // This is done by a special, unique RethrowNode bound to root. |
737 rethrow_exceptions(kit.transfer_exceptions_into_jvms()); | 761 rethrow_exceptions(kit.transfer_exceptions_into_jvms()); |
738 } | 762 } |
739 | 763 |
740 if (!failing() && has_stringbuilder()) { | 764 assert(IncrementalInline || (_late_inlines.length() == 0 && !has_mh_late_inlines()), "incremental inlining is off"); |
741 { | 765 |
742 // remove useless nodes to make the usage analysis simpler | 766 if (_late_inlines.length() == 0 && !has_mh_late_inlines() && !failing() && has_stringbuilder()) { |
743 ResourceMark rm; | 767 inline_string_calls(true); |
744 PhaseRemoveUseless pru(initial_gvn(), &for_igvn); | 768 } |
745 } | 769 |
746 | 770 if (failing()) return; |
747 { | |
748 ResourceMark rm; | |
749 print_method("Before StringOpts", 3); | |
750 PhaseStringOpts pso(initial_gvn(), &for_igvn); | |
751 print_method("After StringOpts", 3); | |
752 } | |
753 | |
754 // now inline anything that we skipped the first time around | |
755 while (_late_inlines.length() > 0) { | |
756 CallGenerator* cg = _late_inlines.pop(); | |
757 cg->do_late_inline(); | |
758 if (failing()) return; | |
759 } | |
760 } | |
761 assert(_late_inlines.length() == 0, "should have been processed"); | |
762 dump_inlining(); | |
763 | 771 |
764 print_method("Before RemoveUseless", 3); | 772 print_method("Before RemoveUseless", 3); |
765 | 773 |
766 // Remove clutter produced by parsing. | 774 // Remove clutter produced by parsing. |
767 if (!failing()) { | 775 if (!failing()) { |
904 _printer(NULL), | 912 _printer(NULL), |
905 #endif | 913 #endif |
906 _dead_node_list(comp_arena()), | 914 _dead_node_list(comp_arena()), |
907 _dead_node_count(0), | 915 _dead_node_count(0), |
908 _congraph(NULL), | 916 _congraph(NULL), |
917 _number_of_mh_late_inlines(0), | |
918 _inlining_progress(false), | |
919 _inlining_incrementally(false), | |
909 _print_inlining_list(NULL), | 920 _print_inlining_list(NULL), |
910 _print_inlining(0) { | 921 _print_inlining(0) { |
911 C = this; | 922 C = this; |
912 | 923 |
913 #ifndef PRODUCT | 924 #ifndef PRODUCT |
1758 igvn.replace_node(n, n->in(1)); | 1769 igvn.replace_node(n, n->in(1)); |
1759 } | 1770 } |
1760 assert(predicate_count()==0, "should be clean!"); | 1771 assert(predicate_count()==0, "should be clean!"); |
1761 } | 1772 } |
1762 | 1773 |
1774 // StringOpts and late inlining of string methods | |
1775 void Compile::inline_string_calls(bool parse_time) { | |
1776 { | |
1777 // remove useless nodes to make the usage analysis simpler | |
1778 ResourceMark rm; | |
1779 PhaseRemoveUseless pru(initial_gvn(), for_igvn()); | |
1780 } | |
1781 | |
1782 { | |
1783 ResourceMark rm; | |
1784 print_method("Before StringOpts", 3); | |
1785 PhaseStringOpts pso(initial_gvn(), for_igvn()); | |
1786 print_method("After StringOpts", 3); | |
1787 } | |
1788 | |
1789 // now inline anything that we skipped the first time around | |
1790 if (!parse_time) { | |
1791 _late_inlines_pos = _late_inlines.length(); | |
1792 } | |
1793 | |
1794 while (_string_late_inlines.length() > 0) { | |
1795 CallGenerator* cg = _string_late_inlines.pop(); | |
1796 cg->do_late_inline(); | |
1797 if (failing()) return; | |
1798 } | |
1799 _string_late_inlines.trunc_to(0); | |
1800 } | |
1801 | |
1802 void Compile::inline_incrementally_one(PhaseIterGVN& igvn) { | |
1803 assert(IncrementalInline, "incremental inlining should be on"); | |
1804 PhaseGVN* gvn = initial_gvn(); | |
1805 | |
1806 set_inlining_progress(false); | |
1807 for_igvn()->clear(); | |
1808 gvn->replace_with(&igvn); | |
1809 | |
1810 int i = 0; | |
1811 | |
1812 for (; i <_late_inlines.length() && !inlining_progress(); i++) { | |
1813 CallGenerator* cg = _late_inlines.at(i); | |
1814 _late_inlines_pos = i+1; | |
1815 cg->do_late_inline(); | |
1816 if (failing()) return; | |
1817 } | |
1818 int j = 0; | |
1819 for (; i < _late_inlines.length(); i++, j++) { | |
1820 _late_inlines.at_put(j, _late_inlines.at(i)); | |
1821 } | |
1822 _late_inlines.trunc_to(j); | |
1823 | |
1824 { | |
1825 ResourceMark rm; | |
1826 PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); | |
1827 } | |
1828 | |
1829 igvn = PhaseIterGVN(gvn); | |
1830 } | |
1831 | |
1832 // Perform incremental inlining until bound on number of live nodes is reached | |
1833 void Compile::inline_incrementally(PhaseIterGVN& igvn) { | |
1834 PhaseGVN* gvn = initial_gvn(); | |
1835 | |
1836 set_inlining_incrementally(true); | |
1837 set_inlining_progress(true); | |
1838 uint low_live_nodes = 0; | |
1839 | |
1840 while(inlining_progress() && _late_inlines.length() > 0) { | |
1841 | |
1842 if (live_nodes() > (uint)LiveNodeCountInliningCutoff) { | |
1843 if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) { | |
1844 // PhaseIdealLoop is expensive so we only try it once we are | |
1845 // out of loop and we only try it again if the previous helped | |
1846 // got the number of nodes down significantly | |
1847 PhaseIdealLoop ideal_loop( igvn, false, true ); | |
1848 if (failing()) return; | |
1849 low_live_nodes = live_nodes(); | |
1850 _major_progress = true; | |
1851 } | |
1852 | |
1853 if (live_nodes() > (uint)LiveNodeCountInliningCutoff) { | |
1854 break; | |
1855 } | |
1856 } | |
1857 | |
1858 inline_incrementally_one(igvn); | |
1859 | |
1860 if (failing()) return; | |
1861 | |
1862 igvn.optimize(); | |
1863 | |
1864 if (failing()) return; | |
1865 } | |
1866 | |
1867 assert( igvn._worklist.size() == 0, "should be done with igvn" ); | |
1868 | |
1869 if (_string_late_inlines.length() > 0) { | |
1870 assert(has_stringbuilder(), "inconsistent"); | |
1871 for_igvn()->clear(); | |
1872 initial_gvn()->replace_with(&igvn); | |
1873 | |
1874 inline_string_calls(false); | |
1875 | |
1876 if (failing()) return; | |
1877 | |
1878 { | |
1879 ResourceMark rm; | |
1880 PhaseRemoveUseless pru(initial_gvn(), for_igvn()); | |
1881 } | |
1882 | |
1883 igvn = PhaseIterGVN(gvn); | |
1884 | |
1885 igvn.optimize(); | |
1886 } | |
1887 | |
1888 set_inlining_incrementally(false); | |
1889 } | |
1890 | |
1891 | |
1763 //------------------------------Optimize--------------------------------------- | 1892 //------------------------------Optimize--------------------------------------- |
1764 // Given a graph, optimize it. | 1893 // Given a graph, optimize it. |
1765 void Compile::Optimize() { | 1894 void Compile::Optimize() { |
1766 TracePhase t1("optimizer", &_t_optimizer, true); | 1895 TracePhase t1("optimizer", &_t_optimizer, true); |
1767 | 1896 |
1787 NOT_PRODUCT( TracePhase t2("iterGVN", &_t_iterGVN, TimeCompiler); ) | 1916 NOT_PRODUCT( TracePhase t2("iterGVN", &_t_iterGVN, TimeCompiler); ) |
1788 igvn.optimize(); | 1917 igvn.optimize(); |
1789 } | 1918 } |
1790 | 1919 |
1791 print_method("Iter GVN 1", 2); | 1920 print_method("Iter GVN 1", 2); |
1921 | |
1922 if (failing()) return; | |
1923 | |
1924 inline_incrementally(igvn); | |
1925 | |
1926 print_method("Incremental Inline", 2); | |
1792 | 1927 |
1793 if (failing()) return; | 1928 if (failing()) return; |
1794 | 1929 |
1795 // Perform escape analysis | 1930 // Perform escape analysis |
1796 if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { | 1931 if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { |
1912 } | 2047 } |
1913 } | 2048 } |
1914 | 2049 |
1915 } // (End scope of igvn; run destructor if necessary for asserts.) | 2050 } // (End scope of igvn; run destructor if necessary for asserts.) |
1916 | 2051 |
2052 dump_inlining(); | |
1917 // A method with only infinite loops has no edges entering loops from root | 2053 // A method with only infinite loops has no edges entering loops from root |
1918 { | 2054 { |
1919 NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); ) | 2055 NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); ) |
1920 if (final_graph_reshaping()) { | 2056 if (final_graph_reshaping()) { |
1921 assert(failing(), "must bail out w/ explicit message"); | 2057 assert(failing(), "must bail out w/ explicit message"); |
3360 } | 3496 } |
3361 } | 3497 } |
3362 | 3498 |
3363 void Compile::dump_inlining() { | 3499 void Compile::dump_inlining() { |
3364 if (PrintInlining) { | 3500 if (PrintInlining) { |
3501 // Print inlining message for candidates that we couldn't inline | |
3502 // for lack of space or non constant receiver | |
3503 for (int i = 0; i < _late_inlines.length(); i++) { | |
3504 CallGenerator* cg = _late_inlines.at(i); | |
3505 cg->print_inlining_late("live nodes > LiveNodeCountInliningCutoff"); | |
3506 } | |
3507 Unique_Node_List useful; | |
3508 useful.push(root()); | |
3509 for (uint next = 0; next < useful.size(); ++next) { | |
3510 Node* n = useful.at(next); | |
3511 if (n->is_Call() && n->as_Call()->generator() != NULL && n->as_Call()->generator()->call_node() == n) { | |
3512 CallNode* call = n->as_Call(); | |
3513 CallGenerator* cg = call->generator(); | |
3514 cg->print_inlining_late("receiver not constant"); | |
3515 } | |
3516 uint max = n->len(); | |
3517 for ( uint i = 0; i < max; ++i ) { | |
3518 Node *m = n->in(i); | |
3519 if ( m == NULL ) continue; | |
3520 useful.push(m); | |
3521 } | |
3522 } | |
3365 for (int i = 0; i < _print_inlining_list->length(); i++) { | 3523 for (int i = 0; i < _print_inlining_list->length(); i++) { |
3366 tty->print(_print_inlining_list->at(i).ss()->as_string()); | 3524 tty->print(_print_inlining_list->at(i).ss()->as_string()); |
3367 } | 3525 } |
3368 } | 3526 } |
3369 } | 3527 } |