changeset 50900:9afb4b449a76 condy-folding

Introduce buildFunctionalInterface method to LambdaMetafactory; avoids a temporary ConstantCallsite when bootstrapping lambdas with condy
author redestad
date Thu, 31 May 2018 14:53:14 +0200
parents ad2dac9ef560
children 8367c588a717
files src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java
diffstat 3 files changed, 68 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Wed May 30 20:00:23 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Thu May 31 14:53:14 2018 +0200
@@ -200,6 +200,17 @@
             throws LambdaConversionException;
 
     /**
+     * Builds an instance of the functional interface directly.
+     *
+     * @return an instance of the functional interface
+     * @throws ReflectiveOperationException
+     * @throws LambdaConversionException If properly formed functional interface
+     * is not found or if creating the functional interface requires parameters
+     */
+    abstract Object buildFunctionalInterfaceInstance()
+            throws LambdaConversionException;
+
+    /**
      * Check the meta-factory arguments for errors
      * @throws LambdaConversionException if there are improper conversions
      */
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Wed May 30 20:00:23 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu May 31 14:53:14 2018 +0200
@@ -187,26 +187,8 @@
     CallSite buildCallSite() throws LambdaConversionException {
         final Class<?> innerClass = spinInnerClass();
         if (invokedType.parameterCount() == 0) {
-            final Constructor<?>[] ctrs = AccessController.doPrivileged(
-                    new PrivilegedAction<>() {
-                @Override
-                public Constructor<?>[] run() {
-                    Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
-                    if (ctrs.length == 1) {
-                        // The lambda implementing inner class constructor is private, set
-                        // it accessible (by us) before creating the constant sole instance
-                        ctrs[0].setAccessible(true);
-                    }
-                    return ctrs;
-                }
-                    });
-            if (ctrs.length != 1) {
-                throw new LambdaConversionException("Expected one lambda constructor for "
-                        + innerClass.getCanonicalName() + ", got " + ctrs.length);
-            }
-
             try {
-                Object inst = ctrs[0].newInstance();
+                Object inst = getConstructor(innerClass).newInstance();
                 return new ConstantCallSite(MethodHandles.constant(samBase, inst));
             }
             catch (ReflectiveOperationException e) {
@@ -226,6 +208,55 @@
     }
 
     /**
+     * Builds an instance of the functional interface directly.
+     *
+     * Generate a class file which implements the functional interface, define
+     * the class, create an instance of the class.
+     *
+     * @return an instance of the functional interface
+     * @throws ReflectiveOperationException
+     * @throws LambdaConversionException If properly formed functional interface
+     * is not found or if the functional interface expects parameters
+     */
+    @Override
+    Object buildFunctionalInterfaceInstance() throws LambdaConversionException {
+        if (invokedType.parameterCount() == 0) {
+            final Class<?> innerClass = spinInnerClass();
+            try {
+                return getConstructor(innerClass).newInstance();
+            }
+            catch (ReflectiveOperationException e) {
+                throw new LambdaConversionException("Exception instantiating lambda object", e);
+            }
+        } else {
+            throw new LambdaConversionException("Building functional interface instances directly " +
+                    "only supported when there are no parameters");
+        }
+    }
+
+    private Constructor<?> getConstructor(Class<?> innerClass) throws LambdaConversionException {
+        final Constructor<?>[] ctrs = AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    @Override
+                    public Constructor<?>[] run() {
+                        Constructor<?>[] ctrs1 = innerClass.getDeclaredConstructors();
+                        if (ctrs1.length == 1) {
+                            // The lambda implementing inner class constructor is private, set
+                            // it accessible (by us) before creating the constant sole instance
+                            ctrs1[0].setAccessible(true);
+                        }
+                        return ctrs1;
+                    }
+                });
+
+        if (ctrs.length != 1) {
+            throw new LambdaConversionException("Expected one lambda constructor for "
+                    + innerClass.getCanonicalName() + ", got " + ctrs.length);
+        }
+        return ctrs[0];
+    }
+
+    /**
      * Generate a class file which implements the functional
      * interface, define and return the class.
      *
--- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Wed May 30 20:00:23 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Thu May 31 14:53:14 2018 +0200
@@ -377,16 +377,13 @@
                                      MethodHandle implMethod,
                                      MethodType instantiatedMethodType)
             throws LambdaConversionException {
-        try {
-            return metafactory(caller, invokedName, MethodType.methodType(functionalInterface),
-                               samMethodType, implMethod, instantiatedMethodType).getTarget().invoke();
-        }
-        catch (LambdaConversionException | LinkageError e) {
-            throw e;
-        }
-        catch (Throwable e) {
-            throw new LambdaConversionException("Exception invoking lambda metafactory", e);
-        }
+        AbstractValidatingLambdaMetafactory mf;
+        mf = new InnerClassLambdaMetafactory(caller, MethodType.methodType(functionalInterface),
+                                             invokedName, samMethodType,
+                                             implMethod, instantiatedMethodType,
+                                             false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
+        mf.validateMetafactoryArgs();
+        return mf.buildFunctionalInterfaceInstance();
     }
 
     // @@@ Special case version of altMetafactory, supporting FLAG_METHODREF