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 7589 : 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; }


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), _alloc_tightly_coupled(alloc_tightly_coupled), _kind(ArrayCopy) {



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


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


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


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