1.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed May 22 17:39:47 2013 -0700 1.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed May 22 18:25:43 2013 -0700 1.3 @@ -1217,27 +1217,28 @@ 1.4 // 1.5 // Input: 1.6 // start - register containing starting address of destination array 1.7 - // end - register containing ending address of destination array 1.8 + // count - elements count 1.9 // scratch - scratch register 1.10 // 1.11 // The input registers are overwritten. 1.12 - // The ending address is inclusive. 1.13 - void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch) { 1.14 - assert_different_registers(start, end, scratch); 1.15 + // 1.16 + void gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) { 1.17 + assert_different_registers(start, count, scratch); 1.18 BarrierSet* bs = Universe::heap()->barrier_set(); 1.19 switch (bs->kind()) { 1.20 case BarrierSet::G1SATBCT: 1.21 case BarrierSet::G1SATBCTLogging: 1.22 - 1.23 { 1.24 - __ pusha(); // push registers (overkill) 1.25 - // must compute element count unless barrier set interface is changed (other platforms supply count) 1.26 - assert_different_registers(start, end, scratch); 1.27 - __ lea(scratch, Address(end, BytesPerHeapOop)); 1.28 - __ subptr(scratch, start); // subtract start to get #bytes 1.29 - __ shrptr(scratch, LogBytesPerHeapOop); // convert to element count 1.30 - __ mov(c_rarg0, start); 1.31 - __ mov(c_rarg1, scratch); 1.32 + __ pusha(); // push registers (overkill) 1.33 + if (c_rarg0 == count) { // On win64 c_rarg0 == rcx 1.34 + assert_different_registers(c_rarg1, start); 1.35 + __ mov(c_rarg1, count); 1.36 + __ mov(c_rarg0, start); 1.37 + } else { 1.38 + assert_different_registers(c_rarg0, count); 1.39 + __ mov(c_rarg0, start); 1.40 + __ mov(c_rarg1, count); 1.41 + } 1.42 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); 1.43 __ popa(); 1.44 } 1.45 @@ -1249,22 +1250,16 @@ 1.46 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); 1.47 1.48 Label L_loop; 1.49 - 1.50 - __ shrptr(start, CardTableModRefBS::card_shift); 1.51 - __ addptr(end, BytesPerHeapOop); 1.52 - __ shrptr(end, CardTableModRefBS::card_shift); 1.53 - __ subptr(end, start); // number of bytes to copy 1.54 - 1.55 - intptr_t disp = (intptr_t) ct->byte_map_base; 1.56 - if (Assembler::is_simm32(disp)) { 1.57 - Address cardtable(noreg, noreg, Address::no_scale, disp); 1.58 - __ lea(scratch, cardtable); 1.59 - } else { 1.60 - ExternalAddress cardtable((address)disp); 1.61 - __ lea(scratch, cardtable); 1.62 - } 1.63 - 1.64 - const Register count = end; // 'end' register contains bytes count now 1.65 + const Register end = count; 1.66 + 1.67 + __ leaq(end, Address(start, count, TIMES_OOP, 0)); // end == start+count*oop_size 1.68 + __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive 1.69 + __ shrptr(start, CardTableModRefBS::card_shift); 1.70 + __ shrptr(end, CardTableModRefBS::card_shift); 1.71 + __ subptr(end, start); // end --> cards count 1.72 + 1.73 + int64_t disp = (int64_t) ct->byte_map_base; 1.74 + __ mov64(scratch, disp); 1.75 __ addptr(start, scratch); 1.76 __ BIND(L_loop); 1.77 __ movb(Address(start, count, Address::times_1), 0); 1.78 @@ -1916,8 +1911,7 @@ 1.79 1.80 __ BIND(L_exit); 1.81 if (is_oop) { 1.82 - __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4)); 1.83 - gen_write_ref_array_post_barrier(saved_to, end_to, rax); 1.84 + gen_write_ref_array_post_barrier(saved_to, dword_count, rax); 1.85 } 1.86 restore_arg_regs(); 1.87 inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free 1.88 @@ -2012,12 +2006,10 @@ 1.89 // Copy in multi-bytes chunks 1.90 copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes); 1.91 1.92 - __ bind(L_exit); 1.93 - if (is_oop) { 1.94 - Register end_to = rdx; 1.95 - __ leaq(end_to, Address(to, dword_count, Address::times_4, -4)); 1.96 - gen_write_ref_array_post_barrier(to, end_to, rax); 1.97 - } 1.98 + __ BIND(L_exit); 1.99 + if (is_oop) { 1.100 + gen_write_ref_array_post_barrier(to, dword_count, rax); 1.101 + } 1.102 restore_arg_regs(); 1.103 inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free 1.104 __ xorptr(rax, rax); // return 0 1.105 @@ -2055,6 +2047,7 @@ 1.106 const Register end_from = from; // source array end address 1.107 const Register end_to = rcx; // destination array end address 1.108 const Register saved_to = to; 1.109 + const Register saved_count = r11; 1.110 // End pointers are inclusive, and if count is not zero they point 1.111 // to the last unit copied: end_to[0] := end_from[0] 1.112 1.113 @@ -2072,6 +2065,8 @@ 1.114 // r9 and r10 may be used to save non-volatile registers 1.115 // 'from', 'to' and 'qword_count' are now valid 1.116 if (is_oop) { 1.117 + // Save to and count for store barrier 1.118 + __ movptr(saved_count, qword_count); 1.119 // no registers are destroyed by this call 1.120 gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized); 1.121 } 1.122 @@ -2104,7 +2099,7 @@ 1.123 1.124 if (is_oop) { 1.125 __ BIND(L_exit); 1.126 - gen_write_ref_array_post_barrier(saved_to, end_to, rax); 1.127 + gen_write_ref_array_post_barrier(saved_to, saved_count, rax); 1.128 } 1.129 restore_arg_regs(); 1.130 if (is_oop) { 1.131 @@ -2187,8 +2182,7 @@ 1.132 1.133 if (is_oop) { 1.134 __ BIND(L_exit); 1.135 - __ lea(rcx, Address(to, saved_count, Address::times_8, -8)); 1.136 - gen_write_ref_array_post_barrier(to, rcx, rax); 1.137 + gen_write_ref_array_post_barrier(to, saved_count, rax); 1.138 } 1.139 restore_arg_regs(); 1.140 if (is_oop) { 1.141 @@ -2375,20 +2369,20 @@ 1.142 // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops. 1.143 // Emit GC store barriers for the oops we have copied (r14 + rdx), 1.144 // and report their number to the caller. 1.145 - assert_different_registers(rax, r14_length, count, to, end_to, rcx); 1.146 - __ lea(end_to, to_element_addr); 1.147 - __ addptr(end_to, -heapOopSize); // make an inclusive end pointer 1.148 - gen_write_ref_array_post_barrier(to, end_to, rscratch1); 1.149 - __ movptr(rax, r14_length); // original oops 1.150 - __ addptr(rax, count); // K = (original - remaining) oops 1.151 - __ notptr(rax); // report (-1^K) to caller 1.152 - __ jmp(L_done); 1.153 + assert_different_registers(rax, r14_length, count, to, end_to, rcx, rscratch1); 1.154 + Label L_post_barrier; 1.155 + __ addptr(r14_length, count); // K = (original - remaining) oops 1.156 + __ movptr(rax, r14_length); // save the value 1.157 + __ notptr(rax); // report (-1^K) to caller (does not affect flags) 1.158 + __ jccb(Assembler::notZero, L_post_barrier); 1.159 + __ jmp(L_done); // K == 0, nothing was copied, skip post barrier 1.160 1.161 // Come here on success only. 1.162 __ BIND(L_do_card_marks); 1.163 - __ addptr(end_to, -heapOopSize); // make an inclusive end pointer 1.164 - gen_write_ref_array_post_barrier(to, end_to, rscratch1); 1.165 - __ xorptr(rax, rax); // return 0 on success 1.166 + __ xorptr(rax, rax); // return 0 on success 1.167 + 1.168 + __ BIND(L_post_barrier); 1.169 + gen_write_ref_array_post_barrier(to, r14_length, rscratch1); 1.170 1.171 // Common exit point (success or failure). 1.172 __ BIND(L_done);