You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2018/01/12 16:18:08 UTC

groovy git commit: Minor refactoring

Repository: groovy
Updated Branches:
  refs/heads/native-lambda 4172bd764 -> 083089fc3


Minor refactoring


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/083089fc
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/083089fc
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/083089fc

Branch: refs/heads/native-lambda
Commit: 083089fc35405379c4a4f27fa1d3123eb396dc67
Parents: 4172bd7
Author: sunlan <su...@apache.org>
Authored: Sat Jan 13 00:18:00 2018 +0800
Committer: sunlan <su...@apache.org>
Committed: Sat Jan 13 00:18:00 2018 +0800

----------------------------------------------------------------------
 .../asm/sc/StaticTypesLambdaWriter.java         | 123 +++++++++++--------
 src/test/groovy/transform/stc/LambdaTest.groovy |  17 +++
 2 files changed, 86 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/083089fc/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
index c847c33..bdf10d8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
@@ -31,8 +31,8 @@ import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.classgen.asm.LambdaWriter;
 import org.codehaus.groovy.classgen.asm.WriterController;
 import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
+import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 import org.objectweb.asm.Handle;
-import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 
@@ -77,50 +77,61 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
                         .collect(Collectors.toList());
 
         if (!(isFunctionInterface(parameterType) && abstractMethodNodeList.size() == 1)) {
+            // if the parameter type is not real FunctionInterface, generate the default bytecode, which is actually a closure
             super.writeLambda(expression);
             return;
         }
 
         MethodNode abstractMethodNode = abstractMethodNodeList.get(0);
-        String abstractMethodName = abstractMethodNode.getName();
-        String abstractMethodDesc = "()L" + parameterType.redirect().getPackageName().replace('.', '/') + "/" + parameterType.redirect().getNameWithoutPackage() + ";";
+        String abstractMethodDesc = createMethodDescriptor(abstractMethodNode);
 
-
-        MethodVisitor mv = controller.getMethodVisitor();
-        ClassNode lambdaEnclosingClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC, abstractMethodNode);
-        MethodNode syntheticLambdaMethodNode = lambdaEnclosingClassNode.getMethods(DO_CALL).get(0);
+        ClassNode lambdaClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC);
+        MethodNode syntheticLambdaMethodNode = lambdaClassNode.getMethods(DO_CALL).get(0);
         String syntheticLambdaMethodWithExactTypeDesc = BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode);
-        String syntheticLambdaMethodDesc =
-                BytecodeHelper.getMethodDescriptor(
-                        abstractMethodNode.getReturnType().getTypeClass(),
-                        Arrays.stream(abstractMethodNode.getParameters())
-                                .map(e -> e.getType().getTypeClass())
-                                .toArray(Class[]::new)
-                );
-
-        controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
-
-        mv.visitInvokeDynamicInsn(
-                abstractMethodName,
-                abstractMethodDesc,
+
+        controller.getOperandStack().push(parameterType.redirect());
+        controller.getMethodVisitor().visitInvokeDynamicInsn(
+                abstractMethodNode.getName(),
+                createAbstractMethodDesc(parameterType),
+                createBootstrapMethod(),
+                createBootstrapMethodArguments(abstractMethodDesc, lambdaClassNode, syntheticLambdaMethodNode, syntheticLambdaMethodWithExactTypeDesc)
+        );
+    }
+
+    private String createAbstractMethodDesc(ClassNode parameterType) {
+        return "()L" + parameterType.redirect().getPackageName().replace('.', '/') + "/" + parameterType.redirect().getNameWithoutPackage() + ";";
+    }
+
+    private Handle createBootstrapMethod() {
+        return new Handle(
+                Opcodes.H_INVOKESTATIC,
+                "java/lang/invoke/LambdaMetafactory",
+                "metafactory",
+                "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+                false
+        );
+    }
+
+    private Object[] createBootstrapMethodArguments(String abstractMethodDesc, ClassNode lambdaClassNode, MethodNode syntheticLambdaMethodNode, String syntheticLambdaMethodWithExactTypeDesc) {
+        return new Object[]{
+                Type.getType(abstractMethodDesc),
                 new Handle(
                         Opcodes.H_INVOKESTATIC,
-                        "java/lang/invoke/LambdaMetafactory",
-                        "metafactory",
-                        "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
+                        lambdaClassNode.getName(),
+                        syntheticLambdaMethodNode.getName(),
+                        syntheticLambdaMethodWithExactTypeDesc,
                         false
                 ),
-                new Object[]{
-                        Type.getType(syntheticLambdaMethodDesc),
-                        new Handle(
-                                Opcodes.H_INVOKESTATIC,
-                                lambdaEnclosingClassNode.getName(),
-                                syntheticLambdaMethodNode.getName(),
-                                syntheticLambdaMethodWithExactTypeDesc,
-                                false
-                        ),
-                        Type.getType(syntheticLambdaMethodWithExactTypeDesc)
-                }
+                Type.getType(syntheticLambdaMethodWithExactTypeDesc)
+        };
+    }
+
+    private String createMethodDescriptor(MethodNode abstractMethodNode) {
+        return BytecodeHelper.getMethodDescriptor(
+                abstractMethodNode.getReturnType().getTypeClass(),
+                Arrays.stream(abstractMethodNode.getParameters())
+                        .map(e -> e.getType().getTypeClass())
+                        .toArray(Class[]::new)
         );
     }
 
