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