--- old/src/jdk/nashorn/internal/runtime/JSType.java 2016-01-20 14:14:50.915064305 +0100 +++ new/src/jdk/nashorn/internal/runtime/JSType.java 2016-01-20 14:14:50.819064307 +0100 @@ -115,14 +115,14 @@ public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class); /** JavaScript compliant conversion function from int to uint32 */ - public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class); + public static final Call TO_UINT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Optimistic", int.class, int.class, int.class); + + /** JavaScript compliant conversion function from int to uint32 */ + public static final Call TO_UINT32_DOUBLE = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Double", double.class, int.class); /** JavaScript compliant conversion function from Object to uint32 */ public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class); - /** JavaScript compliant conversion function from Object to long with type check */ - public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class); - /** JavaScript compliant conversion function from number to uint32 */ public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class); @@ -168,36 +168,6 @@ /** Negate exact exact wrapper for potentially overflowing integer operations */ public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class); - /** Add exact wrapper for potentially overflowing long operations */ - public static final Call ADD_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class); - - /** Sub exact wrapper for potentially overflowing long operations */ - public static final Call SUB_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class); - - /** Multiply exact wrapper for potentially overflowing long operations */ - public static final Call MUL_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class); - - /** Div exact wrapper for potentially integer division that turns into float point */ - public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class); - - /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ - public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class); - - /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ - public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class); - - /** Mod exact wrapper for potentially integer remainders that turns into float point */ - public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class); - - /** Decrement exact wrapper for potentially overflowing long operations */ - public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", long.class, long.class, int.class); - - /** Increment exact wrapper for potentially overflowing long operations */ - public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", long.class, long.class, int.class); - - /** Negate exact exact wrapper for potentially overflowing long operations */ - public static final Call NEGATE_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", long.class, long.class, int.class); - /** Method handle to convert a JS Object to a Java array. */ public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class); @@ -211,7 +181,6 @@ private static final List ACCESSOR_TYPES = Collections.unmodifiableList( Arrays.asList( Type.INT, - Type.LONG, Type.NUMBER, Type.OBJECT)); @@ -219,17 +188,14 @@ public static final int TYPE_UNDEFINED_INDEX = -1; /** table index for integer type - hard coded so it can be used in switches at compile time */ public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); - /** table index for long type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); /** table index for double type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); + public static final int TYPE_DOUBLE_INDEX = 1; //getAccessorTypeIndex(double.class); /** table index for object type - hard coded so it can be used in switches at compile time */ - public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); + public static final int TYPE_OBJECT_INDEX = 2; //getAccessorTypeIndex(Object.class); /** object conversion quickies with JS semantics - used for return value and parameter filter */ public static final List CONVERT_OBJECT = toUnmodifiableList( JSType.TO_INT32.methodHandle(), - JSType.TO_UINT32.methodHandle(), JSType.TO_NUMBER.methodHandle(), null ); @@ -240,7 +206,6 @@ */ public static final List CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList( JSType.TO_INT32_OPTIMISTIC.methodHandle(), - JSType.TO_LONG_OPTIMISTIC.methodHandle(), JSType.TO_NUMBER_OPTIMISTIC.methodHandle(), null ); @@ -252,13 +217,16 @@ /** The value of Undefined cast to a double */ public static final double UNDEFINED_DOUBLE = Double.NaN; + // Minimum and maximum range between which every long value can be precisely represented as a double. + private static final long MAX_PRECISE_DOUBLE = 1L << 53; + private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; + /** * Method handles for getters that return undefined coerced * to the appropriate type */ public static final List GET_UNDEFINED = toUnmodifiableList( MH.constant(int.class, UNDEFINED_INT), - MH.constant(long.class, UNDEFINED_LONG), MH.constant(double.class, UNDEFINED_DOUBLE), MH.constant(Object.class, Undefined.getUndefined()) ); @@ -416,7 +384,7 @@ /** * Returns true if double number can be represented as a long. Note that it returns true for negative - * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsLong(double)}. + * zero. * * @param number a double to inspect * @return true for long representable doubles @@ -426,29 +394,12 @@ } /** - * Returns true if double number can be represented as a long. Note that it returns false for negative - * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}. - * - * @param number a double to inspect - * - * @return true for long representable doubles - */ - public static boolean isStrictlyRepresentableAsLong(final double number) { - return isRepresentableAsLong(number) && isNotNegativeZero(number); - } - - /** - * Returns true if Object can be represented as a long - * - * @param obj an object to inspect - * - * @return true for long representable objects + * Returns true if long number can be represented as double without loss of precision. + * @param number a long number + * @return true if the double representation does not lose precision */ - public static boolean isRepresentableAsLong(final Object obj) { - if (obj instanceof Number) { - return isRepresentableAsLong(((Number)obj).doubleValue()); - } - return false; + public static boolean isRepresentableAsDouble(final long number) { + return MAX_PRECISE_DOUBLE >= number && number >= MIN_PRECISE_DOUBLE; } /** @@ -628,22 +579,6 @@ } /** - * Check whether a string is representable as a JavaScript number - * - * @param str a string - * - * @return true if string can be represented as a number - */ - public static boolean isNumber(final String str) { - try { - Double.parseDouble(str); - return true; - } catch (final NumberFormatException e) { - return false; - } - } - - /** * Returns true if object represents a primitive JavaScript string value. * @param obj the object * @return true if the object represents a primitive JavaScript string value. @@ -1009,35 +944,6 @@ } /** - * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object - * - * @param obj object to convert - * @param programPoint program point - * @return long - */ - public static long toLongOptimistic(final Object obj, final int programPoint) { - if (obj != null) { - final Class clz = obj.getClass(); - if (clz == Long.class || clz == Integer.class) { - return ((Number)obj).longValue(); - } - } - throw new UnwarrantedOptimismException(obj, programPoint); - } - - /** - * Object to int conversion that delegates to either {@link #toLong(Object)} or to - * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not. - * @param obj the object to convert - * @param programPoint the program point; can be invalid. - * @return the value converted to long - * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid. - */ - public static long toLongMaybeOptimistic(final Object obj, final int programPoint) { - return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj); - } - - /** * JavaScript compliant Object to int32 conversion * See ECMA 9.5 ToInt32 * @@ -1074,10 +980,6 @@ return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj); } - // Minimum and maximum range between which every long value can be precisely represented as a double. - private static final long MAX_PRECISE_DOUBLE = 1L << 53; - private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; - /** * JavaScript compliant long to int32 conversion * @@ -1130,6 +1032,29 @@ } /** + * Optimistic JavaScript compliant int to uint32 conversion + * @param num an int + * @param pp the program point + * @return the uint32 value if it can be represented by an int + * @throws UnwarrantedOptimismException if uint32 value cannot be represented by an int + */ + public static int toUint32Optimistic(final int num, final int pp) { + if (num >= 0) { + return num; + } + throw new UnwarrantedOptimismException(toUint32Double(num), pp, Type.NUMBER); + } + + /** + * JavaScript compliant int to uint32 conversion with double return type + * @param num an int + * @return the uint32 value as double + */ + public static double toUint32Double(final int num) { + return (double) toUint32(num); + } + + /** * JavaScript compliant Object to uint16 conversion * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) * @@ -1453,26 +1378,6 @@ try { return Math.addExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x + (long)y, programPoint); - } - } - - /** - * Wrapper for addExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.addExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x + (double)y, programPoint); } } @@ -1493,26 +1398,6 @@ try { return Math.subtractExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x - (long)y, programPoint); - } - } - - /** - * Wrapper for subExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.subtractExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x - (double)y, programPoint); } } @@ -1533,26 +1418,6 @@ try { return Math.multiplyExact(x, y); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x * (long)y, programPoint); - } - } - - /** - * Wrapper for mulExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.multiplyExact(x, y); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException((double)x * (double)y, programPoint); } } @@ -1624,71 +1489,6 @@ } /** - * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as - * long. - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if the result of the division can't be represented as long. - */ - public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - final long res; - try { - res = x / y; - } catch (final ArithmeticException e) { - assert y == 0L; // Only div by zero anticipated - throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); - } - final long rem = x % y; - if (rem == 0L) { - return res; - } - throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); - } - - /** - * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs - * is coerced to long. - * @param x the dividend - * @param y the divisor - * @return the result - */ - public static long divZero(final long x, final long y) { - return y == 0L ? 0L : x / y; - } - - /** - * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs - * is coerced to long. - * @param x the dividend - * @param y the divisor - * @return the remainder - */ - public static long remZero(final long x, final long y) { - return y == 0L ? 0L : x % y; - } - - /** - * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. - * - * @param x first term - * @param y second term - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if the modulo can't be represented as int. - */ - public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { - try { - return x % y; - } catch (final ArithmeticException e) { - assert y == 0L; // Only mod by zero anticipated - throw new UnwarrantedOptimismException(Double.NaN, programPoint); - } - } - - /** * Wrapper for decrementExact * * Catches ArithmeticException and rethrows as UnwarrantedOptimismException @@ -1703,26 +1503,7 @@ try { return Math.decrementExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x - 1, programPoint); - } - } - - /** - * Wrapper for decrementExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x number to negate - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.decrementExact(x); - } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((double)x - 1L, programPoint); + throw new UnwarrantedOptimismException((double)x - 1, programPoint); } } @@ -1741,26 +1522,7 @@ try { return Math.incrementExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((long)x + 1, programPoint); - } - } - - /** - * Wrapper for incrementExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x the number to increment - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - return Math.incrementExact(x); - } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException((double)x + 1L, programPoint); + throw new UnwarrantedOptimismException((double)x + 1, programPoint); } } @@ -1782,28 +1544,6 @@ } return Math.negateExact(x); } catch (final ArithmeticException e) { - throw new UnwarrantedOptimismException(-(long)x, programPoint); - } - } - - /** - * Wrapper for negateExact - * - * Catches ArithmeticException and rethrows as UnwarrantedOptimismException - * containing the result and the program point of the failure - * - * @param x the number to negate - * @param programPoint program point id - * @return the result - * @throws UnwarrantedOptimismException if overflow occurs - */ - public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException { - try { - if (x == 0L) { - throw new UnwarrantedOptimismException(-0.0, programPoint); - } - return Math.negateExact(x); - } catch (final ArithmeticException e) { throw new UnwarrantedOptimismException(-(double)x, programPoint); } } @@ -1835,8 +1575,6 @@ return TYPE_UNDEFINED_INDEX; } else if (type == int.class) { return TYPE_INT_INDEX; - } else if (type == long.class) { - return TYPE_LONG_INDEX; } else if (type == double.class) { return TYPE_DOUBLE_INDEX; } else if (!type.isPrimitive()) { @@ -1937,8 +1675,6 @@ public static Class getBoxedClass(final Class clazz) { if (clazz == int.class) { return Integer.class; - } else if (clazz == long.class) { - return Long.class; } else if (clazz == double.class) { return Double.class; } @@ -1956,8 +1692,6 @@ if (o != null) { if (o.getClass() == Integer.class) { return MH.constant(int.class, ((Integer)o).intValue()); - } else if (o.getClass() == Long.class) { - return MH.constant(long.class, ((Long)o).longValue()); } else if (o.getClass() == Double.class) { return MH.constant(double.class, ((Double)o).doubleValue()); } @@ -1975,8 +1709,6 @@ return Object.class; } else if (o.getClass() == Integer.class) { return int.class; - } else if (o.getClass() == Long.class) { - return long.class; } else if (o.getClass() == Double.class) { return double.class; } else {