--- old/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp 2019-05-21 13:17:34.356823856 -0700 +++ new/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp 2019-05-21 13:17:34.060813288 -0700 @@ -1383,6 +1383,7 @@ } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { #ifdef _LP64 if (UseCompressedClassPointers) { + __ andl(dest->as_register(), oopDesc::compressed_klass_mask()); __ decode_klass_not_null(dest->as_register()); } #endif @@ -1931,8 +1932,8 @@ } void LIR_Assembler::emit_opFlattenedArrayCheck(LIR_OpFlattenedArrayCheck* op) { - // We are loading/storing an array that *may* be a flattened array (e.g., the declared type - // is Object[]). If this array is flattened, take slow path. + // We are loading/storing an array that *may* be a flattened array (the declared type + // Object[], interface[], or VT?[]). If this array is flattened, take slow path. __ load_storage_props(op->tmp()->as_register(), op->array()->as_register()); __ testb(op->tmp()->as_register(), ArrayStorageProperties::flattened_value); @@ -1953,7 +1954,7 @@ void LIR_Assembler::emit_opNullFreeArrayCheck(LIR_OpNullFreeArrayCheck* op) { // This is called when we use aastore into a an array declared as "[LVT;", // where we know VT is not flattenable (due to ValueArrayElemMaxFlatOops, etc). - // However, we need to do a NULL check if the actual array is a "QLVT;". + // However, we need to do a NULL check if the actual array is a "[QVT;". __ load_storage_props(op->tmp()->as_register(), op->array()->as_register()); __ testb(op->tmp()->as_register(), ArrayStorageProperties::null_free_value); @@ -3078,18 +3079,16 @@ } -void LIR_Assembler::arraycopy_flat_check(Register obj, Register tmp, CodeStub* slow_path) { - Address klass_addr = Address(obj, oopDesc::klass_offset_in_bytes()); - if (UseCompressedClassPointers) { - __ movl(tmp, klass_addr); - LP64_ONLY(__ decode_klass_not_null(tmp)); +void LIR_Assembler::arraycopy_valuetype_check(Register obj, Register tmp, CodeStub* slow_path, bool is_dest) { + __ load_storage_props(tmp, obj); + if (is_dest) { + // We also take slow path if it's a null_free destination array, just in case the source array + // contains NULLs. + __ testb(tmp, ArrayStorageProperties::flattened_value | ArrayStorageProperties::null_free_value); } else { - __ movptr(tmp, klass_addr); + __ testb(tmp, ArrayStorageProperties::flattened_value); } - __ movl(tmp, Address(tmp, Klass::layout_helper_offset())); - __ sarl(tmp, Klass::_lh_array_tag_shift); - __ cmpl(tmp, Klass::_lh_array_tag_vt_value); - __ jcc(Assembler::equal, *slow_path->entry()); + __ jcc(Assembler::notEqual, *slow_path->entry()); } @@ -3119,12 +3118,12 @@ return; } - if (flags & LIR_OpArrayCopy::src_flat_check) { - arraycopy_flat_check(src, tmp, stub); + if (flags & LIR_OpArrayCopy::src_valuetype_check) { + arraycopy_valuetype_check(src, tmp, stub, false); } - if (flags & LIR_OpArrayCopy::dst_flat_check) { - arraycopy_flat_check(dst, tmp, stub); + if (flags & LIR_OpArrayCopy::dst_valuetype_check) { + arraycopy_valuetype_check(dst, tmp, stub, true); } // if we don't know anything, just go through the generic arraycopy --- old/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp 2019-05-21 13:17:35.072849423 -0700 +++ new/src/hotspot/cpu/x86/c1_LIRAssembler_x86.hpp 2019-05-21 13:17:34.780838996 -0700 @@ -55,7 +55,7 @@ _deopt_handler_size = NOT_LP64(10) LP64_ONLY(17) }; - void arraycopy_flat_check(Register obj, Register tmp, CodeStub* slow_path); +void arraycopy_valuetype_check(Register obj, Register tmp, CodeStub* slow_path, bool is_dest); public: --- old/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2019-05-21 13:17:35.752873704 -0700 +++ new/src/hotspot/cpu/x86/macroAssembler_x86.cpp 2019-05-21 13:17:35.456863135 -0700 @@ -5107,6 +5107,7 @@ load_metadata(dst, src); #ifdef _LP64 if (UseCompressedClassPointers) { + andl(dst, oopDesc::compressed_klass_mask()); decode_klass_not_null(dst); } else #endif @@ -5397,7 +5398,6 @@ // Note: it will change flags assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert(r != r12_heapbase, "Decoding a klass in r12"); - andl(r, oopDesc::compressed_klass_mask()); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. @@ -5422,7 +5422,6 @@ // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. // Also do not verify_oop as this is called by verify_oop. - andl(src, oopDesc::compressed_klass_mask()); mov64(dst, (int64_t)Universe::narrow_klass_base()); if (Universe::narrow_klass_shift() != 0) { assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); --- old/src/hotspot/share/c1/c1_Instruction.cpp 2019-05-21 13:17:36.532901555 -0700 +++ new/src/hotspot/share/c1/c1_Instruction.cpp 2019-05-21 13:17:36.228890700 -0700 @@ -294,13 +294,12 @@ if (array()->is_loaded_flattened_array() && value()->as_Constant() == NULL) { ciKlass* element_klass = array()->declared_type()->as_value_array_klass()->element_klass(); ciKlass* actual_klass = value()->declared_type()->as_klass(); + + // The following check can fail 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); } 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; --- old/src/hotspot/share/c1/c1_LIR.hpp 2019-05-21 13:17:37.220926121 -0700 +++ new/src/hotspot/share/c1/c1_LIR.hpp 2019-05-21 13:17:36.928915695 -0700 @@ -1279,8 +1279,8 @@ src_objarray = 1 << 10, dst_objarray = 1 << 11, always_slow_path = 1 << 12, - src_flat_check = 1 << 13, - dst_flat_check = 1 << 14, + src_valuetype_check = 1 << 13, + dst_valuetype_check = 1 << 14, all_flags = (1 << 15) - 1 }; --- old/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-05-21 13:17:37.924951259 -0700 +++ new/src/hotspot/share/c1/c1_LIRGenerator.cpp 2019-05-21 13:17:37.624940546 -0700 @@ -791,10 +791,10 @@ flags &= ~LIR_OpArrayCopy::always_slow_path; } if (!src->maybe_flattened_array()) { - flags &= ~LIR_OpArrayCopy::src_flat_check; + flags &= ~LIR_OpArrayCopy::src_valuetype_check; } - if (!dst->maybe_flattened_array()) { - flags &= ~LIR_OpArrayCopy::dst_flat_check; + if (!dst->maybe_flattened_array() && !dst->maybe_null_free_array()) { + flags &= ~LIR_OpArrayCopy::dst_valuetype_check; } if (!src_objarray)