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:30 UTC

[groovy] 01/05: minor refactor

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();
         }