You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/12/12 19:09:51 UTC
[groovy] 02/02: GROOVY-7300: drop dead code and refactor `StaticCompilationTransformer`
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
commit b23f1e1c822ae60e34cef25a6fbdd24b911a40a4
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Dec 12 13:09:38 2021 -0600
GROOVY-7300: drop dead code and refactor `StaticCompilationTransformer`
---
.../groovy/classgen/asm/InvocationWriter.java | 2 +-
.../classgen/asm/sc/StaticInvocationWriter.java | 14 ----
.../PropertyExpressionTransformer.java | 56 +++++++++++++
.../transformers/StaticCompilationTransformer.java | 55 +++++--------
.../VariableExpressionTransformer.java | 92 +++++++++++++---------
5 files changed, 131 insertions(+), 88 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index 9181b6b..05e0007 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -110,7 +110,7 @@ public class InvocationWriter {
public void makeCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, boolean safe, final boolean spreadSafe, boolean implicitThis) {
ClassNode sender;
- if (isSuperExpression(receiver) || isThisExpression(receiver) && !implicitThis) {
+ if (isSuperExpression(receiver) || (isThisExpression(receiver) && !implicitThis)) {
// GROOVY-6045, GROOVY-8693, et al.
sender = controller.getThisType();
implicitThis = false;
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index 5c72843..6fee1be 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -125,20 +125,6 @@ public class StaticInvocationWriter extends InvocationWriter {
}
@Override
- protected boolean makeDirectCall(final Expression origin, final Expression receiver, final Expression message, final Expression arguments, final MethodCallerMultiAdapter adapter, final boolean implicitThis, final boolean containsSpreadExpression) {
- if (origin instanceof MethodCallExpression && isSuperExpression(receiver)) {
- MethodCallExpression mce = (MethodCallExpression) origin;
- if (mce.getMethodTarget() == null && !controller.getCompileStack().isLHS()) { // GROOVY-7300
- ClassNode owner = receiver.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
- if (owner != null) {
- mce.setMethodTarget(owner.getDeclaredMethod(mce.getMethodAsString(), Parameter.EMPTY_ARRAY));
- }
- }
- }
- return super.makeDirectCall(origin, receiver, message, arguments, adapter, implicitThis, containsSpreadExpression);
- }
-
- @Override
public void writeInvokeMethod(final MethodCallExpression call) {
MethodCallExpression old = currentCall;
currentCall = call;
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/PropertyExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/PropertyExpressionTransformer.java
new file mode 100644
index 0000000..bc3d3aa
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/PropertyExpressionTransformer.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.codehaus.groovy.transform.sc.transformers;
+
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.PropertyExpression;
+import org.codehaus.groovy.transform.stc.StaticTypesMarker;
+
+import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+
+class PropertyExpressionTransformer {
+
+ private final StaticCompilationTransformer scTransformer;
+
+ PropertyExpressionTransformer(final StaticCompilationTransformer scTransformer) {
+ this.scTransformer = scTransformer;
+ }
+
+ Expression transformPropertyExpression(final PropertyExpression pe) {
+ if (isThisOrSuper(pe.getObjectExpression())) { // TODO: all obj exp
+ MethodNode dmct = pe.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
+ // NOTE: BinaryExpressionTransformer handles the setter
+ if (dmct != null && dmct.getParameters().length == 0) {
+ MethodCallExpression mce = callX(scTransformer.transform(pe.getObjectExpression()), dmct.getName());
+ mce.setImplicitThis(pe.isImplicitThis());
+ mce.setSpreadSafe(pe.isSpreadSafe());
+ mce.setMethodTarget(dmct);
+ mce.setSourcePosition(pe);
+ mce.copyNodeMetaData(pe);
+ mce.setSafe(pe.isSafe());
+ return mce;
+ }
+ }
+
+ return scTransformer.superTransform(pe);
+ }
+}
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
index 0a8f8a7..1b8e6fc 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticCompilationTransformer.java
@@ -42,13 +42,10 @@ import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.syntax.Types;
import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
-import org.codehaus.groovy.transform.stc.StaticTypesMarker;
import java.util.Iterator;
import java.util.Map;
-import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
-
/**
* Some expressions use symbols as aliases to method calls (<<, +=, ...). In static compilation,
* if such a method call is found, we transform the original binary expression into a method
@@ -75,12 +72,13 @@ public class StaticCompilationTransformer extends ClassCodeExpressionTransformer
// various helpers in order to avoid a potential very big class
private final StaticMethodCallExpressionTransformer staticMethodCallExpressionTransformer = new StaticMethodCallExpressionTransformer(this);
- private final ConstructorCallTransformer constructorCallTransformer = new ConstructorCallTransformer(this);
private final MethodCallExpressionTransformer methodCallExpressionTransformer = new MethodCallExpressionTransformer(this);
- private final BinaryExpressionTransformer binaryExpressionTransformer = new BinaryExpressionTransformer(this);
+ private final ConstructorCallTransformer constructorCallTransformer = new ConstructorCallTransformer(this);
+ private final PropertyExpressionTransformer propertyExpressionTransformer = new PropertyExpressionTransformer(this);
+ private final VariableExpressionTransformer variableExpressionTransformer = new VariableExpressionTransformer();
private final ClosureExpressionTransformer closureExpressionTransformer = new ClosureExpressionTransformer(this);
private final BooleanExpressionTransformer booleanExpressionTransformer = new BooleanExpressionTransformer(this);
- private final VariableExpressionTransformer variableExpressionTransformer = new VariableExpressionTransformer();
+ private final BinaryExpressionTransformer binaryExpressionTransformer = new BinaryExpressionTransformer(this);
private final RangeExpressionTransformer rangeExpressionTransformer = new RangeExpressionTransformer(this);
private final ListExpressionTransformer listExpressionTransformer = new ListExpressionTransformer(this);
private final CastExpressionOptimizer castExpressionTransformer = new CastExpressionOptimizer(this);
@@ -110,53 +108,38 @@ public class StaticCompilationTransformer extends ClassCodeExpressionTransformer
@Override
public Expression transform(final Expression expr) {
- if (expr instanceof BinaryExpression) {
- return binaryExpressionTransformer.transformBinaryExpression((BinaryExpression) expr);
+ if (expr instanceof StaticMethodCallExpression) {
+ return staticMethodCallExpressionTransformer.transformStaticMethodCallExpression((StaticMethodCallExpression) expr);
}
- if (expr instanceof ClosureExpression) {
- return closureExpressionTransformer.transformClosureExpression((ClosureExpression) expr);
+ if (expr instanceof MethodCallExpression) {
+ return methodCallExpressionTransformer.transformMethodCallExpression((MethodCallExpression) expr);
}
if (expr instanceof ConstructorCallExpression) {
return constructorCallTransformer.transformConstructorCall((ConstructorCallExpression) expr);
}
- if (expr instanceof MethodCallExpression) {
- return methodCallExpressionTransformer.transformMethodCallExpression((MethodCallExpression) expr);
+ if (expr instanceof PropertyExpression) {
+ return propertyExpressionTransformer.transformPropertyExpression((PropertyExpression) expr);
}
- if (expr instanceof StaticMethodCallExpression) {
- return staticMethodCallExpressionTransformer.transformStaticMethodCallExpression((StaticMethodCallExpression) expr);
+ if (expr instanceof VariableExpression) {
+ return variableExpressionTransformer.transformVariableExpression((VariableExpression) expr);
+ }
+ if (expr instanceof ClosureExpression) {
+ return closureExpressionTransformer.transformClosureExpression((ClosureExpression) expr);
}
if (expr instanceof BooleanExpression) {
return booleanExpressionTransformer.transformBooleanExpression((BooleanExpression) expr);
}
- if (expr instanceof VariableExpression) {
- return variableExpressionTransformer.transformVariableExpression((VariableExpression) expr);
- }
- if (expr instanceof PropertyExpression && isSuperExpression(((PropertyExpression) expr).getObjectExpression())) { // TODO: all obj exp
- // TODO: delegate to propertyExpressionTransformer.transformPropertyExpression((PropertyExpression) expr);
- MethodNode dmct = expr.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
- // NOTE: BinaryExpressionTransformer handles the setter
- if (dmct != null && dmct.getParameters().length == 0) {
- PropertyExpression pe = (PropertyExpression) expr;
-
- MethodCallExpression mce = new MethodCallExpression(transform(pe.getObjectExpression()), dmct.getName(), MethodCallExpression.NO_ARGUMENTS);
- mce.setImplicitThis(pe.isImplicitThis());
- mce.setSpreadSafe(pe.isSpreadSafe());
- mce.setType(dmct.getReturnType());
- mce.setMethodTarget(dmct);
- mce.setSourcePosition(pe);
- mce.copyNodeMetaData(pe);
- mce.setSafe(pe.isSafe());
- return mce;
- }
+ if (expr instanceof BinaryExpression) {
+ return binaryExpressionTransformer.transformBinaryExpression((BinaryExpression) expr);
}
if (expr instanceof RangeExpression) {
- return rangeExpressionTransformer.transformRangeExpression(((RangeExpression) expr));
+ return rangeExpressionTransformer.transformRangeExpression((RangeExpression) expr);
}
if (expr instanceof ListExpression) {
return listExpressionTransformer.transformListExpression((ListExpression) expr);
}
if (expr instanceof CastExpression) {
- return castExpressionTransformer.transformCastExpression(((CastExpression) expr));
+ return castExpressionTransformer.transformCastExpression((CastExpression) expr);
}
return super.transform(expr);
}
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
index 978fcec..d1c3fd7 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/VariableExpressionTransformer.java
@@ -20,73 +20,91 @@ package org.codehaus.groovy.transform.sc.transformers;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
import org.codehaus.groovy.transform.stc.StaticTypesMarker;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
-/**
- * Transformer for VariableExpression the bytecode backend wouldn't be able to
- * handle otherwise.
- */
-public class VariableExpressionTransformer {
+class VariableExpressionTransformer {
- public Expression transformVariableExpression(final VariableExpression expr) {
- Expression trn = tryTransformDelegateToProperty(expr);
- if (trn == null) {
- trn = tryTransformPrivateFieldAccess(expr);
+ Expression transformVariableExpression(final VariableExpression ve) {
+ Expression xe = tryTransformImplicitReceiver(ve);
+ if (xe == null) {
+ xe = tryTransformPrivateFieldAccess(ve);
+ }
+ if (xe == null) {
+ xe = tryTransformDirectMethodTarget(ve);
+ }
+ if (xe != null) {
+ return xe;
}
- return trn != null ? trn : expr;
+ return ve;
}
- private static Expression tryTransformDelegateToProperty(final VariableExpression expr) {
+ private static Expression tryTransformImplicitReceiver(final VariableExpression ve) {
// we need to transform variable expressions that go to a delegate
// to a property expression, as ACG would lose the information in
// processClassVariable before it reaches any makeCall, that could handle it
- Object val = expr.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
- if (val == null || val.equals(expr.getName())) return null;
+ Object val = ve.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
+ if (val == null || val.equals(ve.getName())) return null;
// TODO: handle the owner and delegate cases better for nested scenarios and potentially remove the need for the implicit this case
- Expression receiver = varX("owner".equals(val) ? (String) val : "delegate".equals(val) ? (String) val : "this");
- // GROOVY-9136 -- object expression should not overlap source range of property; property stands in for original variable expression
- receiver.setLineNumber(expr.getLineNumber());
- receiver.setColumnNumber(expr.getColumnNumber());
+ Expression receiver = new VariableExpression("owner".equals(val) ? (String) val : "delegate".equals(val) ? (String) val : "this");
+ // GROOVY-9136: object expression should not overlap source range of property; property stands in for original variable expression
+ receiver.setColumnNumber(ve.getColumnNumber());
+ receiver.setLineNumber(ve.getLineNumber());
- PropertyExpression pexp = propX(receiver, expr.getName());
- pexp.getProperty().setSourcePosition(expr);
- pexp.copyNodeMetaData(expr);
- pexp.setImplicitThis(true);
+ PropertyExpression pe = propX(receiver, ve.getName());
+ pe.getProperty().setSourcePosition(ve);
+ pe.setImplicitThis(true);
+ pe.copyNodeMetaData(ve);
- ClassNode owner = expr.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
+ ClassNode owner = ve.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
if (owner != null) {
receiver.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, owner);
receiver.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, val);
}
- pexp.removeNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
+ pe.removeNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
- return pexp;
+ return pe;
}
- private static Expression tryTransformPrivateFieldAccess(final VariableExpression expr) {
- FieldNode field = expr.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS);
+ private static Expression tryTransformPrivateFieldAccess(final VariableExpression ve) {
+ FieldNode field = ve.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS);
if (field == null) {
- field = expr.getNodeMetaData(StaticTypesMarker.PV_FIELDS_MUTATION);
+ field = ve.getNodeMetaData(StaticTypesMarker.PV_FIELDS_MUTATION);
}
- if (field != null) {
- // access to a private field from a section of code that normally doesn't have access to it, like a closure or an inner class
- PropertyExpression pexp = !field.isStatic() ? thisPropX(true, expr.getName()) : propX(classX(field.getDeclaringClass()), expr.getName());
- // store the declaring class so that the class writer knows that it will have to call a bridge method
- pexp.getObjectExpression().putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, field.getDeclaringClass());
- pexp.putNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE, field.getOriginType());
- pexp.getProperty().setSourcePosition(expr);
- return pexp;
+ if (field == null) {
+ return null;
}
- return null;
+
+ // access to a private field from a section of code that normally doesn't have access to it, like a closure block or an inner class
+ PropertyExpression pe = !field.isStatic() ? thisPropX(true, ve.getName()) : propX(classX(field.getDeclaringClass()), ve.getName());
+ // store the declaring class so that the class writer knows that it will have to call a bridge method
+ pe.getObjectExpression().putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, field.getDeclaringClass());
+ pe.putNodeMetaData(StaticTypesMarker.DECLARATION_INFERRED_TYPE, field.getOriginType());
+ pe.getProperty().setSourcePosition(ve);
+ return pe;
+ }
+
+ private static Expression tryTransformDirectMethodTarget(final VariableExpression ve) {
+ MethodNode dmct = ve.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
+ // NOTE: BinaryExpressionTransformer handles the setter
+ if (dmct == null || dmct.getParameters().length != 0) {
+ return null;
+ }
+
+ MethodCallExpression mce = callThisX(dmct.getName());
+ mce.getMethod().setSourcePosition(ve);
+ mce.setMethodTarget(dmct);
+ return mce;
}
}