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 9faaa88535 GROOVY-11483: SC: elide spurious `ACONST_NULL` and `POP` 
after setter
9faaa88535 is described below

commit 9faaa88535d5f867bd4ae76bd4cffaa065819d74
Author: Eric Milles <[email protected]>
AuthorDate: Sun Jan 18 13:50:45 2026 -0600

    GROOVY-11483: SC: elide spurious `ACONST_NULL` and `POP` after setter
---
 .../asm/sc/StaticPropertyAccessHelper.java         | 33 ++++++++++++----------
 ...icTypesBinaryExpressionMultiTypeDispatcher.java | 10 ++++---
 .../transformers/ConstructorCallTransformer.java   | 12 ++++----
 .../asm/sc/StaticCompileConstructorsTest.groovy    | 17 +++++++++--
 4 files changed, 46 insertions(+), 26 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
index 6cffa34b55..b655ce705d 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticPropertyAccessHelper.java
@@ -45,27 +45,30 @@ public abstract class StaticPropertyAccessHelper {
             final boolean spreadSafe,
             final boolean returnValue,
             final Expression sourceExpression) {
+        MethodCallExpression call;
+        Expression result;
         if (returnValue) {
-            TemporaryVariableExpression tmp = new 
TemporaryVariableExpression(valueExpression);
-            PoppingMethodCallExpression call = new 
PoppingMethodCallExpression(receiver, setterMethod, tmp);
-            call.setSafe(safe);
-            call.setSpreadSafe(spreadSafe);
-            call.setImplicitThis(implicitThis);
-            call.setSourcePosition(sourceExpression);
-            PoppingListOfExpressionsExpression list = new 
PoppingListOfExpressionsExpression(tmp, call);
-            list.setSourcePosition(sourceExpression);
-            return list;
+            var temp = new TemporaryVariableExpression(valueExpression);
+            var pmce = new PoppingMethodCallExpression(receiver, setterMethod, 
temp);
+            result = new PoppingListOfExpressionsExpression(temp, pmce);
+            result.setSourcePosition(sourceExpression);
+            call = pmce;
         } else {
-            MethodCallExpression call = new MethodCallExpression(receiver, 
setterMethod.getName(), valueExpression);
-            call.setSafe(safe);
-            call.setSpreadSafe(spreadSafe);
-            call.setImplicitThis(implicitThis);
+            call = new MethodCallExpression(receiver, setterMethod.getName(), 
valueExpression);
             call.setMethodTarget(setterMethod);
-            call.setSourcePosition(sourceExpression);
-            return call;
+            result = call;
         }
+        call.setSafe(safe);
+        call.setSpreadSafe(spreadSafe);
+        call.setImplicitThis(implicitThis);
+        call.setNodeMetaData(AsmClassGenerator.ELIDE_EXPRESSION_VALUE, 
Boolean.TRUE); // GROOVY-11843
+        call.setSourcePosition(sourceExpression);
+
+        return result;
     }
 
+    
//--------------------------------------------------------------------------
+
     private static class PoppingListOfExpressionsExpression extends 
ListOfExpressionsExpression {
 
         private final TemporaryVariableExpression tmp;
diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index e139b7331b..c8508b02bf 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -163,7 +163,8 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher 
extends BinaryExpres
                     expressionWithoutAssignment,
                     pexp.isSafe(),
                     pexp.isSpreadSafe(),
-                    pexp.isImplicitThis())) {
+                    pexp.isImplicitThis(),
+                    true)) { // TODO: GROOVY-11843
                 return;
             }
         }
@@ -181,7 +182,8 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher 
extends BinaryExpres
                     expression.getRightExpression(),
                     pexp.isSafe(),
                     pexp.isSpreadSafe(),
-                    pexp.isImplicitThis())) {
+                    pexp.isImplicitThis(),
+                    
!Boolean.TRUE.equals(expression.getNodeMetaData(ELIDE_EXPRESSION_VALUE)))) { // 
GROOVY-11843
                 return;
             }
             // GROOVY-5620: spread-safe operator on LHS is not supported
@@ -241,7 +243,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher 
extends BinaryExpres
         result.visit(controller.getAcg());
     }
 
