src/share/vm/opto/callnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/opto

src/share/vm/opto/callnode.cpp

Print this page
rev 7268 : 6700100: optimize inline_native_clone() for small objects with exact klass
Summary: optimize small instance clones as loads/stores
Reviewed-by:


  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "ci/bcEscapeAnalyzer.hpp"
  27 #include "compiler/oopMap.hpp"
  28 #include "opto/callGenerator.hpp"
  29 #include "opto/callnode.hpp"
  30 #include "opto/castnode.hpp"

  31 #include "opto/escape.hpp"
  32 #include "opto/locknode.hpp"
  33 #include "opto/machnode.hpp"
  34 #include "opto/matcher.hpp"
  35 #include "opto/parse.hpp"
  36 #include "opto/regalloc.hpp"
  37 #include "opto/regmask.hpp"
  38 #include "opto/rootnode.hpp"
  39 #include "opto/runtime.hpp"
  40 
  41 // Portions of code courtesy of Clifford Click
  42 
  43 // Optimization - Graph Style
  44 
  45 //=============================================================================
  46 uint StartNode::size_of() const { return sizeof(*this); }
  47 uint StartNode::cmp( const Node &n ) const
  48 { return _domain == ((StartNode&)n)._domain; }
  49 const Type *StartNode::bottom_type() const { return _domain; }
  50 const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; }


1800   // modify the graph, the value returned from this function is the
1801   // one computed above.
1802   // Escape state is defined after Parse phase.
1803   if (can_reshape && EliminateLocks && !is_non_esc_obj()) {
1804     //
1805     // If we are unlocking an unescaped object, the lock/unlock is unnecessary.
1806     //
1807     ConnectionGraph *cgr = phase->C->congraph();
1808     if (cgr != NULL && cgr->not_global_escape(obj_node())) {
1809       assert(!is_eliminated() || is_coarsened(), "sanity");
1810       // The lock could be marked eliminated by lock coarsening
1811       // code during first IGVN before EA. Replace coarsened flag
1812       // to eliminate all associated locks/unlocks.
1813       this->set_non_esc_obj();
1814     }
1815   }
1816   return result;
1817 }
1818 
1819 ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled)
1820   : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM), _alloc_tightly_coupled(alloc_tightly_coupled), _kind(ArrayCopy) {



1821   init_class_id(Class_ArrayCopy);
1822   init_flags(Flag_is_macro);
1823   C->add_macro_node(this);
1824 }
1825 
1826 uint ArrayCopyNode::size_of() const { return sizeof(*this); }
1827 
1828 ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw,
1829                                    Node* src, Node* src_offset,
1830                                    Node* dest, Node* dest_offset,
1831                                    Node* length,
1832                                    bool alloc_tightly_coupled,
1833                                    Node* src_klass, Node* dest_klass,
1834                                    Node* src_length, Node* dest_length) {
1835 
1836   ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled);
1837   Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac);
1838 
1839   ac->init_req(ArrayCopyNode::Src, src);
1840   ac->init_req(ArrayCopyNode::SrcPos, src_offset);


1852   }
1853 
1854   return ac;
1855 }
1856 
1857 void ArrayCopyNode::connect_outputs(GraphKit* kit) {
1858   kit->set_all_memory_call(this, true);
1859   kit->set_control(kit->gvn().transform(new ProjNode(this,TypeFunc::Control)));
1860   kit->set_i_o(kit->gvn().transform(new ProjNode(this, TypeFunc::I_O)));
1861   kit->make_slow_call_ex(this, kit->env()->Throwable_klass(), true);
1862   kit->set_all_memory_call(this);
1863 }
1864 
1865 #ifndef PRODUCT
1866 const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"};
1867 void ArrayCopyNode::dump_spec(outputStream *st) const {
1868   CallNode::dump_spec(st);
1869   st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
1870 }
1871 #endif







































































































































  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "ci/bcEscapeAnalyzer.hpp"
  27 #include "compiler/oopMap.hpp"
  28 #include "opto/callGenerator.hpp"
  29 #include "opto/callnode.hpp"
  30 #include "opto/castnode.hpp"
  31 #include "opto/convertnode.hpp"
  32 #include "opto/escape.hpp"
  33 #include "opto/locknode.hpp"
  34 #include "opto/machnode.hpp"
  35 #include "opto/matcher.hpp"
  36 #include "opto/parse.hpp"
  37 #include "opto/regalloc.hpp"
  38 #include "opto/regmask.hpp"
  39 #include "opto/rootnode.hpp"
  40 #include "opto/runtime.hpp"
  41 
  42 // Portions of code courtesy of Clifford Click
  43 
  44 // Optimization - Graph Style
  45 
  46 //=============================================================================
  47 uint StartNode::size_of() const { return sizeof(*this); }
  48 uint StartNode::cmp( const Node &n ) const
  49 { return _domain == ((StartNode&)n)._domain; }
  50 const Type *StartNode::bottom_type() const { return _domain; }
  51 const Type *StartNode::Value(PhaseTransform *phase) const { return _domain; }


