--- old/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-02-20 20:12:24.667583795 -0800 +++ new/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-02-20 20:12:24.443575568 -0800 @@ -1659,12 +1659,32 @@ __ branch(lir_cond_equal, T_ILLEGAL, slow_path); } +bool LIRGenerator::needs_flattened_array_store_check(StoreIndexed* x) { + if (ValueArrayFlatten && x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) { + ciType* type = x->value()->declared_type(); + if (type != NULL && type->is_klass()) { + ciKlass* klass = type->as_klass(); + if (klass->is_loaded() && + !(klass->is_valuetype() && klass->as_value_klass()->flatten_array()) && + !klass->is_java_lang_Object() && + !klass->is_interface()) { + // This is known to be a non-flattenable object. If the array is flattened, + // it will be caught by the code generated by array_store_check(). + return false; + } + } + // We're not 100% sure, so let's do the flattened_array_store_check. + return true; + } + return false; +} + void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { assert(x->is_pinned(),""); bool is_loaded_flattened_array = x->array()->is_loaded_flattened_array(); bool needs_range_check = x->compute_needs_range_check(); bool use_length = x->length() != NULL; - bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT; + bool obj_store = x->elt_type() == T_OBJECT; assert(x->elt_type() != T_ARRAY, "never used"); bool needs_store_check = obj_store && !is_loaded_flattened_array && (x->value()->as_Constant() == NULL || !get_jobject_constant(x->value())->is_null_object() || @@ -1684,7 +1704,7 @@ } if (needs_store_check || x->check_boolean() - || is_loaded_flattened_array || x->array()->maybe_flattened_array()) { + || is_loaded_flattened_array || needs_flattened_array_store_check(x)) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -1729,7 +1749,7 @@ } else { StoreFlattenedArrayStub* slow_path = NULL; - if (x->array()->maybe_flattened_array()) { + if (needs_flattened_array_store_check(x)) { // Check if we indeed have a flattened array index.load_item(); slow_path = new StoreFlattenedArrayStub(array.result(), index.result(), value.result(), state_for(x)); @@ -2046,9 +2066,9 @@ LIR_Opr result = rlock_result(x, x->elt_type()); LoadFlattenedArrayStub* slow_path = NULL; - if (x->array()->maybe_flattened_array()) { + if (x->elt_type() == T_OBJECT && x->array()->maybe_flattened_array()) { index.load_item(); - // Check if we indeed have a flattened array + // if we are loading from flattened array, load it using a runtime call slow_path = new LoadFlattenedArrayStub(array.result(), index.result(), result, state_for(x)); check_flattened_array(array, slow_path); }