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

src/share/vm/opto/callnode.hpp

Print this page
rev 7687 : 6912521: System.arraycopy works slower than the simple loop for little lengths
Summary: convert small array copies to series of loads and stores
Reviewed-by:


1103     fields[SrcPos]    = TypeInt::INT;
1104     fields[Dest]      = TypeInstPtr::BOTTOM;
1105     fields[DestPos]   = TypeInt::INT;
1106     fields[Length]    = TypeInt::INT;
1107     fields[SrcLen]    = TypeInt::INT;
1108     fields[DestLen]   = TypeInt::INT;
1109     fields[SrcKlass]  = TypeKlassPtr::BOTTOM;
1110     fields[DestKlass] = TypeKlassPtr::BOTTOM;
1111     const TypeTuple *domain = TypeTuple::make(ParmLimit, fields);
1112 
1113     // create result type (range)
1114     fields = TypeTuple::fields(0);
1115 
1116     const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
1117 
1118     return TypeFunc::make(domain, range);
1119   }
1120 
1121   ArrayCopyNode(Compile* C, bool alloc_tightly_coupled);
1122 

1123   int get_count(PhaseGVN *phase) const;
1124   static const TypePtr* get_address_type(PhaseGVN *phase, Node* n);
1125 
1126   Node* try_clone_instance(PhaseGVN *phase, bool can_reshape, int count);
















1127   bool finish_transform(PhaseGVN *phase, bool can_reshape,
1128                         Node* ctl, Node *mem);
1129 
1130 public:
1131 
1132   enum {
1133     Src   = TypeFunc::Parms,
1134     SrcPos,
1135     Dest,
1136     DestPos,
1137     Length,
1138     SrcLen,
1139     DestLen,
1140     SrcKlass,
1141     DestKlass,
1142     ParmLimit
1143   };
1144 
1145   static ArrayCopyNode* make(GraphKit* kit, bool may_throw,
1146                              Node* src, Node* src_offset,
1147                              Node* dest,  Node* dest_offset,
1148                              Node* length,
1149                              bool alloc_tightly_coupled,
1150                              Node* src_klass = NULL, Node* dest_klass = NULL,
1151                              Node* src_length = NULL, Node* dest_length = NULL);
1152 
1153   void connect_outputs(GraphKit* kit);
1154 
1155   bool is_arraycopy()             const  { assert(_kind != None, "should bet set"); return _kind == ArrayCopy; }
1156   bool is_arraycopy_validated()   const  { assert(_kind != None, "should bet set"); return _kind == ArrayCopy && _arguments_validated; }
1157   bool is_clonebasic()            const  { assert(_kind != None, "should bet set"); return _kind == CloneBasic; }
1158   bool is_cloneoop()              const  { assert(_kind != None, "should bet set"); return _kind == CloneOop; }
1159   bool is_copyof()                const  { assert(_kind != None, "should bet set"); return _kind == CopyOf; }

1160   bool is_copyofrange()           const  { assert(_kind != None, "should bet set"); return _kind == CopyOfRange; }

1161 
1162   void set_arraycopy(bool validated)   { assert(_kind == None, "shouldn't bet set yet"); _kind = ArrayCopy; _arguments_validated = validated; }
1163   void set_clonebasic()                { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneBasic; }
1164   void set_cloneoop()                  { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneOop; }
1165   void set_copyof()                    { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOf; _arguments_validated = false; }
1166   void set_copyofrange()               { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOfRange; _arguments_validated = false; }
1167 
1168   virtual int Opcode() const;
1169   virtual uint size_of() const; // Size is bigger
1170   virtual bool guaranteed_safepoint()  { return false; }
1171   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
1172 
1173   bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
1174 
1175 #ifndef PRODUCT
1176   virtual void dump_spec(outputStream *st) const;
1177 #endif
1178 };
1179 #endif // SHARE_VM_OPTO_CALLNODE_HPP


