[8u] RFR: fix java_calling_convention for longs

Anton Kozlov akozlov at azul.com
Thu Mar 10 17:59:17 UTC 2016


Hi!

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

Fix for this is in attach. It's rather simple, so I hope it could be verified by looking at the code. For now, VMRegPair::set2 used for longs, so if r3 next free register, for long java_calling_convention will call VMRegPair::set2(r3) -> VMRegPair::set_pair(next(r3), r3) -> VMRegPair::set_pair(r4, r3). Calling VMRegPair::set_pair(r0, r3) directly resolves the issue.

Thanks,
Anton
-------------- next part --------------
A non-text attachment was scrubbed...
Name: java_cc_last_long.patch
Type: text/x-patch
Size: 621 bytes
Desc: java_cc_last_long.patch
URL: <http://mail.openjdk.java.net/pipermail/aarch32-port-dev/attachments/20160310/c2a95965/java_cc_last_long.patch>


More information about the aarch32-port-dev mailing list