-    private boolean makeSetProperty(final Expression receiver, final 
Expression message, final Expression arguments, final boolean safe, final 
boolean spreadSafe, final boolean implicitThis) {
+    private boolean makeSetProperty(final Expression receiver, final 
Expression message, final Expression arguments, final boolean safe, final 
boolean spreadSafe, final boolean implicitThis, final boolean returnValue) {
         var receiverType = controller.getTypeChooser().resolveType(receiver, 
controller.getClassNode());
         var thisReceiver = isThisExpression(receiver);
         var propertyName = message.getText();
@@ -282,7 +284,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher 
extends BinaryExpres
                     implicitThis,
                     safe,
                     spreadSafe,
-                    true, // to be replaced with a proper test whether a 
return value should be used or not
+                    returnValue,
                     message
             );
             call.visit(controller.getAcg());
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 7190f94147..af0160e54a 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
@@ -34,7 +34,6 @@ import org.codehaus.groovy.classgen.BytecodeExpression;
 import org.codehaus.groovy.classgen.asm.BytecodeHelper;
 import org.codehaus.groovy.classgen.asm.CompileStack;
 import org.codehaus.groovy.classgen.asm.OperandStack;
-import org.codehaus.groovy.classgen.asm.WriterController;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
 import org.objectweb.asm.MethodVisitor;
@@ -130,9 +129,8 @@ public class ConstructorCallTransformer {
 
         @Override
         public void visit(final MethodVisitor mv) {
-            WriterController controller = acg.getController();
-            CompileStack compileStack = controller.getCompileStack();
-            OperandStack operandStack = controller.getOperandStack();
+            CompileStack compileStack = acg.getController().getCompileStack();
+            OperandStack operandStack = acg.getController().getOperandStack();
 
             ClassNode ctorType = getType();
             // create temporary variable to store new object instance
@@ -149,6 +147,8 @@ public class ConstructorCallTransformer {
             mv.visitMethodInsn(INVOKESPECIAL, ctorTypeName, "<init>", 
signature, false);
             mv.visitVarInsn(ASTORE, tmpObj);
 
+            int mark = operandStack.getStackLength();
+
             // process property initializers
             for (MapEntryExpression entryExpression : 
map.getMapEntryExpressions()) {
                 Expression keyExpression = entryExpression.getKeyExpression();
@@ -163,9 +163,11 @@ public class ConstructorCallTransformer {
                 Expression setExpression = 
staticCompilationTransformer.transform(
                         assignX(varExpression, valExpression) // tmp.key = 
value
                 );
+                
setExpression.putNodeMetaData(AsmClassGenerator.ELIDE_EXPRESSION_VALUE, 
Boolean.TRUE);
                 setExpression.setSourcePosition(entryExpression);
                 setExpression.visit(acg);
-                operandStack.pop();
+
+                operandStack.popDownTo(mark);
             }
 
             // result object
diff --git 
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/StaticCompileConstructorsTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/StaticCompileConstructorsTest.groovy
index c9d8050965..40a2fbd25e 100644
--- 
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/StaticCompileConstructorsTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/StaticCompileConstructorsTest.groovy
@@ -23,7 +23,7 @@ import groovy.transform.stc.ConstructorsSTCTest
 /**
  * Unit tests for static compilation: constructors.
  */
-class StaticCompileConstructorsTest extends ConstructorsSTCTest implements 
StaticCompilationTestSupport {
+final class StaticCompileConstructorsTest extends ConstructorsSTCTest 
implements StaticCompilationTestSupport {
 
     void testMapConstructorError() {
         assertScript '''
@@ -40,11 +40,24 @@ class StaticCompileConstructorsTest extends 
ConstructorsSTCTest implements Stati
             class Person {
                 String name
             }
-
             C.test()
         '''
     }
 
+    // GROOVY-11843
+    void testMapConstructorOptimization() {
+        assertScript '''
+            class C {
+                int i, j, k
+            }
+            new C(i:1, j:2, k:3)
+        '''
+        String script = astTrees.find{ it.key != 'C' }.value[1]
+        Number offset = script.indexOf('run()Ljava/lang/Object;')
+        String method = script.substring(offset, script.indexOf('\n' + 
System.lineSeparator(), offset) + 1)
+        assert method.count('ACONST_NULL') == 0
+    }
+
     void testPrivateConstructorFromClosure() {
         assertScript '''
             class C {

Reply via email to