2840 // Load layout helper (32-bits)
2841 //
2842 // |array_tag| | header_size | element_type | |log2_element_size|
2843 // 32 30 24 16 8 2 0
2844 //
2845 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2846 //
2847
2848 const int lh_offset = in_bytes(Klass::layout_helper_offset());
2849
2850 // Handle objArrays completely differently...
2851 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2852 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
2853 __ jcc(Assembler::equal, L_objArray);
2854
2855 // if (src->klass() != dst->klass()) return -1;
2856 __ load_klass(rax, dst, rklass_tmp);
2857 __ cmpq(r10_src_klass, rax);
2858 __ jcc(Assembler::notEqual, L_failed);
2859
2860 const Register rax_lh = rax; // layout helper
2861 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
2862
2863 // if (!src->is_Array()) return -1;
2864 __ cmpl(rax_lh, Klass::_lh_neutral_value);
2865 __ jcc(Assembler::greaterEqual, L_failed);
2866
2867 // At this point, it is known to be a typeArray (array_tag 0x3).
2868 #ifdef ASSERT
2869 {
2870 BLOCK_COMMENT("assert primitive array {");
2871 Label L;
2872 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
2873 __ jcc(Assembler::greaterEqual, L);
2874 __ stop("must be a primitive array");
2875 __ bind(L);
2876 BLOCK_COMMENT("} assert primitive array done");
2877 }
2878 #endif
2879
2880 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2881 r10, L_failed);
2882
2883 // TypeArrayKlass
2884 //
2885 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2886 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2887 //
2888
2889 const Register r10_offset = r10; // array offset
2890 const Register rax_elsize = rax_lh; // element size
2891
2892 __ movl(r10_offset, rax_lh);
2893 __ shrl(r10_offset, Klass::_lh_header_size_shift);
2961
2962 // Identically typed arrays can be copied without element-wise checks.
2963 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2964 r10, L_failed);
2965
2966 __ lea(from, Address(src, src_pos, TIMES_OOP,
2967 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
2968 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2969 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
2970 __ movl2ptr(count, r11_length); // length
2971 __ BIND(L_plain_copy);
2972 #ifdef _WIN64
2973 __ pop(rklass_tmp); // Restore callee-save rdi
2974 #endif
2975 __ jump(RuntimeAddress(oop_copy_entry));
2976
2977 __ BIND(L_checkcast_copy);
2978 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
2979 {
2980 // Before looking at dst.length, make sure dst is also an objArray.
2981 __ cmpl(Address(rax, lh_offset), objArray_lh);
2982 __ jcc(Assembler::notEqual, L_failed);
2983
2984 // It is safe to examine both src.length and dst.length.
2985 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2986 rax, L_failed);
2987
2988 const Register r11_dst_klass = r11;
2989 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
2990
2991 // Marshal the base address arguments now, freeing registers.
2992 __ lea(from, Address(src, src_pos, TIMES_OOP,
2993 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2994 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2995 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
2996 __ movl(count, length); // length (reloaded)
2997 Register sco_temp = c_rarg3; // this register is free now
2998 assert_different_registers(from, to, count, sco_temp,
2999 r11_dst_klass, r10_src_klass);
3000 assert_clean_int(count, sco_temp);
3001
3002 // Generate the type check.
3003 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|
2840 // Load layout helper (32-bits)
2841 //
2842 // |array_tag| | header_size | element_type | |log2_element_size|
2843 // 32 30 24 16 8 2 0
2844 //
2845 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
2846 //
2847
2848 const int lh_offset = in_bytes(Klass::layout_helper_offset());
2849
2850 // Handle objArrays completely differently...
2851 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
2852 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
2853 __ jcc(Assembler::equal, L_objArray);
2854
2855 // if (src->klass() != dst->klass()) return -1;
2856 __ load_klass(rax, dst, rklass_tmp);
2857 __ cmpq(r10_src_klass, rax);
2858 __ jcc(Assembler::notEqual, L_failed);
2859
2860 // Check for flat inline type array -> return -1
2861 __ test_flat_array_oop(src, rax, L_failed);
2862
2863 // Check for null-free (non-flat) inline type array -> handle as object array
2864 __ test_null_free_array_oop(src, rax, L_objArray);
2865
2866 const Register rax_lh = rax; // layout helper
2867 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
2868
2869 // Check for flat inline type array -> return -1
2870 __ testl(rax_lh, Klass::_lh_array_tag_flat_value_bit_inplace);
2871 __ jcc(Assembler::notZero, L_failed);
2872
2873 // if (!src->is_Array()) return -1;
2874 __ cmpl(rax_lh, Klass::_lh_neutral_value);
2875 __ jcc(Assembler::greaterEqual, L_failed);
2876
2877 // At this point, it is known to be a typeArray (array_tag 0x3).
2878 #ifdef ASSERT
2879 {
2880 BLOCK_COMMENT("assert primitive array {");
2881 Label L;
2882 __ movl(rklass_tmp, rax_lh);
2883 __ sarl(rklass_tmp, Klass::_lh_array_tag_shift);
2884 __ cmpl(rklass_tmp, Klass::_lh_array_tag_type_value);
2885 __ jcc(Assembler::equal, L);
2886 __ stop("must be a primitive array");
2887 __ bind(L);
2888 BLOCK_COMMENT("} assert primitive array done");
2889 }
2890 #endif
2891
2892 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2893 r10, L_failed);
2894
2895 // TypeArrayKlass
2896 //
2897 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
2898 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
2899 //
2900
2901 const Register r10_offset = r10; // array offset
2902 const Register rax_elsize = rax_lh; // element size
2903
2904 __ movl(r10_offset, rax_lh);
2905 __ shrl(r10_offset, Klass::_lh_header_size_shift);
2973
2974 // Identically typed arrays can be copied without element-wise checks.
2975 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
2976 r10, L_failed);
2977
2978 __ lea(from, Address(src, src_pos, TIMES_OOP,
2979 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
2980 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
2981 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
2982 __ movl2ptr(count, r11_length); // length
2983 __ BIND(L_plain_copy);
2984 #ifdef _WIN64
2985 __ pop(rklass_tmp); // Restore callee-save rdi
2986 #endif
2987 __ jump(RuntimeAddress(oop_copy_entry));
2988
2989 __ BIND(L_checkcast_copy);
2990 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
2991 {
2992 // Before looking at dst.length, make sure dst is also an objArray.
2993 // This check also fails for flat arrays which are not supported.
2994 __ cmpl(Address(rax, lh_offset), objArray_lh);
2995 __ jcc(Assembler::notEqual, L_failed);
2996
2997 #ifdef ASSERT
2998 {
2999 BLOCK_COMMENT("assert not null-free array {");
3000 Label L;
3001 __ test_non_null_free_array_oop(dst, rklass_tmp, L);
3002 __ stop("unexpected null-free array");
3003 __ bind(L);
3004 BLOCK_COMMENT("} assert not null-free array");
3005 }
3006 #endif
3007
3008 // It is safe to examine both src.length and dst.length.
3009 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3010 rax, L_failed);
3011
3012 const Register r11_dst_klass = r11;
3013 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3014
3015 // Marshal the base address arguments now, freeing registers.
3016 __ lea(from, Address(src, src_pos, TIMES_OOP,
3017 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3018 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3019 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3020 __ movl(count, length); // length (reloaded)
3021 Register sco_temp = c_rarg3; // this register is free now
3022 assert_different_registers(from, to, count, sco_temp,
3023 r11_dst_klass, r10_src_klass);
3024 assert_clean_int(count, sco_temp);
3025
3026 // Generate the type check.
3027 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|