@@ -128,10 +139,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
         return parameterType.redirect().isInterface() && !parameterType.redirect().getAnnotations(ClassHelper.FunctionalInterface_Type).isEmpty();
     }
 
-    public ClassNode getOrAddLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) {
+    public ClassNode getOrAddLambdaClass(LambdaExpression expression, int mods) {
         ClassNode lambdaClass = lambdaClassMap.get(expression);
         if (lambdaClass == null) {
-            lambdaClass = createLambdaClass(expression, mods, abstractMethodNode);
+            lambdaClass = createLambdaClass(expression, mods);
             lambdaClassMap.put(expression, lambdaClass);
             controller.getAcg().addInnerClass(lambdaClass);
             lambdaClass.addInterface(ClassHelper.GENERATED_LAMBDA_TYPE);
@@ -140,7 +151,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
         return lambdaClass;
     }
 
-    protected ClassNode createLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) {
+    protected ClassNode createLambdaClass(LambdaExpression expression, int mods) {
         ClassNode outerClass = controller.getOutermostClass();
         ClassNode classNode = controller.getClassNode();
         String name = genLambdaClassName();
@@ -159,13 +170,27 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
             answer.setScriptBody(true);
         }
 
+        addSyntheticLambdaMethodNode(expression, answer);
+
+        return answer;
+    }
+
+    private String genLambdaClassName() {
+        ClassNode classNode = controller.getClassNode();
+        ClassNode outerClass = controller.getOutermostClass();
+        MethodNode methodNode = controller.getMethodNode();
+
+        return classNode.getName() + "$"
+                + controller.getContext().getNextLambdaInnerName(outerClass, classNode, methodNode);
+    }
+
+    private void addSyntheticLambdaMethodNode(LambdaExpression expression, InnerClassNode answer) {
         Parameter[] parametersWithExactType = createParametersWithExactType(expression); // expression.getParameters();
+        ClassNode returnType = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); //abstractMethodNode.getReturnType();
 
         MethodNode methodNode =
-                answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, abstractMethodNode.getReturnType(), parametersWithExactType, ClassNode.EMPTY_ARRAY, expression.getCode());
+                answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, returnType, parametersWithExactType, ClassNode.EMPTY_ARRAY, expression.getCode());
         methodNode.setSourcePosition(expression);
-
-        return answer;
     }
 
     private Parameter[] createParametersWithExactType(LambdaExpression expression) {
@@ -174,13 +199,12 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
             parameters = Parameter.EMPTY_ARRAY;
         }
 
-        ClassNode[] blockParameterTypes = expression.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.CLOSURE_ARGUMENTS);
-//        Parameter[] parametersWithExactType = new Parameter[parameters.length];
-
         for (int i = 0; i < parameters.length; i++) {
-            parameters[i].setType(blockParameterTypes[i]);
-            parameters[i].setOriginType(blockParameterTypes[i]);
+            ClassNode inferredType = parameters[i].getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
+            parameters[i].setType(inferredType);
+            parameters[i].setOriginType(inferredType);
         }
+
         return parameters;
     }
 
@@ -188,13 +212,4 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
     protected ClassNode createClosureClass(final ClosureExpression expression, final int mods) {
         return staticTypesClosureWriter.createClosureClass(expression, mods);
     }
-
-    private String genLambdaClassName() {
-        ClassNode classNode = controller.getClassNode();
-        ClassNode outerClass = controller.getOutermostClass();
-        MethodNode methodNode = controller.getMethodNode();
-
-        return classNode.getName() + "$"
-                + controller.getContext().getNextLambdaInnerName(outerClass, classNode, methodNode);
-    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/083089fc/src/test/groovy/transform/stc/LambdaTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index db4aa36..700f9cd 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -39,6 +39,23 @@ class LambdaTest extends GroovyTestCase {
         '''
     }
 
+    /*
+    void testFunction2() {
+        assertScript '''
+        import groovy.transform.CompileStatic
+        import java.util.stream.Collectors
+        import java.util.stream.Stream
+        
+        @CompileStatic
+        void p() {
+            assert [2, 3, 4] == Stream.of(1, 2, 3).map(e -> e.plus 1).collect(Collectors.toList());
+        }
+        
+        p()
+        '''
+    }
+    */
+
     void testBinaryOperator() {
         if (true) return;