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/03/10 22:19:13 UTC

[groovy] branch master updated: rework invoke method implicitThis/thisObject

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


The following commit(s) were added to refs/heads/master by this push:
     new e91f18c  rework invoke method implicitThis/thisObject
e91f18c is described below

commit e91f18c3dc55ae4f9ee378c2d30fd8fd04270ae7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Mar 10 15:36:37 2021 -0600

    rework invoke method implicitThis/thisObject
---
 .../groovy/classgen/AsmClassGenerator.java         |  7 +---
 .../groovy/classgen/asm/InvocationWriter.java      | 43 ++++++++++------------
 .../groovy/classgen/asm/WriterController.java      |  8 ++++
 .../classgen/asm/sc/StaticInvocationWriter.java    | 21 ++++++-----
 .../classgen/asm/sc/StaticTypesLambdaWriter.java   |  7 +---
 5 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index ae99861..bfbd856 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1343,12 +1343,7 @@ public class AsmClassGenerator extends ClassGenerator {
             // "this" in static context is Class instance
             if (controller.isStaticMethod() || controller.getCompileStack().isInSpecialConstructorCall()
                     || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
-                ClassNode thisType = controller.getClassNode();
-                if (controller.isInGeneratedFunction()) {
-                    do { thisType = thisType.getOuterClass();
-                    } while (ClassHelper.isGeneratedFunction(thisType));
-                }
-                classX(thisType).visit(this);
+                classX(controller.getThisType()).visit(this);
             } else {
                 loadThis(expression);
             }
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 eaa920c..ef8c0c3 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -56,7 +56,6 @@ import static org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression;
 import static org.codehaus.groovy.ast.ClassHelper.isFunctionalInterface;
-import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isClassClassNodeWrappingConcreteType;
 import static org.objectweb.asm.Opcodes.AALOAD;
@@ -106,16 +105,16 @@ 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 = controller.getClassNode();
+        ClassNode sender;
         if (isSuperExpression(receiver) || (isThisExpression(receiver) && !implicitThis)) {
-            while (isGeneratedFunction(sender)) {
-                sender = sender.getOuterClass();
-            }
+            sender = controller.getThisType();
             if (isSuperExpression(receiver)) {
                 sender = sender.getSuperClass(); // GROOVY-4035
                 implicitThis = false; // prevent recursion
                 safe = false; // GROOVY-6045
             }
+        } else {
+            sender = controller.getClassNode();
         }
 
         makeCall(origin, new ClassExpression(sender), receiver, message, arguments, adapter, safe, spreadSafe, implicitThis);
@@ -126,13 +125,15 @@ public class InvocationWriter {
 
         ClassNode declaringClass = target.getDeclaringClass();
         String methodName = target.getName();
-        int opcode = INVOKEVIRTUAL;
+        int opcode;
         if (target.isStatic()) {
             opcode = INVOKESTATIC;
         } else if (declaringClass.isInterface()) {
             opcode = INVOKEINTERFACE;
         } else if (target.isPrivate() || isSuperExpression(receiver)) {
             opcode = INVOKESPECIAL;
+        } else {
+            opcode = INVOKEVIRTUAL;
         }
 
         CompileStack compileStack = controller.getCompileStack();
@@ -143,43 +144,37 @@ public class InvocationWriter {
         // handle receiver
         int argumentsToRemove = 0;
         if (opcode != INVOKESTATIC) {
+            argumentsToRemove = 1;
             if (receiver != null) {
-                // load receiver if not static invocation
-                // TODO: fix inner class case
+                Expression objectExpression = receiver;
                 if (implicitThis
                         && classNode.getOuterClass() != null
                         && !classNode.isDerivedFrom(declaringClass)
                         && !classNode.implementsInterface(declaringClass)) {
-                    // we are calling an outer class method
+                    // outer class method invocation
                     compileStack.pushImplicitThis(false);
-                    if (controller.isInGeneratedFunction()) {
-                        new VariableExpression("thisObject").visit(controller.getAcg());
-                    } else { // TODO: handle implicitThis && !isThisExpression(receiver)
-                        Expression expr = new PropertyExpression(new ClassExpression(declaringClass), "this");
-                        expr.visit(controller.getAcg());
+                    if (!controller.isInGeneratedFunction()) {
+                        objectExpression = new PropertyExpression(new ClassExpression(declaringClass), "this");
                     }
                 } else {
                     compileStack.pushImplicitThis(implicitThis);
-                    receiver.visit(controller.getAcg());
                 }
+                objectExpression.visit(controller.getAcg());
                 operandStack.doGroovyCast(declaringClass);
                 compileStack.popImplicitThis();
-                argumentsToRemove += 1;
             } else {
                 mv.visitIntInsn(ALOAD, 0);
                 operandStack.push(classNode);
-                argumentsToRemove += 1;
             }
         }
 
         ClassNode receiverType;
-        if (receiver == null) {
-            receiverType = declaringClass;
-        } else {
+        if (receiver != null) {
             receiverType = controller.getTypeChooser().resolveType(receiver, classNode);
-            if (isClassClassNodeWrappingConcreteType(receiverType) && target.isStatic()) {
+            if (isClassClassNodeWrappingConcreteType(receiverType) && target.isStatic())
                 receiverType = receiverType.getGenericsTypes()[0].getType();
-            }
+        } else {
+            receiverType = declaringClass;
         }
 
         int stackLen = operandStack.getStackLength();
@@ -215,8 +210,8 @@ public class InvocationWriter {
             mv.visitInsn(ACONST_NULL);
         }
         argumentsToRemove += (operandStack.getStackLength() - stackLen);
-        controller.getOperandStack().remove(argumentsToRemove);
-        controller.getOperandStack().push(returnType);
+        operandStack.remove(argumentsToRemove);
+        operandStack.push(returnType);
         return true;
     }
 
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index dd8ba29..d5a59e1 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -287,6 +287,14 @@ public class WriterController {
         this.methodNode = null;
     }
 
+    public ClassNode getThisType() {
+        ClassNode thisType = getClassNode();
+        while (isGeneratedFunction(thisType)) {
+            thisType = thisType.getOuterClass();
+        }
+        return thisType;
+    }
+
     public ClassNode getReturnType() {
         if (methodNode != null) {
             return methodNode.getReturnType();
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 b9712a7..aff3014 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
@@ -84,6 +84,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
+import static org.codehaus.groovy.transform.trait.Traits.isTrait;
 import static org.objectweb.asm.Opcodes.ACONST_NULL;
 import static org.objectweb.asm.Opcodes.ALOAD;
 import static org.objectweb.asm.Opcodes.CHECKCAST;
@@ -364,18 +365,20 @@ public class StaticInvocationWriter extends InvocationWriter {
             }
         } else if (target.isPublic() && receiver != null) {
             if (implicitThis
+                    && controller.isInGeneratedFunction()
                     && !classNode.isDerivedFrom(target.getDeclaringClass())
-                    && !classNode.implementsInterface(target.getDeclaringClass())
-                    && classNode.getOuterClass() != null && controller.isInGeneratedFunction()) {
-                ClassNode current = classNode.getOuterClass();
-                fixedReceiver = varX("thisObject", current);
-                // adjust for multiple levels of nesting if needed
-                while (current.getOuterClass() != null && !target.getDeclaringClass().equals(current)) {
-                    FieldNode thisField = current.getField("this$0");
-                    current = current.getOuterClass();
+                    && !classNode.implementsInterface(target.getDeclaringClass())) {
+                ClassNode thisType = controller.getThisType();
+                if (isTrait(thisType.getOuterClass())) thisType = ClassHelper.DYNAMIC_TYPE; // GROOVY-7242
+
+                fixedReceiver = varX("thisObject", thisType);
+                // account for multiple levels of inner types
+                while (thisType.getOuterClass() != null && !target.getDeclaringClass().equals(thisType)) {
+                    FieldNode thisField = thisType.getField("this$0");
+                    thisType = thisType.getOuterClass();
                     if (thisField != null) {
                         fixedReceiver = propX(fixedReceiver, "this$0");
-                        fixedReceiver.setType(current);
+                        fixedReceiver.setType(thisType);
                         fixedImplicitThis = false;
                     }
                 }
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 1cf4f5b..a92770f 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
@@ -60,7 +60,6 @@ import static org.codehaus.groovy.ast.ClassHelper.SERIALIZABLE_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.SERIALIZEDLAMBDA_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.findSAM;
-import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
 import static org.codehaus.groovy.ast.ClassHelper.long_TYPE;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
@@ -175,11 +174,7 @@ public class StaticTypesLambdaWriter extends LambdaWriter implements AbstractFun
         mv.visitInsn(DUP);
 
         if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall() || !accessingInstanceMembers) {
-            ClassNode classNode = controller.getClassNode();
-            while (isGeneratedFunction(classNode)) {
-                classNode = classNode.getOuterClass();
-            }
-            classX(classNode).visit(controller.getAcg());
+            classX(controller.getThisType()).visit(controller.getAcg());
         } else {
             loadThis();
         }