3019 // Load layout helper (32-bits)
3020 //
3021 // |array_tag| | header_size | element_type | |log2_element_size|
3022 // 32 30 24 16 8 2 0
3023 //
3024 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3025 //
3026
3027 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3028
3029 // Handle objArrays completely differently...
3030 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3031 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3032 __ jcc(Assembler::equal, L_objArray);
3033
3034 // if (src->klass() != dst->klass()) return -1;
3035 __ load_klass(rax, dst, rklass_tmp);
3036 __ cmpq(r10_src_klass, rax);
3037 __ jcc(Assembler::notEqual, L_failed);
3038
3039 const Register rax_lh = rax; // layout helper
3040 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3041
3042 // if (!src->is_Array()) return -1;
3043 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3044 __ jcc(Assembler::greaterEqual, L_failed);
3045
3046 // At this point, it is known to be a typeArray (array_tag 0x3).
3047 #ifdef ASSERT
3048 {
3049 BLOCK_COMMENT("assert primitive array {");
3050 Label L;
3051 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift));
3052 __ jcc(Assembler::greaterEqual, L);
3053 __ stop("must be a primitive array");
3054 __ bind(L);
3055 BLOCK_COMMENT("} assert primitive array done");
3056 }
3057 #endif
3058
3059 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3060 r10, L_failed);
3061
3062 // TypeArrayKlass
3063 //
3064 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3065 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3066 //
3067
3068 const Register r10_offset = r10; // array offset
3069 const Register rax_elsize = rax_lh; // element size
3070
3071 __ movl(r10_offset, rax_lh);
3072 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3140
3141 // Identically typed arrays can be copied without element-wise checks.
3142 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3143 r10, L_failed);
3144
3145 __ lea(from, Address(src, src_pos, TIMES_OOP,
3146 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3147 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3148 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3149 __ movl2ptr(count, r11_length); // length
3150 __ BIND(L_plain_copy);
3151 #ifdef _WIN64
3152 __ pop(rklass_tmp); // Restore callee-save rdi
3153 #endif
3154 __ jump(RuntimeAddress(oop_copy_entry));
3155
3156 __ BIND(L_checkcast_copy);
3157 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3158 {
3159 // Before looking at dst.length, make sure dst is also an objArray.
3160 __ cmpl(Address(rax, lh_offset), objArray_lh);
3161 __ jcc(Assembler::notEqual, L_failed);
3162
3163 // It is safe to examine both src.length and dst.length.
3164 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3165 rax, L_failed);
3166
3167 const Register r11_dst_klass = r11;
3168 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3169
3170 // Marshal the base address arguments now, freeing registers.
3171 __ lea(from, Address(src, src_pos, TIMES_OOP,
3172 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3173 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3174 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3175 __ movl(count, length); // length (reloaded)
3176 Register sco_temp = c_rarg3; // this register is free now
3177 assert_different_registers(from, to, count, sco_temp,
3178 r11_dst_klass, r10_src_klass);
3179 assert_clean_int(count, sco_temp);
3180
3181 // Generate the type check.
3182 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|
3019 // Load layout helper (32-bits)
3020 //
3021 // |array_tag| | header_size | element_type | |log2_element_size|
3022 // 32 30 24 16 8 2 0
3023 //
3024 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
3025 //
3026
3027 const int lh_offset = in_bytes(Klass::layout_helper_offset());
3028
3029 // Handle objArrays completely differently...
3030 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
3031 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
3032 __ jcc(Assembler::equal, L_objArray);
3033
3034 // if (src->klass() != dst->klass()) return -1;
3035 __ load_klass(rax, dst, rklass_tmp);
3036 __ cmpq(r10_src_klass, rax);
3037 __ jcc(Assembler::notEqual, L_failed);
3038
3039 // Check for flat inline type array -> return -1
3040 __ test_flat_array_oop(src, rax, L_failed);
3041
3042 // Check for null-free (non-flat) inline type array -> handle as object array
3043 __ test_null_free_array_oop(src, rax, L_objArray);
3044
3045 const Register rax_lh = rax; // layout helper
3046 __ movl(rax_lh, Address(r10_src_klass, lh_offset));
3047
3048 // Check for flat inline type array -> return -1
3049 __ testl(rax_lh, Klass::_lh_array_tag_flat_value_bit_inplace);
3050 __ jcc(Assembler::notZero, L_failed);
3051
3052 // if (!src->is_Array()) return -1;
3053 __ cmpl(rax_lh, Klass::_lh_neutral_value);
3054 __ jcc(Assembler::greaterEqual, L_failed);
3055
3056 // At this point, it is known to be a typeArray (array_tag 0x3).
3057 #ifdef ASSERT
3058 {
3059 BLOCK_COMMENT("assert primitive array {");
3060 Label L;
3061 __ movl(rklass_tmp, rax_lh);
3062 __ sarl(rklass_tmp, Klass::_lh_array_tag_shift);
3063 __ cmpl(rklass_tmp, Klass::_lh_array_tag_type_value);
3064 __ jcc(Assembler::equal, L);
3065 __ stop("must be a primitive array");
3066 __ bind(L);
3067 BLOCK_COMMENT("} assert primitive array done");
3068 }
3069 #endif
3070
3071 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3072 r10, L_failed);
3073
3074 // TypeArrayKlass
3075 //
3076 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
3077 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
3078 //
3079
3080 const Register r10_offset = r10; // array offset
3081 const Register rax_elsize = rax_lh; // element size
3082
3083 __ movl(r10_offset, rax_lh);
3084 __ shrl(r10_offset, Klass::_lh_header_size_shift);
3152
3153 // Identically typed arrays can be copied without element-wise checks.
3154 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3155 r10, L_failed);
3156
3157 __ lea(from, Address(src, src_pos, TIMES_OOP,
3158 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
3159 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3160 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
3161 __ movl2ptr(count, r11_length); // length
3162 __ BIND(L_plain_copy);
3163 #ifdef _WIN64
3164 __ pop(rklass_tmp); // Restore callee-save rdi
3165 #endif
3166 __ jump(RuntimeAddress(oop_copy_entry));
3167
3168 __ BIND(L_checkcast_copy);
3169 // live at this point: r10_src_klass, r11_length, rax (dst_klass)
3170 {
3171 // Before looking at dst.length, make sure dst is also an objArray.
3172 // This check also fails for flat arrays which are not supported.
3173 __ cmpl(Address(rax, lh_offset), objArray_lh);
3174 __ jcc(Assembler::notEqual, L_failed);
3175
3176 #ifdef ASSERT
3177 {
3178 BLOCK_COMMENT("assert not null-free array {");
3179 Label L;
3180 __ test_non_null_free_array_oop(dst, rklass_tmp, L);
3181 __ stop("unexpected null-free array");
3182 __ bind(L);
3183 BLOCK_COMMENT("} assert not null-free array");
3184 }
3185 #endif
3186
3187 // It is safe to examine both src.length and dst.length.
3188 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
3189 rax, L_failed);
3190
3191 const Register r11_dst_klass = r11;
3192 __ load_klass(r11_dst_klass, dst, rklass_tmp); // reload
3193
3194 // Marshal the base address arguments now, freeing registers.
3195 __ lea(from, Address(src, src_pos, TIMES_OOP,
3196 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3197 __ lea(to, Address(dst, dst_pos, TIMES_OOP,
3198 arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
3199 __ movl(count, length); // length (reloaded)
3200 Register sco_temp = c_rarg3; // this register is free now
3201 assert_different_registers(from, to, count, sco_temp,
3202 r11_dst_klass, r10_src_klass);
3203 assert_clean_int(count, sco_temp);
3204
3205 // Generate the type check.
3206 const int sco_offset = in_bytes(Klass::super_check_offset_offset());
|