[8u] RFR: fix java_calling_convention for longs

Anton Kozlov akozlov at azul.com
Mon Mar 14 09:02:19 UTC 2016


Hi Ed,

Thanks for review! Regarding T_DOUBLE: I beleive that 

    fp_args = round_to(fp_args, 2); // (3rd line of inlined code) 

will guard against descibed situation. If we came here with fp_args ==
15, then fp_args will be rounded first to 16 and then checked against
FP_ArgReg_N boundary.

Java calling convention for floating point arguments looks like integer
register arguments: adjacent single floats will occupy 2 single
registers

    float, float, float -> f0, f1, f2

But if single float (placed to even single register) will be followed
by double float, then one single register will not be used

    float, double, float -> f0, d1(f3:f2), f4 // f1 not used

Note, that C calling convention is different, it places third argument
to f1 in last example.

Thanks,
Anton

On Sun, 2016-03-13 at 15:07 +0000, Edward Nevill wrote:
> Hi Anton,
> 
> Thanks for this. Your fix looks correct. Could you also check the
> code for T_DOUBLE a few lines later.
> 
> 
>     case T_DOUBLE:
>       assert(sig_bt[i + 1] == T_VOID, "expecting half");
>       fp_args = round_to(fp_args, 2);
>       if (fp_args < FP_ArgReg_N) {
>         regs[i].set2(FP_ArgReg[fp_args]->as_VMReg());
>         fp_args += 2;
>       } else {
>         regs[i].set2(VMRegImpl::stack2reg(stk_args));
>         stk_args += 2;
>       }
>       break;
> 
> Here it would seem then if fp_args was == 15 then it could end up
> using f15 and f16 which is invalid? It can only do this if there is a
> mixture of double and float arguments previously.
> 
> Thanks,
> Ed.
> 
> 
> On Thu, 2016-03-10 at 17:59 +0000, Anton Kozlov wrote:
> > Current java calling convention have a bug: when last long argument
> > fitting to be passed on registers, high word could occupy register
> > outside of register set intended for argument passing. With java
> > c/c
> > argument on registers r1,r2,r3,r0: r4 may be used. Test case for
> > this
> > issue is not straightforward, because only few places uses r4
> > directly, so it's rarely destroyed. However, itable_stub is one of
> > them, so here is a test.
> > 
> > === Test ===
> > 
> > class Test {
> >         public static final long goldValue = (0xdeadL << 32) |
> > 0xdead;
> > 
> >         public static void checkLong(long j3) {
> >                 System.out.printf("%s: got %x, should be %x\n", j3
> > ==
> > goldValue ? "OK" : "Fail", j3, goldValue);
> >         }
> > 
> >         interface TestInterface {
> >                 public abstract void callee(int i1, long j3);
> >         }
> > 
> >         class TestImpl1 implements TestInterface {
> >                 @Override
> >                 public void callee(int i1, long j3) {
> >                         checkLong(j3);
> >                 }
> >         }
> > 
> >         class TestImpl2 implements TestInterface {
> >                 @Override
> >                 public void callee(int i1, long j3) {
> >                         checkLong(j3);
> >                 }
> >         }
> > 
> >         class TestImpl3 implements TestInterface {
> >                 @Override
> >                 public void callee(int i1, long j3) {
> >                         checkLong(j3);
> >                 }
> >         }
> > 
> >         public void vmain() {
> >                 TestInterface ifaces[] = { new TestImpl1(), new
> > TestImpl2(), new TestImpl3() };
> >                 TestInterface iface = null;
> >                 for (int i = 0; i < ifaces.length; ++i) {
> >                         iface = ifaces[i];
> >                         iface.callee(0, goldValue);
> >                 }
> >         }
> > 
> >         public static void main(String[] args) {
> >                 Test test = new Test();
> >                 test.vmain();
> >         }
> > }
> > === End of Test ===
> > 
> > However, problem could be verified by hands easier. Calling
> > java_calling_convention for checkLong2 signature will allocate r1
> > for
> > i1, r2 for i2 and r4:r3 for j3; however, r0:r3 expected.
> > 
> > === TestLongPass ===
> > class TestLongPass {
> >         public static final long goldValue = (0x31414L << 32) |
> > 0x31415;
> > 
> >         public static void checkLong2(int i1, int i2, long j3) {
> >                 System.out.printf("%s: got %x, should be %x\n", j3
> > ==
> > goldValue ? "OK" : "Fail", j3, goldValue);
> >         }
> > 
> >         public static void main(String[] args) {
> >                 checkLong2(0, 0, goldValue);
> >         }
> > }
> > === End of TestLongPass
> > 
> > 
> 


More information about the aarch32-port-dev mailing list