< prev index next >

src/hotspot/share/opto/memnode.cpp

Print this page
rev 54102 : 8262295: C2: Out-of-Bounds Array Load from Clone Source
Reviewed-by: kvn, roland, neliasso, thartmann


 521   // Otherwise, one is an allocation and the other a pre-existing value.
 522   if (a1 == NULL && a2 == NULL) {           // neither an allocation
 523     return (p1 != p2) && p1->is_Con() && p2->is_Con();
 524   } else if (a1 != NULL && a2 != NULL) {    // both allocations
 525     return (a1 != a2);
 526   } else if (a1 != NULL) {                  // one allocation a1
 527     // (Note:  p2->is_Con implies p2->in(0)->is_Root, which dominates.)
 528     return all_controls_dominate(p2, a1);
 529   } else { //(a2 != NULL)                   // one allocation a2
 530     return all_controls_dominate(p1, a2);
 531   }
 532   return false;
 533 }
 534 
 535 
 536 // Find an arraycopy that must have set (can_see_stored_value=true) or
 537 // could have set (can_see_stored_value=false) the value for this load
 538 Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const {
 539   ArrayCopyNode* ac = find_array_copy_clone(phase, ld_alloc, mem);
 540   if (ac != NULL) {


















 541     return ac;





 542   } else if (mem->is_Proj() && mem->in(0) != NULL && mem->in(0)->is_ArrayCopy()) {
 543     ArrayCopyNode* ac = mem->in(0)->as_ArrayCopy();
 544 
 545     if (ac->is_arraycopy_validated() ||
 546         ac->is_copyof_validated() ||
 547         ac->is_copyofrange_validated()) {
 548       Node* ld_addp = in(MemNode::Address);
 549       if (ld_addp->is_AddP()) {
 550         Node* ld_base = ld_addp->in(AddPNode::Address);
 551         Node* ld_offs = ld_addp->in(AddPNode::Offset);
 552 
 553         Node* dest = ac->in(ArrayCopyNode::Dest);
 554 
 555         if (dest == ld_base) {
 556           const TypeX *ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
 557           if (ac->modifies(ld_offs_t->_lo, ld_offs_t->_hi, phase, can_see_stored_value)) {
 558             return ac;
 559           }
 560           if (!can_see_stored_value) {
 561             mem = ac->in(TypeFunc::Memory);




 521   // Otherwise, one is an allocation and the other a pre-existing value.
 522   if (a1 == NULL && a2 == NULL) {           // neither an allocation
 523     return (p1 != p2) && p1->is_Con() && p2->is_Con();
 524   } else if (a1 != NULL && a2 != NULL) {    // both allocations
 525     return (a1 != a2);
 526   } else if (a1 != NULL) {                  // one allocation a1
 527     // (Note:  p2->is_Con implies p2->in(0)->is_Root, which dominates.)
 528     return all_controls_dominate(p2, a1);
 529   } else { //(a2 != NULL)                   // one allocation a2
 530     return all_controls_dominate(p1, a2);
 531   }
 532   return false;
 533 }
 534 
 535 
 536 // Find an arraycopy that must have set (can_see_stored_value=true) or
 537 // could have set (can_see_stored_value=false) the value for this load
 538 Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const {
 539   ArrayCopyNode* ac = find_array_copy_clone(phase, ld_alloc, mem);
 540   if (ac != NULL) {
 541     Node* ld_addp = in(MemNode::Address);
 542     Node* src = ac->in(ArrayCopyNode::Src);
 543     const TypeAryPtr* ary_t = phase->type(src)->isa_aryptr();
 544 
 545     // This is a load from a cloned array. The corresponding arraycopy ac must
 546     // have set the value for the load and we can return ac but only if the load
 547     // is known to be within bounds. This is checked below.
 548     if (ary_t != NULL && ld_addp->is_AddP()) {
 549       Node* ld_offs = ld_addp->in(AddPNode::Offset);
 550       BasicType ary_elem = ary_t->klass()->as_array_klass()->element_type()->basic_type();
 551       jlong header = arrayOopDesc::base_offset_in_bytes(ary_elem);
 552       jlong elemsize = type2aelembytes(ary_elem);
 553 
 554       const TypeX*   ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
 555       const TypeInt* sizetype  = ary_t->size();
 556 
 557       if (ld_offs_t->_lo >= header && ld_offs_t->_hi < (sizetype->_lo * elemsize + header)) {
 558         // The load is known to be within bounds. It receives its value from ac.
 559         return ac;
 560       }
 561       // The load is known to be out-of-bounds.
 562     }
 563     // The load could be out-of-bounds. It must not be hoisted but must remain
 564     // dependent on the runtime range check. This is achieved by returning NULL.
 565   } else if (mem->is_Proj() && mem->in(0) != NULL && mem->in(0)->is_ArrayCopy()) {
 566     ArrayCopyNode* ac = mem->in(0)->as_ArrayCopy();
 567 
 568     if (ac->is_arraycopy_validated() ||
 569         ac->is_copyof_validated() ||
 570         ac->is_copyofrange_validated()) {
 571       Node* ld_addp = in(MemNode::Address);
 572       if (ld_addp->is_AddP()) {
 573         Node* ld_base = ld_addp->in(AddPNode::Address);
 574         Node* ld_offs = ld_addp->in(AddPNode::Offset);
 575 
 576         Node* dest = ac->in(ArrayCopyNode::Dest);
 577 
 578         if (dest == ld_base) {
 579           const TypeX *ld_offs_t = phase->type(ld_offs)->isa_intptr_t();
 580           if (ac->modifies(ld_offs_t->_lo, ld_offs_t->_hi, phase, can_see_stored_value)) {
 581             return ac;
 582           }
 583           if (!can_see_stored_value) {
 584             mem = ac->in(TypeFunc::Memory);


< prev index next >