src/cpu/x86/vm/stubGenerator_x86_64.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
6998985 Cdiff src/cpu/x86/vm/stubGenerator_x86_64.cpp
src/cpu/x86/vm/stubGenerator_x86_64.cpp
Print this page
*** 2415,2429 ****
// Input registers
const Register src = c_rarg0; // source array oop
const Register src_pos = c_rarg1; // source position
const Register dst = c_rarg2; // destination array oop
const Register dst_pos = c_rarg3; // destination position
! // elements count is on stack on Win64
! #ifdef _WIN64
! #define C_RARG4 Address(rsp, 6 * wordSize)
#else
! #define C_RARG4 c_rarg4
#endif
{ int modulus = CodeEntryAlignment;
int target = modulus - 5; // 5 = sizeof jmp(L_failed)
int advance = target - (__ offset() % modulus);
--- 2415,2428 ----
// Input registers
const Register src = c_rarg0; // source array oop
const Register src_pos = c_rarg1; // source position
const Register dst = c_rarg2; // destination array oop
const Register dst_pos = c_rarg3; // destination position
! #ifndef _WIN64
! const Register length = c_rarg4;
#else
! const Address length(rsp, 6 * wordSize); // elements count is on stack on Win64
#endif
{ int modulus = CodeEntryAlignment;
int target = modulus - 5; // 5 = sizeof jmp(L_failed)
int advance = target - (__ offset() % modulus);
*** 2486,2516 ****
guarantee(((j1off ^ j4off) & ~15) != 0, "I$ line of 1st & 4th jumps");
// registers used as temp
const Register r11_length = r11; // elements count to copy
const Register r10_src_klass = r10; // array klass
- const Register r9_dst_klass = r9; // dest array klass
// if (length < 0) return -1;
! __ movl(r11_length, C_RARG4); // length (elements count, 32-bits value)
__ testl(r11_length, r11_length);
__ jccb(Assembler::negative, L_failed_0);
__ load_klass(r10_src_klass, src);
#ifdef ASSERT
// assert(src->klass() != NULL);
! BLOCK_COMMENT("assert klasses not null");
! { Label L1, L2;
__ testptr(r10_src_klass, r10_src_klass);
__ jcc(Assembler::notZero, L2); // it is broken if klass is NULL
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
! __ load_klass(r9_dst_klass, dst);
! __ cmpq(r9_dst_klass, 0);
__ jcc(Assembler::equal, L1); // this would be broken also
! BLOCK_COMMENT("assert done");
}
#endif
// Load layout helper (32-bits)
//
--- 2485,2515 ----
guarantee(((j1off ^ j4off) & ~15) != 0, "I$ line of 1st & 4th jumps");
// registers used as temp
const Register r11_length = r11; // elements count to copy
const Register r10_src_klass = r10; // array klass
// if (length < 0) return -1;
! __ movl(r11_length, length); // length (elements count, 32-bits value)
__ testl(r11_length, r11_length);
__ jccb(Assembler::negative, L_failed_0);
__ load_klass(r10_src_klass, src);
#ifdef ASSERT
// assert(src->klass() != NULL);
! {
! BLOCK_COMMENT("assert klasses not null {");
! Label L1, L2;
__ testptr(r10_src_klass, r10_src_klass);
__ jcc(Assembler::notZero, L2); // it is broken if klass is NULL
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
! __ load_klass(rax, dst);
! __ cmpq(rax, 0);
__ jcc(Assembler::equal, L1); // this would be broken also
! BLOCK_COMMENT("} assert klasses not null done");
}
#endif
// Load layout helper (32-bits)
//
*** 2518,2555 ****
// 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);
--- 2517,2556 ----
// 32 30 24 16 8 2 0
//
// array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
//
! const int lh_offset = klassOopDesc::header_size() * HeapWordSize +
Klass::layout_helper_offset_in_bytes();
// Handle objArrays completely differently...
! const jint objArray_lh = Klass::array_layout_helper(T_OBJECT);
! __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh);
__ jcc(Assembler::equal, L_objArray);
// if (src->klass() != dst->klass()) return -1;
! __ load_klass(rax, dst);
! __ cmpq(r10_src_klass, rax);
__ jcc(Assembler::notEqual, L_failed);
+ const Register rax_lh = rax; // layout helper
+ __ movl(rax_lh, Address(r10_src_klass, lh_offset));
+
// 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
! {
! BLOCK_COMMENT("assert primitive array {");
! 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);
+ BLOCK_COMMENT("} assert primitive array done");
}
#endif
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
r10, L_failed);
*** 2603,2632 ****
__ movl2ptr(count, r11_length); // length
__ jump(RuntimeAddress(int_copy_entry));
__ BIND(L_copy_longs);
#ifdef ASSERT
! { Label L;
__ cmpl(rax_elsize, LogBytesPerLong);
__ jcc(Assembler::equal, L);
__ stop("must be long copy, but elsize is wrong");
__ bind(L);
}
#endif
__ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr
__ lea(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr
__ movl2ptr(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);
--- 2604,2636 ----
__ movl2ptr(count, r11_length); // length
__ jump(RuntimeAddress(int_copy_entry));
__ BIND(L_copy_longs);
#ifdef ASSERT
! {
! BLOCK_COMMENT("assert long copy {");
! Label L;
__ cmpl(rax_elsize, LogBytesPerLong);
__ jcc(Assembler::equal, L);
__ stop("must be long copy, but elsize is wrong");
__ bind(L);
+ BLOCK_COMMENT("} assert long copy done");
}
#endif
__ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr
__ lea(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr
__ movl2ptr(count, r11_length); // length
__ jump(RuntimeAddress(long_copy_entry));
// objArrayKlass
__ BIND(L_objArray);
! // live at this point: r10_src_klass, r11_length, src[_pos], dst[_pos]
Label L_plain_copy, L_checkcast_copy;
// test array classes for subtyping
! __ load_klass(rax, dst);
! __ cmpq(r10_src_klass, rax); // 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);
*** 2638,2696 ****
__ movl2ptr(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);
-
// Before looking at dst.length, make sure dst is also an objArray.
! __ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh);
__ jcc(Assembler::notEqual, L_failed);
// It is safe to examine both src.length and dst.length.
- #ifndef _WIN64
- arraycopy_range_checks(src, src_pos, dst, dst_pos, C_RARG4,
- rax, L_failed);
- #else
- __ movl(r11_length, C_RARG4); // reload
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
rax, L_failed);
__ load_klass(r11_dst_klass, dst); // reload
- #endif
// Marshal the base address arguments now, freeing registers.
__ lea(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ lea(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
! __ movl(count, C_RARG4); // length (reloaded)
Register sco_temp = c_rarg3; // this register is free now
assert_different_registers(from, to, count, sco_temp,
r11_dst_klass, r10_src_klass);
assert_clean_int(count, sco_temp);
// Generate the type check.
! int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
Klass::super_check_offset_offset_in_bytes());
__ movl(sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy);
// Fetch destination element klass from the objArrayKlass header.
int ek_offset = (klassOopDesc::header_size() * HeapWordSize +
objArrayKlass::element_klass_offset_in_bytes());
__ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset));
! __ movl(sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
// the checkcast_copy loop needs two extra arguments:
assert(c_rarg3 == sco_temp, "#3 already in place");
! __ movptr(C_RARG4, r11_dst_klass); // dst.klass.element_klass
__ jump(RuntimeAddress(checkcast_copy_entry));
}
__ BIND(L_failed);
__ xorptr(rax, rax);
--- 2642,2692 ----
__ movl2ptr(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, rax (dst_klass)
{
// Before looking at dst.length, make sure dst is also an objArray.
! __ cmpl(Address(rax, lh_offset), objArray_lh);
__ jcc(Assembler::notEqual, L_failed);
// It is safe to examine both src.length and dst.length.
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
rax, L_failed);
+
+ const Register r11_dst_klass = r11;
__ load_klass(r11_dst_klass, dst); // reload
// Marshal the base address arguments now, freeing registers.
__ lea(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ lea(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
! __ movl(count, length); // length (reloaded)
Register sco_temp = c_rarg3; // this register is free now
assert_different_registers(from, to, count, sco_temp,
r11_dst_klass, r10_src_klass);
assert_clean_int(count, sco_temp);
// Generate the type check.
! const int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
Klass::super_check_offset_offset_in_bytes());
__ movl(sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy);
// Fetch destination element klass from the objArrayKlass header.
int ek_offset = (klassOopDesc::header_size() * HeapWordSize +
objArrayKlass::element_klass_offset_in_bytes());
__ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset));
! __ movl( sco_temp, Address(r11_dst_klass, sco_offset));
assert_clean_int(sco_temp, rax);
// the checkcast_copy loop needs two extra arguments:
assert(c_rarg3 == sco_temp, "#3 already in place");
! __ movptr(length, r11_dst_klass); // dst.klass.element_klass
__ jump(RuntimeAddress(checkcast_copy_entry));
}
__ BIND(L_failed);
__ xorptr(rax, rax);
src/cpu/x86/vm/stubGenerator_x86_64.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File