This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY_3_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
commit eea41b890798ccc160754b937098b0f1ca600653 Author: Eric Milles <[email protected]> AuthorDate: Thu Feb 16 08:48:35 2023 -0600 GROOVY-10918: direct store to local variable or parameter (no temporary) --- .../classgen/asm/BinaryExpressionHelper.java | 26 ++++++++++---- .../codehaus/groovy/classgen/asm/CompileStack.java | 2 +- .../classgen/asm/sc/StaticCompilationTest.groovy | 41 +++++++++++----------- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java index 8861238565..6e1ae6602d 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java @@ -377,26 +377,38 @@ public class BinaryExpressionHelper { Expression rightExpression = expression.getRightExpression(); boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression); + // TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware. + ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode()); + if (directAssignment && rightExpression instanceof EmptyExpression) { - VariableExpression ve = (VariableExpression) leftExpression; - BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false); - operandStack.loadOrStoreVariable(var, false); + BytecodeVariable v = compileStack.defineVariable((Variable) leftExpression, lhsType, false); + operandStack.loadOrStoreVariable(v, false); return; } - // evaluate the RHS and store the result - // TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware. - ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode()); + + // evaluate RHS and store the value + if (rightExpression instanceof ListExpression && lhsType.isArray()) { ListExpression list = (ListExpression) rightExpression; ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions()); array.setSourcePosition(list); array.visit(acg); } else if (rightExpression instanceof EmptyExpression) { - loadInitValue(leftExpression.getType()); // TODO: lhsType? + loadInitValue(lhsType); // null or zero (or false) } else { rightExpression.visit(acg); } + // GROOVY-10918: direct store to local variable or parameter (no temp) + if (!defineVariable && leftExpression instanceof VariableExpression) { + BytecodeVariable v = compileStack.getVariable(leftExpression.getText(), false); + if (v != null) { + operandStack.dup(); // return value of the assignment expression + operandStack.storeVar(v); + return; + } + } + ClassNode rhsType = operandStack.getTopOperand(); int rhsValueId; diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java b/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java index a4bb1c5a59..7753839db9 100644 --- a/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java +++ b/src/main/java/org/codehaus/groovy/classgen/asm/CompileStack.java @@ -260,7 +260,7 @@ public class CompileStack implements Opcodes { * @return the index used for this temporary variable */ public int defineTemporaryVariable(final Variable var, final boolean store) { - return defineTemporaryVariable(var.getName(), var.getType(),store); + return defineTemporaryVariable(var.getName(), var.getType(), store); } public BytecodeVariable getVariable(final String variableName ) { diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTest.groovy index 5284303927..33b1323938 100644 --- a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTest.groovy +++ b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTest.groovy @@ -277,27 +277,26 @@ class StaticCompilationTest extends AbstractBytecodeTestCase { } m 'Cedric' ''').hasStrictSequence([ - "ICONST", - "INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;", - "ASTORE", - "L1", - "ALOAD 2", - "POP", - "L2", - "LINENUMBER", - "ALOAD 1", - "ASTORE 3", - "ALOAD 3", - "ASTORE 2", - "ALOAD 3", - "POP", - "L3", - "LINENUMBER", - "ALOAD 2", - "CHECKCAST java/lang/String", - "INVOKEVIRTUAL java/lang/String.toUpperCase ()Ljava/lang/String;", - "ARETURN", - "L4" + 'LINENUMBER 4', + 'ICONST_1', + 'INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;', + 'ASTORE 2', + 'L1', + 'ALOAD 2', + 'POP', + 'L2', + 'LINENUMBER 5', + 'ALOAD 1', + 'DUP', + 'ASTORE 2', + 'POP', + 'L3', + 'LINENUMBER 6', + 'ALOAD 2', + 'CHECKCAST java/lang/String', + 'INVOKEVIRTUAL java/lang/String.toUpperCase ()Ljava/lang/String;', + 'ARETURN', + 'L4' ]) }
