--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Tue Mar 25 14:50:31 2014 -0700
@@ -2919,15 +2919,65 @@
// constant propagation would require that we take care to
// preserve possible side-effects in the condition expression.
+ // One common case is equality expressions involving a constant and null.
+ // Since null is not a constant expression (because null cannot be
+ // represented in the constant pool), equality checks involving null are
+ // not captured by Flow.isTrue/isFalse.
+ // Equality checks involving a constant and null, e.g.
+ // "" == null
+ // are safe to simplify as no side-effects can occur.
+
+ private boolean isTrue(JCTree exp) {
+ if (exp.type.isTrue())
+ return true;
+ Boolean b = expValue(exp);
+ return b == null ? false : b;
+ }
+ private boolean isFalse(JCTree exp) {
+ if (exp.type.isFalse())
+ return true;
+ Boolean b = expValue(exp);
+ return b == null ? false : !b;
+ }
+ /* look for (in)equality relations involving null.
+ * return true - if expression is always true
+ * false - if expression is always false
+ * null - if expression cannot be eliminated
+ */
+ private Boolean expValue(JCTree exp) {
+ while (exp.hasTag(PARENS))
+ exp = ((JCParens)exp).expr;
+
+ boolean eq;
+ switch (exp.getTag()) {
+ case EQ: eq = true; break;
+ case NE: eq = false; break;
+ default:
+ return null;
+ }
+
+ // we have a JCBinary(EQ|NE)
+ // check if we have two literals (constants or null)
+ JCBinary b = (JCBinary)exp;
+ if (b.lhs.type.hasTag(BOT)) return expValueIsNull(eq, b.rhs);
+ if (b.rhs.type.hasTag(BOT)) return expValueIsNull(eq, b.lhs);
+ return null;
+ }
+ private Boolean expValueIsNull(boolean eq, JCTree t) {
+ if (t.type.hasTag(BOT)) return Boolean.valueOf(eq);
+ if (t.hasTag(LITERAL)) return Boolean.valueOf(!eq);
+ return null;
+ }
+
/** Visitor method for conditional expressions.
*/
@Override
public void visitConditional(JCConditional tree) {
JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
- if (cond.type.isTrue()) {
+ if (isTrue(cond)) {
result = convert(translate(tree.truepart, tree.type), tree.type);
addPrunedInfo(cond);
- } else if (cond.type.isFalse()) {
+ } else if (isFalse(cond)) {
result = convert(translate(tree.falsepart, tree.type), tree.type);
addPrunedInfo(cond);
} else {
@@ -2951,10 +3001,10 @@
*/
public void visitIf(JCIf tree) {
JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
- if (cond.type.isTrue()) {
+ if (isTrue(cond)) {
result = translate(tree.thenpart);
addPrunedInfo(cond);
- } else if (cond.type.isFalse()) {
+ } else if (isFalse(cond)) {
if (tree.elsepart != null) {
result = translate(tree.elsepart);
} else {
@@ -3333,21 +3383,21 @@
JCTree lhs = tree.lhs = translate(tree.lhs, formals.head);
switch (tree.getTag()) {
case OR:
- if (lhs.type.isTrue()) {
+ if (isTrue(lhs)) {
result = lhs;
return;
}
- if (lhs.type.isFalse()) {
+ if (isFalse(lhs)) {
result = translate(tree.rhs, formals.tail.head);
return;
}
break;
case AND:
- if (lhs.type.isFalse()) {
+ if (isFalse(lhs)) {
result = lhs;
return;
}
- if (lhs.type.isTrue()) {
+ if (isTrue(lhs)) {
result = translate(tree.rhs, formals.tail.head);
return;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Tue Mar 25 14:50:31 2014 -0700
@@ -2501,6 +2501,8 @@
return;
} catch (IOException ex) {
throw badClassFile("unable.to.access.file", ex.getMessage());
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ throw badClassFile("bad.class.file", c.flatname);
} finally {
currentClassFile = previousClassFile;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Tue Mar 25 14:50:31 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -506,6 +506,11 @@
}
}
+ if (options.get(XSTDOUT) != null) {
+ // Stdout reassigned - ask compiler to close it when it is done
+ comp.closeables = comp.closeables.prepend(log.getWriter(WriterKind.NOTICE));
+ }
+
fileManager = context.get(JavaFileManager.class);
if (!files.isEmpty()) {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java Tue Mar 25 14:50:31 2014 -0700
@@ -399,7 +399,6 @@
public boolean process(OptionHelper helper, String option, String arg) {
try {
Log log = helper.getLog();
- // TODO: this file should be closed at the end of compilation
log.setWriters(new PrintWriter(new FileWriter(arg), true));
} catch (java.io.IOException e) {
helper.error("err.error.writing.file", arg, e);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Mar 25 14:50:31 2014 -0700
@@ -1709,6 +1709,10 @@
cannot access {0}\n\
{1}
+# 0: class name
+compiler.misc.bad.class.file=\
+ class file is invalid for class {0}
+
# 0: file name, 1: message segment
compiler.misc.bad.class.file.header=\
bad class file: {0}\n\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/ConstFoldTest.java Tue Mar 25 14:50:31 2014 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8025505
+ * @summary Constant folding deficiency
+ * @library /tools/javac/lib
+ * @build ToolBox
+ * @run main ConstFoldTest
+ */
+
+import java.net.URL;
+import java.util.List;
+
+public class ConstFoldTest {
+ public static void main(String... args) throws Exception {
+ new ConstFoldTest().run();
+ }
+
+ // This is the test case. This class should end up
+ // as straight-line code with no conditionals
+ class CFTest {
+ void m() {
+ int x;
+ if (1 != 2) x=1; else x=0;
+ if (1 == 2) x=1; else x=0;
+ if ("" != null) x=1; else x=0;
+ if ("" == null) x=1; else x=0;
+ if (null == null) x=1; else x=0;
+ if (null != null) x=1; else x=0;
+
+ x = 1 != 2 ? 1 : 0;
+ x = 1 == 2 ? 1 : 0;
+ x = "" != null ? 1 : 0;
+ x = "" == null ? 1 : 0;
+ x = null == null ? 1 : 0;
+ x = null != null ? 1 : 0;
+
+ boolean b;
+ b = 1 != 2 && true;
+ b = 1 == 2 || true;
+ b = ("" != null) && true;
+ b = ("" == null) || true;
+ b = (null == null) && true;
+ b = (null != null) || true;
+ }
+ }
+
+ // All of the conditionals above should be eliminated.
+ // these if* bytecodes should not be seen
+ final String regex = "\\sif(?:null|nonnull|eq|ne){1}\\s";
+
+ void run() throws Exception {
+ URL url = ConstFoldTest.class.getResource("ConstFoldTest$CFTest.class");
+ String result = ToolBox.javap(new ToolBox.JavaToolArgs().setAllArgs("-c", url.getFile()));
+ System.out.println(result);
+
+ List<String> bad_codes = ToolBox.grep(regex, result, "\n");
+ if (!bad_codes.isEmpty()) {
+ for (String code : bad_codes)
+ System.out.println("Bad OpCode Found: " + code);
+ throw new Exception("constant folding failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/StdoutCloseTest.java Tue Mar 25 14:50:31 2014 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7118295
+ * @summary javac does not explicitly close -Xstdout file
+ * @run main StdoutCloseTest
+ */
+
+
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.main.Main;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class StdoutCloseTest {
+
+ public static void main(String[] args) throws Exception {
+ new StdoutCloseTest().test();
+ }
+
+ static final String program = "public class Test {\n" +
+ " public boolean test() {\n" +
+ " int i;\n" +
+ " if (i > 0) return true;\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n";
+
+ public void test() throws Exception {
+ final String sourceName = "Test.java";
+ final String outName = "Test.out";
+ File source = new File(sourceName);
+ PrintWriter pw = new PrintWriter(source);
+ pw.write(program);
+ pw.flush();
+ pw.close();
+
+ PrintWriter log = compileClass(sourceName, outName);
+
+ File outFile = new File(outName);
+ if (!outFile.exists()) {
+ throw new Exception("Output file was not created!");
+ }
+ if (!log.checkError()) { // will return true if the stream is still open
+ log.close(); // Close output PrintWriter manually
+ throw new Exception("Output file was still open!");
+ }
+ }
+
+ public PrintWriter compileClass(String src, String out) {
+ List<String> options = new ArrayList<>();
+ options.add("-Xstdout");
+ options.add(out);
+ options.add(src);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ Main compiler = new Main("javac", pw);
+ compiler.compile(options.toArray(new String[options.size()]));
+ pw.flush();
+ if (sw.getBuffer().length() > 0) {
+ System.err.println(sw.toString());
+ }
+ return compiler.log.getWriter(Log.WriterKind.NOTICE);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classreader/BadClass.java Tue Mar 25 14:50:31 2014 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6898851
+ * @summary Compiling against this corrupt class file causes a stacktrace from javac
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import java.io.IOException;
+
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ClassWriter;
+import com.sun.tools.javac.Main;
+
+public class BadClass {
+ // Create and compile file containing body; return compiler output
+ static String makeClass(String dir, String filename, String body) throws IOException {
+ File file = new File(dir, filename);
+ try (FileWriter fw = new FileWriter(file)) {
+ fw.write(body);
+ }
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ String args[] = { "-cp", dir, "-d", dir, "-XDrawDiagnostics", file.getPath() };
+ Main.compile(args, pw);
+ pw.close();
+ return sw.toString();
+ }
+
+ public static void main(String... args) throws Exception {
+ new File("d1").mkdir();
+ new File("d2").mkdir();
+
+ // Step 1. build an empty class with an interface
+ makeClass("d1", "Empty.java", "abstract class Empty implements Readable {}");
+
+ // Step 2. Modify classfile to have invalid constant pool index
+ ClassFile cf = ClassFile.read(new File("d1","Empty.class"));
+ cf.interfaces[0] = cf.constant_pool.size() + 10;
+ ClassWriter cw = new ClassWriter();
+ cw.write(cf, new File("d2","Empty.class"));
+
+ // Step 3. Compile use of invalid class
+ String result = makeClass("d2", "EmptyUse.java", "class EmptyUse { Empty e; }");
+ if (!result.contains("compiler.misc.bad.class.file")) {
+ System.out.println(result);
+ throw new Exception("test failed");
+ }
+ }
+}
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Wed Jul 05 19:34:04 2017 +0200
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Tue Mar 25 14:50:31 2014 -0700
@@ -111,3 +111,4 @@
compiler.warn.unknown.enum.constant.reason # in bad class file
compiler.warn.override.equals.but.not.hashcode # when a class overrides equals but not hashCode method from Object
compiler.warn.file.from.future # warning for future modification times on files
+compiler.misc.bad.class.file # class file is malformed