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