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 (&lt;&lt;, +=, ...). 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;
     }
 }