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 2019/12/19 03:09:29 UTC

[groovy] branch GROOVY_3_0_X updated (a22dc2d -> c46093f)

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from a22dc2d  Fix javadoc issue
     new d241634  minor refactor
     new 73cbb4d  Improve robustness
     new 11cf59c  GROOVY-9341: fix "this" support for nested lambda expressions
     new da6bfa3  GROOVY-9342: load static "this" type for static access of properties
     new c46093f  GROOVY-6095, GROOVY-9338: check a wildcard's bounds instead of base type

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../java/org/codehaus/groovy/ast/GenericsType.java |  28 +-
 .../groovy/classgen/asm/ClosureWriter.java         |  76 ++---
 .../codehaus/groovy/classgen/asm/LambdaWriter.java |   9 +-
 .../groovy/classgen/asm/WriterController.java      |   5 +-
 .../classgen/asm/sc/StaticTypesLambdaWriter.java   | 376 +++++++++------------
 .../codehaus/groovy/control/CompilationUnit.java   |   2 +-
 .../codehaus/groovy/vmplugin/VMPluginFactory.java  |  38 ++-
 .../bugs/{Groovy8686.groovy => Groovy9338.groovy}  |  32 +-
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |  23 +-
 src/test/groovy/transform/stc/LambdaTest.groovy    |  18 +-
 .../java/org/codehaus/groovy/ant/VerifyClass.java  |  30 +-
 11 files changed, 324 insertions(+), 313 deletions(-)
 copy src/test/groovy/bugs/{Groovy8686.groovy => Groovy9338.groovy} (57%)


[groovy] 04/05: GROOVY-9342: load static "this" type for static access of properties

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit da6bfa3201ce9dd409af5eb0e1c53f5849d6c42e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Dec 18 19:30:11 2019 -0600

    GROOVY-9342: load static "this" type for static access of properties
    
    (cherry picked from commit 152bda0c62ea060a40de21abd46b5ed28f907b0b)
---
 .../org/codehaus/groovy/classgen/asm/WriterController.java |  5 ++---
 .../groovy/classgen/asm/sc/StaticTypesLambdaWriter.java    | 12 ++++++++----
 src/test/groovy/transform/stc/LambdaTest.groovy            | 14 +++++++++++++-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index 1db4a89..6eae8ab 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.classgen.asm;
 
 import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.InterfaceHelperClassNode;
@@ -41,6 +40,7 @@ import java.util.List;
 import java.util.Map;
 
 import static org.apache.groovy.util.SystemUtil.getBooleanSafe;
+import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
 
 public class WriterController {
 
@@ -283,8 +283,7 @@ public class WriterController {
     }
 
     public boolean isInClosure() {
-        return classNode.getOuterClass() != null
-                && ClassHelper.isGeneratedFunction(classNode);
+        return classNode.getOuterClass() != null && isGeneratedFunction(classNode);
     }
 
     public boolean isInClosureConstructor() {
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 67cf98e..b582e2f 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
@@ -28,7 +28,6 @@ import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.builder.AstStringCompiler;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.LambdaExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
@@ -60,6 +59,7 @@ import static org.codehaus.groovy.ast.ClassHelper.SERIALIZABLE_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.SERIALIZEDLAMBDA_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.findSAM;
+import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
 import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
@@ -175,7 +175,11 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
         mv.visitInsn(DUP);
 
         if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall() || !accessingInstanceMembers) {
-            operandStack.pushConstant(ConstantExpression.NULL);
+            ClassNode classNode = controller.getClassNode();
+            while (isGeneratedFunction(classNode)) {
+                classNode = classNode.getOuterClass();
+            }
+            classX(classNode).visit(controller.getAcg());
         } else {
             loadThis();
         }
@@ -209,9 +213,9 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
         return lambdaSharedVariableParameters;
     }
 
