diff a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -238,10 +238,22 @@ __ bind(cont); POP(src, dst); } } +void LIR_Assembler::arraycopy_inlinetype_check(Register obj, Register tmp, CodeStub* slow_path, bool is_dest, bool null_check) { + if (null_check) { + __ beqz(obj, *slow_path->entry(), /* is_far */ true); + } + if (is_dest) { + __ test_null_free_array_oop(obj, tmp, *slow_path->entry()); + __ test_flat_array_oop(obj, tmp, *slow_path->entry()); + } else { + __ test_flat_array_oop(obj, tmp, *slow_path->entry()); + } +} + void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { ciArrayKlass *default_type = op->expected_type(); Register src = op->src()->as_register(); Register dst = op->dst()->as_register(); Register src_pos = op->src_pos()->as_register(); @@ -252,16 +264,29 @@ CodeStub* stub = op->stub(); int flags = op->flags(); BasicType basic_type = default_type != nullptr ? default_type->element_type()->basic_type() : T_ILLEGAL; if (is_reference_type(basic_type)) { basic_type = T_OBJECT; } + if (flags & LIR_OpArrayCopy::always_slow_path) { + __ j(*stub->entry()); + __ bind(*stub->continuation()); + return; + } + // if we don't know anything, just go through the generic arraycopy if (default_type == nullptr) { generic_arraycopy(src, src_pos, length, dst, dst_pos, stub); return; } + if (flags & LIR_OpArrayCopy::src_inlinetype_check) { + arraycopy_inlinetype_check(src, tmp, stub, false, (flags & LIR_OpArrayCopy::src_null_check)); + } + if (flags & LIR_OpArrayCopy::dst_inlinetype_check) { + arraycopy_inlinetype_check(dst, tmp, stub, true, (flags & LIR_OpArrayCopy::dst_null_check)); + } + assert(default_type != nullptr && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); arraycopy_simple_check(src, src_pos, length, dst, dst_pos, tmp, stub, flags);