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 2020/02/14 20:36:06 UTC
[groovy] 04/06: add builders for BytecodeExpression supporting
closure/lambda
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 70218abc6f8f11028830a9bfe6e1fd065e6219a3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Feb 14 12:19:08 2020 -0600
add builders for BytecodeExpression supporting closure/lambda
(cherry picked from commit 158ebffaf8e682ce4a7e6c8e2bc4f393b5824a4c)
---
.../codehaus/groovy/ast/tools/GeneralUtils.java | 22 +++++
.../org/codehaus/groovy/classgen/Verifier.java | 13 ++-
.../classgen/asm/sc/StaticTypesCallSiteWriter.java | 21 ++---
.../asm/sc/StaticTypesUnaryExpressionHelper.java | 99 ++++++++++------------
.../transformers/ConstructorCallTransformer.java | 36 ++++----
5 files changed, 98 insertions(+), 93 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
index 49b7163..47b45cc 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GeneralUtils.java
@@ -60,12 +60,14 @@ import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
+import org.codehaus.groovy.classgen.BytecodeExpression;
import org.codehaus.groovy.classgen.Verifier;
import org.codehaus.groovy.control.io.ReaderSource;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
import org.codehaus.groovy.transform.AbstractASTTransformation;
+import org.objectweb.asm.MethodVisitor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -74,6 +76,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
import static org.apache.groovy.util.BeanUtils.capitalize;
import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_IDENTICAL;
@@ -156,6 +159,21 @@ public class GeneralUtils {
return block;
}
+ public static BytecodeExpression bytecodeX(Consumer<MethodVisitor> writer) {
+ return new BytecodeExpression() {
+ @Override
+ public void visit(final MethodVisitor visitor) {
+ writer.accept(visitor);
+ }
+ };
+ }
+
+ public static BytecodeExpression bytecodeX(ClassNode type, Consumer<MethodVisitor> writer) {
+ BytecodeExpression expression = bytecodeX(writer);
+ expression.setType(type);
+ return expression;
+ }
+
public static MethodCallExpression callSuperX(String methodName, Expression args) {
return callX(varX("super"), methodName, args);
}
@@ -757,6 +775,10 @@ public class GeneralUtils {
return new PropertyExpression(owner, property);
}
+ public static PropertyExpression propX(Expression owner, Expression property, boolean safe) {
+ return new PropertyExpression(owner, property, safe);
+ }
+
public static PropertyExpression thisPropX(boolean implicit, String property) {
PropertyExpression pexp = propX(varX("this"), property);
pexp.setImplicitThis(implicit);
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 6b24a15..4310bfb 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -93,6 +93,7 @@ import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getPropertyName;
import static org.apache.groovy.ast.tools.MethodNodeUtils.methodDescriptorWithoutReturnType;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
@@ -162,13 +163,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
final String classInternalName = BytecodeHelper.getClassInternalName(node);
metaClassField =
node.addField("metaClass", ACC_PRIVATE | ACC_TRANSIENT | ACC_SYNTHETIC, ClassHelper.METACLASS_TYPE,
- new BytecodeExpression(ClassHelper.METACLASS_TYPE) {
- @Override
- public void visit(MethodVisitor mv) {
- mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
- }
- });
+ bytecodeX(ClassHelper.METACLASS_TYPE, mv -> {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ })
+ );
metaClassField.setSynthetic(true);
return metaClassField;
}
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 5c19e6c..313ee38 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -77,6 +77,7 @@ import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
import static org.codehaus.groovy.ast.ClassHelper.int_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
@@ -350,13 +351,10 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitVarInsn(ALOAD, var);
- final ClassNode finalComponentType = componentType;
- PropertyExpression pexp = propX(new BytecodeExpression(finalComponentType) {
- @Override
- public void visit(final MethodVisitor mv) {
- mv.visitVarInsn(ALOAD, next);
- }
- }, propertyName);
+ PropertyExpression pexp = propX(
+ bytecodeX(componentType, v -> v.visitVarInsn(ALOAD, next)),
+ propertyName
+ );
pexp.visit(controller.getAcg());
controller.getOperandStack().box();
controller.getOperandStack().remove(1);
@@ -430,13 +428,8 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
if (currentCall != null && currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER) != null) {
property = currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
String[] props = property.split("\\.");
- BytecodeExpression thisLoader = new BytecodeExpression(CLOSURE_TYPE) {
- @Override
- public void visit(final MethodVisitor mv) {
- mv.visitVarInsn(ALOAD, 0); // load this
- }
- };
- PropertyExpression pexp = new PropertyExpression(thisLoader, constX(props[0]), safe);
+ BytecodeExpression thisLoader = bytecodeX(CLOSURE_TYPE, mv -> mv.visitVarInsn(ALOAD, 0));
+ PropertyExpression pexp = propX(thisLoader, constX(props[0]), safe);
for (int i = 1, n = props.length; i < n; i += 1) {
pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, CLOSURE_TYPE);
pexp = propX(pexp, props[i]);
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
index c02e0e2..51a8ed4 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesUnaryExpressionHelper.java
@@ -30,7 +30,6 @@ import org.codehaus.groovy.classgen.asm.TypeChooser;
import org.codehaus.groovy.classgen.asm.UnaryExpressionHelper;
import org.codehaus.groovy.classgen.asm.WriterController;
import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import static org.codehaus.groovy.ast.ClassHelper.boolean_TYPE;
@@ -42,6 +41,7 @@ import static org.codehaus.groovy.ast.ClassHelper.int_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
/**
* An unary expression helper which generates optimized bytecode depending on
@@ -63,27 +63,24 @@ public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper impl
public void writeBitwiseNegate(final BitwiseNegationExpression expression) {
expression.getExpression().visit(controller.getAcg());
if (isPrimitiveOnTop()) {
- final ClassNode top = getTopOperand();
- if (top==int_TYPE || top==short_TYPE || top==byte_TYPE || top==char_TYPE || top==long_TYPE) {
- BytecodeExpression bytecodeExpression = new BytecodeExpression() {
- @Override
- public void visit(final MethodVisitor mv) {
- if (long_TYPE==top) {
- mv.visitLdcInsn(-1);
- mv.visitInsn(LXOR);
- } else {
- mv.visitInsn(ICONST_M1);
- mv.visitInsn(IXOR);
- if (byte_TYPE==top) {
- mv.visitInsn(I2B);
- } else if (char_TYPE==top) {
- mv.visitInsn(I2C);
- } else if (short_TYPE==top) {
- mv.visitInsn(I2S);
- }
+ ClassNode top = getTopOperand();
+ if (top == int_TYPE || top == short_TYPE || top == byte_TYPE || top == char_TYPE || top == long_TYPE) {
+ BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
+ if (long_TYPE == top) {
+ mv.visitLdcInsn(-1);
+ mv.visitInsn(LXOR);
+ } else {
+ mv.visitInsn(ICONST_M1);
+ mv.visitInsn(IXOR);
+ if (byte_TYPE == top) {
+ mv.visitInsn(I2B);
+ } else if (char_TYPE == top) {
+ mv.visitInsn(I2C);
+ } else if (short_TYPE == top) {
+ mv.visitInsn(I2S);
}
}
- };
+ });
bytecodeExpression.visit(controller.getAcg());
controller.getOperandStack().remove(1);
return;
@@ -100,19 +97,16 @@ public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper impl
if (typeChooser.resolveType(subExpression, classNode) == boolean_TYPE) {
subExpression.visit(controller.getAcg());
controller.getOperandStack().doGroovyCast(boolean_TYPE);
- BytecodeExpression bytecodeExpression = new BytecodeExpression() {
- @Override
- public void visit(final MethodVisitor mv) {
- Label ne = new Label();
- mv.visitJumpInsn(IFNE, ne);
- mv.visitInsn(ICONST_1);
- Label out = new Label();
- mv.visitJumpInsn(GOTO, out);
- mv.visitLabel(ne);
- mv.visitInsn(ICONST_0);
- mv.visitLabel(out);
- }
- };
+ BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
+ Label ne = new Label();
+ mv.visitJumpInsn(IFNE, ne);
+ mv.visitInsn(ICONST_1);
+ Label out = new Label();
+ mv.visitJumpInsn(GOTO, out);
+ mv.visitLabel(ne);
+ mv.visitInsn(ICONST_0);
+ mv.visitLabel(out);
+ });
bytecodeExpression.visit(controller.getAcg());
controller.getOperandStack().remove(1);
return;
@@ -124,29 +118,26 @@ public class StaticTypesUnaryExpressionHelper extends UnaryExpressionHelper impl
public void writeUnaryMinus(final UnaryMinusExpression expression) {
expression.getExpression().visit(controller.getAcg());
if (isPrimitiveOnTop()) {
- final ClassNode top = getTopOperand();
- if (top!=boolean_TYPE) {
- BytecodeExpression bytecodeExpression = new BytecodeExpression() {
- @Override
- public void visit(final MethodVisitor mv) {
- if (int_TYPE == top || short_TYPE == top || byte_TYPE==top || char_TYPE==top) {
- mv.visitInsn(INEG);
- if (byte_TYPE==top) {
- mv.visitInsn(I2B);
- } else if (char_TYPE==top) {
- mv.visitInsn(I2C);
- } else if (short_TYPE==top) {
- mv.visitInsn(I2S);
- }
- } else if (long_TYPE == top) {
- mv.visitInsn(LNEG);
- } else if (float_TYPE == top) {
- mv.visitInsn(FNEG);
- } else if (double_TYPE == top) {
- mv.visitInsn(DNEG);
+ ClassNode top = getTopOperand();
+ if (top != boolean_TYPE) {
+ BytecodeExpression bytecodeExpression = bytecodeX(mv -> {
+ if (int_TYPE == top || short_TYPE == top || byte_TYPE == top || char_TYPE == top) {
+ mv.visitInsn(INEG);
+ if (byte_TYPE == top) {
+ mv.visitInsn(I2B);
+ } else if (char_TYPE == top) {
+ mv.visitInsn(I2C);
+ } else if (short_TYPE == top) {
+ mv.visitInsn(I2S);
}
+ } else if (long_TYPE == top) {
+ mv.visitInsn(LNEG);
+ } else if (float_TYPE == top) {
+ mv.visitInsn(FNEG);
+ } else if (double_TYPE == top) {
+ mv.visitInsn(DNEG);
}
- };
+ });
bytecodeExpression.visit(controller.getAcg());
controller.getOperandStack().remove(1);
return;
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/ConstructorCallTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/ConstructorCallTransformer.java
index 9c269ea..d4f31e4 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/ConstructorCallTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/ConstructorCallTransformer.java
@@ -29,7 +29,6 @@ import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MapEntryExpression;
import org.codehaus.groovy.ast.expr.MapExpression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.BytecodeExpression;
@@ -45,12 +44,15 @@ import org.objectweb.asm.Opcodes;
import java.util.List;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
public class ConstructorCallTransformer {
private final StaticCompilationTransformer staticCompilationTransformer;
- public ConstructorCallTransformer(StaticCompilationTransformer staticCompilationTransformer) {
+ public ConstructorCallTransformer(final StaticCompilationTransformer staticCompilationTransformer) {
this.staticCompilationTransformer = staticCompilationTransformer;
}
@@ -116,8 +118,9 @@ public class ConstructorCallTransformer {
this.originalCall = originalCall;
this.setSourcePosition(originalCall);
this.copyNodeMetaData(originalCall);
- List<Expression> originalExpressions = originalCall.getArguments() instanceof TupleExpression ?
- ((TupleExpression)originalCall.getArguments()).getExpressions() : null;
+ List<Expression> originalExpressions = originalCall.getArguments() instanceof TupleExpression
+ ? ((TupleExpression) originalCall.getArguments()).getExpressions()
+ : null;
this.innerClassCall = originalExpressions != null && originalExpressions.size() == 2;
}
@@ -133,12 +136,12 @@ public class ConstructorCallTransformer {
@Override
public void visit(final MethodVisitor mv) {
- final WriterController controller = acg.getController();
- final OperandStack operandStack = controller.getOperandStack();
- final CompileStack compileStack = controller.getCompileStack();
+ WriterController controller = acg.getController();
+ CompileStack compileStack = controller.getCompileStack();
+ OperandStack operandStack = controller.getOperandStack();
// create a temporary variable to store the constructed object
- final int tmpObj = compileStack.defineTemporaryVariable("tmpObj", declaringClass, false);
+ int tmpObj = compileStack.defineTemporaryVariable("tmpObj", declaringClass, false);
String classInternalName = BytecodeHelper.getClassInternalName(declaringClass);
mv.visitTypeInsn(NEW, classInternalName);
mv.visitInsn(DUP);
@@ -147,7 +150,7 @@ public class ConstructorCallTransformer {
// load "this"
mv.visitVarInsn(ALOAD, 0);
InnerClassNode icn = (InnerClassNode) declaringClass.redirect();
- Parameter[] params = { new Parameter(icn.getOuterClass(), "$p$") };
+ Parameter[] params = {new Parameter(icn.getOuterClass(), "$p$")};
desc = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, params);
}
mv.visitMethodInsn(INVOKESPECIAL, classInternalName, "<init>", desc, false);
@@ -155,17 +158,14 @@ public class ConstructorCallTransformer {
// load every field
for (MapEntryExpression entryExpression : map.getMapEntryExpressions()) {
- int line = entryExpression.getLineNumber();
- int col = entryExpression.getColumnNumber();
Expression keyExpression = staticCompilationTransformer.transform(entryExpression.getKeyExpression());
Expression valueExpression = staticCompilationTransformer.transform(entryExpression.getValueExpression());
- BinaryExpression bexp = new BinaryExpression(new PropertyExpression(new BytecodeExpression(declaringClass) {
- @Override
- public void visit(final MethodVisitor mv) {
- mv.visitVarInsn(ALOAD, tmpObj);
- }
- }, keyExpression),
- Token.newSymbol("=", line, col),
+ BinaryExpression bexp = binX(
+ propX(
+ bytecodeX(declaringClass, v -> v.visitVarInsn(ALOAD, tmpObj)),
+ keyExpression
+ ),
+ Token.newSymbol("=", entryExpression.getLineNumber(), entryExpression.getColumnNumber()),
valueExpression
);
bexp.setSourcePosition(entryExpression);