Repository: groovy
Updated Branches:
  refs/heads/native-lambda b6ea72dbf -> fb8e3d10b


Add missing `ALOAD` to fix generating bytecode


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

Branch: refs/heads/native-lambda
Commit: fb8e3d10b9bcce46ebb474657d67036b14c2bffc
Parents: b6ea72d
Author: sunlan <[email protected]>
Authored: Mon Jan 15 15:35:13 2018 +0800
Committer: sunlan <[email protected]>
Committed: Mon Jan 15 15:35:13 2018 +0800

----------------------------------------------------------------------
 .../groovy/classgen/asm/ClosureWriter.java      |  2 +-
 .../asm/sc/StaticTypesLambdaWriter.java         | 94 ++++++++++++++++++--
 src/test/groovy/transform/stc/LambdaTest.groovy | 88 ++++++------------
 3 files changed, 113 insertions(+), 71 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/fb8e3d10/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
index d6e215d..429fe3b 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/ClosureWriter.java
@@ -338,7 +338,7 @@ public class ClosureWriter {
      * same method, in this case the constructor. A closure should not
      * have more than one constructor!
      */
-    private static void removeInitialValues(Parameter[] params) {
+    protected static void removeInitialValues(Parameter[] params) {
         for (int i = 0; i < params.length; i++) {
             if (params[i].hasInitialExpression()) {
                 Parameter p = new Parameter(params[i].getType(), 
params[i].getName());

http://git-wip-us.apache.org/repos/asf/groovy/blob/fb8e3d10/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesLambdaWriter.java
index e91e777..99c0215 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
@@ -19,6 +19,8 @@
 
 package org.codehaus.groovy.classgen.asm.sc;
 
+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.InnerClassNode;
@@ -27,12 +29,16 @@ import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.LambdaExpression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 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.stc.StaticTypesMarker;
 import org.objectweb.asm.Handle;
+import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 
@@ -45,6 +51,7 @@ import java.util.stream.Stream;
 
 import static 
org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.PARAMETER_TYPE;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ALOAD;
 
 /**
  * Writer responsible for generating lambda classes in statically compiled 
mode.
@@ -53,7 +60,7 @@ import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 public class StaticTypesLambdaWriter extends LambdaWriter {
     public static final String DO_CALL = "doCall";
     public static final String ORIGINAL_PARAMETERS_WITH_EXACT_TYPE = 
"__ORIGINAL_PARAMETERS_WITH_EXACT_TYPE";
-    public static final String LAMBDA_SHARED_VARIABLES = 
"_LAMBDA_SHARED_VARIABLES";
+    public static final String LAMBDA_SHARED_VARIABLES = 
"__LAMBDA_SHARED_VARIABLES";
     private StaticTypesClosureWriter staticTypesClosureWriter;
     private WriterController controller;
     private WriterControllerFactory factory;
@@ -91,9 +98,18 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
         ClassNode lambdaClassNode = getOrAddLambdaClass(expression, 
ACC_PUBLIC);
         MethodNode syntheticLambdaMethodNode = 
lambdaClassNode.getMethods(DO_CALL).get(0);
 
+        MethodVisitor mv = controller.getMethodVisitor();
+        OperandStack operandStack = controller.getOperandStack();
 
-        controller.getOperandStack().push(parameterType.redirect());
-        controller.getMethodVisitor().visitInvokeDynamicInsn(
+        Parameter[] lambdaSharedVariableParameters = 
syntheticLambdaMethodNode.getNodeMetaData(LAMBDA_SHARED_VARIABLES);
+        for (int i = 0; i < lambdaSharedVariableParameters.length; i++) {
+            mv.visitVarInsn(ALOAD, i);
+            
operandStack.doGroovyCast(lambdaSharedVariableParameters[i].getType().redirect());
+//            
operandStack.push(lambdaSharedVariableParameters[i].getType().redirect());
+        }
+
+        operandStack.push(parameterType.redirect());
+        mv.visitInvokeDynamicInsn(
                 abstractMethodNode.getName(),
                 createAbstractMethodDesc(syntheticLambdaMethodNode, 
parameterType),
                 createBootstrapMethod(),
@@ -193,15 +209,40 @@ public class StaticTypesLambdaWriter extends LambdaWriter 
{
     private void addSyntheticLambdaMethodNode(LambdaExpression expression, 
InnerClassNode answer) {
         Parameter[] parametersWithExactType = 
createParametersWithExactType(expression); // expression.getParameters();
         ClassNode returnType = 
expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); 
//abstractMethodNode.getReturnType();
-        Parameter[] lambdaSharedVariables = 
getLambdaSharedVariables(expression);
-        Parameter[] methodParameter = 
Stream.concat(Arrays.stream(lambdaSharedVariables), 
Arrays.stream(parametersWithExactType)).toArray(Parameter[]::new);
+        Parameter[] localVariableParameters = 
getLambdaSharedVariables(expression);
+        removeInitialValues(localVariableParameters);
+        Parameter[] methodParameter = 
Stream.concat(Arrays.stream(localVariableParameters), 
Arrays.stream(parametersWithExactType)).toArray(Parameter[]::new);
 
         MethodNode methodNode =
-                answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | 
Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, returnType, methodParameter, 
ClassNode.EMPTY_ARRAY, expression.getCode());
+                answer.addMethod(
+                        DO_CALL,
+                        Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | 
Opcodes.ACC_SYNTHETIC,
+                        returnType,
+                        methodParameter,
+                        ClassNode.EMPTY_ARRAY,
+                        expression.getCode()
+                );
         methodNode.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, 
parametersWithExactType);
-        methodNode.putNodeMetaData(LAMBDA_SHARED_VARIABLES, 
lambdaSharedVariables);
+        methodNode.putNodeMetaData(LAMBDA_SHARED_VARIABLES, 
localVariableParameters);
 
         methodNode.setSourcePosition(expression);
+
+
+        LocalVariableReplacementVisitor localVariableReplacementVisitor = new 
LocalVariableReplacementVisitor(methodNode);
+
+        localVariableReplacementVisitor.visitMethod(methodNode);
+
+//        System.out.println(methodNode);
+
+        /*
+        VariableScope varScope = expression.getVariableScope();
+        if (varScope == null) {
+            throw new RuntimeException(
+                    "Must have a VariableScope by now! for expression: " + 
expression + " class: " + answer.getName());
+        } else {
+            methodNode.setVariableScope(varScope.copy());
+        }
+        */
     }
 
     private Parameter[] createParametersWithExactType(LambdaExpression 
expression) {
@@ -223,4 +264,43 @@ public class StaticTypesLambdaWriter extends LambdaWriter {
     protected ClassNode createClosureClass(final ClosureExpression expression, 
final int mods) {
         return staticTypesClosureWriter.createClosureClass(expression, mods);
     }
+
+    private static final class LocalVariableReplacementVisitor extends 
ClassCodeVisitorSupport {
+        private MethodNode methodNode;
+
+        public LocalVariableReplacementVisitor(MethodNode methodNode) {
+            this.methodNode = methodNode;
+        }
+
+        @Override
+        protected SourceUnit getSourceUnit() {
+            return null;
+        }
+
+        @Override
+        public void visitVariableExpression(VariableExpression expression) {
+            if (expression.isClosureSharedVariable()) {
+                final String variableName = expression.getName();
+//                System.out.println(">>>>>>>>>>>>>>>>>>>>>>\n");
+//                System.out.println("1, " + variableName + ":" + 
expression.isClosureSharedVariable() + "::" + expression.getAccessedVariable());
+                Parameter[] parametersWithSameVariableName =
+                        Arrays.stream(methodNode.getParameters())
+                                .filter(e -> variableName.equals(e.getName()))
+                                .toArray(Parameter[]::new);
+
+                if (parametersWithSameVariableName.length != 1) {
+                    throw new 
GroovyBugError(parametersWithSameVariableName.length + " parameters with same 
name " + variableName + " found(Expect only one matched).");
+                }
+//                System.out.println("2, " + variableName + ":" + 
parametersWithSameVariableName[0]);
+
+                
expression.setAccessedVariable(parametersWithSameVariableName[0]);
+                expression.setClosureSharedVariable(false);
+
+//                System.out.println("<<<<<<<<<<<<<<<<<<<<<<\n");
+
+            }
+
+            super.visitVariableExpression(expression);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/fb8e3d10/src/test/groovy/transform/stc/LambdaTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy 
b/src/test/groovy/transform/stc/LambdaTest.groovy
index 73ba540..dbd789a 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -199,69 +199,8 @@ TestScript0.groovy: 14: [Static type checking] - Cannot 
find matching method jav
         if (true) return
 
         // FIXME
-        /*
-General error during class generation: ASM reporting processing error for 
Test1#p with signature void p() in TestScript0.groovy:12. TestScript0.groovy
-
-groovy.lang.GroovyRuntimeException: ASM reporting processing error for Test1#p 
with signature void p() in TestScript0.groovy:12. TestScript0.groovy
-       at 
org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:447)
-       at 
org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:132)
-       at 
org.codehaus.groovy.classgen.AsmClassGenerator.visitMethod(AsmClassGenerator.java:568)
-       at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1095)
-       at 
org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:54)
-       at 
org.codehaus.groovy.classgen.AsmClassGenerator.visitClass(AsmClassGenerator.java:261)
-       at 
org.codehaus.groovy.control.CompilationUnit$18.call(CompilationUnit.java:853)
-       at 
org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1092)
-       at 
org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:634)
-       at 
org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:612)
-       at 
org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:589)
-       at 
groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:359)
-       at groovy.lang.GroovyClassLoader.access$300(GroovyClassLoader.java:92)
-       at groovy.lang.GroovyClassLoader$5.provide(GroovyClassLoader.java:328)
-       at groovy.lang.GroovyClassLoader$5.provide(GroovyClassLoader.java:325)
-       at 
org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache.getAndPut(ConcurrentCommonCache.java:138)
-       at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:323)
-       at groovy.lang.GroovyShell.parseClass(GroovyShell.java:548)
-       at groovy.lang.GroovyShell.parse(GroovyShell.java:560)
-       at groovy.lang.GroovyShell.evaluate(GroovyShell.java:444)
-       at groovy.lang.GroovyShell.evaluate(GroovyShell.java:483)
-       at groovy.lang.GroovyShell.evaluate(GroovyShell.java:464)
-       at groovy.test.GroovyAssert.assertScript(GroovyAssert.java:83)
-       at groovy.util.GroovyTestCase.assertScript(GroovyTestCase.java:203)
-       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-       at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-       at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-       at java.lang.reflect.Method.invoke(Method.java:498)
-       at 
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
-       at 
org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
-       at 
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:51)
-       at 
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:157)
-       at 
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:169)
-       at 
groovy.transform.stc.LambdaTest.testFunctionWithLocalVariables(LambdaTest.groovy:203)
-       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-       at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
-       at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
-       at java.lang.reflect.Method.invoke(Method.java:498)
-       at junit.framework.TestCase.runTest(TestCase.java:176)
-       at junit.framework.TestCase.runBare(TestCase.java:141)
-       at junit.framework.TestResult$1.protect(TestResult.java:122)
-       at junit.framework.TestResult.runProtected(TestResult.java:142)
-       at junit.framework.TestResult.run(TestResult.java:125)
-       at junit.framework.TestCase.run(TestCase.java:129)
-       at junit.framework.TestSuite.runTest(TestSuite.java:252)
-       at junit.framework.TestSuite.run(TestSuite.java:247)
-       at 
org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
-       at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
-       at 
com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
-       at 
com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
-       at 
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
-       at 
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
-Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
-       at org.objectweb.asm.Frame.merge(Frame.java:1501)
-       at org.objectweb.asm.Frame.merge(Frame.java:1478)
-       at org.objectweb.asm.MethodWriter.visitMaxs(MethodWriter.java:1497)
-       at 
org.codehaus.groovy.classgen.AsmClassGenerator.visitConstructorOrMethod(AsmClassGenerator.java:428)
-       ... 51 more
-
+        /* What we expect is '#1', '#2', '#3'
+[groovy.lang.Reference@46d63dbb1, groovy.lang.Reference@46d63dbb2, 
groovy.lang.Reference@46d63dbb3]
          */
 
         assertScript '''
@@ -282,4 +221,27 @@ Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
         }
         '''
     }
+
+    /*
+    void testLabs() {
+
+        assertScript '''
+        import groovy.transform.CompileStatic
+        import java.util.stream.Collectors
+        import java.util.stream.Stream
+        
+        @CompileStatic
+        public class Test1 {
+            public static void main(String[] args) {
+                p();
+            }
+        
+            public static void p() {
+                String x = "#"
+                System.out.println(Stream.of(1, 2, 3).map(e -> x + 
e).collect(Collectors.toList()));
+            }
+        }
+        '''
+    }
+    */
 }

Reply via email to