[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