--- a/hotspot/src/share/vm/opto/parseHelper.cpp Tue Nov 04 07:09:34 2014 -1000
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Thu Nov 06 09:40:58 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);
}