8024039: javac, previous solution for JDK-8022186 was incorrect

Fri, 06 Sep 2013 09:53:24 +0100

author
vromero
date
Fri, 06 Sep 2013 09:53:24 +0100
changeset 2009
7c7b4aea6d50
parent 2008
e32a8a29643a
child 2010
64328fe5e4a6
child 2011
c9d6f4749f87

8024039: javac, previous solution for JDK-8022186 was incorrect
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/comp/Lower.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/jvm/Gen.java file | annotate | diff | comparison | revisions
test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Sep 05 16:35:47 2013 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Sep 06 09:53:24 2013 +0100
     1.3 @@ -49,7 +49,6 @@
     1.4  import static com.sun.tools.javac.code.TypeTag.*;
     1.5  import static com.sun.tools.javac.jvm.ByteCodes.*;
     1.6  import static com.sun.tools.javac.tree.JCTree.Tag.*;
     1.7 -import javax.lang.model.type.TypeKind;
     1.8  
     1.9  /** This pass translates away some syntactic sugar: inner classes,
    1.10   *  class literals, assertions, foreach loops, etc.
    1.11 @@ -3830,15 +3829,26 @@
    1.12  
    1.13      @Override
    1.14      public void visitTry(JCTry tree) {
    1.15 -        /* special case of try without catchers and with finally emtpy.
    1.16 -         * Don't give it a try, translate only the body.
    1.17 -         */
    1.18          if (tree.resources.isEmpty()) {
    1.19 +            /* special case of try without catchers and with finally emtpy.
    1.20 +             * Don't give it a try, translate only the body.
    1.21 +             */
    1.22              if (tree.catchers.isEmpty() &&
    1.23                  tree.finalizer.getStatements().isEmpty()) {
    1.24                  result = translate(tree.body);
    1.25              } else {
    1.26 -                super.visitTry(tree);
    1.27 +                /* also if the body is empty we only need to generate the finalizer
    1.28 +                 * provided that it's not empty.
    1.29 +                 */
    1.30 +                if (tree.body.getStatements().isEmpty()) {
    1.31 +                    if (tree.finalizer.getStatements().isEmpty()) {
    1.32 +                        result = translate(tree.body);
    1.33 +                    } else {
    1.34 +                        result = translate(tree.finalizer);
    1.35 +                    }
    1.36 +                } else {
    1.37 +                    super.visitTry(tree);
    1.38 +                }
    1.39              }
    1.40          } else {
    1.41              result = makeTwrTry(tree);
     2.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Thu Sep 05 16:35:47 2013 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Sep 06 09:53:24 2013 +0100
     2.3 @@ -1478,82 +1478,74 @@
     2.4              code.statBegin(TreeInfo.endPos(body));
     2.5              genFinalizer(env);
     2.6              code.statBegin(TreeInfo.endPos(env.tree));
     2.7 -            Chain exitChain;
     2.8 -            if (startpc != endpc) {
     2.9 -                exitChain = code.branch(goto_);
    2.10 -            } else {
    2.11 -                exitChain = code.branch(dontgoto);
    2.12 +            Chain exitChain = code.branch(goto_);
    2.13 +            endFinalizerGap(env);
    2.14 +            if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
    2.15 +                // start off with exception on stack
    2.16 +                code.entryPoint(stateTry, l.head.param.sym.type);
    2.17 +                genCatch(l.head, env, startpc, endpc, gaps);
    2.18 +                genFinalizer(env);
    2.19 +                if (hasFinalizer || l.tail.nonEmpty()) {
    2.20 +                    code.statBegin(TreeInfo.endPos(env.tree));
    2.21 +                    exitChain = Code.mergeChains(exitChain,
    2.22 +                                                 code.branch(goto_));
    2.23 +                }
    2.24 +                endFinalizerGap(env);
    2.25              }
    2.26 -            endFinalizerGap(env);
    2.27 -            if (startpc != endpc) {
    2.28 -                for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
    2.29 -                    // start off with exception on stack
    2.30 -                    code.entryPoint(stateTry, l.head.param.sym.type);
    2.31 -                    genCatch(l.head, env, startpc, endpc, gaps);
    2.32 -                    genFinalizer(env);
    2.33 -                    if (hasFinalizer || l.tail.nonEmpty()) {
    2.34 -                        code.statBegin(TreeInfo.endPos(env.tree));
    2.35 -                        exitChain = Code.mergeChains(exitChain,
    2.36 -                                                     code.branch(goto_));
    2.37 -                    }
    2.38 -                    endFinalizerGap(env);
    2.39 +            if (hasFinalizer) {
    2.40 +                // Create a new register segement to avoid allocating
    2.41 +                // the same variables in finalizers and other statements.
    2.42 +                code.newRegSegment();
    2.43 +
    2.44 +                // Add a catch-all clause.
    2.45 +
    2.46 +                // start off with exception on stack
    2.47 +                int catchallpc = code.entryPoint(stateTry, syms.throwableType);
    2.48 +
    2.49 +                // Register all exception ranges for catch all clause.
    2.50 +                // The range of the catch all clause is from the beginning
    2.51 +                // of the try or synchronized block until the present
    2.52 +                // code pointer excluding all gaps in the current
    2.53 +                // environment's GenContext.
    2.54 +                int startseg = startpc;
    2.55 +                while (env.info.gaps.nonEmpty()) {
    2.56 +                    int endseg = env.info.gaps.next().intValue();
    2.57 +                    registerCatch(body.pos(), startseg, endseg,
    2.58 +                                  catchallpc, 0);
    2.59 +                    startseg = env.info.gaps.next().intValue();
    2.60                  }
    2.61 +                code.statBegin(TreeInfo.finalizerPos(env.tree));
    2.62 +                code.markStatBegin();
    2.63  
    2.64 -                if (hasFinalizer) {
    2.65 -                    // Create a new register segement to avoid allocating
    2.66 -                    // the same variables in finalizers and other statements.
    2.67 -                    code.newRegSegment();
    2.68 +                Item excVar = makeTemp(syms.throwableType);
    2.69 +                excVar.store();
    2.70 +                genFinalizer(env);
    2.71 +                excVar.load();
    2.72 +                registerCatch(body.pos(), startseg,
    2.73 +                              env.info.gaps.next().intValue(),
    2.74 +                              catchallpc, 0);
    2.75 +                code.emitop0(athrow);
    2.76 +                code.markDead();
    2.77  
    2.78 -                    // Add a catch-all clause.
    2.79 +                // If there are jsr's to this finalizer, ...
    2.80 +                if (env.info.cont != null) {
    2.81 +                    // Resolve all jsr's.
    2.82 +                    code.resolve(env.info.cont);
    2.83  
    2.84 -                    // start off with exception on stack
    2.85 -                    int catchallpc = code.entryPoint(stateTry, syms.throwableType);
    2.86 -
    2.87 -                    // Register all exception ranges for catch all clause.
    2.88 -                    // The range of the catch all clause is from the beginning
    2.89 -                    // of the try or synchronized block until the present
    2.90 -                    // code pointer excluding all gaps in the current
    2.91 -                    // environment's GenContext.
    2.92 -                    int startseg = startpc;
    2.93 -                    while (env.info.gaps.nonEmpty()) {
    2.94 -                        int endseg = env.info.gaps.next().intValue();
    2.95 -                        registerCatch(body.pos(), startseg, endseg,
    2.96 -                                      catchallpc, 0);
    2.97 -                        startseg = env.info.gaps.next().intValue();
    2.98 -                    }
    2.99 +                    // Mark statement line number
   2.100                      code.statBegin(TreeInfo.finalizerPos(env.tree));
   2.101                      code.markStatBegin();
   2.102  
   2.103 -                    Item excVar = makeTemp(syms.throwableType);
   2.104 -                    excVar.store();
   2.105 -                    genFinalizer(env);
   2.106 -                    excVar.load();
   2.107 -                    registerCatch(body.pos(), startseg,
   2.108 -                                  env.info.gaps.next().intValue(),
   2.109 -                                  catchallpc, 0);
   2.110 -                    code.emitop0(athrow);
   2.111 +                    // Save return address.
   2.112 +                    LocalItem retVar = makeTemp(syms.throwableType);
   2.113 +                    retVar.store();
   2.114 +
   2.115 +                    // Generate finalizer code.
   2.116 +                    env.info.finalize.genLast();
   2.117 +
   2.118 +                    // Return.
   2.119 +                    code.emitop1w(ret, retVar.reg);
   2.120                      code.markDead();
   2.121 -
   2.122 -                    // If there are jsr's to this finalizer, ...
   2.123 -                    if (env.info.cont != null) {
   2.124 -                        // Resolve all jsr's.
   2.125 -                        code.resolve(env.info.cont);
   2.126 -
   2.127 -                        // Mark statement line number
   2.128 -                        code.statBegin(TreeInfo.finalizerPos(env.tree));
   2.129 -                        code.markStatBegin();
   2.130 -
   2.131 -                        // Save return address.
   2.132 -                        LocalItem retVar = makeTemp(syms.throwableType);
   2.133 -                        retVar.store();
   2.134 -
   2.135 -                        // Generate finalizer code.
   2.136 -                        env.info.finalize.genLast();
   2.137 -
   2.138 -                        // Return.
   2.139 -                        code.emitop1w(ret, retVar.reg);
   2.140 -                        code.markDead();
   2.141 -                    }
   2.142                  }
   2.143              }
   2.144              // Resolve all breaks.
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java	Fri Sep 06 09:53:24 2013 +0100
     3.3 @@ -0,0 +1,124 @@
     3.4 +/*
     3.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +/*
    3.30 + * @test
    3.31 + * @bug 8024039
    3.32 + * @summary javac, previous solution for JDK-8022186 was incorrect
    3.33 + * @library /tools/javac/lib
    3.34 + * @build ToolBox
    3.35 + * @run main NoDeadCodeGenerationOnTrySmtTest
    3.36 + */
    3.37 +
    3.38 +import java.io.File;
    3.39 +import java.nio.file.Paths;
    3.40 +
    3.41 +import com.sun.tools.classfile.ClassFile;
    3.42 +import com.sun.tools.classfile.Code_attribute;
    3.43 +import com.sun.tools.classfile.Code_attribute.Exception_data;
    3.44 +import com.sun.tools.classfile.Method;
    3.45 +import com.sun.tools.javac.util.Assert;
    3.46 +
    3.47 +public class NoDeadCodeGenerationOnTrySmtTest {
    3.48 +
    3.49 +    static final String testSource =
    3.50 +        "public class Test {\n" +
    3.51 +        "    void m1(int arg) {\n" +
    3.52 +        "        synchronized (new Integer(arg)) {\n" +
    3.53 +        "            {\n" +
    3.54 +        "                label0:\n" +
    3.55 +        "                do {\n" +
    3.56 +        "                    break label0;\n" +
    3.57 +        "                } while (arg != 0);\n" +
    3.58 +        "            }\n" +
    3.59 +        "        }\n" +
    3.60 +        "    }\n" +
    3.61 +
    3.62 +        "    void m2(int arg) {\n" +
    3.63 +        "        synchronized (new Integer(arg)) {\n" +
    3.64 +        "            {\n" +
    3.65 +        "                label0:\n" +
    3.66 +        "                {\n" +
    3.67 +        "                    break label0;\n" +
    3.68 +        "                }\n" +
    3.69 +        "            }\n" +
    3.70 +        "        }\n" +
    3.71 +        "    }\n" +
    3.72 +        "}";
    3.73 +
    3.74 +    static final int[][] expectedExceptionTable = {
    3.75 +    //  {from,         to,         target,      type},
    3.76 +        {11,           13,         16,          0},
    3.77 +        {16,           19,         16,          0}
    3.78 +    };
    3.79 +
    3.80 +    static final String[] methodsToLookFor = {"m1", "m2"};
    3.81 +
    3.82 +    public static void main(String[] args) throws Exception {
    3.83 +        new NoDeadCodeGenerationOnTrySmtTest().run();
    3.84 +    }
    3.85 +
    3.86 +    void run() throws Exception {
    3.87 +        compileTestClass();
    3.88 +        checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
    3.89 +                "Test.class").toUri()), methodsToLookFor);
    3.90 +    }
    3.91 +
    3.92 +    void compileTestClass() throws Exception {
    3.93 +        ToolBox.JavaToolArgs javacSuccessArgs =
    3.94 +                new ToolBox.JavaToolArgs().setSources(testSource);
    3.95 +        ToolBox.javac(javacSuccessArgs);
    3.96 +    }
    3.97 +
    3.98 +    void checkClassFile(final File cfile, String[] methodsToFind) throws Exception {
    3.99 +        ClassFile classFile = ClassFile.read(cfile);
   3.100 +        int numberOfmethodsFound = 0;
   3.101 +        for (String methodToFind : methodsToFind) {
   3.102 +            for (Method method : classFile.methods) {
   3.103 +                if (method.getName(classFile.constant_pool).equals(methodToFind)) {
   3.104 +                    numberOfmethodsFound++;
   3.105 +                    Code_attribute code = (Code_attribute) method.attributes.get("Code");
   3.106 +                    Assert.check(code.exception_table_langth == expectedExceptionTable.length,
   3.107 +                            "The ExceptionTable found has a length different to the expected one");
   3.108 +                    int i = 0;
   3.109 +                    for (Exception_data entry: code.exception_table) {
   3.110 +                        Assert.check(entry.start_pc == expectedExceptionTable[i][0] &&
   3.111 +                                entry.end_pc == expectedExceptionTable[i][1] &&
   3.112 +                                entry.handler_pc == expectedExceptionTable[i][2] &&
   3.113 +                                entry.catch_type == expectedExceptionTable[i][3],
   3.114 +                                "Exception table entry at pos " + i + " differ from expected.");
   3.115 +                        i++;
   3.116 +                    }
   3.117 +                }
   3.118 +            }
   3.119 +        }
   3.120 +        Assert.check(numberOfmethodsFound == 2, "Some seek methods were not found");
   3.121 +    }
   3.122 +
   3.123 +    void error(String msg) {
   3.124 +        throw new AssertionError(msg);
   3.125 +    }
   3.126 +
   3.127 +}

mercurial