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 2020/12/08 22:58:24 UTC

[groovy] branch master updated: refactor shared logic

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 e9db9ce  refactor shared logic
e9db9ce is described below

commit e9db9ce907e6fd8c5e742883074631ade1152334
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Dec 8 16:58:13 2020 -0600

    refactor shared logic
---
 .../groovy/classgen/asm/StatementWriter.java       | 100 ++++++++++-----------
 1 file changed, 46 insertions(+), 54 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 7714d0a..e2505fc 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -21,7 +21,6 @@ package org.codehaus.groovy.classgen.asm;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
 import org.codehaus.groovy.ast.expr.ClosureListExpression;
@@ -345,97 +344,78 @@ public class StatementWriter {
 
         Statement tryStatement = statement.getTryStatement();
         Statement finallyStatement = statement.getFinallyStatement();
-
-        // start try block, label needed for exception table
-        Label tryStart = new Label();
-        mv.visitLabel(tryStart);
         BlockRecorder tryBlock = makeBlockRecorder(finallyStatement);
-        tryBlock.startRange(tryStart);
 
+        startRange(tryBlock, mv);
         tryStatement.visit(controller.getAcg());
 
-        // goto finally part
+        // skip past catch block(s)
         Label finallyStart = new Label();
         mv.visitJumpInsn(GOTO, finallyStart);
 
-        Label tryEnd = new Label();
-        mv.visitLabel(tryEnd);
-        tryBlock.closeRange(tryEnd);
-        // pop for "makeBlockRecorder(finallyStatement)"
-        controller.getCompileStack().pop();
+        closeRange(tryBlock, mv);
+        // pop for BlockRecorder
+        compileStack.pop();
 
         BlockRecorder catches = makeBlockRecorder(finallyStatement);
         for (CatchStatement catchStatement : statement.getCatchStatements()) {
-            ClassNode exceptionType = catchStatement.getExceptionType();
-            String exceptionTypeInternalName = BytecodeHelper.getClassInternalName(exceptionType);
+            Label catchBlock = startRange(catches, mv);
 
-            // start catch block, label needed for exception table
-            Label catchStart = new Label();
-            mv.visitLabel(catchStart);
-            catches.startRange(catchStart);
-
-            // create exception variable and store the exception
-            Parameter exceptionVariable = catchStatement.getVariable();
+            // create variable for the exception
             compileStack.pushState();
-            compileStack.defineVariable(exceptionVariable, true);
+            // TODO: Is it okay that "catch (e)" makes variable type Object?
+            compileStack.defineVariable(catchStatement.getVariable(), true);
             // handle catch body
             catchStatement.visit(controller.getAcg());
-            // place holder to avoid problems with empty catch blocks
+            // placeholder to avoid problems with empty catch block
             mv.visitInsn(NOP);
             // pop for the variable
-            controller.getCompileStack().pop();
+            compileStack.pop();
 
             // end of catch
-            Label catchEnd = new Label();
-            mv.visitLabel(catchEnd);
-            catches.closeRange(catchEnd);
-
-            // goto finally start
+            closeRange(catches, mv);
             mv.visitJumpInsn(GOTO, finallyStart);
-            compileStack.writeExceptionTable(tryBlock, catchStart, exceptionTypeInternalName);
+            compileStack.writeExceptionTable(tryBlock, catchBlock,
+                    BytecodeHelper.getClassInternalName(catchStatement.getExceptionType()));
         }
 
         // used to handle exceptions in catches and regularly visited finals
-        Label catchAny = new Label();
+        Label catchAll = new Label();
 
-        // add "catch any" block to exception table for try part we do this
-        // after the exception blocks, because else this one would supersede
-        // any of those otherwise
-        compileStack.writeExceptionTable(tryBlock, catchAny, null);
+        // add "catch all" block to exception table for try part; we do this
+        // after the exception blocks so they are not superseded by this one
+        compileStack.writeExceptionTable(tryBlock, catchAll, null);
         // same for the catch parts
-        compileStack.writeExceptionTable(catches, catchAny, null);
+        compileStack.writeExceptionTable(catches , catchAll, null);
 
-        // pop for "makeBlockRecorder(catches)"
+        // pop for BlockRecorder
         compileStack.pop();
 
         // start finally
         mv.visitLabel(finallyStart);
         finallyStatement.visit(controller.getAcg());
 
-        // goto after all-catching block
-        Label skipCatchAll = new Label();
-        mv.visitJumpInsn(GOTO, skipCatchAll);
+        // skip past all-catching block
+        Label afterCatchAll = new Label();
+        mv.visitJumpInsn(GOTO, afterCatchAll);
 
-        // start a block catching any Exception
-        mv.visitLabel(catchAny);
-        // store exception
-        // TODO: maybe define a Throwable and use it here instead of Object
-        operandStack.push(ClassHelper.OBJECT_TYPE);
-        int anyExceptionIndex = compileStack.defineTemporaryVariable("exception", true);
+        mv.visitLabel(catchAll);
+        operandStack.push(ClassHelper.make(Throwable.class));
+        int anyThrowableIndex = compileStack.defineTemporaryVariable("throwable", true);
 
         // GROOVY-9199
         controller.resetLineNumber();
         int line = finallyStatement.getLineNumber();
-        if (line > 0) mv.visitLineNumber(line, catchAny);
+        if (line > 0) mv.visitLineNumber(line, catchAll);
 
         finallyStatement.visit(controller.getAcg());
 
-        // load the exception and rethrow it
-        mv.visitVarInsn(ALOAD, anyExceptionIndex);
+        // load the throwable and rethrow it
+        mv.visitVarInsn(ALOAD, anyThrowableIndex);
         mv.visitInsn(ATHROW);
 
-        mv.visitLabel(skipCatchAll);
-        compileStack.removeVar(anyExceptionIndex);
+        mv.visitLabel(afterCatchAll);
+        compileStack.removeVar(anyThrowableIndex);
     }
 
     private BlockRecorder makeBlockRecorder(final Statement finallyStatement) {
@@ -449,6 +429,19 @@ public class StatementWriter {
         return recorder;
     }
 
+    private static Label startRange(final BlockRecorder br, final MethodVisitor mv) {
+        Label label = new Label();
+        mv.visitLabel(label);
+        br.startRange(label);
+        return label;
+    }
+
+    private static void  closeRange(final BlockRecorder br, final MethodVisitor mv) {
+        Label label = new Label();
+        mv.visitLabel(label);
+        br.closeRange(label);
+    }
+
     public void writeSwitch(final SwitchStatement statement) {
         controller.getAcg().onLineNumber(statement, "visitSwitch");
         writeStatementLabel(statement);
@@ -599,9 +592,8 @@ public class StatementWriter {
         OperandStack operandStack = controller.getOperandStack();
         ClassNode returnType = controller.getReturnType();
 
-        if (returnType == ClassHelper.VOID_TYPE) {
-            if (!(statement.isReturningNullOrVoid())) {
-                //TODO: move to Verifier
+        if (returnType.equals(ClassHelper.VOID_TYPE)) {
+            if (!statement.isReturningNullOrVoid()) { // TODO: move to Verifier
                 controller.getAcg().throwException("Cannot use return statement with an expression on a method that returns void");
             }
             controller.getCompileStack().applyBlockRecorder();