8066230: Undefined object type assertion when computing TypeBounds
authorattila
Mon, 08 Dec 2014 15:13:16 +0100
changeset 27968 52e31251a179
parent 27967 b6ffb73f6ca4
child 27969 c03b64ccbd0f
8066230: Undefined object type assertion when computing TypeBounds Reviewed-by: hannesw, lagergren
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
nashorn/test/script/basic/JDK-8066230.js
nashorn/test/script/basic/JDK-8066230.js.EXPECTED
--- 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