Fri, 06 Sep 2013 09:53:24 +0100
8024039: javac, previous solution for JDK-8022186 was incorrect
Reviewed-by: jjg
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 +}