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/02/18 05:02:40 UTC

[3/3] groovy git commit: Port native lambda to Java7

Port native lambda to Java7

Just port its implementation and make the code can run on Java7, so when running on Java7, native lambda is still closure.


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

Branch: refs/heads/GROOVY_2_6_X
Commit: 727c89a39d6360bb905eac36a68515a78aa78d9c
Parents: af33df8
Author: danielsun1106 <re...@hotmail.com>
Authored: Sun Feb 18 13:00:36 2018 +0800
Committer: danielsun1106 <re...@hotmail.com>
Committed: Sun Feb 18 13:02:27 2018 +0800

----------------------------------------------------------------------
 .../codehaus/groovy/ast/CodeVisitorSupport.java |  5 ++
 .../codehaus/groovy/ast/GroovyCodeVisitor.java  |  4 +-
 .../groovy/classgen/asm/InvocationWriter.java   | 16 +++--
 .../asm/sc/StaticTypesLambdaWriter.java         | 30 +++++----
 .../customizers/SecureASTCustomizer.java        |  6 ++
 src/test/groovy/transform/stc/LambdaTest.groovy | 65 ++++++++++++++++++++
 6 files changed, 107 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java b/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
index 523475e..e0b003d 100644
--- a/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
+++ b/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
@@ -35,6 +35,7 @@ import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.ListExpression;
 import org.codehaus.groovy.ast.expr.MapEntryExpression;
 import org.codehaus.groovy.ast.expr.MapExpression;
@@ -227,6 +228,10 @@ public abstract class CodeVisitorSupport implements GroovyCodeVisitor {
         expression.getCode().visit(this);
     }
 
+    public void visitLambdaExpression(LambdaExpression expression) {
+        visitClosureExpression(expression);
+    }
+
     public void visitTupleExpression(TupleExpression expression) {
         visitListOfExpressions(expression.getExpressions());
     }

http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
index db793cc..f2f8027 100644
--- a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
@@ -139,9 +139,7 @@ public interface GroovyCodeVisitor {
 
     void visitClosureExpression(ClosureExpression expression);
 
-    default void visitLambdaExpression(LambdaExpression expression) {
-        visitClosureExpression(expression);
-    }
+    void visitLambdaExpression(LambdaExpression expression);
 
     void visitTupleExpression(TupleExpression expression);
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index 6ab3fd9..b9c5b62 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -32,6 +32,7 @@ import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.ExpressionTransformer;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.ast.expr.SpreadExpression;
@@ -528,13 +529,18 @@ public class InvocationWriter {
         ClassNode type = call.getObjectExpression().getType();
         final MethodNode methodNode = ClassHelper.findSAM(type);
 
-        call = (MethodCallExpression) call.transformExpression(expression -> {
-            if (!(expression instanceof ConstantExpression)) {
-                return expression;
-            }
+        call = (MethodCallExpression) call.transformExpression(new ExpressionTransformer() {
+            @Override
+            public Expression transform(Expression expression) {
+                if (!(expression instanceof ConstantExpression)) {
+                    return expression;
+                }
 
-            return new ConstantExpression(methodNode.getName());
+                return new ConstantExpression(methodNode.getName());
+            }
         });
+
+
         call.setMethodTarget(methodNode);
         return call;
     }

http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/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 ab45f9c..6184181 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
@@ -42,6 +42,7 @@ import org.codehaus.groovy.classgen.asm.WriterController;
 import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.transform.stc.StaticTypesMarker;
+import org.codehaus.groovy.vmplugin.VMPluginFactory;
 import org.objectweb.asm.Handle;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
@@ -52,7 +53,6 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
 
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_LAMBDA_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PARAMETER_TYPE;
@@ -78,6 +78,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
     public static final String IS_GENERATED_CONSTRUCTOR = "__IS_GENERATED_CONSTRUCTOR";
     public static final String LAMBDA_WRAPPER = "__lambda_wrapper";
     public static final String SAM_NAME = "__SAM_NAME";
+    private static final boolean PRE_JAVA8 = VMPluginFactory.getPlugin().getVersion() < 8;
     private StaticTypesClosureWriter staticTypesClosureWriter;
     private WriterController controller;
     private WriterControllerFactory factory;
@@ -98,8 +99,8 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
     public void writeLambda(LambdaExpression expression) {
         ClassNode lambdaType = getLambdaType(expression);
 
-        if (!ClassHelper.isFunctionalInterface(lambdaType.redirect())) {
-            // if the parameter type is not real FunctionInterface, generate the default bytecode, which is actually a closure
+        if (PRE_JAVA8 || !ClassHelper.isFunctionalInterface(lambdaType.redirect())) {
+            // if running on pre8 JVM or the parameter type is not real FunctionInterface, generate the default bytecode, which is actually a closure
             super.writeLambda(expression);
             return;
         }
@@ -203,10 +204,14 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
 
         loadSharedVariables(syntheticLambdaMethodNode);
 
-        List<ConstructorNode> constructorNodeList =
-                lambdaWrapperClassNode.getDeclaredConstructors().stream()
-                        .filter(e -> Boolean.TRUE.equals(e.getNodeMetaData(IS_GENERATED_CONSTRUCTOR)))
-                        .collect(Collectors.toList());
+        List<ConstructorNode> constructorNodeList = new LinkedList<>();
+        for (ConstructorNode e : lambdaWrapperClassNode.getDeclaredConstructors()) {
+            if (!Boolean.TRUE.equals(e.getNodeMetaData(IS_GENERATED_CONSTRUCTOR))) {
+                continue;
+            }
+
+            constructorNodeList.add(e);
+        }
 
         if (constructorNodeList.size() == 0) {
             throw new GroovyBugError("Failed to find the generated constructor");
@@ -268,16 +273,19 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
                         BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode),
                         lambdaClassNode.isInterface()
                 ),
-                Type.getType(BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode.getReturnType(), syntheticLambdaMethodNode.getNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE)))
+                Type.getType(BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode.getReturnType(), (Parameter[]) syntheticLambdaMethodNode.getNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE)))
         };
     }
 
     private String createMethodDescriptor(MethodNode abstractMethodNode) {
+        List<Class> typeClassList = new LinkedList<>();
+        for (Parameter e : abstractMethodNode.getParameters()) {
+            typeClassList.add(e.getType().getTypeClass());
+        }
+
         return BytecodeHelper.getMethodDescriptor(
                 abstractMethodNode.getReturnType().getTypeClass(),
-                Arrays.stream(abstractMethodNode.getParameters())
-                        .map(e -> e.getType().getTypeClass())
-                        .toArray(Class[]::new)
+                typeClassList.toArray(new Class[0])
         );
     }
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java b/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
index 1bb302b..c839e7e 100644
--- a/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
+++ b/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
@@ -42,6 +42,7 @@ import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.ListExpression;
 import org.codehaus.groovy.ast.expr.MapEntryExpression;
 import org.codehaus.groovy.ast.expr.MapExpression;
