3581 // Load layout helper (32-bits)
3582 //
3583 // |array_tag| | header_size | element_type | |log2_element_size|
3584 // 32 30 24 16 8 2 0
3585 //
3586 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3587 //
3588
3589 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3590
3591 // Handle objArrays completely differently...
3592 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3593 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3594 __ jcc(Assembler::equal, L_objArray);
3595
3596 // if (src->klass() != dst->klass()) return -1;
3597 __ load_klass(rax, dst, rklass_tmp);
3598 __ cmpq(r10_src_klass, rax);
3599 __ jcc(Assembler::notEqual, L_failed);
3600
3601 const Register rax_lh = rax; // layout helper
3602 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3603
3604 // if (!src->is_Array()) return -1;
3605 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3606 __ jcc(Assembler::greaterEqual, L_failed);
3607
3608 // At this point, it is known to be a typeArray (array_tag 0x3).
3609 #ifdef ASSERT
3610 {
3611 BLOCK_COMMENT("assert primitive array {");
3612 Label L;
3613 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
3614 __ jcc(Assembler::greaterEqual, L);
3615 __ stop("must be a primitive array");
3616 __ bind(L);
3617 BLOCK_COMMENT("} assert primitive array done");
3618 }
3619 #endif
3620
3621 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3622 r10, L_failed);
3623
3624 // TypeArrayKlass
3625 //
3626 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3627 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3628 //
3629
3630 const Register r10_offset = r10; // array offset
3631 const Register rax_elsize = rax_lh; // element size
3632
3633 __ movl(r10_offset, rax_lh);
3634 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3702
3703 // Identically typed arrays can be copied without element-wise checks.
3704 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3705 r10, L_failed);
3706
3707 __ lea(from, Address(src, src_pos, TIMES_OOP,
3708 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3709 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3710 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3711 __ movl2ptr(count, r11_length); // length
3712 __ BIND(L_plain_copy);
3713 #ifdef _WIN64
3714 __ pop_ppx(rklass_tmp); // Restore callee-save rdi
3715 #endif
3716 __ jump(RuntimeAddress(oop_copy_entry));
3717
3718 __ BIND(L_checkcast_copy);
3719 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3720 {
3721 // Before looking at dst.length, make sure dst is also an objArray.
3722 __ cmpl(Address(rax, lh_offset), objArray_lh);
3723 __ jcc(Assembler::notEqual, L_failed);
3724
3725 // It is safe to examine both src.length and dst.length.
3726 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3727 rax, L_failed);
3728
3729 const Register r11_dst_klass = r11;
3730 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3731
3732 // Marshal the base address arguments now, freeing registers.
3733 __ lea(from, Address(src, src_pos, TIMES_OOP,
3734 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3735 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3736 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3737 __ movl(count, length); // length (reloaded)
3738 Register sco_temp = c_rarg3; // this register is free now
3739 assert_different_registers(from, to, count, sco_temp,
3740 r11_dst_klass, r10_src_klass);
3741 assert_clean_int(count, sco_temp);
3742
3743 // Generate the type check.
3744 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|
3581 // Load layout helper (32-bits)
3582 //
3583 // |array_tag| | header_size | element_type | |log2_element_size|
3584 // 32 30 24 16 8 2 0
3585 //
3586 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3587 //
3588
3589 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3590
3591 // Handle objArrays completely differently...
3592 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3593 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3594 __ jcc(Assembler::equal, L_objArray);
3595
3596 // if (src->klass() != dst->klass()) return -1;
3597 __ load_klass(rax, dst, rklass_tmp);
3598 __ cmpq(r10_src_klass, rax);
3599 __ jcc(Assembler::notEqual, L_failed);
3600
3601 // Check for flat inline type array -> return -1
3602 __ test_flat_array_oop(src, rax, L_failed);
3603
3604 // Check for null-free (non-flat) inline type array -> handle as object array
3605 __ test_null_free_array_oop(src, rax, L_objArray);
3606
3607 const Register rax_lh = rax; // layout helper
3608 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3609
3610 // Check for flat inline type array -> return -1
3611 __ testl(rax_lh, Klass::_lh_array_tag_flat_value_bit_inplace);
3612 __ jcc(Assembler::notZero, L_failed);
3613
3614 // if (!src->is_Array()) return -1;
3615 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3616 __ jcc(Assembler::greaterEqual, L_failed);
3617
3618 // At this point, it is known to be a typeArray (array_tag 0x3).
3619 #ifdef ASSERT
3620 {
3621 BLOCK_COMMENT("assert primitive array {");
3622 Label L;
3623 __ movl(rklass_tmp, rax_lh);
3624 __ sarl(rklass_tmp, Klass::_lh_array_tag_shift);
3625 __ cmpl(rklass_tmp, Klass::_lh_array_tag_type_value);
3626 __ jcc(Assembler::equal, L);
3627 __ stop("must be a primitive array");
3628 __ bind(L);
3629 BLOCK_COMMENT("} assert primitive array done");
3630 }
3631 #endif
3632
3633 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3634 r10, L_failed);
3635
3636 // TypeArrayKlass
3637 //
3638 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3639 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3640 //
3641
3642 const Register r10_offset = r10; // array offset
3643 const Register rax_elsize = rax_lh; // element size
3644
3645 __ movl(r10_offset, rax_lh);
3646 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3714
3715 // Identically typed arrays can be copied without element-wise checks.
3716 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3717 r10, L_failed);
3718
3719 __ lea(from, Address(src, src_pos, TIMES_OOP,
3720 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3721 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3722 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3723 __ movl2ptr(count, r11_length); // length
3724 __ BIND(L_plain_copy);
3725 #ifdef _WIN64
3726 __ pop_ppx(rklass_tmp); // Restore callee-save rdi
3727 #endif
3728 __ jump(RuntimeAddress(oop_copy_entry));
3729
3730 __ BIND(L_checkcast_copy);
3731 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3732 {
3733 // Before looking at dst.length, make sure dst is also an objArray.
3734 // This check also fails for flat arrays which are not supported.
3735 __ cmpl(Address(rax, lh_offset), objArray_lh);
3736 __ jcc(Assembler::notEqual, L_failed);
3737
3738 #ifdef ASSERT
3739 {
3740 BLOCK_COMMENT("assert not null-free array {");
3741 Label L;
3742 __ test_non_null_free_array_oop(dst, rklass_tmp, L);
3743 __ stop("unexpected null-free array");
3744 __ bind(L);
3745 BLOCK_COMMENT("} assert not null-free array");
3746 }
3747 #endif
3748
3749 // It is safe to examine both src.length and dst.length.
3750 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3751 rax, L_failed);
3752
3753 const Register r11_dst_klass = r11;
3754 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3755
3756 // Marshal the base address arguments now, freeing registers.
3757 __ lea(from, Address(src, src_pos, TIMES_OOP,
3758 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3759 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3760 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3761 __ movl(count, length); // length (reloaded)
3762 Register sco_temp = c_rarg3; // this register is free now
3763 assert_different_registers(from, to, count, sco_temp,
3764 r11_dst_klass, r10_src_klass);
3765 assert_clean_int(count, sco_temp);
3766
3767 // Generate the type check.
3768 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|