Thu, 04 Sep 2014 18:57:14 +0200
8056129: AtomicInteger is treated as primitive number with optimistic compilation
Reviewed-by: jlaskey, lagergren
1.1 --- a/src/jdk/nashorn/internal/runtime/JSType.java Mon Sep 08 15:51:27 2014 +0530 1.2 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Sep 04 18:57:14 2014 +0200 1.3 @@ -938,11 +938,8 @@ 1.4 * @return double 1.5 */ 1.6 public static int toInt32Optimistic(final Object obj, final int programPoint) { 1.7 - if (obj != null) { 1.8 - final Class<?> clz = obj.getClass(); 1.9 - if (clz == Integer.class) { 1.10 - return ((Integer)obj).intValue(); 1.11 - } 1.12 + if (obj != null && obj.getClass() == Integer.class) { 1.13 + return ((Integer)obj).intValue(); 1.14 } 1.15 throw new UnwarrantedOptimismException(obj, programPoint); 1.16 }
2.1 --- a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Mon Sep 08 15:51:27 2014 +0530 2.2 +++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Thu Sep 04 18:57:14 2014 +0200 2.3 @@ -191,19 +191,20 @@ 2.4 } 2.5 2.6 /** 2.7 - * Returns the argument value as an int. If the argument is not a Number object that can be exactly represented as 2.8 - * an int, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 2.9 - * can use it. See {code CodeGenerator.ENSURE_INT}. 2.10 + * Returns the argument value as an int. If the argument is not a wrapper for a primitive numeric type 2.11 + * with a value that can be exactly represented as an int, throw an {@link UnwarrantedOptimismException}. 2.12 + * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_INT}. 2.13 * @param arg the original argument. 2.14 * @param programPoint the program point used in the exception 2.15 * @return the value of the argument as an int. 2.16 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as an int. 2.17 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with 2.18 + * a value that can be exactly represented as an int. 2.19 */ 2.20 public static int ensureInt(final Object arg, final int programPoint) { 2.21 // NOTE: this doesn't delegate to ensureInt(double, int) as in that case if arg were a Long, it would throw a 2.22 // (potentially imprecise) Double in the UnwarrantedOptimismException. This way, it will put the correct valued 2.23 // Long into the exception. 2.24 - if (arg instanceof Number) { 2.25 + if (isPrimitiveNumberWrapper(arg)) { 2.26 final double d = ((Number)arg).doubleValue(); 2.27 if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) { 2.28 return (int)d; 2.29 @@ -212,6 +213,15 @@ 2.30 throw new UnwarrantedOptimismException(arg, programPoint); 2.31 } 2.32 2.33 + private static boolean isPrimitiveNumberWrapper(final Object obj) { 2.34 + if (obj == null) { 2.35 + return false; 2.36 + } 2.37 + final Class<?> c = obj.getClass(); 2.38 + return c == Integer.class || c == Double.class || c == Long.class || 2.39 + c == Float.class || c == Short.class || c == Byte.class; 2.40 + } 2.41 + 2.42 @SuppressWarnings("unused") 2.43 private static int ensureInt(final boolean arg, final int programPoint) { 2.44 throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT); 2.45 @@ -236,35 +246,40 @@ 2.46 } 2.47 2.48 /** 2.49 - * Returns the argument value as a long. If the argument is not a Number object that can be exactly represented as 2.50 - * a long, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 2.51 - * can use it. See {code CodeGenerator.ENSURE_LONG}. 2.52 + * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type 2.53 + * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}. 2.54 + * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}. 2.55 * @param arg the original argument. 2.56 * @param programPoint the program point used in the exception 2.57 * @return the value of the argument as a long. 2.58 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long. 2.59 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with 2.60 + * a value that can be exactly represented as a long 2.61 */ 2.62 public static long ensureLong(final Object arg, final int programPoint) { 2.63 - if (arg instanceof Long) { 2.64 - // Must check for Long separately, as Long.doubleValue() isn't precise. 2.65 - return ((Long)arg).longValue(); 2.66 - } else if (arg instanceof Number) { 2.67 - return ensureLong(((Number)arg).doubleValue(), programPoint); 2.68 + if (arg != null) { 2.69 + final Class<?> c = arg.getClass(); 2.70 + if (c == Long.class) { 2.71 + // Must check for Long separately, as Long.doubleValue() isn't precise. 2.72 + return ((Long)arg).longValue(); 2.73 + } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class || 2.74 + c == Byte.class) { 2.75 + return ensureLong(((Number)arg).doubleValue(), programPoint); 2.76 + } 2.77 } 2.78 throw new UnwarrantedOptimismException(arg, programPoint); 2.79 } 2.80 2.81 /** 2.82 - * Returns the argument value as a double. If the argument is not a Number object, throw an 2.83 - * {@link UnwarrantedOptimismException}.This method is only public so that generated script code can use it. See 2.84 - * {code CodeGenerator.ENSURE_NUMBER}. 2.85 + * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type 2.86 + * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code 2.87 + * can use it. See {code CodeGenerator.ENSURE_NUMBER}. 2.88 * @param arg the original argument. 2.89 * @param programPoint the program point used in the exception 2.90 * @return the value of the argument as a double. 2.91 - * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long. 2.92 + * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type. 2.93 */ 2.94 public static double ensureNumber(final Object arg, final int programPoint) { 2.95 - if (arg instanceof Number) { // arg == null -> false 2.96 + if (isPrimitiveNumberWrapper(arg)) { 2.97 return ((Number)arg).doubleValue(); 2.98 } 2.99 throw new UnwarrantedOptimismException(arg, programPoint);
3.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Mon Sep 08 15:51:27 2014 +0530 3.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Sep 04 18:57:14 2014 +0200 3.3 @@ -628,18 +628,20 @@ 3.4 Class<?> widest = Integer.class; 3.5 3.6 for (final Object item : items) { 3.7 - final Class<?> itemClass = item == null ? null : item.getClass(); 3.8 + if (item == null) { 3.9 + return Object.class; 3.10 + } 3.11 + final Class<?> itemClass = item.getClass(); 3.12 if (itemClass == Long.class) { 3.13 if (widest == Integer.class) { 3.14 widest = Long.class; 3.15 } 3.16 - } else if (itemClass == Double.class) { 3.17 + } else if (itemClass == Double.class || itemClass == Float.class) { 3.18 if (widest == Integer.class || widest == Long.class) { 3.19 widest = Double.class; 3.20 } 3.21 - } else if (!(item instanceof Number)) { 3.22 - widest = Object.class; 3.23 - break; 3.24 + } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) { 3.25 + return Object.class; 3.26 } 3.27 } 3.28
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/script/basic/JDK-8056129.js Thu Sep 04 18:57:14 2014 +0200 4.3 @@ -0,0 +1,42 @@ 4.4 +/* 4.5 + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +/** 4.28 + * JDK-8056129: AtomicInteger is treated as primitive number with optimistic compilation 4.29 + * 4.30 + * @test 4.31 + * @run 4.32 + */ 4.33 + 4.34 +var AtomicInteger = java.util.concurrent.atomic.AtomicInteger; 4.35 + 4.36 +function getAtomic() { 4.37 + return new AtomicInteger() 4.38 +} 4.39 +var x = getAtomic() 4.40 +print(x instanceof AtomicInteger) 4.41 + 4.42 +var a = [] 4.43 +a.push(x) 4.44 +var y = a[0] 4.45 +print(y instanceof AtomicInteger)
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/script/basic/JDK-8056129.js.EXPECTED Thu Sep 04 18:57:14 2014 +0200 5.3 @@ -0,0 +1,2 @@ 5.4 +true 5.5 +true