[aarch64-port-dev ] RFR: Fix out by one in writing array barriers

Andrew Haley aph at redhat.com
Thu Dec 12 05:30:18 PST 2013


On 12/12/2013 01:03 PM, Edward Nevill wrote:
> Hi,
> 
> The following patch fixes some problems I am seeing with GC in the JTReg hotspot tests, specifically compiler/8010927/Test8010927
> 
> The problem seems to be an out by one error in gen_write_ref_array_post_barrier
> 
> The original code reads
> 
>            __ lsr(start, start, CardTableModRefBS::card_shift);
>            __ add(end, end, BytesPerHeapOop);
>            __ lsr(end, end, CardTableModRefBS::card_shift);
>            __ sub(end, end, start); // number of bytes to copy
> 
>           const Register count = end; // 'end' register contains bytes count now
>           __ mov(scratch, (address)ct->byte_map_base);
>           __ add(start, start, scratch);
>           __ BIND(L_loop);
>           __ strb(zr, Address(start, count));
>           __ subs(count, count, 1);
>           __ br(Assembler::HI, L_loop);
> 
> This seems to me to be broken. The last store in the loop is always
> 
> strb zr, [start, 1]
> 
> because of the BHI. However it must store to [start, 0] because for
> each HeapOOP it must do
> 
> [base + [addr >> card_shift]] = 0
> 
> However in the above the last store is done to
> 
> [base + [addr >> card_shift] + 1] = 0
> 
> The end condition of the loop should therefore be BHS, not BHI to
> include 0.
> 
> However, this sometimes stores 1 too many (and sometimes not). The
> problem is the
> 
> add end, end, BytesPerHeapOop
> 
> which converts the inclusive pointer to an exclusive
> pointer. However this is not what we want. What we want is to store
> 0 in all the bytes in the range
> 
> [base + [start >> card_shift]] to [base + [end >> card_shift]]
> 
> The following patch fixes this.
> 
> OK to push?

I agree with this diagnosis.  However:

The first store is done to [base + [end >> card_shift]].  I think this
is wrong, because [base + [end >> card_shift]] is outside the range.
We need to make in an inclusive pointer.  So, we need to subtract 1
from end, not add it:

           __ lsr(start, start, CardTableModRefBS::card_shift);
           __ sub(end, end, BytesPerHeapOop); // end - 1 to make inclusive
           __ lsr(end, end, CardTableModRefBS::card_shift);
           __ sub(end, end, start); // number of bytes to copy

          const Register count = end; // 'end' register contains bytes count now
	  __ mov(scratch, (address)ct->byte_map_base);
          __ add(start, start, scratch);
	  __ BIND(L_loop);
	  __ strb(zr, Address(start, count));
          __ subs(count, count, 1);
          __ br(Assembler::HS, L_loop);

Andrew.





More information about the aarch64-port-dev mailing list