[8u] RFR: fix java_calling_convention for longs

Edward Nevill edward.nevill at gmail.com
Sun Mar 13 15:07:09 UTC 2016


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