Repository: groovy Updated Branches: refs/heads/native-lambda 61474c1ee -> b6ea72dbf
Minor refactoring to prepare supporting local variables Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/b6ea72db Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/b6ea72db Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/b6ea72db Branch: refs/heads/native-lambda Commit: b6ea72dbf2ee4ab63fb1b96569de609679807a34 Parents: 61474c1 Author: sunlan <[email protected]> Authored: Sun Jan 14 07:47:17 2018 +0800 Committer: sunlan <[email protected]> Committed: Sun Jan 14 07:47:17 2018 +0800 ---------------------------------------------------------------------- .../groovy/classgen/asm/LambdaWriter.java | 5 ++ .../asm/sc/StaticTypesLambdaWriter.java | 29 +++++-- .../groovy/runtime/ProxyGeneratorAdapter.java | 2 +- src/test/gls/generics/GenericsTestBase.java | 2 +- src/test/groovy/transform/stc/LambdaTest.groovy | 88 ++++++++++++++++++++ 5 files changed, 115 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/b6ea72db/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java ---------------------------------------------------------------------- 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 3a39688..6c0b53d 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/LambdaWriter.java @@ -18,6 +18,7 @@ */ package org.codehaus.groovy.classgen.asm; +import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.expr.LambdaExpression; public class LambdaWriter extends ClosureWriter { @@ -28,4 +29,8 @@ public class LambdaWriter extends ClosureWriter { public void writeLambda(LambdaExpression expression) { super.writeClosure(expression); } + + protected Parameter[] getLambdaSharedVariables(LambdaExpression expression) { + return super.getClosureSharedVariables(expression); + } } http://git-wip-us.apache.org/repos/asf/groovy/blob/b6ea72db/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 bdf10d8..e91e777 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 @@ -41,6 +41,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.codehaus.groovy.classgen.asm.sc.StaticInvocationWriter.PARAMETER_TYPE; import static org.objectweb.asm.Opcodes.ACC_PUBLIC; @@ -51,6 +52,8 @@ 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"; private StaticTypesClosureWriter staticTypesClosureWriter; private WriterController controller; private WriterControllerFactory factory; @@ -87,19 +90,22 @@ public class StaticTypesLambdaWriter extends LambdaWriter { ClassNode lambdaClassNode = getOrAddLambdaClass(expression, ACC_PUBLIC); MethodNode syntheticLambdaMethodNode = lambdaClassNode.getMethods(DO_CALL).get(0); - String syntheticLambdaMethodWithExactTypeDesc = BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode); + controller.getOperandStack().push(parameterType.redirect()); controller.getMethodVisitor().visitInvokeDynamicInsn( abstractMethodNode.getName(), - createAbstractMethodDesc(parameterType), + createAbstractMethodDesc(syntheticLambdaMethodNode, parameterType), createBootstrapMethod(), - createBootstrapMethodArguments(abstractMethodDesc, lambdaClassNode, syntheticLambdaMethodNode, syntheticLambdaMethodWithExactTypeDesc) + createBootstrapMethodArguments(abstractMethodDesc, lambdaClassNode, syntheticLambdaMethodNode) ); } - private String createAbstractMethodDesc(ClassNode parameterType) { - return "()L" + parameterType.redirect().getPackageName().replace('.', '/') + "/" + parameterType.redirect().getNameWithoutPackage() + ";"; + private String createAbstractMethodDesc(MethodNode syntheticLambdaMethodNode, ClassNode parameterType) { + Parameter[] lambdaSharedVariables = syntheticLambdaMethodNode.getNodeMetaData(LAMBDA_SHARED_VARIABLES); + String methodDescriptor = BytecodeHelper.getMethodDescriptor(parameterType.redirect(), lambdaSharedVariables); + + return methodDescriptor; } private Handle createBootstrapMethod() { @@ -112,17 +118,17 @@ public class StaticTypesLambdaWriter extends LambdaWriter { ); } - private Object[] createBootstrapMethodArguments(String abstractMethodDesc, ClassNode lambdaClassNode, MethodNode syntheticLambdaMethodNode, String syntheticLambdaMethodWithExactTypeDesc) { + private Object[] createBootstrapMethodArguments(String abstractMethodDesc, ClassNode lambdaClassNode, MethodNode syntheticLambdaMethodNode) { return new Object[]{ Type.getType(abstractMethodDesc), new Handle( Opcodes.H_INVOKESTATIC, lambdaClassNode.getName(), syntheticLambdaMethodNode.getName(), - syntheticLambdaMethodWithExactTypeDesc, + BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode), false ), - Type.getType(syntheticLambdaMethodWithExactTypeDesc) + Type.getType(BytecodeHelper.getMethodDescriptor(syntheticLambdaMethodNode.getReturnType(), syntheticLambdaMethodNode.getNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE))) }; } @@ -187,9 +193,14 @@ 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); MethodNode methodNode = - answer.addMethod(DO_CALL, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, returnType, parametersWithExactType, 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.setSourcePosition(expression); } http://git-wip-us.apache.org/repos/asf/groovy/blob/b6ea72db/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java index 207a7ca..0e1f6cc 100644 --- a/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java +++ b/src/main/java/org/codehaus/groovy/runtime/ProxyGeneratorAdapter.java @@ -142,7 +142,7 @@ public class ProxyGeneratorAdapter extends ClassVisitor implements Opcodes { final ClassLoader proxyLoader, final boolean emptyBody, final Class delegateClass) { - super(Opcodes.ASM4, new ClassWriter(0)); + super(Opcodes.ASM5, new ClassWriter(0)); this.loader = proxyLoader != null ? createInnerLoader(proxyLoader, interfaces) : findClassLoader(superClass, interfaces); this.visitedMethods = new LinkedHashSet<Object>(); this.delegatedClosures = closureMap.isEmpty() ? EMPTY_DELEGATECLOSURE_MAP : new HashMap<String, Boolean>(); http://git-wip-us.apache.org/repos/asf/groovy/blob/b6ea72db/src/test/gls/generics/GenericsTestBase.java ---------------------------------------------------------------------- diff --git a/src/test/gls/generics/GenericsTestBase.java b/src/test/gls/generics/GenericsTestBase.java index 801806f..dc5fc94 100644 --- a/src/test/gls/generics/GenericsTestBase.java +++ b/src/test/gls/generics/GenericsTestBase.java @@ -57,7 +57,7 @@ public abstract class GenericsTestBase extends GroovyTestCase { } private class GenericsTester extends ClassVisitor { public GenericsTester(ClassVisitor cv) { - super(Opcodes.ASM4,cv); + super(Opcodes.ASM5,cv); } public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { http://git-wip-us.apache.org/repos/asf/groovy/blob/b6ea72db/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 ba471fb..73ba540 100644 --- a/src/test/groovy/transform/stc/LambdaTest.groovy +++ b/src/test/groovy/transform/stc/LambdaTest.groovy @@ -194,4 +194,92 @@ TestScript0.groovy: 14: [Static type checking] - Cannot find matching method jav } ''' } + + void testFunctionWithLocalVariables() { + 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 + + */ + + 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 = "#" + assert ['#1', '#2', '#3'] == Stream.of(1, 2, 3).map(e -> x + e).collect(Collectors.toList()); + } + } + ''' + } }
