--- old/src/hotspot/share/c1/c1_Instruction.cpp 2019-02-20 20:12:23.423538106 -0800 +++ new/src/hotspot/share/c1/c1_Instruction.cpp 2019-02-20 20:12:23.203530025 -0800 @@ -147,7 +147,7 @@ return false; } -bool Instruction::maybe_flattened_array() const { +bool Instruction::maybe_flattened_array() { if (ValueArrayFlatten) { ciType* type = declared_type(); if (type != NULL) { @@ -167,6 +167,10 @@ return true; } } + } else if (as_Phi() != NULL) { + // Type info gets lost during Phi merging, but we might be storing into a + // flattened array, so we should do a runtime check. + return true; } } --- old/src/hotspot/share/c1/c1_Instruction.hpp 2019-02-20 20:12:24.043560876 -0800 +++ new/src/hotspot/share/c1/c1_Instruction.hpp 2019-02-20 20:12:23.815552503 -0800 @@ -511,7 +511,7 @@ bool is_flattened_array() const; // FIXME -- remove it bool is_loaded_flattened_array() const; - bool maybe_flattened_array() const; + bool maybe_flattened_array(); Instruction *insert_after_same_bci(Instruction *i) { #ifndef PRODUCT --- 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); } --- old/src/hotspot/share/c1/c1_LIRGenerator.hpp 2019-02-20 20:12:25.307607301 -0800 +++ new/src/hotspot/share/c1/c1_LIRGenerator.hpp 2019-02-20 20:12:25.083599074 -0800 @@ -267,6 +267,7 @@ void do_vectorizedMismatch(Intrinsic* x); void access_flattened_array(bool is_load, LIRItem& array, LIRItem& index, LIRItem& obj_item); + bool needs_flattened_array_store_check(StoreIndexed* x); void check_flattened_array(LIRItem& array, CodeStub* slow_path); public: