src/cpu/x86/vm/stubGenerator_x86_64.cpp

Print this page
rev 146 : [mq]: mixa.layout.patch

*** 1042,1051 **** --- 1042,1052 ---- static address int_copy_entry; static address long_copy_entry; static address oop_copy_entry; static address checkcast_copy_entry; + static address unsafe_copy_entry; // // Verify that a register contains clean 32-bits positive value // (high 32-bits are 0) so it could be used in 64-bits shifts. //
*** 2326,2335 **** --- 2327,2339 ---- StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); __ enter(); // required for proper stackwalking of RuntimeStub frame + checkcast_copy_entry = __ pc(); + BLOCK_COMMENT("Entry:"); + // bump this on entry, not on exit: inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr); __ movq(bits, from); __ orq(bits, to);
*** 2513,2559 **** } #endif // Load layout helper (32-bits) // ! // |array_tag| | header_size | element_type | |log2_element_size| ! // 32 30 24 16 8 2 0 // ! // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 // int lh_offset = klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(); const Register rax_lh = rax; // layout helper __ movl(rax_lh, Address(r10_src_klass, lh_offset)); // Handle objArrays completely differently... ! jint objArray_lh = Klass::array_layout_helper(T_OBJECT); __ cmpl(rax_lh, objArray_lh); __ jcc(Assembler::equal, L_objArray); // if (src->klass() != dst->klass()) return -1; __ load_klass(r9_dst_klass, dst); __ cmpq(r10_src_klass, r9_dst_klass); __ jcc(Assembler::notEqual, L_failed); ! // if (!src->is_Array()) return -1; ! __ cmpl(rax_lh, Klass::_lh_neutral_value); __ jcc(Assembler::greaterEqual, L_failed); - // At this point, it is known to be a typeArray (array_tag 0x3). - #ifdef ASSERT - { Label L; - __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); - __ jcc(Assembler::greaterEqual, L); - __ stop("must be a primitive array"); - __ bind(L); - } - #endif - arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, r10, L_failed); // typeArrayKlass // --- 2517,2556 ---- } #endif // Load layout helper (32-bits) // ! // | array_tag | element_type | log2_element_size | header_size | ! // 32 28 24 16 0 // ! // array_tag: typeArray = 0xF, objArray = 0xD, normal instance = 0x0 // int lh_offset = klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(); const Register rax_lh = rax; // layout helper __ movl(rax_lh, Address(r10_src_klass, lh_offset)); // Handle objArrays completely differently... ! // This is necessary because they have covariant element types. ! // The next type check (for src.klass == dst.klass), can get a ! // false negative in the case of object arrays. ! jint objArray_lh = LayoutHelper::for_array(T_OBJECT).as_int(); __ cmpl(rax_lh, objArray_lh); __ jcc(Assembler::equal, L_objArray); // if (src->klass() != dst->klass()) return -1; __ load_klass(r9_dst_klass, dst); __ cmpq(r10_src_klass, r9_dst_klass); __ jcc(Assembler::notEqual, L_failed); ! // if (!src->has_length_field()) return -1; ! __ cmpl(rax_lh, LayoutHelper::_neutral_value); __ jcc(Assembler::greaterEqual, L_failed); arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, r10, L_failed); // typeArrayKlass //
*** 2563,2578 **** const Register r10_offset = r10; // array offset const Register rax_elsize = rax_lh; // element size __ movl(r10_offset, rax_lh); ! __ shrl(r10_offset, Klass::_lh_header_size_shift); ! __ andq(r10_offset, Klass::_lh_header_size_mask); // array_offset __ addq(src, r10_offset); // src array offset __ addq(dst, r10_offset); // dst array offset BLOCK_COMMENT("choose copy loop based on element size"); ! __ andl(rax_lh, Klass::_lh_log2_element_size_mask); // rax_lh -> rax_elsize // next registers should be set before the jump to corresponding stub const Register from = c_rarg0; // source array address const Register to = c_rarg1; // destination array address const Register count = c_rarg2; // elements count --- 2560,2576 ---- const Register r10_offset = r10; // array offset const Register rax_elsize = rax_lh; // element size __ movl(r10_offset, rax_lh); ! assert(LayoutHelper::_header_size_shift == 0, ""); ! __ andl(r10_offset, LayoutHelper::_header_size_mask); // array_offset __ addq(src, r10_offset); // src array offset __ addq(dst, r10_offset); // dst array offset BLOCK_COMMENT("choose copy loop based on element size"); ! __ shrl(rax_lh, LayoutHelper::_element_size_shift); ! __ andl(rax_lh, LayoutHelper::_element_size_mask); // rax_lh -> rax_elsize // next registers should be set before the jump to corresponding stub const Register from = c_rarg0; // source array address const Register to = c_rarg1; // destination array address const Register count = c_rarg2; // elements count
*** 2616,2634 **** __ leaq(from, Address(src, src_pos, Address::times_8, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr __ movslq(count, r11_length); // length __ jump(RuntimeAddress(long_copy_entry)); // objArrayKlass __ BIND(L_objArray); // live at this point: r10_src_klass, src[_pos], dst[_pos] - Label L_plain_copy, L_checkcast_copy; // test array classes for subtyping __ load_klass(r9_dst_klass, dst); __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality ! __ jcc(Assembler::notEqual, L_checkcast_copy); // Identically typed arrays can be copied without element-wise checks. arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, r10, L_failed); --- 2614,2633 ---- __ leaq(from, Address(src, src_pos, Address::times_8, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr __ movslq(count, r11_length); // length __ jump(RuntimeAddress(long_copy_entry)); + Label L_different_objArray, L_plain_copy, L_checkcast_copy; + // objArrayKlass __ BIND(L_objArray); // live at this point: r10_src_klass, src[_pos], dst[_pos] // test array classes for subtyping __ load_klass(r9_dst_klass, dst); __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality ! __ jcc(Assembler::notEqual, L_different_objArray); // Identically typed arrays can be copied without element-wise checks. arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, r10, L_failed);
*** 2638,2648 **** arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr __ movslq(count, r11_length); // length __ BIND(L_plain_copy); __ jump(RuntimeAddress(oop_copy_entry)); ! __ BIND(L_checkcast_copy); // live at this point: r10_src_klass, !r11_length { // assert(r11_length == C_RARG4); // will reload from here Register r11_dst_klass = r11; __ load_klass(r11_dst_klass, dst); --- 2637,2647 ---- arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr __ movslq(count, r11_length); // length __ BIND(L_plain_copy); __ jump(RuntimeAddress(oop_copy_entry)); ! __ BIND(L_different_objArray); // live at this point: r10_src_klass, !r11_length { // assert(r11_length == C_RARG4); // will reload from here Register r11_dst_klass = r11; __ load_klass(r11_dst_klass, dst);