2641 // Load layout helper (32-bits)
2642 //
2643 // |array_tag| | header_size | element_type | |log2_element_size|
2644 // 32 30 24 16 8 2 0
2645 //
2646 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2647 //
2648
2649 const int lh_offset = in_bytes(Klass::layout_helper_offset());
2650
2651 // Handle objArrays completely differently...
2652 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2653 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
2654 __ jcc(Assembler::equal, L_objArray);
2655
2656 // if (src->klass() != dst->klass()) return -1;
2657 __ load_klass(rax, dst, rklass_tmp);
2658 __ cmpq(r10_src_klass, rax);
2659 __ jcc(Assembler::notEqual, L_failed);
2660
2661 const Register rax_lh = rax; // layout helper
2662 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
2663
2664 // if (!src->is_Array()) return -1;
2665 __ cmpl(rax_lh, Klass::_lh_neutral_value);
2666 __ jcc(Assembler::greaterEqual, L_failed);
2667
2668 // At this point, it is known to be a typeArray (array_tag 0x3).
2669 #ifdef ASSERT
2670 {
2671 BLOCK_COMMENT("assert primitive array {");
2672 Label L;
2673 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
2674 __ jcc(Assembler::greaterEqual, L);
2675 __ stop("must be a primitive array");
2676 __ bind(L);
2677 BLOCK_COMMENT("} assert primitive array done");
2678 }
2679 #endif
2680
2681 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2682 r10, L_failed);
2683
2684 // TypeArrayKlass
2685 //
2686 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2687 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2688 //
2689
2690 const Register r10_offset = r10; // array offset
2691 const Register rax_elsize = rax_lh; // element size
2692
2693 __ movl(r10_offset, rax_lh);
2694 __ shrl(r10_offset, Klass::_lh_header_size_shift);
2762
2763 // Identically typed arrays can be copied without element-wise checks.
2764 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2765 r10, L_failed);
2766
2767 __ lea(from, Address(src, src_pos, TIMES_OOP,
2768 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
2769 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2770 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
2771 __ movl2ptr(count, r11_length); // length
2772 __ BIND(L_plain_copy);
2773 #ifdef _WIN64
2774 __ pop(rklass_tmp); // Restore callee-save rdi
2775 #endif
2776 __ jump(RuntimeAddress(oop_copy_entry));
2777
2778 __ BIND(L_checkcast_copy);
2779 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
2780 {
2781 // Before looking at dst.length, make sure dst is also an objArray.
2782 __ cmpl(Address(rax, lh_offset), objArray_lh);
2783 __ jcc(Assembler::notEqual, L_failed);
2784
2785 // It is safe to examine both src.length and dst.length.
2786 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2787 rax, L_failed);
2788
2789 const Register r11_dst_klass = r11;
2790 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
2791
2792 // Marshal the base address arguments now, freeing registers.
2793 __ lea(from, Address(src, src_pos, TIMES_OOP,
2794 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2795 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2796 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2797 __ movl(count, length); // length (reloaded)
2798 Register sco_temp = c_rarg3; // this register is free now
2799 assert_different_registers(from, to, count, sco_temp,
2800 r11_dst_klass, r10_src_klass);
2801 assert_clean_int(count, sco_temp);
2802
2803 // Generate the type check.
2804 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|
2641 // Load layout helper (32-bits)
2642 //
2643 // |array_tag| | header_size | element_type | |log2_element_size|
2644 // 32 30 24 16 8 2 0
2645 //
2646 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2647 //
2648
2649 const int lh_offset = in_bytes(Klass::layout_helper_offset());
2650
2651 // Handle objArrays completely differently...
2652 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2653 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
2654 __ jcc(Assembler::equal, L_objArray);
2655
2656 // if (src->klass() != dst->klass()) return -1;
2657 __ load_klass(rax, dst, rklass_tmp);
2658 __ cmpq(r10_src_klass, rax);
2659 __ jcc(Assembler::notEqual, L_failed);
2660
2661 // Check for flat inline type array -> return -1
2662 __ test_flat_array_oop(src, rax, L_failed);
2663
2664 // Check for null-free (non-flat) inline type array -> handle as object array
2665 __ test_null_free_array_oop(src, rax, L_objArray);
2666
2667 const Register rax_lh = rax; // layout helper
2668 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
2669
2670 // Check for flat inline type array -> return -1
2671 __ testl(rax_lh, Klass::_lh_array_tag_flat_value_bit_inplace);
2672 __ jcc(Assembler::notZero, L_failed);
2673
2674 // if (!src->is_Array()) return -1;
2675 __ cmpl(rax_lh, Klass::_lh_neutral_value);
2676 __ jcc(Assembler::greaterEqual, L_failed);
2677
2678 // At this point, it is known to be a typeArray (array_tag 0x3).
2679 #ifdef ASSERT
2680 {
2681 BLOCK_COMMENT("assert primitive array {");
2682 Label L;
2683 __ movl(rklass_tmp, rax_lh);
2684 __ sarl(rklass_tmp, Klass::_lh_array_tag_shift);
2685 __ cmpl(rklass_tmp, Klass::_lh_array_tag_type_value);
2686 __ jcc(Assembler::equal, L);
2687 __ stop("must be a primitive array");
2688 __ bind(L);
2689 BLOCK_COMMENT("} assert primitive array done");
2690 }
2691 #endif
2692
2693 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2694 r10, L_failed);
2695
2696 // TypeArrayKlass
2697 //
2698 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2699 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2700 //
2701
2702 const Register r10_offset = r10; // array offset
2703 const Register rax_elsize = rax_lh; // element size
2704
2705 __ movl(r10_offset, rax_lh);
2706 __ shrl(r10_offset, Klass::_lh_header_size_shift);
2774
2775 // Identically typed arrays can be copied without element-wise checks.
2776 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2777 r10, L_failed);
2778
2779 __ lea(from, Address(src, src_pos, TIMES_OOP,
2780 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
2781 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2782 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
2783 __ movl2ptr(count, r11_length); // length
2784 __ BIND(L_plain_copy);
2785 #ifdef _WIN64
2786 __ pop(rklass_tmp); // Restore callee-save rdi
2787 #endif
2788 __ jump(RuntimeAddress(oop_copy_entry));
2789
2790 __ BIND(L_checkcast_copy);
2791 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
2792 {
2793 // Before looking at dst.length, make sure dst is also an objArray.
2794 // This check also fails for flat arrays which are not supported.
2795 __ cmpl(Address(rax, lh_offset), objArray_lh);
2796 __ jcc(Assembler::notEqual, L_failed);
2797
2798 #ifdef ASSERT
2799 {
2800 BLOCK_COMMENT("assert not null-free array {");
2801 Label L;
2802 __ test_non_null_free_array_oop(dst, rklass_tmp, L);
2803 __ stop("unexpected null-free array");
2804 __ bind(L);
2805 BLOCK_COMMENT("} assert not null-free array");
2806 }
2807 #endif
2808
2809 // It is safe to examine both src.length and dst.length.
2810 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2811 rax, L_failed);
2812
2813 const Register r11_dst_klass = r11;
2814 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
2815
2816 // Marshal the base address arguments now, freeing registers.
2817 __ lea(from, Address(src, src_pos, TIMES_OOP,
2818 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2819 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2820 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2821 __ movl(count, length); // length (reloaded)
2822 Register sco_temp = c_rarg3; // this register is free now
2823 assert_different_registers(from, to, count, sco_temp,
2824 r11_dst_klass, r10_src_klass);
2825 assert_clean_int(count, sco_temp);
2826
2827 // Generate the type check.
2828 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|