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

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


The following commit(s) were added to refs/heads/master by this push:
     new f682375  minor refactor
f682375 is described below

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

    minor refactor
---
 .../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();
         }

Reply via email to