< prev index next >
src/jdk/nashorn/internal/runtime/JSType.java
Print this page
@@ -113,18 +113,18 @@
/** JavaScript compliant conversion function from double to int32 */
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);
/** JavaScript compliant conversion function from number to String */
public static final Call TO_STRING_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, double.class);
@@ -166,40 +166,10 @@
public static final Call INCREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", int.class, int.class, int.class);
/** 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);
/** Method handle for void returns. */
public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class);
@@ -209,40 +179,35 @@
* in the dual--fields world
*/
private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
Arrays.asList(
Type.INT,
- Type.LONG,
Type.NUMBER,
Type.OBJECT));
/** table index for undefined type - hard coded so it can be used in switches at compile time */
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<MethodHandle> CONVERT_OBJECT = toUnmodifiableList(
JSType.TO_INT32.methodHandle(),
- JSType.TO_UINT32.methodHandle(),
JSType.TO_NUMBER.methodHandle(),
null
);
/**
* object conversion quickies with JS semantics - used for return value and parameter filter, optimistic
* throws exception upon incompatible type (asking for a narrower one than the storage)
*/
public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList(
JSType.TO_INT32_OPTIMISTIC.methodHandle(),
- JSType.TO_LONG_OPTIMISTIC.methodHandle(),
JSType.TO_NUMBER_OPTIMISTIC.methodHandle(),
null
);
/** The value of Undefined cast to an int32 */
@@ -250,17 +215,20 @@
/** The value of Undefined cast to a long */
public static final long UNDEFINED_LONG = 0L;
/** 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<MethodHandle> 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())
);
private static final double INT32_LIMIT = 4294967296.0;
@@ -414,43 +382,26 @@
return false;
}
/**
* 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
*/
public static boolean isRepresentableAsLong(final double number) {
return (long)number == number;
}
/**
- * 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
+ * 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 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
- */
- 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;
}
/**
* Returns true if the number is not the negative zero ({@code -0.0d}).
* @param number the number to test
@@ -626,26 +577,10 @@
}
return toString(obj);
}
/**
- * 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.
*/
public static boolean isString(final Object obj) {
@@ -1007,39 +942,10 @@
public static long toLong(final double num) {
return (long)num;
}
/**
- * 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
*
* @param obj an object
* @return an int32
@@ -1072,14 +978,10 @@
*/
public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) {
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
*
* @param num a long
* @return an int32
@@ -1128,10 +1030,33 @@
public static long toUint32(final int num) {
return num & MAX_UINT;
}
/**
+ * 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)
*
* @param obj an object
* @return a uint16
@@ -1451,30 +1376,10 @@
*/
public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
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);
}
}
/**
@@ -1491,30 +1396,10 @@
*/
public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
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);
}
}
/**
@@ -1531,30 +1416,10 @@
*/
public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
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);
}
}
/**
@@ -1622,75 +1487,10 @@
throw new UnwarrantedOptimismException(Double.NaN, programPoint);
}
}
/**
- * 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
* containing the result and the program point of the failure
*
@@ -1701,30 +1501,11 @@
*/
public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
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);
}
}
/**
* Wrapper for incrementExact
@@ -1739,30 +1520,11 @@
*/
public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
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);
}
}
/**
* Wrapper for negateExact
@@ -1780,32 +1542,10 @@
if (x == 0) {
throw new UnwarrantedOptimismException(-0.0, programPoint);
}
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);
}
}
/**
@@ -1833,12 +1573,10 @@
public static int getAccessorTypeIndex(final Class<?> type) {
if (type == null) {
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()) {
return TYPE_OBJECT_INDEX;
}
@@ -1935,12 +1673,10 @@
* @return the boxed type of clazz, or unchanged if not primitive
*/
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;
}
assert !clazz.isPrimitive();
return clazz;
@@ -1954,12 +1690,10 @@
*/
public static MethodHandle unboxConstant(final Object o) {
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());
}
}
return MH.constant(Object.class, o);
@@ -1973,12 +1707,10 @@
public static Class<?> unboxedFieldType(final Object o) {
if (o == null) {
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 {
return Object.class;
}
< prev index next >