src/cpu/x86/vm/stubGenerator_x86_64.cpp

Print this page
rev 4534 : 8010927: Kitchensink crashed with SIGSEGV, Problematic frame: v ~StubRoutines::checkcast_arraycopy
Summary: Changed gen_write_ref_array_post_barrier() code on x64 to pass start address and number of copied oop elements. In generate_checkcast_copy() skip post barrier code if no elements are copied.
Reviewed-by: roland

*** 1243,1273 **** // // Generate code for an array write post barrier // // Input: // start - register containing starting address of destination array ! // end - register containing ending address of destination array // scratch - scratch register // // The input registers are overwritten. ! // The ending address is inclusive. ! void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch) { ! assert_different_registers(start, end, scratch); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: - { __ pusha(); // push registers (overkill) ! // must compute element count unless barrier set interface is changed (other platforms supply count) ! assert_different_registers(start, end, scratch); ! __ lea(scratch, Address(end, BytesPerHeapOop)); ! __ subptr(scratch, start); // subtract start to get #bytes ! __ shrptr(scratch, LogBytesPerHeapOop); // convert to element count __ mov(c_rarg0, start); ! __ mov(c_rarg1, scratch); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); __ popa(); } break; case BarrierSet::CardTableModRef: --- 1243,1274 ---- // // Generate code for an array write post barrier // // Input: // start - register containing starting address of destination array ! // count - elements count // scratch - scratch register // // The input registers are overwritten. ! // ! void gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) { ! assert_different_registers(start, count, scratch); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { __ pusha(); // push registers (overkill) ! if (c_rarg0 == count) { // On win64 c_rarg0 == rcx ! assert_different_registers(c_rarg1, start); ! __ mov(c_rarg1, count); __ mov(c_rarg0, start); ! } else { ! assert_different_registers(c_rarg0, count); ! __ mov(c_rarg0, start); ! __ mov(c_rarg1, count); ! } __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); __ popa(); } break; case BarrierSet::CardTableModRef:
*** 1275,1300 **** { CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); Label L_loop; __ shrptr(start, CardTableModRefBS::card_shift); - __ addptr(end, BytesPerHeapOop); __ shrptr(end, CardTableModRefBS::card_shift); ! __ subptr(end, start); // number of bytes to copy ! intptr_t disp = (intptr_t) ct->byte_map_base; ! if (Assembler::is_simm32(disp)) { ! Address cardtable(noreg, noreg, Address::no_scale, disp); ! __ lea(scratch, cardtable); ! } else { ! ExternalAddress cardtable((address)disp); ! __ lea(scratch, cardtable); ! } ! ! const Register count = end; // 'end' register contains bytes count now __ addptr(start, scratch); __ BIND(L_loop); __ movb(Address(start, count, Address::times_1), 0); __ decrement(count); __ jcc(Assembler::greaterEqual, L_loop); --- 1276,1295 ---- { CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); Label L_loop; + const Register end = count; + __ leaq(end, Address(start, count, TIMES_OOP, 0)); // end == start+count*oop_size + __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive __ shrptr(start, CardTableModRefBS::card_shift); __ shrptr(end, CardTableModRefBS::card_shift); ! __ subptr(end, start); // end --> cards count ! int64_t disp = (int64_t) ct->byte_map_base; ! __ mov64(scratch, disp); __ addptr(start, scratch); __ BIND(L_loop); __ movb(Address(start, count, Address::times_1), 0); __ decrement(count); __ jcc(Assembler::greaterEqual, L_loop);
*** 1942,1953 **** __ movl(rax, Address(end_from, 8)); __ movl(Address(end_to, 8), rax); __ BIND(L_exit); if (is_oop) { ! __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4)); ! gen_write_ref_array_post_barrier(saved_to, end_to, rax); } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame --- 1937,1947 ---- __ movl(rax, Address(end_from, 8)); __ movl(Address(end_to, 8), rax); __ BIND(L_exit); if (is_oop) { ! gen_write_ref_array_post_barrier(saved_to, dword_count, rax); } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame
*** 2038,2052 **** __ ret(0); // Copy in multi-bytes chunks copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); ! __ bind(L_exit); if (is_oop) { ! Register end_to = rdx; ! __ leaq(end_to, Address(to, dword_count, Address::times_4, -4)); ! gen_write_ref_array_post_barrier(to, end_to, rax); } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame --- 2032,2044 ---- __ ret(0); // Copy in multi-bytes chunks copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); ! __ BIND(L_exit); if (is_oop) { ! gen_write_ref_array_post_barrier(to, dword_count, rax); } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame
*** 2081,2090 **** --- 2073,2083 ---- const Register to = rsi; // destination array address const Register qword_count = rdx; // elements count const Register end_from = from; // source array end address const Register end_to = rcx; // destination array end address const Register saved_to = to; + const Register saved_count = r11; // End pointers are inclusive, and if count is not zero they point // to the last unit copied: end_to[0] := end_from[0] __ enter(); // required for proper stackwalking of RuntimeStub frame // Save no-overlap entry point for generate_conjoint_long_oop_copy()
*** 2098,2107 **** --- 2091,2102 ---- setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers // 'from', 'to' and 'qword_count' are now valid if (is_oop) { + // Save to and count for store barrier + __ movptr(saved_count, qword_count); // no registers are destroyed by this call gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized); } // Copy from low to high addresses. Use 'to' as scratch.
*** 2130,2140 **** // Copy in multi-bytes chunks copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); if (is_oop) { __ BIND(L_exit); ! gen_write_ref_array_post_barrier(saved_to, end_to, rax); } restore_arg_regs(); if (is_oop) { inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free } else { --- 2125,2135 ---- // Copy in multi-bytes chunks copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); if (is_oop) { __ BIND(L_exit); ! gen_write_ref_array_post_barrier(saved_to, saved_count, rax); } restore_arg_regs(); if (is_oop) { inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free } else {
*** 2213,2224 **** // Copy in multi-bytes chunks copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); if (is_oop) { __ BIND(L_exit); ! __ lea(rcx, Address(to, saved_count, Address::times_8, -8)); ! gen_write_ref_array_post_barrier(to, rcx, rax); } restore_arg_regs(); if (is_oop) { inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free } else { --- 2208,2218 ---- // Copy in multi-bytes chunks copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); if (is_oop) { __ BIND(L_exit); ! gen_write_ref_array_post_barrier(to, saved_count, rax); } restore_arg_regs(); if (is_oop) { inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free } else {
*** 2401,2425 **** // It was a real error; we must depend on the caller to finish the job. // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops. // Emit GC store barriers for the oops we have copied (r14 + rdx), // and report their number to the caller. ! assert_different_registers(rax, r14_length, count, to, end_to, rcx); ! __ lea(end_to, to_element_addr); ! __ addptr(end_to, -heapOopSize); // make an inclusive end pointer ! gen_write_ref_array_post_barrier(to, end_to, rscratch1); ! __ movptr(rax, r14_length); // original oops ! __ addptr(rax, count); // K = (original - remaining) oops ! __ notptr(rax); // report (-1^K) to caller ! __ jmp(L_done); // Come here on success only. __ BIND(L_do_card_marks); - __ addptr(end_to, -heapOopSize); // make an inclusive end pointer - gen_write_ref_array_post_barrier(to, end_to, rscratch1); __ xorptr(rax, rax); // return 0 on success // Common exit point (success or failure). __ BIND(L_done); __ movptr(r13, Address(rsp, saved_r13_offset * wordSize)); __ movptr(r14, Address(rsp, saved_r14_offset * wordSize)); restore_arg_regs(); --- 2395,2419 ---- // It was a real error; we must depend on the caller to finish the job. // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops. // Emit GC store barriers for the oops we have copied (r14 + rdx), // and report their number to the caller. ! assert_different_registers(rax, r14_length, count, to, end_to, rcx, rscratch1); ! Label L_post_barrier; ! __ addptr(r14_length, count); // K = (original - remaining) oops ! __ movptr(rax, r14_length); // save the value ! __ notptr(rax); // report (-1^K) to caller (does not affect flags) ! __ jccb(Assembler::notZero, L_post_barrier); ! __ jmp(L_done); // K == 0, nothing was copied, skip post barrier // Come here on success only. __ BIND(L_do_card_marks); __ xorptr(rax, rax); // return 0 on success + __ BIND(L_post_barrier); + gen_write_ref_array_post_barrier(to, r14_length, rscratch1); + // Common exit point (success or failure). __ BIND(L_done); __ movptr(r13, Address(rsp, saved_r13_offset * wordSize)); __ movptr(r14, Address(rsp, saved_r14_offset * wordSize)); restore_arg_regs();