@@ -989,6 +990,11 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             expression.getCode().visit(this);
         }
 
+        @Override
+        public void visitLambdaExpression(LambdaExpression expression) {
+            visitClosureExpression(expression);
+        }
+
         public void visitTupleExpression(final TupleExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getExpressions());

http://git-wip-us.apache.org/repos/asf/groovy/blob/727c89a3/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 a24e3c1..0e2345f 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -19,10 +19,15 @@
 
 package groovy.transform.stc
 
+import org.codehaus.groovy.vmplugin.VMPluginFactory
+
 class LambdaTest extends GroovyTestCase {
     private static final boolean SKIP_ERRORS = true;
+    private static final boolean PRE_JAVA8 = VMPluginFactory.getPlugin().getVersion() < 8;
 
     void testFunction() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -42,6 +47,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionScript() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -57,6 +64,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testBinaryOperator() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -76,6 +85,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testConsumer() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -96,6 +107,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testPredicate() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -117,6 +130,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testUnaryOperator() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -138,6 +153,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testBiConsumer() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -158,6 +175,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithLocalVariables() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -179,6 +198,8 @@ class LambdaTest extends GroovyTestCase {
 
 
     void testFunctionWithLocalVariables2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -200,6 +221,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithLocalVariables4() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -221,6 +244,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithStaticMethodCall() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -246,6 +271,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithStaticMethodCall2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -271,6 +298,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithInstanceMethodCall() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -294,6 +323,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionInConstructor() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -317,6 +348,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithInstanceMethodCall2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -340,6 +373,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithInstanceMethodCall3() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -363,6 +398,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionCall() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -384,6 +421,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionCall2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -405,6 +444,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionCall3() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -426,6 +467,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testConsumerCall() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -449,6 +492,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testConsumerCall2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -472,6 +517,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testConsumerCall3() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -495,6 +542,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testSamCall() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -520,6 +569,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testSamCall2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -545,6 +596,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithUpdatingLocalVariable() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -566,6 +619,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithUpdatingLocalVariable2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -587,6 +642,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithVariableDeclaration() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -609,6 +666,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithMixingVariableDeclarationAndMethodInvocation() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -637,6 +696,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithNestedLambda() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -664,6 +725,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithNestedLambda2() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors
@@ -689,6 +752,8 @@ class LambdaTest extends GroovyTestCase {
     }
 
     void testFunctionWithNestedLambda3() {
+        if (PRE_JAVA8) return;
+
         assertScript '''
         import groovy.transform.CompileStatic
         import java.util.stream.Collectors