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.