1801   // modify the graph, the value returned from this function is the
1802   // one computed above.
1803   // Escape state is defined after Parse phase.
1804   if (can_reshape && EliminateLocks && !is_non_esc_obj()) {
1805     //
1806     // If we are unlocking an unescaped object, the lock/unlock is unnecessary.
1807     //
1808     ConnectionGraph *cgr = phase->C->congraph();
1809     if (cgr != NULL && cgr->not_global_escape(obj_node())) {
1810       assert(!is_eliminated() || is_coarsened(), "sanity");
1811       // The lock could be marked eliminated by lock coarsening
1812       // code during first IGVN before EA. Replace coarsened flag
1813       // to eliminate all associated locks/unlocks.
1814       this->set_non_esc_obj();
1815     }
1816   }
1817   return result;
1818 }
1819 
1820 ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled)
1821   : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM),
1822     _alloc_tightly_coupled(alloc_tightly_coupled),
1823     _kind(None),
1824     _arguments_validated(false) {
1825   init_class_id(Class_ArrayCopy);
1826   init_flags(Flag_is_macro);
1827   C->add_macro_node(this);
1828 }
1829 
1830 uint ArrayCopyNode::size_of() const { return sizeof(*this); }
1831 
1832 ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw,
1833                                    Node* src, Node* src_offset,
1834                                    Node* dest, Node* dest_offset,
1835                                    Node* length,
1836                                    bool alloc_tightly_coupled,
1837                                    Node* src_klass, Node* dest_klass,
1838                                    Node* src_length, Node* dest_length) {
1839 
1840   ArrayCopyNode* ac = new ArrayCopyNode(kit->C, alloc_tightly_coupled);
1841   Node* prev_mem = kit->set_predefined_input_for_runtime_call(ac);
1842 
1843   ac->init_req(ArrayCopyNode::Src, src);
1844   ac->init_req(ArrayCopyNode::SrcPos, src_offset);


1856   }
1857 
1858   return ac;
1859 }
1860 
1861 void ArrayCopyNode::connect_outputs(GraphKit* kit) {
1862   kit->set_all_memory_call(this, true);
1863   kit->set_control(kit->gvn().transform(new ProjNode(this,TypeFunc::Control)));
1864   kit->set_i_o(kit->gvn().transform(new ProjNode(this, TypeFunc::I_O)));
1865   kit->make_slow_call_ex(this, kit->env()->Throwable_klass(), true);
1866   kit->set_all_memory_call(this);
1867 }
1868 
1869 #ifndef PRODUCT
1870 const char* ArrayCopyNode::_kind_names[] = {"arraycopy", "arraycopy, validated arguments", "clone", "oop array clone", "CopyOf", "CopyOfRange"};
1871 void ArrayCopyNode::dump_spec(outputStream *st) const {
1872   CallNode::dump_spec(st);
1873   st->print(" (%s%s)", _kind_names[_kind], _alloc_tightly_coupled ? ", tightly coupled allocation" : "");
1874 }
1875 #endif
1876 
1877 int ArrayCopyNode::get_count(PhaseGVN *phase) const {
1878   Node* src = in(ArrayCopyNode::Src);
1879   const Type* src_type = phase->type(src);
1880 
1881   assert(is_clonebasic(), "unexpected arraycopy type");
1882   if (src_type->isa_instptr()) {
1883     const TypeInstPtr* inst_src = src_type->is_instptr();
1884     ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
1885     // ciInstanceKlass::nof_nonstatic_fields() doesn't take injected
1886     // fields into account. They are rare anyway so easier to simply
1887     // skip instances with injected fields.
1888     if ((!inst_src->klass_is_exact() && (ik->is_interface() || ik->has_subklass())) || ik->has_injected_fields()) {
1889       return -1;
1890     }
1891     int nb_fields = ik->nof_nonstatic_fields();
1892     return nb_fields;
1893   }
1894   return -1;
1895 }
1896 
1897 Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int count) {
1898   assert(is_clonebasic(), "unexpected arraycopy type");
1899 
1900   Node* src = in(ArrayCopyNode::Src);
1901   Node* dest = in(ArrayCopyNode::Dest);
1902   Node* ctl = in(TypeFunc::Control);
1903   Node* in_mem = in(TypeFunc::Memory);
1904 
1905   const Type* src_type = phase->type(src);
1906   const Type* dest_type = phase->type(dest);
1907 
1908   assert(src->is_AddP(), "should be base + off");
1909   assert(dest->is_AddP(), "should be base + off");
1910   Node* base_src = src->in(AddPNode::Base);
1911   Node* base_dest = dest->in(AddPNode::Base);
1912 
1913   MergeMemNode* mem = MergeMemNode::make(in_mem);
1914 
1915   const TypeInstPtr* inst_src = src_type->is_instptr();
1916 
1917   if (!inst_src->klass_is_exact()) {
1918     ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
1919     assert(!ik->is_interface() && !ik->has_subklass(), "inconsistent klass hierarchy");
1920     phase->C->dependencies()->assert_leaf_type(ik);
1921   }
1922 
1923   ciInstanceKlass* ik = inst_src->klass()->as_instance_klass();
1924   assert(ik->nof_nonstatic_fields() <= ArrayCopyLoadStoreMaxElem, "too many fields");
1925 
1926   for (int i = 0; i < count; i++) {
1927     ciField* field = ik->nonstatic_field_at(i);
1928     int fieldidx = phase->C->alias_type(field)->index();
1929     const TypePtr* adr_type = phase->C->alias_type(field)->adr_type();
1930     Node* off = phase->MakeConX(field->offset());
1931     Node* next_src = phase->transform(new AddPNode(base_src,base_src,off));
1932     Node* next_dest = phase->transform(new AddPNode(base_dest,base_dest,off));
1933     BasicType bt = field->layout_type();
1934 
1935     const Type *type;
1936     if (bt == T_OBJECT) {
1937       if (!field->type()->is_loaded()) {
1938         type = TypeInstPtr::BOTTOM;
1939       } else {
1940         ciType* field_klass = field->type();
1941         type = TypeOopPtr::make_from_klass(field_klass->as_klass());
1942       }
1943     } else {
1944       type = Type::get_const_basic_type(bt);
1945     }
1946 
1947     Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered);
1948     v = phase->transform(v);
1949     Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered);
1950     s = phase->transform(s);
1951     mem->set_memory_at(fieldidx, s);
1952   }
1953   
1954   if (!finish_transform(phase, can_reshape, ctl, mem)) {
1955     return NULL;
1956   }
1957 
1958   return mem;
1959 }
1960 
1961 bool ArrayCopyNode::finish_transform(PhaseGVN *phase, bool can_reshape,
1962                                      Node* ctl, Node *mem) {
1963   if (can_reshape) {
1964     PhaseIterGVN* igvn = phase->is_IterGVN();
1965     assert(is_clonebasic(), "unexpected arraycopy type");
1966     Node* out_mem = proj_out(TypeFunc::Memory);
1967     
1968     if (out_mem->outcnt() != 1 || !out_mem->raw_out(0)->is_MergeMem() ||
1969         out_mem->raw_out(0)->outcnt() != 1 || !out_mem->raw_out(0)->raw_out(0)->is_MemBar()) {
1970       assert(!GraphKit::use_ReduceInitialCardMarks(), "can only happen with card marking");
1971       return false;
1972     }
1973     
1974     igvn->replace_node(out_mem->raw_out(0), mem);
1975     
1976     Node* out_ctl = proj_out(TypeFunc::Control);
1977     igvn->replace_node(out_ctl, ctl);
1978   }
1979   return true;
1980 }
1981 
1982 
1983 Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
1984   
1985   if (StressArrayCopyMacroNode && !can_reshape) return NULL;
1986 
1987   // See if it's a small array copy and we can inline it as
1988   // loads/stores
1989   // Here we can only do:
1990   // - clone for which we don't need to do card marking
1991 
1992   if (!is_clonebasic()) {
1993     return NULL;
1994   }
1995 
1996   if (in(TypeFunc::Control)->is_top() || in(TypeFunc::Memory)->is_top()) {
1997     return NULL;
1998   }
1999 
2000   int count = get_count(phase);
2001 
2002   if (count < 0 || count > ArrayCopyLoadStoreMaxElem) {
2003     return NULL;
2004   }
2005 
2006   Node* mem = try_clone_instance(phase, can_reshape, count);
2007   return mem;
2008 }
src/share/vm/opto/callnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File