1103     fields[SrcPos]    = TypeInt::INT;
1104     fields[Dest]      = TypeInstPtr::BOTTOM;
1105     fields[DestPos]   = TypeInt::INT;
1106     fields[Length]    = TypeInt::INT;
1107     fields[SrcLen]    = TypeInt::INT;
1108     fields[DestLen]   = TypeInt::INT;
1109     fields[SrcKlass]  = TypeKlassPtr::BOTTOM;
1110     fields[DestKlass] = TypeKlassPtr::BOTTOM;
1111     const TypeTuple *domain = TypeTuple::make(ParmLimit, fields);
1112 
1113     // create result type (range)
1114     fields = TypeTuple::fields(0);
1115 
1116     const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
1117 
1118     return TypeFunc::make(domain, range);
1119   }
1120 
1121   ArrayCopyNode(Compile* C, bool alloc_tightly_coupled);
1122 
1123   intptr_t get_length_if_constant(PhaseGVN *phase) const;
1124   int get_count(PhaseGVN *phase) const;
1125   static const TypePtr* get_address_type(PhaseGVN *phase, Node* n);
1126 
1127   Node* try_clone_instance(PhaseGVN *phase, bool can_reshape, int count);
1128   Node* conv_I2X_offset(PhaseGVN *phase, Node* offset, const TypeAryPtr* ary_t);
1129   bool prepare_array_copy(PhaseGVN *phase, bool can_reshape,
1130                           Node*& adr_src, Node*& base_src, Node*& adr_dest, Node*& base_dest,
1131                           BasicType& copy_type, const Type*& value_type, bool& disjoint_bases);
1132   void array_copy_test_overlap(PhaseGVN *phase, bool can_reshape,
1133                                bool disjoint_bases, Node*& forward_ctl, Node*& backward_ctl);
1134   Node* array_copy_forward(PhaseGVN *phase, bool can_reshape, Node* ctl,
1135                            Node* start_mem_src, Node* start_mem_dest,
1136                            const TypePtr* atp_src, const TypePtr* atp_dest,
1137                            Node* adr_src, Node* base_src, Node* adr_dest, Node* base_dest,
1138                            BasicType copy_type, const Type* value_type, int count);
1139   Node* array_copy_backward(PhaseGVN *phase, bool can_reshape, Node* ctl,
1140                             Node *start_mem_src, Node* start_mem_dest,
1141                             const TypePtr* atp_src, const TypePtr* atp_dest,
1142                             Node* adr_src, Node* base_src, Node* adr_dest, Node* base_dest,
1143                             BasicType copy_type, const Type* value_type, int count);
1144   bool finish_transform(PhaseGVN *phase, bool can_reshape,
1145                         Node* ctl, Node *mem);
1146 
1147 public:
1148 
1149   enum {
1150     Src   = TypeFunc::Parms,
1151     SrcPos,
1152     Dest,
1153     DestPos,
1154     Length,
1155     SrcLen,
1156     DestLen,
1157     SrcKlass,
1158     DestKlass,
1159     ParmLimit
1160   };
1161 
1162   static ArrayCopyNode* make(GraphKit* kit, bool may_throw,
1163                              Node* src, Node* src_offset,
1164                              Node* dest,  Node* dest_offset,
1165                              Node* length,
1166                              bool alloc_tightly_coupled,
1167                              Node* src_klass = NULL, Node* dest_klass = NULL,
1168                              Node* src_length = NULL, Node* dest_length = NULL);
1169 
1170   void connect_outputs(GraphKit* kit);
1171 
1172   bool is_arraycopy()             const  { assert(_kind != None, "should bet set"); return _kind == ArrayCopy; }
1173   bool is_arraycopy_validated()   const  { assert(_kind != None, "should bet set"); return _kind == ArrayCopy && _arguments_validated; }
1174   bool is_clonebasic()            const  { assert(_kind != None, "should bet set"); return _kind == CloneBasic; }
1175   bool is_cloneoop()              const  { assert(_kind != None, "should bet set"); return _kind == CloneOop; }
1176   bool is_copyof()                const  { assert(_kind != None, "should bet set"); return _kind == CopyOf; }
1177   bool is_copyof_validated()      const  { assert(_kind != None, "should bet set"); return _kind == CopyOf && _arguments_validated; }
1178   bool is_copyofrange()           const  { assert(_kind != None, "should bet set"); return _kind == CopyOfRange; }
1179   bool is_copyofrange_validated() const  { assert(_kind != None, "should bet set"); return _kind == CopyOfRange && _arguments_validated; }
1180 
1181   void set_arraycopy(bool validated)   { assert(_kind == None, "shouldn't bet set yet"); _kind = ArrayCopy; _arguments_validated = validated; }
1182   void set_clonebasic()                { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneBasic; }
1183   void set_cloneoop()                  { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneOop; }
1184   void set_copyof(bool validated)      { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOf; _arguments_validated = validated; }
1185   void set_copyofrange(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOfRange; _arguments_validated = validated; }
1186 
1187   virtual int Opcode() const;
1188   virtual uint size_of() const; // Size is bigger
1189   virtual bool guaranteed_safepoint()  { return false; }
1190   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
1191 
1192   bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
1193 
1194 #ifndef PRODUCT
1195   virtual void dump_spec(outputStream *st) const;
1196 #endif
1197 };
1198 #endif // SHARE_VM_OPTO_CALLNODE_HPP
src/share/vm/opto/callnode.hpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File