-    private String createAbstractMethodDesc(final ClassNode functionalInterface, final ClassNode lambdaClassNode) {
+    private String createAbstractMethodDesc(final ClassNode functionalInterface, final ClassNode lambdaClass) {
         List<Parameter> lambdaSharedVariables = new LinkedList<>();
-        prependParameter(lambdaSharedVariables, "__lambda_this", lambdaClassNode);
+        prependParameter(lambdaSharedVariables, "__lambda_this", lambdaClass);
         return BytecodeHelper.getMethodDescriptor(functionalInterface, lambdaSharedVariables.toArray(Parameter.EMPTY_ARRAY));
     }
 
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index ac3f138..d7b9553 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -1053,7 +1053,7 @@ final class LambdaTest {
     }
 
     @Test // GROOVY-9332
-    void testStaticInitializeBlocks() {
+    void testStaticInitializeBlocks1() {
         assertScript '''
             @groovy.transform.CompileStatic
             class Test1 {
@@ -1078,6 +1078,18 @@ final class LambdaTest {
         '''
     }
 
+    @Test // GROOVY-9342
+    void testStaticInitializeBlocks3() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Test1 {
+                static int acc = 1
+                static { [1, 2, 3].forEach((Integer i) -> acc += i) }
+            }
+            assert Test1.acc == 7
+        '''
+    }
+
     @Test
     void testAccessingThis1() {
         assertScript '''


[groovy] 05/05: GROOVY-6095, GROOVY-9338: check a wildcard's bounds instead of base type

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit c46093f0f7cdacd4c94af77a91748336e4cc2fc5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Dec 14 15:00:45 2019 -0600

    GROOVY-6095, GROOVY-9338: check a wildcard's bounds instead of base type
    
    (cherry picked from commit a553168a1937254e5904e2eb50d39df808bbc85a)
---
 .../java/org/codehaus/groovy/ast/GenericsType.java | 28 ++++++++--
 src/test/groovy/bugs/Groovy9338.groovy             | 60 ++++++++++++++++++++++
 src/test/groovy/transform/stc/BugsSTCTest.groovy   | 23 ++++++---
 3 files changed, 100 insertions(+), 11 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/GenericsType.java b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
index d63e59f..585cf57 100644
--- a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
+++ b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
@@ -415,8 +415,17 @@ public class GenericsType extends ASTNode {
                                         // check for recursive generic typedef, like in <T extends Comparable<? super T>>
                                         gt = classNodePlaceholders.getOrDefault(new GenericsTypeName(gt.getName()), gt);
                                     }
-                                    match = implementsInterfaceOrIsSubclassOf(gt.getType(), classNodeType.getType());
-
+                                    // GROOVY-6095, GROOVY-9338
+                                    if (classNodeType.isWildcard()) {
+                                        if (classNodeType.getLowerBound() != null
+                                                || classNodeType.getUpperBounds() != null) {
+                                            match = classNodeType.checkGenerics(gt.getType());
+                                        } else {
+                                            match = false; // "?" (from Comparable<?>) does not satisfy anything
+                                        }
+                                    } else {
+                                        match = implementsInterfaceOrIsSubclassOf(gt.getType(), classNodeType.getType());
+                                    }
                                 } else if (redirectBoundType.getUpperBounds() != null) {
                                     // ex: class Comparable<Integer> <=> bound Comparable<? extends T & I>
                                     for (ClassNode upperBound : redirectBoundType.getUpperBounds()) {
@@ -425,9 +434,18 @@ public class GenericsType extends ASTNode {
                                             // check for recursive generic typedef, like in <T extends Comparable<? super T>>
                                             gt = classNodePlaceholders.getOrDefault(new GenericsTypeName(gt.getName()), gt);
                                         }
-                                        match = implementsInterfaceOrIsSubclassOf(classNodeType.getType(), gt.getType())
-                                                || classNodeType.isCompatibleWith(gt.getType()); // workaround for GROOVY-6095
-
+                                        // GROOVY-6095, GROOVY-9338
+                                        if (classNodeType.isWildcard()) {
+                                            if (classNodeType.getLowerBound() != null) {
+                                                match = gt.checkGenerics(classNodeType.getLowerBound());
+                                            } else if (classNodeType.getUpperBounds() != null) {
+                                                match = gt.checkGenerics(classNodeType.getUpperBounds()[0]);
+                                            } else {
+                                                match = false; // "?" (from Comparable<?>) does not satisfy anything
+                                            }
+                                        } else {
+                                            match = implementsInterfaceOrIsSubclassOf(classNodeType.getType(), gt.getType());
+                                        }
                                         if (!match) break;
                                     }
                                 }
diff --git a/src/test/groovy/bugs/Groovy9338.groovy b/src/test/groovy/bugs/Groovy9338.groovy
new file mode 100644
index 0000000..34813f8
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9338.groovy
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy9338 {
+
+    @Test
+    void testGenericsUnsatisfied1() {
+        def err = shouldFail '''
+            void meth(Class<? extends CharSequence> c) {
+                print c.simpleName
+            }
+            @groovy.transform.CompileStatic
+            void test() {
+                def c = (Class<?>) String.class\n
+                meth(c)
+            }
+            test()
+        '''
+        assert err =~ /Cannot call \w+#meth\(java.lang.Class <\? extends java.lang.CharSequence>\) with arguments \[java.lang.Class <\?>\]/
+    }
+
+    @Test
+    void testGenericsUnsatisfied2() {
+        def err = shouldFail '''
+            void meth(Class<? super CharSequence> c) {
+                print c.simpleName
+            }
+            @groovy.transform.CompileStatic
+            void test() {
+                def c = (Class<?>) String.class\n
+                meth(c)
+            }
+            test()
+        '''
+        assert err =~ /Cannot call \w+#meth\(java.lang.Class <\? super java.lang.CharSequence>\) with arguments \[java.lang.Class <\?>\]/
+    }
+}
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index 37e0a99..28b1d77 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -151,13 +151,24 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
 
     void testGroovy7477NullGenericsType() {
         assertScript '''
-        class L<E> extends ArrayList<E> {
-            boolean removeIf(Comparator<? super E> filter) { }
-        }
-        L<String> items = ['foo', 'bar'] as L<String>
-        items.removeIf({a, b -> 1} as Comparator<?>)
-        assert items
+            class L<E> extends ArrayList<E> {
+                boolean removeIf(Comparator<? super E> filter) {
+                }
+            }
+            def items = ['foo', 'bar'] as L<String>
+            items.removeIf({a, b -> 1} as Comparator<String>)
+            assert items
         '''
+
+        shouldFailWithMessages '''
+            class L<E> extends ArrayList<E> {
+                boolean removeIf(Comparator<? super E> filter) {
+                }
+            }
+            L<String> items = ['foo', 'bar'] as L<String>
+            items.removeIf({a, b -> 1} as Comparator<?>)
+            assert items
+        ''', 'Cannot call L <String>#removeIf(java.util.Comparator <? super java.lang.String>) with arguments [java.util.Comparator <?>]'
     }
 
     void testGroovy5482ListsAndFlowTyping() {


[groovy] 03/05: GROOVY-9341: fix "this" support for nested lambda expressions

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 11cf59c0d4a7a67cc695c11193236f4b8e32c557
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Dec 18 18:29:03 2019 -0600

    GROOVY-9341: fix "this" support for nested lambda expressions
    
    ClosureWriter#loadThis() writes call to Closure#getThisObject()
    
    (cherry picked from commit 3a883ef8b3a5fc71352dbf95c6f741d10e99e203)
---
 .../org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java  | 3 +--
 src/test/groovy/transform/stc/LambdaTest.groovy                       | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

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 cfce5c5..67cf98e 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
@@ -177,8 +177,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
         if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall() || !accessingInstanceMembers) {
             operandStack.pushConstant(ConstantExpression.NULL);
         } else {
-            mv.visitVarInsn(ALOAD, 0);
-            operandStack.push(controller.getClassNode());
+            loadThis();
         }
 
         operandStack.dup();
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 48cf528..ac3f138 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -1031,7 +1031,7 @@ final class LambdaTest {
         '''
     }
 
-    @Test @NotYetImplemented
+    @Test
     void testNestedLambdaAccessingInstanceFields() {
         assertScript '''
             @groovy.transform.CompileStatic
@@ -1097,7 +1097,7 @@ final class LambdaTest {
         '''
     }
 
-    @Test @NotYetImplemented
+    @Test
     void testAccessingThis2() {
         assertScript '''
             @groovy.transform.CompileStatic


[groovy] 02/05: Improve robustness

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 73cbb4d41f218deadcf830b929c2f9544795e8e2
Author: Daniel Sun <su...@apache.org>
AuthorDate: Thu Dec 19 08:23:46 2019 +0800

    Improve robustness
    
    (cherry picked from commit 2737292fcc9b0a16e1fdd90d7a0347e083bd7cec)
---
 .../codehaus/groovy/vmplugin/VMPluginFactory.java  | 38 +++++++++++++++-------
 .../java/org/codehaus/groovy/ant/VerifyClass.java  | 30 ++++++++++-------
 2 files changed, 46 insertions(+), 22 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/vmplugin/VMPluginFactory.java b/src/main/java/org/codehaus/groovy/vmplugin/VMPluginFactory.java
index f6cf64a..679c1b6 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/VMPluginFactory.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/VMPluginFactory.java
@@ -18,14 +18,21 @@
  */
 package org.codehaus.groovy.vmplugin;
 
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.vmplugin.v7.Java7;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
 /**
  * Factory class to get functionality based on the VM version.
  * The usage of this class is not for public use, only for the
  * runtime.
  */
 public class VMPluginFactory {
+    private static final Logger LOGGER = Logger.getLogger(VMPluginFactory.class.getName());
 
     private static final String JDK8_CLASSNAME_CHECK = "java.util.Optional";
     private static final String JDK9_CLASSNAME_CHECK = "java.lang.Module";
@@ -33,7 +40,7 @@ public class VMPluginFactory {
     private static final String JDK8_PLUGIN_NAME = "org.codehaus.groovy.vmplugin.v8.Java8";
     private static final String JDK9_PLUGIN_NAME = "org.codehaus.groovy.vmplugin.v9.Java9";
 
-    private static final VMPlugin plugin;
+    private static final VMPlugin PLUGIN;
 
     static {
         VMPlugin target = createPlugin(JDK9_CLASSNAME_CHECK, JDK9_PLUGIN_NAME);
@@ -43,20 +50,29 @@ public class VMPluginFactory {
                 target = new Java7();
             }
         }
-        plugin = target;
+
+        PLUGIN = target;
     }
 
     public static VMPlugin getPlugin() {
-        return plugin;
+        return PLUGIN;
     }
 
-    private static VMPlugin createPlugin(String classNameCheck, String pluginName) {
-        try {
-            ClassLoader loader = VMPluginFactory.class.getClassLoader();
-            loader.loadClass(classNameCheck);
-            return (VMPlugin) loader.loadClass(pluginName).getDeclaredConstructor().newInstance();
-        } catch (Throwable ex) {
-            return null;
-        }
+    private static VMPlugin createPlugin(final String classNameCheck, final String pluginName) {
+        return AccessController.doPrivileged((PrivilegedAction<VMPlugin>) () -> {
+            try {
+                ClassLoader loader = VMPluginFactory.class.getClassLoader();
+                loader.loadClass(classNameCheck);
+                return (VMPlugin) loader.loadClass(pluginName).getDeclaredConstructor().newInstance();
+            } catch (Throwable t) {
+                if (LOGGER.isLoggable(Level.FINE)) {
+                    LOGGER.fine("Trying to create VM plugin `" + pluginName + "` by checking `" + classNameCheck
+                            + "`, but failed:\n" + DefaultGroovyMethods.asString(t)
+                    );
+                }
+
+                return null;
+            }
+        });
     }
 }
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/VerifyClass.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/VerifyClass.java
index f660d40..975c4c5 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/VerifyClass.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/VerifyClass.java
@@ -31,9 +31,11 @@ import org.objectweb.asm.tree.analysis.SimpleVerifier;
 import org.objectweb.asm.util.CheckClassAdapter;
 import org.objectweb.asm.util.TraceMethodVisitor;
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.List;
 
 /**
@@ -94,18 +96,24 @@ public class VerifyClass extends MatchingTask {
     }
 
     private boolean readClass(String clazz) throws IOException {
-        ClassReader cr = new ClassReader(new FileInputStream(clazz));
-        ClassNode ca = new ClassNode() {
-            public void visitEnd() {
-                //accept(cv);
-            }
-        };
-        cr.accept(new CheckClassAdapter(ca), ClassWriter.COMPUTE_MAXS);
-        boolean failed = false;
+        ClassNode ca;
+        try (final InputStream inputStream =
+                     new BufferedInputStream(
+                             new FileInputStream(clazz))) {
+            ClassReader cr = new ClassReader(inputStream);
+            ca = new ClassNode() {
+                @Override
+                public void visitEnd() {
+                    //accept(cv);
+                }
+            };
+            cr.accept(new CheckClassAdapter(ca), ClassWriter.COMPUTE_MAXS);
+        }
 
-        List methods = ca.methods;
-        for (int i = 0; i < methods.size(); ++i) {
-            MethodNode method = (MethodNode) methods.get(i);
+        boolean failed = false;
+        List<MethodNode> methods = ca.methods;
+        for (int i = 0, n = methods.size(); i < n; ++i) {
+            MethodNode method = methods.get(i);
             if (method.instructions.size() > 0) {
                 Analyzer a = new Analyzer(new SimpleVerifier());
                 try {


[groovy] 01/05: minor refactor

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit d24163444b25f4f79e573f771136bfe60155868a
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Dec 18 17:13:29 2019 -0600

    minor refactor
    
    (cherry picked from commit f682375eab8f75d41781a6e5e9ce8815ab7836dd)
---
 .../groovy/classgen/asm/ClosureWriter.java         |  76 ++---
 .../codehaus/groovy/classgen/asm/LambdaWriter.java |   9 +-
 .../classgen/asm/sc/StaticTypesLambdaWriter.java   | 371 +++++++++------------
 .../codehaus/groovy/control/CompilationUnit.java   |   2 +-
 4 files changed, 197 insertions(+), 261 deletions(-)

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 4b6cfc9..7156dd9 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -70,17 +70,14 @@ public class ClosureWriter {
 
     protected interface UseExistingReference {}
 
-    private final Map<Expression,ClassNode> closureClassMap;
-    private final WriterController controller;
-    private final WriterControllerFactory factory;
-
-    public ClosureWriter(WriterController wc) {
-        this.controller = wc;
-        closureClassMap = new HashMap<Expression,ClassNode>();
-        factory = normalController -> controller;
+    protected final WriterController controller;
+    private final Map<Expression,ClassNode> closureClasses = new HashMap<>();
+
+    public ClosureWriter(final WriterController controller) {
+        this.controller = controller;
     }
 
-    public void writeClosure(ClosureExpression expression) {
+    public void writeClosure(final ClosureExpression expression) {
         CompileStack compileStack = controller.getCompileStack();
         MethodVisitor mv = controller.getMethodVisitor();
         ClassNode classNode = controller.getClassNode();
@@ -94,8 +91,8 @@ public class ClosureWriter {
         }
         ClassNode closureClass = getOrAddClosureClass(expression, mods);
         String closureClassinternalName = BytecodeHelper.getClassInternalName(closureClass);
-        List constructors = closureClass.getDeclaredConstructors();
-        ConstructorNode node = (ConstructorNode) constructors.get(0);
+        List<ConstructorNode> constructors = closureClass.getDeclaredConstructors();
+        ConstructorNode node = constructors.get(0);
 
         Parameter[] localVariableParams = node.getParameters();
 
@@ -128,13 +125,13 @@ public class ClosureWriter {
         mv.visitMethodInsn(INVOKESPECIAL, closureClassinternalName, "<init>", BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, localVariableParams), false);
         controller.getOperandStack().replace(ClassHelper.CLOSURE_TYPE, localVariableParams.length);
     }
-    
-    public static void loadReference(String name, WriterController controller) {
+
+    public static void loadReference(final String name, final WriterController controller) {
         CompileStack compileStack = controller.getCompileStack();
         MethodVisitor mv = controller.getMethodVisitor();
         ClassNode classNode = controller.getClassNode();
         AsmClassGenerator acg = controller.getAcg();
-        
+
         // compileStack.containsVariable(name) means to ask if the variable is already declared
         // compileStack.getScope().isReferencedClassVariable(name) means to ask if the variable is a field
         // If it is no field and is not yet declared, then it is either a closure shared variable or
@@ -158,19 +155,19 @@ public class ClosureWriter {
         }
     }
 
-    public ClassNode getOrAddClosureClass(ClosureExpression expression, int mods) {
-        ClassNode closureClass = closureClassMap.get(expression);
+    public ClassNode getOrAddClosureClass(final ClosureExpression expression, final int modifiers) {
+        ClassNode closureClass = closureClasses.get(expression);
         if (closureClass == null) {
-            closureClass = createClosureClass(expression, mods);
-            closureClassMap.put(expression, closureClass);
+            closureClass = createClosureClass(expression, modifiers);
+            closureClasses.put(expression, closureClass);
             controller.getAcg().addInnerClass(closureClass);
             closureClass.addInterface(ClassHelper.GENERATED_CLOSURE_Type);
-            closureClass.putNodeMetaData(WriterControllerFactory.class, factory);
+            closureClass.putNodeMetaData(WriterControllerFactory.class, (WriterControllerFactory) x -> controller);
         }
         return closureClass;
     }
 
-    private static boolean classNodeUsesReferences(ClassNode classNode) {
+    private static boolean classNodeUsesReferences(final ClassNode classNode) {
         boolean ret = classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE;
         if (ret) return ret;
         if (classNode instanceof InnerClassNode) {
@@ -179,11 +176,10 @@ public class ClosureWriter {
         }
         return false;
     }
-    
-    protected ClassNode createClosureClass(ClosureExpression expression, int mods) {
+
+    protected ClassNode createClosureClass(final ClosureExpression expression, final int modifiers) {
         ClassNode classNode = controller.getClassNode();
         ClassNode outerClass = controller.getOutermostClass();
-//        MethodNode methodNode = controller.getMethodNode();
         String name = genClosureClassName();
         boolean staticMethodOrInStaticClass = controller.isStaticMethod() || classNode.isStaticClass();
 
@@ -201,7 +197,7 @@ public class ClosureWriter {
         Parameter[] localVariableParams = getClosureSharedVariables(expression);
         removeInitialValues(localVariableParams);
 
-        InnerClassNode answer = new InnerClassNode(classNode, name, mods, ClassHelper.CLOSURE_TYPE.getPlainNodeReference()); 
+        InnerClassNode answer = new InnerClassNode(classNode, name, modifiers, ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
         answer.setEnclosingMethod(controller.getMethodNode());
         answer.setSynthetic(true);
         answer.setUsingGenerics(outerClass.isUsingGenerics());
@@ -253,13 +249,13 @@ public class ClosureWriter {
         addFieldsAndGettersForLocalVariables(answer, localVariableParams);
 
         addConstructor(expression, localVariableParams, answer, block);
-        
+
         correctAccessedVariable(answer,expression);
-        
+
         return answer;
     }
 
-    protected ConstructorNode addConstructor(ClosureExpression expression, Parameter[] localVariableParams, InnerClassNode answer, BlockStatement block) {
+    protected ConstructorNode addConstructor(final ClosureExpression expression, final Parameter[] localVariableParams, final InnerClassNode answer, final BlockStatement block) {
         Parameter[] params = new Parameter[2 + localVariableParams.length];
         params[0] = new Parameter(ClassHelper.OBJECT_TYPE, OUTER_INSTANCE);
         params[1] = new Parameter(ClassHelper.OBJECT_TYPE, THIS_OBJECT);
@@ -271,7 +267,7 @@ public class ClosureWriter {
         return constructorNode;
     }
 
-    protected void addFieldsAndGettersForLocalVariables(InnerClassNode answer, Parameter[] localVariableParams) {
+    protected void addFieldsAndGettersForLocalVariables(final InnerClassNode answer, final Parameter[] localVariableParams) {
         for (Parameter param : localVariableParams) {
             String paramName = param.getName();
             ClassNode type = param.getType();
@@ -298,7 +294,7 @@ public class ClosureWriter {
         }
     }
 
-    protected BlockStatement createBlockStatementForConstructor(ClosureExpression expression, ClassNode outerClass, ClassNode thisClassNode) {
+    protected BlockStatement createBlockStatementForConstructor(final ClosureExpression expression, final ClassNode outerClass, final ClassNode thisClassNode) {
         BlockStatement block = new BlockStatement();
         // this block does not get a source position, because we don't
         // want this synthetic constructor to show up in corbertura reports
@@ -329,12 +325,12 @@ public class ClosureWriter {
     protected static class CorrectAccessedVariableVisitor extends CodeVisitorSupport {
         private InnerClassNode icn;
 
-        public CorrectAccessedVariableVisitor(InnerClassNode icn) {
+        public CorrectAccessedVariableVisitor(final InnerClassNode icn) {
             this.icn = icn;
         }
 
         @Override
-        public void visitVariableExpression(VariableExpression expression) {
+        public void visitVariableExpression(final VariableExpression expression) {
             Variable v = expression.getAccessedVariable();
             if (v == null) return;
             if (!(v instanceof FieldNode)) return;
@@ -346,7 +342,7 @@ public class ClosureWriter {
         }
     }
 
-    private static void correctAccessedVariable(final InnerClassNode closureClass, ClosureExpression ce) {
+    private static void correctAccessedVariable(final InnerClassNode closureClass, final ClosureExpression ce) {
         new CorrectAccessedVariableVisitor(closureClass).visitClosureExpression(ce);
     }
 
@@ -357,7 +353,7 @@ public class ClosureWriter {
      * same method, in this case the constructor. A closure should not
      * have more than one constructor!
      */
-    protected static void removeInitialValues(Parameter[] params) {
+    protected static void removeInitialValues(final Parameter[] params) {
         for (int i = 0; i < params.length; i++) {
             if (params[i].hasInitialExpression()) {
                 Parameter p = new Parameter(params[i].getType(), params[i].getName());
@@ -367,13 +363,13 @@ public class ClosureWriter {
         }
     }
 
-    public boolean addGeneratedClosureConstructorCall(ConstructorCallExpression call) {
+    public boolean addGeneratedClosureConstructorCall(final ConstructorCallExpression call) {
         ClassNode classNode = controller.getClassNode();
         if (!classNode.declaresInterface(ClassHelper.GENERATED_CLOSURE_Type)) return false;
 
         AsmClassGenerator acg = controller.getAcg();
         OperandStack operandStack = controller.getOperandStack();
-        
+
         MethodVisitor mv = controller.getMethodVisitor();
         mv.visitVarInsn(ALOAD, 0);
         ClassNode callNode = classNode.getSuperClass();
@@ -391,12 +387,12 @@ public class ClosureWriter {
         return true;
     }
 
-    protected Parameter[] getClosureSharedVariables(ClosureExpression ce) {
+    protected Parameter[] getClosureSharedVariables(final ClosureExpression ce) {
         VariableScope scope = ce.getVariableScope();
         Parameter[] ret = new Parameter[scope.getReferencedLocalVariablesCount()];
         int index = 0;
-        for (Iterator iter = scope.getReferencedLocalVariablesIterator(); iter.hasNext();) {
-            Variable element = (org.codehaus.groovy.ast.Variable) iter.next();
+        for (Iterator<Variable> iter = scope.getReferencedLocalVariablesIterator(); iter.hasNext();) {
+            Variable element = iter.next();
             Parameter p = new Parameter(element.getType(), element.getName());
             p.setOriginType(element.getOriginType());
             p.setClosureSharedVariable(element.isClosureSharedVariable());
@@ -405,8 +401,8 @@ public class ClosureWriter {
         }
         return ret;
     }
-    
-    private void loadThis() {
+
+    protected void loadThis() {
         MethodVisitor mv = controller.getMethodVisitor();
         mv.visitVarInsn(ALOAD, 0);
         if (controller.isInClosure()) {
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
index 6c0b53d..d1536bb 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java
@@ -22,15 +22,16 @@ import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.LambdaExpression;
 
 public class LambdaWriter extends ClosureWriter {
-    public LambdaWriter(WriterController wc) {
-        super(wc);
+
+    public LambdaWriter(final WriterController controller) {
+        super(controller);
     }
 
-    public void writeLambda(LambdaExpression expression) {
+    public void writeLambda(final LambdaExpression expression) {
         super.writeClosure(expression);
     }
 
-    protected Parameter[] getLambdaSharedVariables(LambdaExpression expression) {
+    protected Parameter[] getLambdaSharedVariables(final LambdaExpression expression) {
         return super.getClosureSharedVariables(expression);
     }
 }
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 05dae39..cfce5c5 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
@@ -16,20 +16,17 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.codehaus.groovy.classgen.asm.sc;
 
-import org.apache.groovy.util.ObjectHolder;
 import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.CodeVisitorSupport;
 import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.builder.AstStringCompiler;
-import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
@@ -45,7 +42,6 @@ import org.codehaus.groovy.classgen.asm.LambdaWriter;
 import org.codehaus.groovy.classgen.asm.OperandStack;
 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.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 import org.objectweb.asm.MethodVisitor;
@@ -55,10 +51,19 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.stream.Collectors;
+import java.util.Optional;
 
+import static org.codehaus.groovy.ast.ClassHelper.CLOSURE_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.GENERATED_LAMBDA_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.SERIALIZABLE_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.SERIALIZEDLAMBDA_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.findSAM;
+import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
@@ -80,266 +85,229 @@ import static org.objectweb.asm.Opcodes.NEW;
  * Writer responsible for generating lambda classes in statically compiled mode.
  */
 public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFunctionalInterfaceWriter {
-    private static final String DO_CALL = "doCall";
-    private static final String LAMBDA_SHARED_VARIABLES = "__LAMBDA_SHARED_VARIABLES";
-    private static final String LAMBDA_THIS = "__lambda_this";
-    private static final String INIT = "<init>";
+
     private static final String IS_GENERATED_CONSTRUCTOR = "__IS_GENERATED_CONSTRUCTOR";
+    private static final String LAMBDA_SHARED_VARIABLES = "__LAMBDA_SHARED_VARIABLES";
+
     private final StaticTypesClosureWriter staticTypesClosureWriter;
-    private final WriterController controller;
-    private final WriterControllerFactory factory;
-    private final Map<Expression,ClassNode> lambdaClassMap = new HashMap<>();
-
-    public StaticTypesLambdaWriter(WriterController wc) {
-        super(wc);
-        this.staticTypesClosureWriter = new StaticTypesClosureWriter(wc);
-        this.controller = wc;
-        this.factory = normalController -> controller;
+    private final Map<Expression, ClassNode> lambdaClassNodes = new HashMap<>();
+
+    public StaticTypesLambdaWriter(final WriterController controller) {
+        super(controller);
+        this.staticTypesClosureWriter = new StaticTypesClosureWriter(controller);
     }
 
     @Override
-    public void writeLambda(LambdaExpression expression) {
-        ClassNode functionalInterfaceType = getFunctionalInterfaceType(expression);
-        if (null == functionalInterfaceType) {
-            // if the parameter type failed to be inferred, generate the default bytecode, which is actually a closure
+    public void writeLambda(final LambdaExpression expression) {
+        ClassNode functionalInterface = getFunctionalInterfaceType(expression);
+        if (functionalInterface == null || !functionalInterface.isInterface()) {
             super.writeLambda(expression);
             return;
         }
 
-        ClassNode redirect = functionalInterfaceType.redirect();
-        if (!ClassHelper.isFunctionalInterface(redirect)) {
-            // if the parameter type is not real FunctionalInterface, generate the default bytecode, which is actually a closure
+        MethodNode abstractMethod = findSAM(functionalInterface.redirect());
+        if (abstractMethod == null) {
             super.writeLambda(expression);
             return;
         }
 
-        boolean implementsSerializable = functionalInterfaceType.implementsInterface(SERIALIZABLE_TYPE);
-        expression.setSerializable(expression.isSerializable() || implementsSerializable);
-
-        MethodNode abstractMethodNode = ClassHelper.findSAM(redirect);
-        String abstractMethodDesc = createMethodDescriptor(abstractMethodNode);
-
-        ClassNode classNode = controller.getClassNode();
-
-        boolean isInterface = classNode.isInterface();
-        ClassNode lambdaWrapperClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC | ACC_FINAL | (isInterface ? ACC_STATIC : 0) | ACC_SYNTHETIC, abstractMethodNode);
-        MethodNode syntheticLambdaMethodNode = lambdaWrapperClassNode.getMethods(DO_CALL).get(0);
+        if (!expression.isSerializable() && functionalInterface.implementsInterface(SERIALIZABLE_TYPE)) {
+            expression.setSerializable(true);
+        }
 
-        boolean canDeserialize = classNode.hasMethod(createDeserializeLambdaMethodName(lambdaWrapperClassNode), createDeserializeLambdaMethodParams());
+        ClassNode enclosingClass = controller.getClassNode();
+        int modifiers = ACC_FINAL | ACC_PUBLIC | ACC_SYNTHETIC;
+        if (enclosingClass.isInterface()) modifiers |= ACC_STATIC;
+        ClassNode lambdaClass = getOrAddLambdaClass(expression, modifiers, abstractMethod);
+        MethodNode lambdaMethod = lambdaClass.getMethods("doCall").get(0);
 
+        boolean canDeserialize = enclosingClass.hasMethod(createDeserializeLambdaMethodName(lambdaClass), createDeserializeLambdaMethodParams());
         if (!canDeserialize) {
             if (expression.isSerializable()) {
-                addDeserializeLambdaMethodForEachLambdaExpression(expression, lambdaWrapperClassNode);
+                addDeserializeLambdaMethodForEachLambdaExpression(expression, lambdaClass);
                 addDeserializeLambdaMethod();
             }
-
-            boolean accessingInstanceMembers = isAccessingInstanceMembersOfEnclosingClass(syntheticLambdaMethodNode);
-            newGroovyLambdaWrapperAndLoad(lambdaWrapperClassNode, expression, accessingInstanceMembers);
+            newGroovyLambdaWrapperAndLoad(lambdaClass, expression, isAccessingInstanceMembersOfEnclosingClass(lambdaMethod));
         }
 
         MethodVisitor mv = controller.getMethodVisitor();
-        OperandStack operandStack = controller.getOperandStack();
-
         mv.visitInvokeDynamicInsn(
-                abstractMethodNode.getName(),
-                createAbstractMethodDesc(functionalInterfaceType, lambdaWrapperClassNode),
-                createBootstrapMethod(isInterface, expression.isSerializable()),
-                createBootstrapMethodArguments(abstractMethodDesc, H_INVOKEVIRTUAL, lambdaWrapperClassNode, syntheticLambdaMethodNode, expression.isSerializable())
+                abstractMethod.getName(),
+                createAbstractMethodDesc(functionalInterface.redirect(), lambdaClass),
+                createBootstrapMethod(enclosingClass.isInterface(), expression.isSerializable()),
+                createBootstrapMethodArguments(createMethodDescriptor(abstractMethod), H_INVOKEVIRTUAL, lambdaClass, lambdaMethod, expression.isSerializable())
         );
-
         if (expression.isSerializable()) {
             mv.visitTypeInsn(CHECKCAST, "java/io/Serializable");
         }
 
-        operandStack.replace(redirect, 1);
+        OperandStack operandStack = controller.getOperandStack();
+        operandStack.replace(functionalInterface.redirect(), 1);
     }
 
-    private Parameter[] createDeserializeLambdaMethodParams() {
-        return new Parameter[]{new Parameter(ClassHelper.SERIALIZEDLAMBDA_TYPE, SERIALIZED_LAMBDA_PARAM_NAME)};
+    private static Parameter[] createDeserializeLambdaMethodParams() {
+        return new Parameter[]{new Parameter(SERIALIZEDLAMBDA_TYPE, "serializedLambda")};
     }
 
-    private void loadEnclosingClassInstance(boolean accessingInstanceMembers) {
-        MethodVisitor mv = controller.getMethodVisitor();
-        OperandStack operandStack = controller.getOperandStack();
-        CompileStack compileStack = controller.getCompileStack();
+    private static boolean isAccessingInstanceMembersOfEnclosingClass(final MethodNode syntheticLambdaMethodNode) {
+        boolean[] result = new boolean[1];
 
-        if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall() || !accessingInstanceMembers) {
-            operandStack.pushConstant(ConstantExpression.NULL);
-        } else {
-            mv.visitVarInsn(ALOAD, 0);
-            operandStack.push(controller.getClassNode());
-        }
-    }
-
-    private boolean isAccessingInstanceMembersOfEnclosingClass(MethodNode syntheticLambdaMethodNode) {
-        ObjectHolder<Boolean> objectHolder = new ObjectHolder<>(false);
-        ClassCodeVisitorSupport classCodeVisitorSupport = new ClassCodeVisitorSupport() {
+        GroovyCodeVisitor visitor = new CodeVisitorSupport() {
             @Override
-            public void visitVariableExpression(VariableExpression expression) {
+            public void visitVariableExpression(final VariableExpression expression) {
                 if (expression.isThisExpression()) {
-                    objectHolder.setObject(true);
+                    result[0] = true;
                 }
             }
-
-            @Override
-            protected SourceUnit getSourceUnit() {
-                return null;
-            }
         };
+        syntheticLambdaMethodNode.getCode().visit(visitor);
 
-        classCodeVisitorSupport.visitMethod(syntheticLambdaMethodNode);
-
-        return objectHolder.getObject();
+        return result[0];
     }
 
-    private void newGroovyLambdaWrapperAndLoad(ClassNode lambdaWrapperClassNode, LambdaExpression expression, boolean accessingInstanceMembers) {
+    private void newGroovyLambdaWrapperAndLoad(final ClassNode lambdaClass, final LambdaExpression expression, final boolean accessingInstanceMembers) {
+        CompileStack compileStack = controller.getCompileStack();
+        OperandStack operandStack = controller.getOperandStack();
         MethodVisitor mv = controller.getMethodVisitor();
-        String lambdaWrapperClassInternalName = BytecodeHelper.getClassInternalName(lambdaWrapperClassNode);
-        mv.visitTypeInsn(NEW, lambdaWrapperClassInternalName);
+
+        String lambdaClassInternalName = BytecodeHelper.getClassInternalName(lambdaClass);
+        mv.visitTypeInsn(NEW, lambdaClassInternalName);
         mv.visitInsn(DUP);
 
-        loadEnclosingClassInstance(accessingInstanceMembers);
-        controller.getOperandStack().dup();
+        if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall() || !accessingInstanceMembers) {
+            operandStack.pushConstant(ConstantExpression.NULL);
+        } else {
+            mv.visitVarInsn(ALOAD, 0);
+            operandStack.push(controller.getClassNode());
+        }
+
+        operandStack.dup();
 
         loadSharedVariables(expression);
 
-        List<ConstructorNode> constructorNodeList =
-                lambdaWrapperClassNode.getDeclaredConstructors().stream()
-                        .filter(e -> Boolean.TRUE.equals(e.getNodeMetaData(IS_GENERATED_CONSTRUCTOR)))
-                        .collect(Collectors.toList());
-
-        if (constructorNodeList.size() == 0) {
+        Optional<ConstructorNode> generatedConstructor = lambdaClass.getDeclaredConstructors().stream()
+                .filter(ctor -> Boolean.TRUE.equals(ctor.getNodeMetaData(IS_GENERATED_CONSTRUCTOR))).findFirst();
+        if (!generatedConstructor.isPresent()) {
             throw new GroovyBugError("Failed to find the generated constructor");
         }
 
-        ConstructorNode constructorNode = constructorNodeList.get(0);
-        Parameter[] lambdaWrapperClassConstructorParameters = constructorNode.getParameters();
-        mv.visitMethodInsn(INVOKESPECIAL, lambdaWrapperClassInternalName, INIT, BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, lambdaWrapperClassConstructorParameters), lambdaWrapperClassNode.isInterface());
-        OperandStack operandStack = controller.getOperandStack();
-        operandStack.replace(ClassHelper.CLOSURE_TYPE, lambdaWrapperClassConstructorParameters.length);
+        Parameter[] lambdaClassConstructorParameters = generatedConstructor.get().getParameters();
+        mv.visitMethodInsn(INVOKESPECIAL, lambdaClassInternalName, "<init>", BytecodeHelper.getMethodDescriptor(VOID_TYPE, lambdaClassConstructorParameters), lambdaClass.isInterface());
+
+        operandStack.replace(CLOSURE_TYPE, lambdaClassConstructorParameters.length);
     }
 
-    private Parameter[] loadSharedVariables(LambdaExpression expression) {
+    private Parameter[] loadSharedVariables(final LambdaExpression expression) {
         Parameter[] lambdaSharedVariableParameters = expression.getNodeMetaData(LAMBDA_SHARED_VARIABLES);
+
         for (Parameter parameter : lambdaSharedVariableParameters) {
-            String parameterName = parameter.getName();
-            loadReference(parameterName, controller);
-            if (parameter.getNodeMetaData(LambdaWriter.UseExistingReference.class) == null) {
-                parameter.setNodeMetaData(LambdaWriter.UseExistingReference.class, Boolean.TRUE);
+            loadReference(parameter.getName(), controller);
+            if (parameter.getNodeMetaData(UseExistingReference.class) == null) {
+                parameter.setNodeMetaData(UseExistingReference.class, Boolean.TRUE);
             }
         }
 
         return lambdaSharedVariableParameters;
     }
 
-    private String createAbstractMethodDesc(ClassNode functionalInterfaceType, ClassNode lambdaClassNode) {
-        List<Parameter> lambdaSharedVariableList = new LinkedList<>();
-
-        prependParameter(lambdaSharedVariableList, LAMBDA_THIS, lambdaClassNode);
-
-        return BytecodeHelper.getMethodDescriptor(functionalInterfaceType.redirect(), lambdaSharedVariableList.toArray(Parameter.EMPTY_ARRAY));
+    private String createAbstractMethodDesc(final ClassNode functionalInterface, final ClassNode lambdaClassNode) {
+        List<Parameter> lambdaSharedVariables = new LinkedList<>();
+        prependParameter(lambdaSharedVariables, "__lambda_this", lambdaClassNode);
+        return BytecodeHelper.getMethodDescriptor(functionalInterface, lambdaSharedVariables.toArray(Parameter.EMPTY_ARRAY));
     }
 
-    public ClassNode getOrAddLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) {
-        ClassNode lambdaClass = lambdaClassMap.get(expression);
-        if (lambdaClass == null) {
-            lambdaClass = createLambdaClass(expression, mods, abstractMethodNode);
-            lambdaClassMap.put(expression, lambdaClass);
+    private ClassNode getOrAddLambdaClass(final LambdaExpression expression, final int modifiers, final MethodNode abstractMethod) {
+        return lambdaClassNodes.computeIfAbsent(expression, key -> {
+            ClassNode lambdaClass = createLambdaClass(expression, modifiers, abstractMethod);
             controller.getAcg().addInnerClass(lambdaClass);
-            lambdaClass.addInterface(ClassHelper.GENERATED_LAMBDA_TYPE);
-            lambdaClass.putNodeMetaData(WriterControllerFactory.class, factory);
-        }
-        lambdaClass.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, Boolean.TRUE);
-        return lambdaClass;
+            lambdaClass.addInterface(GENERATED_LAMBDA_TYPE);
+            lambdaClass.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, Boolean.TRUE);
+            lambdaClass.putNodeMetaData(WriterControllerFactory.class, (WriterControllerFactory) x -> controller);
+            return lambdaClass;
+        });
+    }
+
+    @Override
+    protected ClassNode createClosureClass(final ClosureExpression expression, final int modifiers) {
+        return staticTypesClosureWriter.createClosureClass(expression, modifiers);
     }
 
-    protected ClassNode createLambdaClass(LambdaExpression expression, int mods, MethodNode abstractMethodNode) {
-        ClassNode outerClass = controller.getOutermostClass();
-        ClassNode classNode = controller.getClassNode();
-        String name = genLambdaClassName();
-        boolean staticMethodOrInStaticClass = controller.isStaticMethod() || classNode.isStaticClass();
+    protected ClassNode createLambdaClass(final LambdaExpression expression, final int modifiers, final MethodNode abstractMethod) {
+        ClassNode enclosingClass = controller.getClassNode();
+        ClassNode outermostClass = controller.getOutermostClass();
+        boolean staticMethodOrInStaticClass = (controller.isStaticMethod() || enclosingClass.isStaticClass());
 
-        InnerClassNode answer = new InnerClassNode(classNode, name, mods, ClassHelper.CLOSURE_TYPE.getPlainNodeReference());
-        answer.setEnclosingMethod(controller.getMethodNode());
-        answer.setSynthetic(true);
-        answer.setUsingGenerics(outerClass.isUsingGenerics());
-        answer.setSourcePosition(expression);
+        InnerClassNode lambdaClass = new InnerClassNode(enclosingClass, nextLambdaClassName(), modifiers, CLOSURE_TYPE.getPlainNodeReference());
+      //lambdaClass.setUsingGenerics(outermostClass.isUsingGenerics());
+        lambdaClass.setEnclosingMethod(controller.getMethodNode());
+        lambdaClass.setSourcePosition(expression);
+        lambdaClass.setSynthetic(true);
 
-        if (expression.isSerializable()) {
-            addSerialVersionUIDField(answer);
+        if (controller.isInScriptBody()) {
+            lambdaClass.setScriptBody(true);
         }
-
         if (staticMethodOrInStaticClass) {
-            answer.setStaticClass(true);
+            lambdaClass.setStaticClass(true);
         }
-        if (controller.isInScriptBody()) {
-            answer.setScriptBody(true);
+        if (expression.isSerializable()) {
+            addSerialVersionUIDField(lambdaClass);
         }
 
-        MethodNode syntheticLambdaMethodNode = addSyntheticLambdaMethodNode(expression, answer, abstractMethodNode);
+        MethodNode syntheticLambdaMethodNode = addSyntheticLambdaMethodNode(expression, lambdaClass, abstractMethod);
         Parameter[] localVariableParameters = expression.getNodeMetaData(LAMBDA_SHARED_VARIABLES);
 
-        addFieldsAndGettersForLocalVariables(answer, localVariableParameters);
-        ConstructorNode constructorNode = addConstructor(expression, localVariableParameters, answer, createBlockStatementForConstructor(expression, outerClass, classNode));
+        addFieldsAndGettersForLocalVariables(lambdaClass, localVariableParameters);
+        ConstructorNode constructorNode = addConstructor(expression, localVariableParameters, lambdaClass, createBlockStatementForConstructor(expression, outermostClass, enclosingClass));
         constructorNode.putNodeMetaData(IS_GENERATED_CONSTRUCTOR, Boolean.TRUE);
 
-        new LambdaBodyTransformationVisitor(answer).visitMethod(syntheticLambdaMethodNode);
+        syntheticLambdaMethodNode.getCode().visit(new CorrectAccessedVariableVisitor(lambdaClass));
 
-        return answer;
+        return lambdaClass;
     }
 
-    private void addSerialVersionUIDField(InnerClassNode answer) {
-        answer.addFieldFirst("serialVersionUID", ACC_PRIVATE | ACC_STATIC | ACC_FINAL, ClassHelper.long_TYPE, new ConstantExpression(-1L, true));
+    private String nextLambdaClassName() {
+        ClassNode enclosingClass = controller.getClassNode();
+        ClassNode outermostClass = controller.getOutermostClass();
+        return enclosingClass.getName() + "$" + controller.getContext().getNextLambdaInnerName(outermostClass, enclosingClass, controller.getMethodNode());
     }
 
-    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 static void addSerialVersionUIDField(final ClassNode lambdaClass) {
+        lambdaClass.addFieldFirst("serialVersionUID", ACC_PRIVATE | ACC_STATIC | ACC_FINAL, long_TYPE, constX(-1L, true));
     }
 
-    private MethodNode addSyntheticLambdaMethodNode(LambdaExpression expression, InnerClassNode answer, MethodNode abstractMethodNode) {
-        Parameter[] parametersWithExactType = createParametersWithExactType(expression); // expression.getParameters();
-//        ClassNode returnType = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); //abstractMethodNode.getReturnType();
+    private MethodNode addSyntheticLambdaMethodNode(final LambdaExpression expression, final ClassNode lambdaClass, final MethodNode abstractMethod) {
+        Parameter[] parametersWithExactType = createParametersWithExactType(expression);
         Parameter[] localVariableParameters = getLambdaSharedVariables(expression);
         removeInitialValues(localVariableParameters);
 
-        List<Parameter> methodParameterList = new LinkedList<>(Arrays.asList(parametersWithExactType));
-
-        MethodNode methodNode =
-                answer.addMethod(
-                        DO_CALL,
-                        ACC_PUBLIC,
-                        abstractMethodNode.getReturnType() /*ClassHelper.OBJECT_TYPE*/ /*returnType*/,
-                        methodParameterList.toArray(Parameter.EMPTY_ARRAY),
-                        ClassNode.EMPTY_ARRAY,
-                        expression.getCode()
-                );
-        methodNode.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, parametersWithExactType);
+        MethodNode doCallMethod = lambdaClass.addMethod(
+                "doCall",
+                ACC_PUBLIC,
+                abstractMethod.getReturnType(),
+                Arrays.copyOf(parametersWithExactType, parametersWithExactType.length),
+                ClassNode.EMPTY_ARRAY,
+                expression.getCode()
+        );
+        doCallMethod.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, parametersWithExactType);
         expression.putNodeMetaData(LAMBDA_SHARED_VARIABLES, localVariableParameters);
-        methodNode.setSourcePosition(expression);
+        doCallMethod.setSourcePosition(expression);
 
-        return methodNode;
+        return doCallMethod;
     }
 
-    private Parameter[] createParametersWithExactType(LambdaExpression expression) {
+    private Parameter[] createParametersWithExactType(final LambdaExpression expression) {
         Parameter[] parameters = expression.getParameters();
         if (parameters == null) {
             parameters = Parameter.EMPTY_ARRAY;
         }
 
         for (Parameter parameter : parameters) {
-            ClassNode parameterType = parameter.getType();
             ClassNode inferredType = parameter.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
-
-            if (null == inferredType) {
+            if (inferredType == null) {
                 continue;
             }
 
-            ClassNode type = convertParameterType(parameterType, inferredType);
+            ClassNode type = convertParameterType(parameter.getType(), inferredType);
 
             parameter.setType(type);
             parameter.setOriginType(type);
@@ -348,16 +316,15 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
         return parameters;
     }
 
-    private static final String SERIALIZED_LAMBDA_PARAM_NAME = "serializedLambda";
-    private static final String DESERIALIZE_LAMBDA_METHOD_NAME = "$deserializeLambda$";
     private void addDeserializeLambdaMethod() {
-        ClassNode classNode = controller.getClassNode();
+        ClassNode enclosingClass = controller.getClassNode();
         Parameter[] parameters = createDeserializeLambdaMethodParams();
-        if (classNode.hasMethod(DESERIALIZE_LAMBDA_METHOD_NAME, parameters)) {
+        if (enclosingClass.hasMethod("$deserializeLambda$", parameters)) {
             return;
         }
+
         Statement code = block(
-                declS(localVarX("enclosingClass", ClassHelper.DYNAMIC_TYPE), new ClassExpression(classNode)),
+                declS(localVarX("enclosingClass", OBJECT_TYPE), classX(enclosingClass)),
                 ((BlockStatement) new AstStringCompiler().compile(
                         "return enclosingClass" +
                                 ".getDeclaredMethod(\"\\$deserializeLambda_${serializedLambda.getImplClass().replace('/', '$')}\\$\", serializedLambda.getClass())" +
@@ -365,75 +332,47 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
                 ).get(0)).getStatements().get(0)
         );
 
-        classNode.addSyntheticMethod(
-                DESERIALIZE_LAMBDA_METHOD_NAME,
+        enclosingClass.addSyntheticMethod(
+                "$deserializeLambda$",
                 ACC_PRIVATE | ACC_STATIC,
-                ClassHelper.OBJECT_TYPE,
+                OBJECT_TYPE,
                 parameters,
                 ClassNode.EMPTY_ARRAY,
                 code);
     }
 
-    private void addDeserializeLambdaMethodForEachLambdaExpression(LambdaExpression lambdaExpression, ClassNode lambdaWrapperClassNode) {
-        ClassNode classNode = controller.getClassNode();
+    private void addDeserializeLambdaMethodForEachLambdaExpression(final LambdaExpression expression, final ClassNode lambdaClass) {
+        ClassNode enclosingClass = controller.getClassNode();
         Statement code = block(
                 new BytecodeSequence(new BytecodeInstruction() {
                     @Override
-                    public void visit(MethodVisitor mv) {
-                        callGetCapturedArg(mv, ICONST_0, lambdaWrapperClassNode);
-                    }
-
-                    private void callGetCapturedArg(MethodVisitor mv, int capturedArgIndex, ClassNode resultType) {
-                        OperandStack operandStack = controller.getOperandStack();
-
+                    public void visit(final MethodVisitor mv) {
                         mv.visitVarInsn(ALOAD, 0);
-                        mv.visitInsn(capturedArgIndex);
+                        mv.visitInsn(ICONST_0);
                         mv.visitMethodInsn(
                                 INVOKEVIRTUAL,
                                 "java/lang/invoke/SerializedLambda",
                                 "getCapturedArg",
                                 "(I)Ljava/lang/Object;",
                                 false);
-                        mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(resultType));
-                        operandStack.push(resultType);
+                        mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(lambdaClass));
+                        OperandStack operandStack = controller.getOperandStack();
+                        operandStack.push(lambdaClass);
                     }
                 }),
-                returnS(lambdaExpression)
+                returnS(expression)
         );
 
-        classNode.addSyntheticMethod(
-                createDeserializeLambdaMethodName(lambdaWrapperClassNode),
+        enclosingClass.addSyntheticMethod(
+                createDeserializeLambdaMethodName(lambdaClass),
                 ACC_PUBLIC | ACC_STATIC,
-                ClassHelper.OBJECT_TYPE,
+                OBJECT_TYPE,
                 createDeserializeLambdaMethodParams(),
                 ClassNode.EMPTY_ARRAY,
                 code);
     }
 
-    private String createDeserializeLambdaMethodName(ClassNode lambdaWrapperClassNode) {
-        return "$deserializeLambda_" + lambdaWrapperClassNode.getName().replace('.', '$') + "$";
-    }
-
-    @Override
-    protected ClassNode createClosureClass(final ClosureExpression expression, final int mods) {
-        return staticTypesClosureWriter.createClosureClass(expression, mods);
-    }
-
-    private static final class LambdaBodyTransformationVisitor extends ClassCodeVisitorSupport {
-        private final CorrectAccessedVariableVisitor correctAccessedVariableVisitor;
-
-        public LambdaBodyTransformationVisitor(InnerClassNode icn) {
-            this.correctAccessedVariableVisitor = new CorrectAccessedVariableVisitor(icn);
-        }
-
-        @Override
-        public void visitVariableExpression(VariableExpression expression) {
-            correctAccessedVariableVisitor.visitVariableExpression(expression);
-        }
-
-        @Override
-        protected SourceUnit getSourceUnit() {
-            return null;
-        }
+    private static String createDeserializeLambdaMethodName(final ClassNode lambdaClass) {
+        return "$deserializeLambda_" + lambdaClass.getName().replace('.', '$') + "$";
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 62f5cee..c33846d 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -677,7 +677,7 @@ public class CompilationUnit extends ProcessingUnit {
         }
     }
 
-    private void sortClasses() throws CompilationFailedException {
+    private void sortClasses() {
         for (ModuleNode module : getAST().getModules()) {
             module.sortClasses();
         }