MH inlining fails for a package-private and protected calls

Paul Sandoz paul.sandoz at oracle.com
Fri Oct 24 20:52:33 UTC 2014


Hi,

I am observing that inlining of a MH invocation to a package private method fails.

Below is a simple test that test MHs to a public, package-private and protected methods.

Using the tip of JDK 9 with "java  -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining MHInlineTest" produces the following:

               !            @ 10   MHInlineTest::testPublicMH (24 bytes)   inline (hot)
                              @ 7   java.lang.invoke.LambdaForm$MH/314265080::invokeExact_MT (17 bytes)   force inline by annotation
                                @ 2   java.lang.invoke.Invokers::checkExactType (30 bytes)   force inline by annotation
                                  @ 11   java.lang.invoke.MethodHandle::type (5 bytes)   accessor
                                @ 13   java.lang.invoke.LambdaForm$DMH/285377351::invokeVirtual_LL_V (15 bytes)   force inline by annotation
                                  @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes)   force inline by annotation
                                  @ 11   MHInlineTest$B::public_x (6 bytes)   inline (hot)

               !            @ 29   MHInlineTest::testProtectedMH (24 bytes)   inline (hot)
                              @ 7   java.lang.invoke.LambdaForm$MH/314265080::invokeExact_MT (17 bytes)   force inline by annotation
                                @ 2   java.lang.invoke.Invokers::checkExactType (30 bytes)   force inline by annotation
                                  @ 11   java.lang.invoke.MethodHandle::type (5 bytes)   accessor
                                @ 13   java.lang.invoke.LambdaForm$DMH/285377351::invokeVirtual_LL_V (15 bytes)   force inline by annotation
                                  @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes)   force inline by annotation
                                  @ 11   MHInlineTest$A::protected_x (6 bytes)   virtual call

               !            @ 48   MHInlineTest::testPackageMH (24 bytes)   inline (hot)
                              @ 7   java.lang.invoke.LambdaForm$MH/314265080::invokeExact_MT (17 bytes)   force inline by annotation
                                @ 2   java.lang.invoke.Invokers::checkExactType (30 bytes)   force inline by annotation
                                  @ 11   java.lang.invoke.MethodHandle::type (5 bytes)   accessor
                                @ 13   java.lang.invoke.LambdaForm$DMH/285377351::invokeVirtual_LL_V (15 bytes)   force inline by annotation
                                  @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes)   force inline by annotation
                                  @ 11   MHInlineTest$A::package_x (6 bytes)   virtual call

               !            @ 67   MHInlineTest::testPackageFinalMH (24 bytes)   inline (hot)
                              @ 7   java.lang.invoke.LambdaForm$MH/314265080::invokeExact_MT (17 bytes)   force inline by annotation
                                @ 2   java.lang.invoke.Invokers::checkExactType (30 bytes)   force inline by annotation
                                  @ 11   java.lang.invoke.MethodHandle::type (5 bytes)   accessor
                                @ 13   java.lang.invoke.LambdaForm$DMH/344560770::invokeSpecial_LL_V (15 bytes)   force inline by annotation
                                  @ 1   java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes)   force inline by annotation
                                  @ 11   MHInlineTest$A::package_final_x (6 bytes)   inline (hot)

                            @ 86   MHInlineTest::testPackage (8 bytes)   inline (hot)
                              @ 4   MHInlineTest$B::package_x (6 bytes)   inline (hot)

Note that:

- inlining bails out for the MH to the package-private and and protected method, but does not bail out for an explicit package-protected call.

- the same LambdaForms are used for all virtual invocations.

Is that the expected behaviour?

Paul.

public class MHInlineTest {

    public static class A {
        volatile String s;

        public void public_x(String s) {
            this.s = s;
        }

        void protected_x(String s) {
            this.s = s;
        }

        void package_x(String s) {
            this.s = s;
        }

        final void package_final_x(String s) {
            this.s = s;
        }
    }

    public static final class B extends A {
        volatile String s;

        @Override
        public void public_x(String s) {
            this.s = s;
        }

        @Override
        void protected_x(String s) {
            this.s = s;
        }

        @Override
        void package_x(String s) {
            this.s = s;
        }
    }

    static final MethodHandle A_PUBLIC_X;
    static final MethodHandle A_PROTECTED_X;
    static final MethodHandle A_PACKAGE_X;
    static final MethodHandle A_PACKAGE_FINAL_X;

    static {
        try {
            A_PUBLIC_X = MethodHandles.lookup().findVirtual(
                    A.class, "public_x", MethodType.methodType(void.class, String.class));
            A_PROTECTED_X = MethodHandles.lookup().findVirtual(
                    A.class, "protected_x", MethodType.methodType(void.class, String.class));
            A_PACKAGE_X = MethodHandles.lookup().findVirtual(
                    A.class, "package_x", MethodType.methodType(void.class, String.class));
            A_PACKAGE_FINAL_X = MethodHandles.lookup().findVirtual(
                    A.class, "package_final_x", MethodType.methodType(void.class, String.class));
        }
        catch (Exception e) {
            throw new Error(e);
        }
    }

    static final A a = new B();

    public static void main(String[] args) {
        for (int i = 0; i < 1000_0000; i++) {
            testPublicMH("X");
        }
        for (int i = 0; i < 1000_0000; i++) {
            testProtectedMH("X");
        }
        for (int i = 0; i < 1000_0000; i++) {
            testPackageMH("X");
        }
        for (int i = 0; i < 1000_0000; i++) {
            testPackageFinalMH("X");
        }
        for (int i = 0; i < 1000_0000; i++) {
            testPackage("X");
        }
        System.out.println("END");
    }

    private static void testPublicMH(String x) {
        try {
            A_PUBLIC_X.invokeExact(a, x);
        }
        catch (Throwable throwable) {
            throw new Error(throwable);
        }
    }

    private static void testProtectedMH(String x) {
        try {
            A_PROTECTED_X.invokeExact(a, x);
        }
        catch (Throwable throwable) {
            throw new Error(throwable);
        }
    }

    private static void testPackageMH(String x) {
        try {
            A_PACKAGE_X.invokeExact(a, x);
        }
        catch (Throwable throwable) {
            throw new Error(throwable);
        }
    }

    private static void testPackageFinalMH(String x) {
        try {
            A_PACKAGE_FINAL_X.invokeExact(a, x);
        }
        catch (Throwable throwable) {
            throw new Error(throwable);
        }
    }

    private static void testPackage(String x) {
        a.package_x(x);
    }
}

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 841 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20141024/f8bbda05/signature.asc>


More information about the hotspot-compiler-dev mailing list