7040592: Gen.java: fix code for handling 'null' literal when expected type is array
Summary: Eliminate needless checkcast when null is assigned to a multi-dimensional array typedobject
Reviewed-by: mcimadamore
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Mon Mar 30 17:09:14 2015 +0530
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Mon Mar 23 09:48:37 2015 +0530
@@ -497,13 +497,9 @@
case aaload: {
state.pop(1);// index
Type a = state.stack[state.stacksize-1];
+ Assert.check(!a.hasTag(BOT)); // null type as is cannot be indexed.
state.pop(1);
- //sometimes 'null type' is treated as a one-dimensional array type
- //see Gen.visitLiteral - we should handle this case accordingly
- Type stackType = a.hasTag(BOT) ?
- syms.objectType :
- types.erasure(types.elemtype(a));
- state.push(stackType); }
+ state.push(types.erasure(types.elemtype(a))); }
break;
case goto_:
markDead();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Mar 30 17:09:14 2015 +0530
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Mar 23 09:48:37 2015 +0530
@@ -1860,6 +1860,13 @@
public void visitAssign(JCAssign tree) {
Item l = genExpr(tree.lhs, tree.lhs.type);
genExpr(tree.rhs, tree.lhs.type).load();
+ if (tree.rhs.type.hasTag(BOT)) {
+ /* This is just a case of widening reference conversion that per 5.1.5 simply calls
+ for "regarding a reference as having some other type in a manner that can be proved
+ correct at compile time."
+ */
+ code.state.forceStackTop(tree.lhs.type);
+ }
result = items.makeAssignItem(l);
}
@@ -2272,12 +2279,7 @@
public void visitLiteral(JCLiteral tree) {
if (tree.type.hasTag(BOT)) {
code.emitop0(aconst_null);
- if (types.dimensions(pt) > 1) {
- code.emitop2(checkcast, makeRef(tree.pos(), pt));
- result = items.makeStackItem(pt);
- } else {
- result = items.makeStackItem(tree.type);
- }
+ result = items.makeStackItem(tree.type);
}
else
result = items.makeImmediateItem(tree.type, tree.value);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T7040592/CoerceNullToMoreSpecificTypeTest.java Mon Mar 23 09:48:37 2015 +0530
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, 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 7040592
+ * @summary Test that the assertion in State.forceStackTop does not fail at compile time.
+ */
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import org.w3c.dom.Element;
+
+public class CoerceNullToMoreSpecificTypeTest {
+ abstract class NodeImpl {
+ }
+
+ NodeImpl ownerNode;
+
+ public Element getElement() {
+ return (Element) (isOwned() ? ownerNode : null);
+ }
+
+ boolean isOwned() {
+ return true;
+ }
+
+ static void processArrays(boolean expectNulls, Object [] nulla, Object [][] nullaa) {
+ if (expectNulls) {
+ if (nulla != null || nullaa != null) {
+ throw new AssertionError("Null actual, but not null formal");
+ }
+ } else {
+ if (nulla.length != 123 || nullaa.length != 321)
+ throw new AssertionError("Wrong arrays received");
+ }
+ }
+
+ public static void main(String[] args) {
+ ArrayList<Class<?>> typeList = new ArrayList<>();
+ Field rf = null;
+ typeList.add((rf != null) ? rf.getType() : null);
+ processArrays(true, null, null);
+ processArrays(false, new Object[123], new Object[321][]);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T7040592/T7040592.java Mon Mar 23 09:48:37 2015 +0530
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 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 7040592
+ * @summary Verify that null can be assigned freely to array types without a checkcast
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Paths;
+
+public class T7040592 {
+
+ private static final String assertionErrorMsg =
+ "null should be assignable to array type without a checkcast";
+
+ public static void main(String[] args) {
+ new T7040592().run();
+ }
+
+ void run() {
+ check("-c", Paths.get(System.getProperty("test.classes"),
+ "T7040592_01.class").toString());
+ }
+
+ void check(String... params) {
+ StringWriter s;
+ String out;
+ try (PrintWriter pw = new PrintWriter(s = new StringWriter())) {
+ com.sun.tools.javap.Main.run(params, pw);
+ out = s.toString();
+ }
+ if (out.contains("checkcast")) {
+ throw new AssertionError(assertionErrorMsg);
+ }
+ }
+
+}
+
+class T7040592_01 {
+ static void handleArrays(Object [] a, Object [][] b, Object [][][] c) {
+ }
+ public static void main(String[] args) {
+ Object a[];
+ Object o = (a = null)[0];
+ Object b[][];
+ o = (b = null)[0][0];
+ Object c[][][];
+ o = (c = null)[0][0][0];
+ handleArrays(null, null, null);
+ }
+}