--- old/src/hotspot/share/c1/c1_Instruction.cpp 2019-05-19 19:47:50.191941462 -0700 +++ new/src/hotspot/share/c1/c1_Instruction.cpp 2019-05-19 19:47:49.907931543 -0700 @@ -146,11 +146,9 @@ if (ValueArrayFlatten) { ciType* type = declared_type(); if (type != NULL && type->is_value_array_klass()) { - ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass(); - assert(element_klass->is_loaded(), "ciValueKlasses are always loaded"); - if (element_klass->flatten_array()) { - return true; - } + ciValueArrayKlass* vak = type->as_value_array_klass(); + ArrayStorageProperties props = vak->storage_properties(); + return (!props.is_empty() && props.is_null_free() && props.is_flattened()); } } @@ -161,18 +159,13 @@ if (ValueArrayFlatten) { ciType* type = declared_type(); if (type != NULL) { - if (type->is_value_array_klass()) { - ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass(); - assert(element_klass->is_loaded(), "ciValueKlasses are always loaded"); - if (element_klass->flatten_array()) { - return true; - } - } else if (type->is_obj_array_klass()) { + if (type->is_obj_array_klass()) { + // Check for array covariance. One of the following declared types may be a flattened array: ciKlass* element_klass = type->as_obj_array_klass()->element_klass(); - if (!element_klass->is_loaded() || element_klass->is_java_lang_Object() || element_klass->is_interface()) { - // Array covariance: - // (ValueType[] <: Object[]) - // (ValueType[] <: []) + if (!element_klass->is_loaded() || + element_klass->is_java_lang_Object() || // (ValueType[] <: Object[]) + element_klass->is_interface() || // (ValueType[] <: []) + (element_klass->is_valuetype() && element_klass->as_value_klass()->flatten_array())) { // (ValueType[] <: ValueType?[]) // We will add a runtime check for flat-ness. return true; } @@ -180,8 +173,8 @@ // This can happen as a parameter to System.arraycopy() return true; } - } else if (as_Phi() != NULL) { - // Type info gets lost during Phi merging, but we might be storing into a + } else { + // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a // flattened array, so we should do a runtime check. return true; } @@ -190,6 +183,29 @@ return false; } +bool Instruction::maybe_null_free_array() { + ciType* type = declared_type(); + if (type != NULL) { + if (type->is_obj_array_klass()) { + // Check for array covariance. One of the following declared types may be a null-free array: + ciKlass* element_klass = type->as_obj_array_klass()->element_klass(); + if (!element_klass->is_loaded() || + element_klass->is_java_lang_Object() || // (ValueType[] <: Object[]) + element_klass->is_interface() || // (ValueType[] <: []) + element_klass->is_valuetype()) { // (ValueType[] <: ValueType?[]) + // We will add a runtime check for flat-ness. + return true; + } + } + } else { + // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a + // flattened array, so we should do a runtime check. + return true; + } + + return false; +} + #ifndef PRODUCT void Instruction::check_state(ValueStack* state) { if (state != NULL) { @@ -280,6 +296,11 @@ ciKlass* actual_klass = value()->declared_type()->as_klass(); if (element_klass == actual_klass) { return true; + } else { + // This can happen with inlining: + // void test45_inline(Object[] oa, Object o, int index) { oa[index] = o; } + // void test45(MyValue1[] va, int index, MyValue2 v) { test45_inline(va, v, index); } + return false; } } return false; @@ -296,7 +317,7 @@ ciType* NewObjectArray::exact_type() const { ciKlass* element_klass = klass(); - if (element_klass->is_valuetype()) { + if (is_never_null() && element_klass->is_valuetype()) { return ciValueArrayKlass::make(element_klass); } else { return ciObjArrayKlass::make(element_klass);