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