< prev index next >

src/hotspot/share/opto/arraycopynode.cpp

Print this page
rev 52710 : Upstream/backport Shenandoah to JDK11u


  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 "gc/shared/barrierSet.hpp"
  27 #include "gc/shared/c2/barrierSetC2.hpp"
  28 #include "gc/shared/c2/cardTableBarrierSetC2.hpp"
  29 #include "opto/arraycopynode.hpp"
  30 #include "opto/graphKit.hpp"
  31 #include "runtime/sharedRuntime.hpp"
  32 #include "utilities/macros.hpp"



  33 
  34 ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled, bool has_negative_length_guard)
  35   : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM),
  36     _alloc_tightly_coupled(alloc_tightly_coupled),
  37     _has_negative_length_guard(has_negative_length_guard),
  38     _kind(None),
  39     _arguments_validated(false),
  40     _src_type(TypeOopPtr::BOTTOM),
  41     _dest_type(TypeOopPtr::BOTTOM) {
  42   init_class_id(Class_ArrayCopy);
  43   init_flags(Flag_is_macro);
  44   C->add_macro_node(this);
  45 }
  46 
  47 uint ArrayCopyNode::size_of() const { return sizeof(*this); }
  48 
  49 ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw,
  50                                    Node* src, Node* src_offset,
  51                                    Node* dest, Node* dest_offset,
  52                                    Node* length,


 188     const TypePtr* adr_type = phase->C->alias_type(field)->adr_type();
 189     Node* off = phase->MakeConX(field->offset());
 190     Node* next_src = phase->transform(new AddPNode(base_src,base_src,off));
 191     Node* next_dest = phase->transform(new AddPNode(base_dest,base_dest,off));
 192     BasicType bt = field->layout_type();
 193 
 194     const Type *type;
 195     if (bt == T_OBJECT) {
 196       if (!field->type()->is_loaded()) {
 197         type = TypeInstPtr::BOTTOM;
 198       } else {
 199         ciType* field_klass = field->type();
 200         type = TypeOopPtr::make_from_klass(field_klass->as_klass());
 201       }
 202     } else {
 203       type = Type::get_const_basic_type(bt);
 204     }
 205 
 206     Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered);
 207     v = phase->transform(v);





 208     Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered);
 209     s = phase->transform(s);
 210     mem->set_memory_at(fieldidx, s);
 211   }
 212 
 213   if (!finish_transform(phase, can_reshape, ctl, mem)) {
 214     // Return NodeSentinel to indicate that the transform failed
 215     return NodeSentinel;
 216   }
 217 
 218   return mem;
 219 }
 220 
 221 bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
 222                                        Node*& adr_src,
 223                                        Node*& base_src,
 224                                        Node*& adr_dest,
 225                                        Node*& base_dest,
 226                                        BasicType& copy_type,
 227                                        const Type*& value_type,


 356                                         const TypePtr* atp_src,
 357                                         const TypePtr* atp_dest,
 358                                         Node* adr_src,
 359                                         Node* base_src,
 360                                         Node* adr_dest,
 361                                         Node* base_dest,
 362                                         BasicType copy_type,
 363                                         const Type* value_type,
 364                                         int count) {
 365   Node* mem = phase->C->top();
 366   if (!forward_ctl->is_top()) {
 367     // copy forward
 368     mem = start_mem_dest;
 369     uint alias_idx_src = phase->C->get_alias_index(atp_src);
 370     uint alias_idx_dest = phase->C->get_alias_index(atp_dest);
 371     bool same_alias = (alias_idx_src == alias_idx_dest);
 372 
 373     if (count > 0) {
 374       Node* v = LoadNode::make(*phase, forward_ctl, start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered);
 375       v = phase->transform(v);





 376       mem = StoreNode::make(*phase, forward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered);
 377       mem = phase->transform(mem);
 378       for (int i = 1; i < count; i++) {
 379         Node* off  = phase->MakeConX(type2aelembytes(copy_type) * i);
 380         Node* next_src = phase->transform(new AddPNode(base_src,adr_src,off));
 381         Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off));
 382         v = LoadNode::make(*phase, forward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered);
 383         v = phase->transform(v);





 384         mem = StoreNode::make(*phase, forward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered);
 385         mem = phase->transform(mem);
 386       }
 387     } else if(can_reshape) {
 388       PhaseIterGVN* igvn = phase->is_IterGVN();
 389       igvn->_worklist.push(adr_src);
 390       igvn->_worklist.push(adr_dest);
 391     }
 392   }
 393   return mem;
 394 }
 395 
 396 Node* ArrayCopyNode::array_copy_backward(PhaseGVN *phase,
 397                                          bool can_reshape,
 398                                          Node* backward_ctl,
 399                                          Node* start_mem_src,
 400                                          Node* start_mem_dest,
 401                                          const TypePtr* atp_src,
 402                                          const TypePtr* atp_dest,
 403                                          Node* adr_src,


 405                                          Node* adr_dest,
 406                                          Node* base_dest,
 407                                          BasicType copy_type,
 408                                          const Type* value_type,
 409                                          int count) {
 410   Node* mem = phase->C->top();
 411   if (!backward_ctl->is_top()) {
 412     // copy backward
 413     mem = start_mem_dest;
 414     uint alias_idx_src = phase->C->get_alias_index(atp_src);
 415     uint alias_idx_dest = phase->C->get_alias_index(atp_dest);
 416     bool same_alias = (alias_idx_src == alias_idx_dest);
 417 
 418     if (count > 0) {
 419       for (int i = count-1; i >= 1; i--) {
 420         Node* off  = phase->MakeConX(type2aelembytes(copy_type) * i);
 421         Node* next_src = phase->transform(new AddPNode(base_src,adr_src,off));
 422         Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off));
 423         Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered);
 424         v = phase->transform(v);





 425         mem = StoreNode::make(*phase, backward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered);
 426         mem = phase->transform(mem);
 427       }
 428       Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered);
 429       v = phase->transform(v);





 430       mem = StoreNode::make(*phase, backward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered);
 431       mem = phase->transform(mem);
 432     } else if(can_reshape) {
 433       PhaseIterGVN* igvn = phase->is_IterGVN();
 434       igvn->_worklist.push(adr_src);
 435       igvn->_worklist.push(adr_dest);
 436     }
 437   }
 438   return mem;
 439 }
 440 
 441 bool ArrayCopyNode::finish_transform(PhaseGVN *phase, bool can_reshape,
 442                                      Node* ctl, Node *mem) {
 443   if (can_reshape) {
 444     PhaseIterGVN* igvn = phase->is_IterGVN();
 445     igvn->set_delay_transform(false);
 446     if (is_clonebasic()) {
 447       Node* out_mem = proj_out(TypeFunc::Memory);
 448 
 449       BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();


 468       }
 469       if (callprojs.fallthrough_memproj != NULL) {
 470         igvn->replace_node(callprojs.fallthrough_memproj, mem);
 471       }
 472       if (callprojs.fallthrough_catchproj != NULL) {
 473         igvn->replace_node(callprojs.fallthrough_catchproj, ctl);
 474       }
 475 
 476       // The ArrayCopyNode is not disconnected. It still has the
 477       // projections for the exception case. Replace current
 478       // ArrayCopyNode with a dummy new one with a top() control so
 479       // that this part of the graph stays consistent but is
 480       // eventually removed.
 481 
 482       set_req(0, phase->C->top());
 483       remove_dead_region(phase, can_reshape);
 484     }
 485   } else {
 486     if (in(TypeFunc::Control) != ctl) {
 487       // we can't return new memory and control from Ideal at parse time
 488       assert(!is_clonebasic(), "added control for clone?");

 489       return false;
 490     }
 491   }
 492   return true;
 493 }
 494 
 495 
 496 Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
 497   if (remove_dead_region(phase, can_reshape))  return this;
 498 
 499   if (StressArrayCopyMacroNode && !can_reshape) {
 500     phase->record_for_igvn(this);
 501     return NULL;
 502   }
 503 
 504   // See if it's a small array copy and we can inline it as
 505   // loads/stores
 506   // Here we can only do:
 507   // - arraycopy if all arguments were validated before and we don't
 508   // need card marking




  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 "gc/shared/barrierSet.hpp"
  27 #include "gc/shared/c2/barrierSetC2.hpp"
  28 #include "gc/shared/c2/cardTableBarrierSetC2.hpp"
  29 #include "opto/arraycopynode.hpp"
  30 #include "opto/graphKit.hpp"
  31 #include "runtime/sharedRuntime.hpp"
  32 #include "utilities/macros.hpp"
  33 #if INCLUDE_SHENANDOAHGC
  34 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  35 #endif
  36 
  37 ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled, bool has_negative_length_guard)
  38   : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM),
  39     _alloc_tightly_coupled(alloc_tightly_coupled),
  40     _has_negative_length_guard(has_negative_length_guard),
  41     _kind(None),
  42     _arguments_validated(false),
  43     _src_type(TypeOopPtr::BOTTOM),
  44     _dest_type(TypeOopPtr::BOTTOM) {
  45   init_class_id(Class_ArrayCopy);
  46   init_flags(Flag_is_macro);
  47   C->add_macro_node(this);
  48 }
  49 
  50 uint ArrayCopyNode::size_of() const { return sizeof(*this); }
  51 
  52 ArrayCopyNode* ArrayCopyNode::make(GraphKit* kit, bool may_throw,
  53                                    Node* src, Node* src_offset,
  54                                    Node* dest, Node* dest_offset,
  55                                    Node* length,


 191     const TypePtr* adr_type = phase->C->alias_type(field)->adr_type();
 192     Node* off = phase->MakeConX(field->offset());
 193     Node* next_src = phase->transform(new AddPNode(base_src,base_src,off));
 194     Node* next_dest = phase->transform(new AddPNode(base_dest,base_dest,off));
 195     BasicType bt = field->layout_type();
 196 
 197     const Type *type;
 198     if (bt == T_OBJECT) {
 199       if (!field->type()->is_loaded()) {
 200         type = TypeInstPtr::BOTTOM;
 201       } else {
 202         ciType* field_klass = field->type();
 203         type = TypeOopPtr::make_from_klass(field_klass->as_klass());
 204       }
 205     } else {
 206       type = Type::get_const_basic_type(bt);
 207     }
 208 
 209     Node* v = LoadNode::make(*phase, ctl, mem->memory_at(fieldidx), next_src, adr_type, type, bt, MemNode::unordered);
 210     v = phase->transform(v);
 211 #if INCLUDE_SHENANDOAHGC
 212     if (UseShenandoahGC && bt == T_OBJECT) {
 213       v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v);
 214     }
 215 #endif
 216     Node* s = StoreNode::make(*phase, ctl, mem->memory_at(fieldidx), next_dest, adr_type, v, bt, MemNode::unordered);
 217     s = phase->transform(s);
 218     mem->set_memory_at(fieldidx, s);
 219   }
 220 
 221   if (!finish_transform(phase, can_reshape, ctl, mem)) {
 222     // Return NodeSentinel to indicate that the transform failed
 223     return NodeSentinel;
 224   }
 225 
 226   return mem;
 227 }
 228 
 229 bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
 230                                        Node*& adr_src,
 231                                        Node*& base_src,
 232                                        Node*& adr_dest,
 233                                        Node*& base_dest,
 234                                        BasicType& copy_type,
 235                                        const Type*& value_type,


 364                                         const TypePtr* atp_src,
 365                                         const TypePtr* atp_dest,
 366                                         Node* adr_src,
 367                                         Node* base_src,
 368                                         Node* adr_dest,
 369                                         Node* base_dest,
 370                                         BasicType copy_type,
 371                                         const Type* value_type,
 372                                         int count) {
 373   Node* mem = phase->C->top();
 374   if (!forward_ctl->is_top()) {
 375     // copy forward
 376     mem = start_mem_dest;
 377     uint alias_idx_src = phase->C->get_alias_index(atp_src);
 378     uint alias_idx_dest = phase->C->get_alias_index(atp_dest);
 379     bool same_alias = (alias_idx_src == alias_idx_dest);
 380 
 381     if (count > 0) {
 382       Node* v = LoadNode::make(*phase, forward_ctl, start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered);
 383       v = phase->transform(v);
 384 #if INCLUDE_SHENANDOAHGC
 385       if (UseShenandoahGC && copy_type == T_OBJECT) {
 386         v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v);
 387       }
 388 #endif
 389       mem = StoreNode::make(*phase, forward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered);
 390       mem = phase->transform(mem);
 391       for (int i = 1; i < count; i++) {
 392         Node* off  = phase->MakeConX(type2aelembytes(copy_type) * i);
 393         Node* next_src = phase->transform(new AddPNode(base_src,adr_src,off));
 394         Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off));
 395         v = LoadNode::make(*phase, forward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered);
 396         v = phase->transform(v);
 397 #if INCLUDE_SHENANDOAHGC
 398         if (UseShenandoahGC && copy_type == T_OBJECT) {
 399           v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v);
 400         }
 401 #endif
 402         mem = StoreNode::make(*phase, forward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered);
 403         mem = phase->transform(mem);
 404       }
 405     } else if(can_reshape) {
 406       PhaseIterGVN* igvn = phase->is_IterGVN();
 407       igvn->_worklist.push(adr_src);
 408       igvn->_worklist.push(adr_dest);
 409     }
 410   }
 411   return mem;
 412 }
 413 
 414 Node* ArrayCopyNode::array_copy_backward(PhaseGVN *phase,
 415                                          bool can_reshape,
 416                                          Node* backward_ctl,
 417                                          Node* start_mem_src,
 418                                          Node* start_mem_dest,
 419                                          const TypePtr* atp_src,
 420                                          const TypePtr* atp_dest,
 421                                          Node* adr_src,


 423                                          Node* adr_dest,
 424                                          Node* base_dest,
 425                                          BasicType copy_type,
 426                                          const Type* value_type,
 427                                          int count) {
 428   Node* mem = phase->C->top();
 429   if (!backward_ctl->is_top()) {
 430     // copy backward
 431     mem = start_mem_dest;
 432     uint alias_idx_src = phase->C->get_alias_index(atp_src);
 433     uint alias_idx_dest = phase->C->get_alias_index(atp_dest);
 434     bool same_alias = (alias_idx_src == alias_idx_dest);
 435 
 436     if (count > 0) {
 437       for (int i = count-1; i >= 1; i--) {
 438         Node* off  = phase->MakeConX(type2aelembytes(copy_type) * i);
 439         Node* next_src = phase->transform(new AddPNode(base_src,adr_src,off));
 440         Node* next_dest = phase->transform(new AddPNode(base_dest,adr_dest,off));
 441         Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, next_src, atp_src, value_type, copy_type, MemNode::unordered);
 442         v = phase->transform(v);
 443 #if INCLUDE_SHENANDOAHGC
 444         if (UseShenandoahGC && copy_type == T_OBJECT) {
 445           v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v);
 446         }
 447 #endif
 448         mem = StoreNode::make(*phase, backward_ctl,mem,next_dest,atp_dest,v, copy_type, MemNode::unordered);
 449         mem = phase->transform(mem);
 450       }
 451       Node* v = LoadNode::make(*phase, backward_ctl, same_alias ? mem : start_mem_src, adr_src, atp_src, value_type, copy_type, MemNode::unordered);
 452       v = phase->transform(v);
 453 #if INCLUDE_SHENANDOAHGC
 454       if (UseShenandoahGC && copy_type == T_OBJECT) {
 455         v = ShenandoahBarrierSetC2::bsc2()->arraycopy_load_reference_barrier(phase, v);
 456       }
 457 #endif
 458       mem = StoreNode::make(*phase, backward_ctl, mem, adr_dest, atp_dest, v, copy_type, MemNode::unordered);
 459       mem = phase->transform(mem);
 460     } else if(can_reshape) {
 461       PhaseIterGVN* igvn = phase->is_IterGVN();
 462       igvn->_worklist.push(adr_src);
 463       igvn->_worklist.push(adr_dest);
 464     }
 465   }
 466   return mem;
 467 }
 468 
 469 bool ArrayCopyNode::finish_transform(PhaseGVN *phase, bool can_reshape,
 470                                      Node* ctl, Node *mem) {
 471   if (can_reshape) {
 472     PhaseIterGVN* igvn = phase->is_IterGVN();
 473     igvn->set_delay_transform(false);
 474     if (is_clonebasic()) {
 475       Node* out_mem = proj_out(TypeFunc::Memory);
 476 
 477       BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();


 496       }
 497       if (callprojs.fallthrough_memproj != NULL) {
 498         igvn->replace_node(callprojs.fallthrough_memproj, mem);
 499       }
 500       if (callprojs.fallthrough_catchproj != NULL) {
 501         igvn->replace_node(callprojs.fallthrough_catchproj, ctl);
 502       }
 503 
 504       // The ArrayCopyNode is not disconnected. It still has the
 505       // projections for the exception case. Replace current
 506       // ArrayCopyNode with a dummy new one with a top() control so
 507       // that this part of the graph stays consistent but is
 508       // eventually removed.
 509 
 510       set_req(0, phase->C->top());
 511       remove_dead_region(phase, can_reshape);
 512     }
 513   } else {
 514     if (in(TypeFunc::Control) != ctl) {
 515       // we can't return new memory and control from Ideal at parse time
 516       assert(!is_clonebasic() || UseShenandoahGC, "added control for clone?");
 517       phase->record_for_igvn(this);
 518       return false;
 519     }
 520   }
 521   return true;
 522 }
 523 
 524 
 525 Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) {
 526   if (remove_dead_region(phase, can_reshape))  return this;
 527 
 528   if (StressArrayCopyMacroNode && !can_reshape) {
 529     phase->record_for_igvn(this);
 530     return NULL;
 531   }
 532 
 533   // See if it's a small array copy and we can inline it as
 534   // loads/stores
 535   // Here we can only do:
 536   // - arraycopy if all arguments were validated before and we don't
 537   // need card marking


< prev index next >