8066230: Undefined object type assertion when computing TypeBounds
Reviewed-by: hannesw, lagergren
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Dec 05 20:17:51 2014 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Dec 08 15:13:16 2014 +0100
@@ -571,9 +571,11 @@
// Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
// than the lower explicit bound, but it should also not be wider than
- final Type narrowestOperandType = Type.narrowest(Type.widest(lhs.getType(), rhs.getType()), explicitOperandBounds.widest);
+ final Type lhsType = undefinedToNumber(lhs.getType());
+ final Type rhsType = undefinedToNumber(rhs.getType());
+ final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
- if (noToPrimitiveConversion(lhs.getType(), explicitOperandBounds.widest) || rhs.isLocal()) {
+ if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
// Can reorder. We might still need to separate conversion, but at least we can do it with reordering
if (forceConversionSeparation) {
// Can reorder, but can't move conversion into the operand as the operation depends on operands
@@ -594,10 +596,10 @@
// Can't reorder. Load and convert separately.
final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
- final Type lhsType = method.peekType();
+ final Type lhsLoadedType = method.peekType();
loadExpression(rhs, safeConvertBounds, false);
final Type convertedLhsType = operandBounds.within(method.peekType());
- if (convertedLhsType != lhsType) {
+ if (convertedLhsType != lhsLoadedType) {
// Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
method.swap().convert(convertedLhsType).swap();
}
@@ -609,6 +611,10 @@
return method;
}
+ private static final Type undefinedToNumber(final Type type) {
+ return type == Type.UNDEFINED ? Type.NUMBER : type;
+ }
+
private static final class TypeBounds {
final Type narrowest;
final Type widest;
@@ -3151,9 +3157,8 @@
} else {
final Type identType = identNode.getType();
if(identType == Type.UNDEFINED) {
- // The symbol must not be slotted; the initializer is either itself undefined (explicit assignment of
- // undefined to undefined), or the left hand side is a dead variable.
- assert !identNode.getSymbol().isScope();
+ // The initializer is either itself undefined (explicit assignment of undefined to undefined),
+ // or the left hand side is a dead variable.
assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
loadAndDiscard(init);
return false;
@@ -3576,9 +3581,9 @@
operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
} else {
// Non-optimistic, non-FP +. Allow it to overflow.
- operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest),
- Type.OBJECT);
- forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest);
+ final Type widestOperationType = binaryNode.getWidestOperationType();
+ operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
+ forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
}
loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066230.js Mon Dec 08 15:13:16 2014 +0100
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8066230: Undefined object type assertion when computing TypeBounds
+ *
+ * @test
+ * @run
+ */
+
+(function() { void null + 0; })();
+(function() { var x; x += void x; })();
+(function() { var a = true + x, x; })();
+print("SUCCESS");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8066230.js.EXPECTED Mon Dec 08 15:13:16 2014 +0100
@@ -0,0 +1,1 @@
+SUCCESS