Print this page
rev 6883 : 8057622: java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest: SEGV inside compiled code (sparc)
Summary: In Parse::array_store_check(), add control edge FROM IfTrue branch of runtime type check of the destination array TO loading _element_klass from destination array.
Reviewed-by: kvn, roland, anoll
Contributed-by: Zoltan Majo <zoltan.majo@oracle.com>

Split Split Close
Expand all
Collapse all
          --- old/hotspot/src/share/vm/opto/parseHelper.cpp
          +++ new/hotspot/src/share/vm/opto/parseHelper.cpp
↓ open down ↓ 148 lines elided ↑ open up ↑
 149  149      // This cutout lets us avoid the uncommon_trap(Reason_array_check)
 150  150      // below, which turns into a performance liability if the
 151  151      // gen_checkcast folds up completely.
 152  152      return;
 153  153    }
 154  154  
 155  155    // Extract the array klass type
 156  156    int klass_offset = oopDesc::klass_offset_in_bytes();
 157  157    Node* p = basic_plus_adr( ary, ary, klass_offset );
 158  158    // p's type is array-of-OOPS plus klass_offset
 159      -  Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) );
      159 +  Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS));
 160  160    // Get the array klass
 161  161    const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr();
 162  162  
 163      -  // array_klass's type is generally INexact array-of-oop.  Heroically
 164      -  // cast the array klass to EXACT array and uncommon-trap if the cast
 165      -  // fails.
      163 +  // The type of array_klass is usually INexact array-of-oop.  Heroically
      164 +  // cast array_klass to EXACT array and uncommon-trap if the cast fails.
      165 +  // Make constant out of the inexact array klass, but use it only if the cast
      166 +  // succeeds.
 166  167    bool always_see_exact_class = false;
 167  168    if (MonomorphicArrayCheck
 168      -      && !too_many_traps(Deoptimization::Reason_array_check)) {
      169 +      && !too_many_traps(Deoptimization::Reason_array_check)
      170 +      && !tak->klass_is_exact()
      171 +      && tak != TypeKlassPtr::OBJECT) {
      172 +      // Regarding the fourth condition in the if-statement from above:
      173 +      //
      174 +      // If the compiler has determined that the type of array 'ary' (represented
      175 +      // by 'array_klass') is java/lang/Object, the compiler must not assume that
      176 +      // the array 'ary' is monomorphic.
      177 +      //
      178 +      // If 'ary' were of type java/lang/Object, this arraystore would have to fail,
      179 +      // because it is not possible to perform a arraystore into an object that is not
      180 +      // a "proper" array.
      181 +      //
      182 +      // Therefore, let's obtain at runtime the type of 'ary' and check if we can still
      183 +      // successfully perform the store.
      184 +      //
      185 +      // The implementation reasons for the condition are the following:
      186 +      //
      187 +      // java/lang/Object is the superclass of all arrays, but it is represented by the VM
      188 +      // as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect
      189 +      // 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses.
      190 +      //
      191 +      // See issue JDK-8057622 for details.
      192 +
 169  193      always_see_exact_class = true;
 170  194      // (If no MDO at all, hope for the best, until a trap actually occurs.)
 171      -  }
 172  195  
 173      -  // Is the array klass is exactly its defined type?
 174      -  if (always_see_exact_class && !tak->klass_is_exact()) {
 175  196      // Make a constant out of the inexact array klass
 176  197      const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr();
 177  198      Node* con = makecon(extak);
 178  199      Node* cmp = _gvn.transform(new (C) CmpPNode( array_klass, con ));
 179  200      Node* bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::eq ));
 180  201      Node* ctrl= control();
 181  202      { BuildCutout unless(this, bol, PROB_MAX);
 182  203        uncommon_trap(Deoptimization::Reason_array_check,
 183  204                      Deoptimization::Action_maybe_recompile,
 184  205                      tak->klass());
↓ open down ↓ 10 lines elided ↑ open up ↑
 195  216        }
 196  217        array_klass = con;      // Use cast value moving forward
 197  218      }
 198  219    }
 199  220  
 200  221    // Come here for polymorphic array klasses
 201  222  
 202  223    // Extract the array element class
 203  224    int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset());
 204  225    Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset);
 205      -  Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) );
      226 +  // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true,
      227 +  // we must set a control edge from the IfTrue node created by the uncommon_trap above to the
      228 +  // LoadKlassNode.
      229 +  Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL,
      230 +                                                       immutable_memory(), p2, tak));
 206  231  
 207  232    // Check (the hard way) and throw if not a subklass.
 208  233    // Result is ignored, we just need the CFG effects.
 209      -  gen_checkcast( obj, a_e_klass );
      234 +  gen_checkcast(obj, a_e_klass);
 210  235  }
 211  236  
 212  237  
 213  238  void Parse::emit_guard_for_new(ciInstanceKlass* klass) {
 214  239    // Emit guarded new
 215  240    //   if (klass->_init_thread != current_thread ||
 216  241    //       klass->_init_state != being_initialized)
 217  242    //      uncommon_trap
 218  243    Node* cur_thread = _gvn.transform( new (C) ThreadLocalNode() );
 219  244    Node* merge = new (C) RegionNode(3);
↓ open down ↓ 378 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX