src/cpu/x86/vm/stubGenerator_x86_32.cpp

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

*** 1462,1471 **** --- 1462,1472 ---- // // Examines the alignment of the operands and dispatches // to a long, int, short, or byte copy loop. // address generate_unsafe_copy(const char *name, + address* entry, address byte_copy_entry, address short_copy_entry, address int_copy_entry, address long_copy_entry) {
*** 1492,1501 **** --- 1493,1505 ---- __ movl(count, count_arg); // bump this on entry, not on exit: inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr); + *entry = __ pc(); // Entry point from generic arraycopy stub. + BLOCK_COMMENT("Entry:"); + const Register bits = rsi; __ movl(bits, from); __ orl(bits, to); __ orl(bits, count);
*** 1573,1582 **** --- 1577,1587 ---- address entry_jbyte_arraycopy, address entry_jshort_arraycopy, address entry_jint_arraycopy, address entry_oop_arraycopy, address entry_jlong_arraycopy, + address entry_unsafe_arraycopy, address entry_checkcast_arraycopy) { Label L_failed, L_failed_0, L_objArray; { int modulus = CodeEntryAlignment; int target = modulus - 5; // 5 = sizeof jmp(L_failed)
*** 1674,1720 **** } #endif //ASSERT // 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(); Address src_klass_lh_addr(rcx_src_klass, lh_offset); // Handle objArrays completely differently... ! jint objArray_lh = Klass::array_layout_helper(T_OBJECT); __ cmpl(src_klass_lh_addr, objArray_lh); __ jcc(Assembler::equal, L_objArray); // if (src->klass() != dst->klass()) return -1; __ cmpl(rcx_src_klass, dst_klass_addr); ! __ jccb(Assembler::notEqual, L_failed_0); const Register rcx_lh = rcx; // layout helper assert(rcx_lh == rcx_src_klass, "known alias"); __ movl(rcx_lh, src_klass_lh_addr); ! // if (!src->is_Array()) return -1; ! __ cmpl(rcx_lh, Klass::_lh_neutral_value); __ jcc(Assembler::greaterEqual, L_failed_0); // signed cmp - // At this point, it is known to be a typeArray (array_tag 0x3). - #ifdef ASSERT - { Label L; - __ cmpl(rcx_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); - __ jcc(Assembler::greaterEqual, L); // signed cmp - __ stop("must be a primitive array"); - __ bind(L); - } - #endif - assert_different_registers(src, src_pos, dst, dst_pos, rcx_lh); arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed); // typeArrayKlass // --- 1679,1718 ---- } #endif //ASSERT // 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(); Address src_klass_lh_addr(rcx_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(src_klass_lh_addr, objArray_lh); __ jcc(Assembler::equal, L_objArray); // if (src->klass() != dst->klass()) return -1; __ cmpl(rcx_src_klass, dst_klass_addr); ! __ jcc(Assembler::notEqual, L_failed_0); const Register rcx_lh = rcx; // layout helper assert(rcx_lh == rcx_src_klass, "known alias"); __ movl(rcx_lh, src_klass_lh_addr); ! // if (!src->has_length_field()) return -1; ! __ cmpl(rcx_lh, LayoutHelper::_neutral_value); __ jcc(Assembler::greaterEqual, L_failed_0); // signed cmp assert_different_registers(src, src_pos, dst, dst_pos, rcx_lh); arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed); // typeArrayKlass //
*** 1725,1739 **** const Register src_array = src; // src array offset const Register dst_array = dst; // dst array offset const Register rdi_elsize = rdi; // log2 element size __ movl(rsi_offset, rcx_lh); ! __ shrl(rsi_offset, Klass::_lh_header_size_shift); ! __ andl(rsi_offset, Klass::_lh_header_size_mask); // array_offset __ addl(src_array, rsi_offset); // src array offset __ addl(dst_array, rsi_offset); // dst array offset ! __ andl(rcx_lh, Klass::_lh_log2_element_size_mask); // log2 elsize // next registers should be set before the jump to corresponding stub const Register from = src; // source array address const Register to = dst; // destination array address const Register count = rcx; // elements count --- 1723,1738 ---- const Register src_array = src; // src array offset const Register dst_array = dst; // dst array offset const Register rdi_elsize = rdi; // log2 element size __ movl(rsi_offset, rcx_lh); ! assert(LayoutHelper::_header_size_shift == 0, ""); ! __ andl(rsi_offset, LayoutHelper::_header_size_mask); // array_offset __ addl(src_array, rsi_offset); // src array offset __ addl(dst_array, rsi_offset); // dst array offset ! __ shrl(rcx_lh, LayoutHelper::_element_size_shift); ! __ andl(rcx_lh, LayoutHelper::_element_size_mask); // log2 elsize // next registers should be set before the jump to corresponding stub const Register from = src; // source array address const Register to = dst; // destination array address const Register count = rcx; // elements count
*** 1745,1760 **** BLOCK_COMMENT("scale indexes to element size"); __ movl(rsi, SRC_POS); // src_pos __ shll(rsi); // src_pos << rcx (log2 elsize) assert(src_array == from, ""); __ addl(from, rsi); // from = src_array + SRC_POS << log2 elsize ! __ movl(rdi, DST_POS); // dst_pos ! __ shll(rdi); // dst_pos << rcx (log2 elsize) assert(dst_array == to, ""); ! __ addl(to, rdi); // to = dst_array + DST_POS << log2 elsize __ movl(FROM, from); // src_addr - __ movl(rdi_elsize, rcx_lh); // log2 elsize __ movl(count, LENGTH); // elements count BLOCK_COMMENT("choose copy loop based on element size"); __ cmpl(rdi_elsize, 0); --- 1744,1758 ---- BLOCK_COMMENT("scale indexes to element size"); __ movl(rsi, SRC_POS); // src_pos __ shll(rsi); // src_pos << rcx (log2 elsize) assert(src_array == from, ""); __ addl(from, rsi); // from = src_array + SRC_POS << log2 elsize ! __ movl(rsi, DST_POS); // dst_pos (reuse rsi for a temp) ! __ shll(rsi); // dst_pos << rcx (log2 elsize) assert(dst_array == to, ""); ! __ addl(to, rsi); // to = dst_array + DST_POS << log2 elsize __ movl(FROM, from); // src_addr __ movl(count, LENGTH); // elements count BLOCK_COMMENT("choose copy loop based on element size"); __ cmpl(rdi_elsize, 0);
*** 1777,1794 **** __ popl(rdi); __ popl(rsi); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); // objArrayKlass __ BIND(L_objArray); // live at this point: rcx_src_klass, src[_pos], dst[_pos] - Label L_plain_copy, L_checkcast_copy; // test array classes for subtyping __ cmpl(rcx_src_klass, dst_klass_addr); // usual case is exact equality ! __ jccb(Assembler::notEqual, L_checkcast_copy); // Identically typed arrays can be copied without element-wise checks. assert_different_registers(src, src_pos, dst, dst_pos, rcx_src_klass); arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed); --- 1775,1793 ---- __ popl(rdi); __ popl(rsi); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); + Label L_different_objArray, L_plain_copy, L_checkcast_copy; + // objArrayKlass __ BIND(L_objArray); // live at this point: rcx_src_klass, src[_pos], dst[_pos] // test array classes for subtyping __ cmpl(rcx_src_klass, dst_klass_addr); // usual case is exact equality ! __ jccb(Assembler::notEqual, L_different_objArray); // Identically typed arrays can be copied without element-wise checks. assert_different_registers(src, src_pos, dst, dst_pos, rcx_src_klass); arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed);
*** 1803,1813 **** __ movl(FROM, from); // src_addr __ movl(TO, to); // dst_addr __ movl(COUNT, count); // count __ jump(RuntimeAddress(entry_oop_arraycopy)); ! __ BIND(L_checkcast_copy); // live at this point: rcx_src_klass, dst[_pos], src[_pos] { // Handy offsets: int ek_offset = (klassOopDesc::header_size() * HeapWordSize + objArrayKlass::element_klass_offset_in_bytes()); --- 1802,1812 ---- __ movl(FROM, from); // src_addr __ movl(TO, to); // dst_addr __ movl(COUNT, count); // count __ jump(RuntimeAddress(entry_oop_arraycopy)); ! __ BIND(L_different_objArray); // live at this point: rcx_src_klass, dst[_pos], src[_pos] { // Handy offsets: int ek_offset = (klassOopDesc::header_size() * HeapWordSize + objArrayKlass::element_klass_offset_in_bytes());
*** 1821,1831 **** Address dst_klass_lh_addr(rsi_dst_klass, lh_offset); // Before looking at dst.length, make sure dst is also an objArray. __ movl(rsi_dst_klass, dst_klass_addr); __ cmpl(dst_klass_lh_addr, objArray_lh); ! __ jccb(Assembler::notEqual, L_failed); // It is safe to examine both src.length and dst.length. __ movl(src_pos, SRC_POS); // reload rsi arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed); // (Now src_pos and dst_pos are killed, but not src and dst.) --- 1820,1830 ---- Address dst_klass_lh_addr(rsi_dst_klass, lh_offset); // Before looking at dst.length, make sure dst is also an objArray. __ movl(rsi_dst_klass, dst_klass_addr); __ cmpl(dst_klass_lh_addr, objArray_lh); ! __ jcc(Assembler::notEqual, L_failed); // It is safe to examine both src.length and dst.length. __ movl(src_pos, SRC_POS); // reload rsi arraycopy_range_checks(src, src_pos, dst, dst_pos, LENGTH, L_failed); // (Now src_pos and dst_pos are killed, but not src and dst.)
*** 1895,1904 **** --- 1894,1904 ---- address entry_jbyte_arraycopy; address entry_jshort_arraycopy; address entry_jint_arraycopy; address entry_oop_arraycopy; address entry_jlong_arraycopy; + address entry_unsafe_arraycopy; address entry_checkcast_arraycopy; StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_copy(T_BYTE, true, Address::times_1, &entry, "arrayof_jbyte_disjoint_arraycopy");
*** 1961,1970 **** --- 1961,1971 ---- generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", + &entry_unsafe_arraycopy, entry_jbyte_arraycopy, entry_jshort_arraycopy, entry_jint_arraycopy, entry_jlong_arraycopy);
*** 1973,1982 **** --- 1974,1984 ---- entry_jbyte_arraycopy, entry_jshort_arraycopy, entry_jint_arraycopy, entry_oop_arraycopy, entry_jlong_arraycopy, + entry_unsafe_arraycopy, entry_checkcast_arraycopy); } public: // Information about frame layout at time of blocking runtime call.