src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java

Print this page
rev 9538 : generates MH link to static factory for lambdas
rev 9539 : fix bytecode loading constructor parameters
rev 9540 : whitespace cleaning

@@ -47,10 +47,11 @@
 
     private static final int CLASSFILE_VERSION = 51;
     private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
     private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
     private static final String NAME_CTOR = "<init>";
+    private static final String NAME_FACTORY = "get$Lambda";
 
     //Serialization support
     private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
     private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
     private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";

@@ -190,13 +191,11 @@
             });
             Object inst = ctrs[0].newInstance();
             return new ConstantCallSite(MethodHandles.constant(samBase, inst));
         } else {
             return new ConstantCallSite(
-                    MethodHandles.Lookup.IMPL_LOOKUP
-                                        .findConstructor(innerClass, constructorType)
-                                        .asType(constructorType.changeReturnType(samBase)));
+                    MethodHandles.Lookup.IMPL_LOOKUP.findStatic(innerClass, NAME_FACTORY, invokedType));
         }
     }
 
     /**
      * Generate a class file which implements the functional

@@ -232,10 +231,14 @@
             fv.visitEnd();
         }
 
         generateConstructor();
 
+        if (invokedType.parameterCount() != 0) {
+            generateFactory();
+        }
+
         // Forward the SAM method
         String methodDescriptor = samMethodType.toMethodDescriptorString();
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
                                           methodDescriptor, null, null);
         new ForwardingMethodGenerator(mv).generate(methodDescriptor);

@@ -287,10 +290,28 @@
                                   classBytes, 0, classBytes.length,
                                   loader, pd);
     }
 
     /**
+     * Generate the factory method for the class
+     */
+    private void generateFactory() {
+        MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
+        m.visitCode();
+        m.visitTypeInsn(NEW, lambdaClassName);
+        m.visitInsn(Opcodes.DUP);
+        for (int typeIndex = 0, varIndex = 0; typeIndex < argTypes.length; typeIndex++) {
+            m.visitVarInsn(argTypes[typeIndex].getOpcode(ILOAD), varIndex);
+            varIndex += argTypes[typeIndex].getSize();
+        }
+        m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorDesc);
+        m.visitInsn(ARETURN);
+        m.visitMaxs(-1, -1);
+        m.visitEnd();
+    }
+
+    /**
      * Generate the constructor for the class
      */
     private void generateConstructor() {
         // Generate constructor
         MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,