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