src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java
changeset 48921 576e024f10b6
parent 48895 7a1916641c0c
child 48930 b1a5b4ad7427
--- a/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java	Tue Feb 20 11:45:16 2018 -0500
+++ b/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java	Tue Feb 20 17:49:15 2018 +0100
@@ -116,8 +116,24 @@
                                                         argv[0], argv[1]);
                         break;
                     case 3:
-                        result = bootstrapMethod.invoke(caller, name, type,
-                                                        argv[0], argv[1], argv[2]);
+                        // Special case the LambdaMetafactory::metafactory BSM
+                        //
+                        // By invoking exactly, we can avoid generating a number of
+                        // classes on first (and subsequent) lambda initialization,
+                        // most of which won't be shared with other invoke uses.
+                        MethodType bsmType = bootstrapMethod.type();
+                        if (isLambdaMetafactoryIndyBSM(bsmType)) {
+                            result = (CallSite)bootstrapMethod
+                                    .invokeExact(caller, name, (MethodType)type, (MethodType)argv[0],
+                                                 (MethodHandle)argv[1], (MethodType)argv[2]);
+                        } else if (isLambdaMetafactoryCondyBSM(bsmType)) {
+                            result = bootstrapMethod
+                                    .invokeExact(caller, name, (Class<?>)type, (MethodType)argv[0],
+                                                 (MethodHandle)argv[1], (MethodType)argv[2]);
+                        } else {
+                            result = bootstrapMethod.invoke(caller, name, type,
+                                                            argv[0], argv[1], argv[2]);
+                        }
                         break;
                     case 4:
                         result = bootstrapMethod.invoke(caller, name, type,
@@ -175,6 +191,30 @@
         }
     }
 
+    private static final MethodType LMF_INDY_MT = MethodType.methodType(CallSite.class,
+            Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
+
+    private static final MethodType LMF_CONDY_MT = MethodType.methodType(Object.class,
+            Lookup.class, String.class, Class.class, MethodType.class, MethodHandle.class, MethodType.class);
+
+    /**
+     * @return true iff the BSM method type exactly matches
+     *         {@see java.lang.invoke.LambdaMetafactory#metafactory(
+     *          MethodHandles.Lookup,String,Class,MethodType,MethodHandle,MethodType)}
+     */
+    private static boolean isLambdaMetafactoryCondyBSM(MethodType bsmType) {
+        return bsmType == LMF_CONDY_MT;
+    }
+
+    /**
+     * @return true iff the BSM method type exactly matches
+     *         {@see java.lang.invoke.LambdaMetafactory#metafactory(
+     *          MethodHandles.Lookup,String,MethodType,MethodType,MethodHandle,MethodType)}
+     */
+    private static boolean isLambdaMetafactoryIndyBSM(MethodType bsmType) {
+        return bsmType == LMF_INDY_MT;
+    }
+
     /** The JVM produces java.lang.Integer values to box
      *  CONSTANT_Integer boxes but does not intern them.
      *  Let's intern them.  This is slightly wrong for