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);