Mercurial > hg > graal-compiler
diff src/share/vm/opto/parseHelper.cpp @ 20627:e7b3d177adda
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>
author | zmajo |
---|---|
date | Mon, 10 Nov 2014 17:14:59 +0100 |
parents | 2113136690bc |
children | 7848fc12602b |
line wrap: on
line diff
--- a/src/share/vm/opto/parseHelper.cpp Fri Nov 07 09:36:34 2014 -0800 +++ b/src/share/vm/opto/parseHelper.cpp Mon Nov 10 17:14:59 2014 +0100 @@ -156,22 +156,43 @@ int klass_offset = oopDesc::klass_offset_in_bytes(); Node* p = basic_plus_adr( ary, ary, klass_offset ); // p's type is array-of-OOPS plus klass_offset - Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) ); + Node* array_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), p, TypeInstPtr::KLASS)); // Get the array klass const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); - // array_klass's type is generally INexact array-of-oop. Heroically - // cast the array klass to EXACT array and uncommon-trap if the cast - // fails. + // The type of array_klass is usually INexact array-of-oop. Heroically + // cast array_klass to EXACT array and uncommon-trap if the cast fails. + // Make constant out of the inexact array klass, but use it only if the cast + // succeeds. bool always_see_exact_class = false; if (MonomorphicArrayCheck - && !too_many_traps(Deoptimization::Reason_array_check)) { + && !too_many_traps(Deoptimization::Reason_array_check) + && !tak->klass_is_exact() + && tak != TypeKlassPtr::OBJECT) { + // Regarding the fourth condition in the if-statement from above: + // + // If the compiler has determined that the type of array 'ary' (represented + // by 'array_klass') is java/lang/Object, the compiler must not assume that + // the array 'ary' is monomorphic. + // + // If 'ary' were of type java/lang/Object, this arraystore would have to fail, + // because it is not possible to perform a arraystore into an object that is not + // a "proper" array. + // + // Therefore, let's obtain at runtime the type of 'ary' and check if we can still + // successfully perform the store. + // + // The implementation reasons for the condition are the following: + // + // java/lang/Object is the superclass of all arrays, but it is represented by the VM + // as an InstanceKlass. The checks generated by gen_checkcast() (see below) expect + // 'array_klass' to be ObjArrayKlass, which can result in invalid memory accesses. + // + // See issue JDK-8057622 for details. + always_see_exact_class = true; // (If no MDO at all, hope for the best, until a trap actually occurs.) - } - // Is the array klass is exactly its defined type? - if (always_see_exact_class && !tak->klass_is_exact()) { // Make a constant out of the inexact array klass const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); Node* con = makecon(extak); @@ -202,11 +223,15 @@ // Extract the array element class int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); - Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) ); + // We are allowed to use the constant type only if cast succeeded. If always_see_exact_class is true, + // we must set a control edge from the IfTrue node created by the uncommon_trap above to the + // LoadKlassNode. + Node* a_e_klass = _gvn.transform(LoadKlassNode::make(_gvn, always_see_exact_class ? control() : NULL, + immutable_memory(), p2, tak)); // Check (the hard way) and throw if not a subklass. // Result is ignored, we just need the CFG effects. - gen_checkcast( obj, a_e_klass ); + gen_checkcast(obj, a_e_klass); }