src/cpu/x86/vm/stubGenerator_x86_64.cpp

changeset 5156
3f281b313240
parent 4873
e961c11b85fe
child 5259
ef57c43512d6
     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);

mercurial