8056129: AtomicInteger is treated as primitive number with optimistic compilation

Thu, 04 Sep 2014 18:57:14 +0200

author
attila
date
Thu, 04 Sep 2014 18:57:14 +0200
changeset 993
45f9decf4fb5
parent 992
7caec82669a4
child 994
f5be4bdd0f6e

8056129: AtomicInteger is treated as primitive number with optimistic compilation
Reviewed-by: jlaskey, lagergren

src/jdk/nashorn/internal/runtime/JSType.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayData.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8056129.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8056129.js.EXPECTED file | annotate | diff | comparison | revisions
     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

mercurial