Repository: groovy
Updated Branches:
  refs/heads/native-lambda 97649f9d1 -> b0aaa1ef9


Refine bytecode generation of native lambda


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

Branch: refs/heads/native-lambda
Commit: b0aaa1ef96c7f56efb4e7b7099fb4d61381f6d53
Parents: 97649f9
Author: sunlan <[email protected]>
Authored: Fri Jan 12 17:42:44 2018 +0800
Committer: sunlan <[email protected]>
Committed: Fri Jan 12 17:42:44 2018 +0800

----------------------------------------------------------------------
 .../java/org/codehaus/groovy/ast/Parameter.java |  4 ++
 .../groovy/classgen/asm/ClosureWriter.java      |  4 +-
 .../asm/sc/StaticTypesLambdaWriter.java         | 65 +++++++++++++++-----
 src/test/groovy/transform/stc/LambdaTest.groovy | 45 +++++++++++---
 4 files changed, 93 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/b0aaa1ef/src/main/java/org/codehaus/groovy/ast/Parameter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/Parameter.java 
b/src/main/java/org/codehaus/groovy/ast/Parameter.java
index 1b22128..b2ddb09 100644
--- a/src/main/java/org/codehaus/groovy/ast/Parameter.java
+++ b/src/main/java/org/codehaus/groovy/ast/Parameter.java
@@ -123,4 +123,8 @@ public class Parameter extends AnnotatedNode implements 
Variable {
     public void setModifiers(int modifiers) {
         this.modifiers = modifiers;
     }
+
+    public Expression getDefaultValue() {
+        return defaultValue;
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/b0aaa1ef/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
index 33ce035..d6e215d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -185,7 +185,7 @@ public class ClosureWriter {
         ClassNode classNode = controller.getClassNode();
         ClassNode outerClass = controller.getOutermostClass();
 //        MethodNode methodNode = controller.getMethodNode();
-        String name = genInnerClassName();
+        String name = genClosureClassName();
         boolean staticMethodOrInStaticClass = controller.isStaticMethod() || 
classNode.isStaticClass();
 
         Parameter[] parameters = expression.getParameters();
@@ -305,7 +305,7 @@ public class ClosureWriter {
         return answer;
     }
 
-    protected String genInnerClassName() {
+    private String genClosureClassName() {
         ClassNode classNode = controller.getClassNode();
         ClassNode outerClass = controller.getOutermostClass();
         MethodNode methodNode = controller.getMethodNode();

http://git-wip-us.apache.org/repos/asf/groovy/blob/b0aaa1ef/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 46cbe15..29c0e40 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
@@ -38,6 +38,7 @@ import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -98,9 +99,16 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
                 ACC_PUBLIC + ACC_FINAL + ACC_STATIC);
 
         MethodVisitor mv = controller.getMethodVisitor();
-        ClassNode lambdaEnclosingClassNode = getOrAddLambdaClass(expression, 
ACC_PUBLIC);
+        ClassNode lambdaEnclosingClassNode = getOrAddLambdaClass(expression, 
ACC_PUBLIC, abstractMethodNode);
         MethodNode syntheticLambdaMethodNode = 
lambdaEnclosingClassNode.getMethods(DO_CALL).get(0);
-        String syntheticLambdaMethodDesc = 
BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode);
+        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);
 
@@ -112,23 +120,26 @@ public class StaticTypesLambdaWriter extends LambdaWriter 
{
                         "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),
-                new Object[] {
+                        false
+                ),
+                new Object[]{
                         Type.getType(syntheticLambdaMethodDesc),
                         new Handle(
                                 Opcodes.H_INVOKESTATIC,
                                 lambdaEnclosingClassNode.getName(),
                                 syntheticLambdaMethodNode.getName(),
-                                syntheticLambdaMethodDesc,
-                                false),
-                        Type.getType(syntheticLambdaMethodDesc)
-                });
+                                syntheticLambdaMethodWithExactTypeDesc,
+                                false
+                        ),
+                        Type.getType(syntheticLambdaMethodWithExactTypeDesc)
+                }
+        );
     }
 
