3064 // Load layout helper (32-bits)
3065 //
3066 // |array_tag| | header_size | element_type | |log2_element_size|
3067 // 32 30 24 16 8 2 0
3068 //
3069 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3070 //
3071
3072 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3073
3074 // Handle objArrays completely differently...
3075 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3076 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3077 __ jcc(Assembler::equal, L_objArray);
3078
3079 // if (src->klass() != dst->klass()) return -1;
3080 __ load_klass(rax, dst, rklass_tmp);
3081 __ cmpq(r10_src_klass, rax);
3082 __ jcc(Assembler::notEqual, L_failed);
3083
3084 const Register rax_lh = rax; // layout helper
3085 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3086
3087 // if (!src->is_Array()) return -1;
3088 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3089 __ jcc(Assembler::greaterEqual, L_failed);
3090
3091 // At this point, it is known to be a typeArray (array_tag 0x3).
3092 #ifdef ASSERT
3093 {
3094 BLOCK_COMMENT("assert primitive array {");
3095 Label L;
3096 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
3097 __ jcc(Assembler::greaterEqual, L);
3098 __ stop("must be a primitive array");
3099 __ bind(L);
3100 BLOCK_COMMENT("} assert primitive array done");
3101 }
3102 #endif
3103
3104 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3105 r10, L_failed);
3106
3107 // TypeArrayKlass
3108 //
3109 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3110 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3111 //
3112
3113 const Register r10_offset = r10; // array offset
3114 const Register rax_elsize = rax_lh; // element size
3115
3116 __ movl(r10_offset, rax_lh);
3117 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3185
3186 // Identically typed arrays can be copied without element-wise checks.
3187 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3188 r10, L_failed);
3189
3190 __ lea(from, Address(src, src_pos, TIMES_OOP,
3191 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3192 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3193 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3194 __ movl2ptr(count, r11_length); // length
3195 __ BIND(L_plain_copy);
3196 #ifdef _WIN64
3197 __ pop_ppx(rklass_tmp); // Restore callee-save rdi
3198 #endif
3199 __ jump(RuntimeAddress(oop_copy_entry));
3200
3201 __ BIND(L_checkcast_copy);
3202 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3203 {
3204 // Before looking at dst.length, make sure dst is also an objArray.
3205 __ cmpl(Address(rax, lh_offset), objArray_lh);
3206 __ jcc(Assembler::notEqual, L_failed);
3207
3208 // It is safe to examine both src.length and dst.length.
3209 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3210 rax, L_failed);
3211
3212 const Register r11_dst_klass = r11;
3213 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3214
3215 // Marshal the base address arguments now, freeing registers.
3216 __ lea(from, Address(src, src_pos, TIMES_OOP,
3217 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3218 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3219 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3220 __ movl(count, length); // length (reloaded)
3221 Register sco_temp = c_rarg3; // this register is free now
3222 assert_different_registers(from, to, count, sco_temp,
3223 r11_dst_klass, r10_src_klass);
3224 assert_clean_int(count, sco_temp);
3225
3226 // Generate the type check.
3227 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|
3064 // Load layout helper (32-bits)
3065 //
3066 // |array_tag| | header_size | element_type | |log2_element_size|
3067 // 32 30 24 16 8 2 0
3068 //
3069 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3070 //
3071
3072 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3073
3074 // Handle objArrays completely differently...
3075 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3076 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3077 __ jcc(Assembler::equal, L_objArray);
3078
3079 // if (src->klass() != dst->klass()) return -1;
3080 __ load_klass(rax, dst, rklass_tmp);
3081 __ cmpq(r10_src_klass, rax);
3082 __ jcc(Assembler::notEqual, L_failed);
3083
3084 // Check for flat inline type array -> return -1
3085 __ test_flat_array_oop(src, rax, L_failed);
3086
3087 // Check for null-free (non-flat) inline type array -> handle as object array
3088 __ test_null_free_array_oop(src, rax, L_objArray);
3089
3090 const Register rax_lh = rax; // layout helper
3091 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3092
3093 // Check for flat inline type array -> return -1
3094 __ testl(rax_lh, Klass::_lh_array_tag_flat_value_bit_inplace);
3095 __ jcc(Assembler::notZero, L_failed);
3096
3097 // if (!src->is_Array()) return -1;
3098 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3099 __ jcc(Assembler::greaterEqual, L_failed);
3100
3101 // At this point, it is known to be a typeArray (array_tag 0x3).
3102 #ifdef ASSERT
3103 {
3104 BLOCK_COMMENT("assert primitive array {");
3105 Label L;
3106 __ movl(rklass_tmp, rax_lh);
3107 __ sarl(rklass_tmp, Klass::_lh_array_tag_shift);
3108 __ cmpl(rklass_tmp, Klass::_lh_array_tag_type_value);
3109 __ jcc(Assembler::equal, L);
3110 __ stop("must be a primitive array");
3111 __ bind(L);
3112 BLOCK_COMMENT("} assert primitive array done");
3113 }
3114 #endif
3115
3116 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3117 r10, L_failed);
3118
3119 // TypeArrayKlass
3120 //
3121 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3122 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3123 //
3124
3125 const Register r10_offset = r10; // array offset
3126 const Register rax_elsize = rax_lh; // element size
3127
3128 __ movl(r10_offset, rax_lh);
3129 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3197
3198 // Identically typed arrays can be copied without element-wise checks.
3199 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3200 r10, L_failed);
3201
3202 __ lea(from, Address(src, src_pos, TIMES_OOP,
3203 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3204 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3205 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3206 __ movl2ptr(count, r11_length); // length
3207 __ BIND(L_plain_copy);
3208 #ifdef _WIN64
3209 __ pop_ppx(rklass_tmp); // Restore callee-save rdi
3210 #endif
3211 __ jump(RuntimeAddress(oop_copy_entry));
3212
3213 __ BIND(L_checkcast_copy);
3214 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3215 {
3216 // Before looking at dst.length, make sure dst is also an objArray.
3217 // This check also fails for flat arrays which are not supported.
3218 __ cmpl(Address(rax, lh_offset), objArray_lh);
3219 __ jcc(Assembler::notEqual, L_failed);
3220
3221 #ifdef ASSERT
3222 {
3223 BLOCK_COMMENT("assert not null-free array {");
3224 Label L;
3225 __ test_non_null_free_array_oop(dst, rklass_tmp, L);
3226 __ stop("unexpected null-free array");
3227 __ bind(L);
3228 BLOCK_COMMENT("} assert not null-free array");
3229 }
3230 #endif
3231
3232 // It is safe to examine both src.length and dst.length.
3233 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3234 rax, L_failed);
3235
3236 const Register r11_dst_klass = r11;
3237 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3238
3239 // Marshal the base address arguments now, freeing registers.
3240 __ lea(from, Address(src, src_pos, TIMES_OOP,
3241 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3242 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3243 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3244 __ movl(count, length); // length (reloaded)
3245 Register sco_temp = c_rarg3; // this register is free now
3246 assert_different_registers(from, to, count, sco_temp,
3247 r11_dst_klass, r10_src_klass);
3248 assert_clean_int(count, sco_temp);
3249
3250 // Generate the type check.
3251 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|