-    public ClassNode getOrAddLambdaClass(LambdaExpression expression, int 
mods) {
+    public ClassNode getOrAddLambdaClass(LambdaExpression expression, int 
mods, MethodNode abstractMethodNode) {
         ClassNode lambdaClass = lambdaClassMap.get(expression);
         if (lambdaClass == null) {
-            lambdaClass = createLambdaClass(expression, mods);
+            lambdaClass = createLambdaClass(expression, mods, 
abstractMethodNode);
             lambdaClassMap.put(expression, lambdaClass);
             controller.getAcg().addInnerClass(lambdaClass);
             lambdaClass.addInterface(ClassHelper.GENERATED_LAMBDA_TYPE);
@@ -137,10 +148,10 @@ public class StaticTypesLambdaWriter extends LambdaWriter 
{
         return lambdaClass;
     }
 
-    protected ClassNode createLambdaClass(LambdaExpression expression, int 
mods) {
+    protected ClassNode createLambdaClass(LambdaExpression expression, int 
mods, MethodNode abstractMethodNode) {
         ClassNode outerClass = controller.getOutermostClass();
         ClassNode classNode = controller.getClassNode();
-        String name = genInnerClassName();
+        String name = genLambdaClassName();
         boolean staticMethodOrInStaticClass = controller.isStaticMethod() || 
classNode.isStaticClass();
 
         InnerClassNode answer = new InnerClassNode(classNode, name, mods, 
ClassHelper.LAMBDA_TYPE.getPlainNodeReference());
@@ -156,20 +167,42 @@ public class StaticTypesLambdaWriter extends LambdaWriter 
{
             answer.setScriptBody(true);
         }
 
+        Parameter[] parametersWithExactType = 
createParametersWithExactType(expression); // expression.getParameters();
+
+        MethodNode methodNode =
+                answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | 
Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, abstractMethodNode.getReturnType(), 
parametersWithExactType, ClassNode.EMPTY_ARRAY, expression.getCode());
+        methodNode.setSourcePosition(expression);
+
+        return answer;
+    }
+
+    private Parameter[] createParametersWithExactType(LambdaExpression 
expression) {
         Parameter[] parameters = expression.getParameters();
         if (parameters == null) {
             parameters = Parameter.EMPTY_ARRAY;
         }
 
-        MethodNode methodNode =
-                answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | 
Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, ClassHelper.OBJECT_TYPE, 
parameters, ClassNode.EMPTY_ARRAY, expression.getCode());
-        methodNode.setSourcePosition(expression);
+        ClassNode[] blockParameterTypes = 
expression.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.CLOSURE_ARGUMENTS);
+//        Parameter[] parametersWithExactType = new 
Parameter[parameters.length];
 
-        return answer;
+        for (int i = 0; i < parameters.length; i++) {
+            parameters[i].setType(blockParameterTypes[i]);
+            parameters[i].setOriginType(blockParameterTypes[i]);
+        }
+        return parameters;
     }
 
     @Override
     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/b0aaa1ef/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 0b9e189..e7ae05f 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -30,25 +30,56 @@ class LambdaTest extends GroovyTestCase {
         public class Test1 {
             public static void main(String[] args) {
                 p1();
-//                p2();
-        //        p3();
             }
         
             public static void p1() {
-                assert [2, 3, 4] == Stream.of(1, 2, 3).map(e -> e + 
1).collect(Collectors.toList());
+                assert [2, 3, 4] == Stream.of(1, 2, 3).map(e -> e.plus 
1).collect(Collectors.toList());
             }
+        }
+        '''
+
+    }
+
+    void testMethodCall2() {
+        if (true) return;
+
+        // the test can pass only in dynamic mode now, it can not pass static 
type checking...
+
+        assertScript '''
+        import groovy.transform.CompileStatic
+        import java.util.stream.Collectors
+        import java.util.stream.Stream
         
-            /*
+        @CompileStatic
+        public class Test1 {
+            public static void main(String[] args) {
+                p2();
+            }
+            
             public static void p2() {
                 assert 13 == Stream.of(1, 2, 3).reduce(7, (r, e) -> r + e);
             }
-            */
+        }
+        '''
+
+    }
+
+    void testMethodCall3() {
+        assertScript '''
+        import groovy.transform.CompileStatic
+        import java.util.stream.Collectors
+        import java.util.stream.Stream
+        
+        @CompileStatic
+        public class Test1 {
+            public static void main(String[] args) {
+                p3();
+            }
             
-            /*
             public static void p3() {
                 Stream.of(1, 2, 3).forEach(e -> { System.out.println(e + 1); 
});
             }
-            */
+            
         }
         '''
 

Reply via email to