98 99 /** JavaScript compliant conversion function from Object to number with type check */ 100 public static final Call TO_NUMBER_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumberOptimistic", double.class, Object.class, int.class); 101 102 /** JavaScript compliant conversion function from Object to String */ 103 public static final Call TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, Object.class); 104 105 /** JavaScript compliant conversion function from Object to int32 */ 106 public static final Call TO_INT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, Object.class); 107 108 /** JavaScript compliant conversion function from Object to int32 */ 109 public static final Call TO_INT32_L = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, long.class); 110 111 /** JavaScript compliant conversion function from Object to int32 with type check */ 112 public static final Call TO_INT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32Optimistic", int.class, Object.class, int.class); 113 114 /** JavaScript compliant conversion function from double to int32 */ 115 public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class); 116 117 /** JavaScript compliant conversion function from int to uint32 */ 118 public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class); 119 120 /** JavaScript compliant conversion function from Object to uint32 */ 121 public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class); 122 123 /** JavaScript compliant conversion function from Object to long with type check */ 124 public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class); 125 126 /** JavaScript compliant conversion function from number to uint32 */ 127 public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class); 128 129 /** JavaScript compliant conversion function from number to String */ 130 public static final Call TO_STRING_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, double.class); 131 132 /** Combined call to toPrimitive followed by toString. */ 133 public static final Call TO_PRIMITIVE_TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToString", String.class, Object.class); 134 135 /** Combined call to toPrimitive followed by toCharSequence. */ 136 public static final Call TO_PRIMITIVE_TO_CHARSEQUENCE = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToCharSequence", CharSequence.class, Object.class); 137 138 /** Throw an unwarranted optimism exception */ 139 public static final Call THROW_UNWARRANTED = staticCall(JSTYPE_LOOKUP, JSType.class, "throwUnwarrantedOptimismException", Object.class, Object.class, int.class); 140 141 /** Add exact wrapper for potentially overflowing integer operations */ 142 public static final Call ADD_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", int.class, int.class, int.class, int.class); 143 144 /** Sub exact wrapper for potentially overflowing integer operations */ 145 public static final Call SUB_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", int.class, int.class, int.class, int.class); 151 public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class); 152 153 /** Div zero wrapper for integer division that handles (0/0)|0 == 0 */ 154 public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class); 155 156 /** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */ 157 public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class); 158 159 /** Mod exact wrapper for potentially integer remainders that turns into float point */ 160 public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class); 161 162 /** Decrement exact wrapper for potentially overflowing integer operations */ 163 public static final Call DECREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", int.class, int.class, int.class); 164 165 /** Increment exact wrapper for potentially overflowing integer operations */ 166 public static final Call INCREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", int.class, int.class, int.class); 167 168 /** Negate exact exact wrapper for potentially overflowing integer operations */ 169 public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class); 170 171 /** Add exact wrapper for potentially overflowing long operations */ 172 public static final Call ADD_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class); 173 174 /** Sub exact wrapper for potentially overflowing long operations */ 175 public static final Call SUB_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class); 176 177 /** Multiply exact wrapper for potentially overflowing long operations */ 178 public static final Call MUL_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class); 179 180 /** Div exact wrapper for potentially integer division that turns into float point */ 181 public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class); 182 183 /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ 184 public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class); 185 186 /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ 187 public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class); 188 189 /** Mod exact wrapper for potentially integer remainders that turns into float point */ 190 public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class); 191 192 /** Decrement exact wrapper for potentially overflowing long operations */ 193 public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", long.class, long.class, int.class); 194 195 /** Increment exact wrapper for potentially overflowing long operations */ 196 public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", long.class, long.class, int.class); 197 198 /** Negate exact exact wrapper for potentially overflowing long operations */ 199 public static final Call NEGATE_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", long.class, long.class, int.class); 200 201 /** Method handle to convert a JS Object to a Java array. */ 202 public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class); 203 204 /** Method handle for void returns. */ 205 public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); 206 207 /** 208 * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide 209 * in the dual--fields world 210 */ 211 private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList( 212 Arrays.asList( 213 Type.INT, 214 Type.LONG, 215 Type.NUMBER, 216 Type.OBJECT)); 217 218 /** table index for undefined type - hard coded so it can be used in switches at compile time */ 219 public static final int TYPE_UNDEFINED_INDEX = -1; 220 /** table index for integer type - hard coded so it can be used in switches at compile time */ 221 public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); 222 /** table index for long type - hard coded so it can be used in switches at compile time */ 223 public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); 224 /** table index for double type - hard coded so it can be used in switches at compile time */ 225 public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); 226 /** table index for object type - hard coded so it can be used in switches at compile time */ 227 public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); 228 229 /** object conversion quickies with JS semantics - used for return value and parameter filter */ 230 public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList( 231 JSType.TO_INT32.methodHandle(), 232 JSType.TO_UINT32.methodHandle(), 233 JSType.TO_NUMBER.methodHandle(), 234 null 235 ); 236 237 /** 238 * object conversion quickies with JS semantics - used for return value and parameter filter, optimistic 239 * throws exception upon incompatible type (asking for a narrower one than the storage) 240 */ 241 public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList( 242 JSType.TO_INT32_OPTIMISTIC.methodHandle(), 243 JSType.TO_LONG_OPTIMISTIC.methodHandle(), 244 JSType.TO_NUMBER_OPTIMISTIC.methodHandle(), 245 null 246 ); 247 248 /** The value of Undefined cast to an int32 */ 249 public static final int UNDEFINED_INT = 0; 250 /** The value of Undefined cast to a long */ 251 public static final long UNDEFINED_LONG = 0L; 252 /** The value of Undefined cast to a double */ 253 public static final double UNDEFINED_DOUBLE = Double.NaN; 254 255 /** 256 * Method handles for getters that return undefined coerced 257 * to the appropriate type 258 */ 259 public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList( 260 MH.constant(int.class, UNDEFINED_INT), 261 MH.constant(long.class, UNDEFINED_LONG), 262 MH.constant(double.class, UNDEFINED_DOUBLE), 263 MH.constant(Object.class, Undefined.getUndefined()) 264 ); 265 266 private static final double INT32_LIMIT = 4294967296.0; 267 268 /** 269 * Constructor 270 * 271 * @param typeName the type name 272 */ 273 private JSType(final String typeName) { 274 this.typeName = typeName; 275 } 276 277 /** 278 * The external type name as returned by ECMAScript "typeof" operator 279 * 280 * @return type name for this type 281 */ 399 public static boolean isStrictlyRepresentableAsInt(final double number) { 400 return isRepresentableAsInt(number) && isNotNegativeZero(number); 401 } 402 403 /** 404 * Returns true if Object can be represented as an int 405 * 406 * @param obj an object to inspect 407 * 408 * @return true for int representable objects 409 */ 410 public static boolean isRepresentableAsInt(final Object obj) { 411 if (obj instanceof Number) { 412 return isRepresentableAsInt(((Number)obj).doubleValue()); 413 } 414 return false; 415 } 416 417 /** 418 * Returns true if double number can be represented as a long. Note that it returns true for negative 419 * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsLong(double)}. 420 * 421 * @param number a double to inspect 422 * @return true for long representable doubles 423 */ 424 public static boolean isRepresentableAsLong(final double number) { 425 return (long)number == number; 426 } 427 428 /** 429 * Returns true if double number can be represented as a long. Note that it returns false for negative 430 * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}. 431 * 432 * @param number a double to inspect 433 * 434 * @return true for long representable doubles 435 */ 436 public static boolean isStrictlyRepresentableAsLong(final double number) { 437 return isRepresentableAsLong(number) && isNotNegativeZero(number); 438 } 439 440 /** 441 * Returns true if Object can be represented as a long 442 * 443 * @param obj an object to inspect 444 * 445 * @return true for long representable objects 446 */ 447 public static boolean isRepresentableAsLong(final Object obj) { 448 if (obj instanceof Number) { 449 return isRepresentableAsLong(((Number)obj).doubleValue()); 450 } 451 return false; 452 } 453 454 /** 455 * Returns true if the number is not the negative zero ({@code -0.0d}). 456 * @param number the number to test 457 * @return true if it is not the negative zero, false otherwise. 458 */ 459 private static boolean isNotNegativeZero(final double number) { 460 return Double.doubleToRawLongBits(number) != 0x8000000000000000L; 461 } 462 463 /** 464 * Check whether an object is primitive 465 * 466 * @param obj an object 467 * 468 * @return true if object is primitive (includes null and undefined) 469 */ 470 public static boolean isPrimitive(final Object obj) { 471 return obj == null || 611 */ 612 public static String toString(final Object obj) { 613 return toStringImpl(obj, false); 614 } 615 616 /** 617 * If obj is an instance of {@link ConsString} cast to CharSequence, else return 618 * result of {@link #toString(Object)}. 619 * 620 * @param obj an object 621 * @return an instance of String or ConsString 622 */ 623 public static CharSequence toCharSequence(final Object obj) { 624 if (obj instanceof ConsString) { 625 return (CharSequence) obj; 626 } 627 return toString(obj); 628 } 629 630 /** 631 * Check whether a string is representable as a JavaScript number 632 * 633 * @param str a string 634 * 635 * @return true if string can be represented as a number 636 */ 637 public static boolean isNumber(final String str) { 638 try { 639 Double.parseDouble(str); 640 return true; 641 } catch (final NumberFormatException e) { 642 return false; 643 } 644 } 645 646 /** 647 * Returns true if object represents a primitive JavaScript string value. 648 * @param obj the object 649 * @return true if the object represents a primitive JavaScript string value. 650 */ 651 public static boolean isString(final Object obj) { 652 return obj instanceof String || obj instanceof ConsString; 653 } 654 655 /** 656 * JavaScript compliant conversion of integer to String 657 * 658 * @param num an integer 659 * 660 * @return a string 661 */ 662 public static String toString(final int num) { 663 return Integer.toString(num); 664 } 665 666 /** 992 * caller's responsibility to handle such values correctly.</p> 993 * 994 * @param obj an object 995 * @return a long 996 */ 997 public static long toLong(final Object obj) { 998 return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj)); 999 } 1000 1001 /** 1002 * Converts a double to long. 1003 * 1004 * @param num the double to convert 1005 * @return the converted long value 1006 */ 1007 public static long toLong(final double num) { 1008 return (long)num; 1009 } 1010 1011 /** 1012 * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object 1013 * 1014 * @param obj object to convert 1015 * @param programPoint program point 1016 * @return long 1017 */ 1018 public static long toLongOptimistic(final Object obj, final int programPoint) { 1019 if (obj != null) { 1020 final Class<?> clz = obj.getClass(); 1021 if (clz == Long.class || clz == Integer.class) { 1022 return ((Number)obj).longValue(); 1023 } 1024 } 1025 throw new UnwarrantedOptimismException(obj, programPoint); 1026 } 1027 1028 /** 1029 * Object to int conversion that delegates to either {@link #toLong(Object)} or to 1030 * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not. 1031 * @param obj the object to convert 1032 * @param programPoint the program point; can be invalid. 1033 * @return the value converted to long 1034 * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid. 1035 */ 1036 public static long toLongMaybeOptimistic(final Object obj, final int programPoint) { 1037 return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj); 1038 } 1039 1040 /** 1041 * JavaScript compliant Object to int32 conversion 1042 * See ECMA 9.5 ToInt32 1043 * 1044 * @param obj an object 1045 * @return an int32 1046 */ 1047 public static int toInt32(final Object obj) { 1048 return toInt32(toNumber(obj)); 1049 } 1050 1051 /** 1052 * Optimistic int conversion - throws UnwarrantedOptimismException if double, long or Object 1053 * 1054 * @param obj object to convert 1055 * @param programPoint program point 1056 * @return double 1057 */ 1058 public static int toInt32Optimistic(final Object obj, final int programPoint) { 1059 if (obj != null && obj.getClass() == Integer.class) { 1060 return ((Integer)obj).intValue(); 1061 } 1062 throw new UnwarrantedOptimismException(obj, programPoint); 1063 } 1064 1065 /** 1066 * Object to int conversion that delegates to either {@link #toInt32(Object)} or to 1067 * {@link #toInt32Optimistic(Object, int)} depending on whether the program point is valid or not. 1068 * @param obj the object to convert 1069 * @param programPoint the program point; can be invalid. 1070 * @return the value converted to int 1071 * @throws UnwarrantedOptimismException if the value can't be represented as int and the program point is valid. 1072 */ 1073 public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) { 1074 return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj); 1075 } 1076 1077 // Minimum and maximum range between which every long value can be precisely represented as a double. 1078 private static final long MAX_PRECISE_DOUBLE = 1L << 53; 1079 private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; 1080 1081 /** 1082 * JavaScript compliant long to int32 conversion 1083 * 1084 * @param num a long 1085 * @return an int32 1086 */ 1087 public static int toInt32(final long num) { 1088 return (int)(num >= MIN_PRECISE_DOUBLE && num <= MAX_PRECISE_DOUBLE ? num : (long)(num % INT32_LIMIT)); 1089 } 1090 1091 1092 /** 1093 * JavaScript compliant number to int32 conversion 1094 * 1095 * @param num a number 1096 * @return an int32 1097 */ 1098 public static int toInt32(final double num) { 1099 return (int)doubleToInt32(num); 1100 } 1113 * JavaScript compliant number to uint32 conversion 1114 * 1115 * @param num a number 1116 * @return a uint32 1117 */ 1118 public static long toUint32(final double num) { 1119 return doubleToInt32(num) & MAX_UINT; 1120 } 1121 1122 /** 1123 * JavaScript compliant int to uint32 conversion 1124 * 1125 * @param num an int 1126 * @return a uint32 1127 */ 1128 public static long toUint32(final int num) { 1129 return num & MAX_UINT; 1130 } 1131 1132 /** 1133 * JavaScript compliant Object to uint16 conversion 1134 * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) 1135 * 1136 * @param obj an object 1137 * @return a uint16 1138 */ 1139 public static int toUint16(final Object obj) { 1140 return toUint16(toNumber(obj)); 1141 } 1142 1143 /** 1144 * JavaScript compliant number to uint16 conversion 1145 * 1146 * @param num a number 1147 * @return a uint16 1148 */ 1149 public static int toUint16(final int num) { 1150 return num & 0xffff; 1151 } 1152 1436 private static Object throwUnwarrantedOptimismException(final Object value, final int programPoint) { 1437 throw new UnwarrantedOptimismException(value, programPoint); 1438 } 1439 1440 /** 1441 * Wrapper for addExact 1442 * 1443 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1444 * containing the result and the program point of the failure 1445 * 1446 * @param x first term 1447 * @param y second term 1448 * @param programPoint program point id 1449 * @return the result 1450 * @throws UnwarrantedOptimismException if overflow occurs 1451 */ 1452 public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1453 try { 1454 return Math.addExact(x, y); 1455 } catch (final ArithmeticException e) { 1456 throw new UnwarrantedOptimismException((long)x + (long)y, programPoint); 1457 } 1458 } 1459 1460 /** 1461 * Wrapper for addExact 1462 * 1463 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1464 * containing the result and the program point of the failure 1465 * 1466 * @param x first term 1467 * @param y second term 1468 * @param programPoint program point id 1469 * @return the result 1470 * @throws UnwarrantedOptimismException if overflow occurs 1471 */ 1472 public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1473 try { 1474 return Math.addExact(x, y); 1475 } catch (final ArithmeticException e) { 1476 throw new UnwarrantedOptimismException((double)x + (double)y, programPoint); 1477 } 1478 } 1479 1480 /** 1481 * Wrapper for subExact 1482 * 1483 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1484 * containing the result and the program point of the failure 1485 * 1486 * @param x first term 1487 * @param y second term 1488 * @param programPoint program point id 1489 * @return the result 1490 * @throws UnwarrantedOptimismException if overflow occurs 1491 */ 1492 public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1493 try { 1494 return Math.subtractExact(x, y); 1495 } catch (final ArithmeticException e) { 1496 throw new UnwarrantedOptimismException((long)x - (long)y, programPoint); 1497 } 1498 } 1499 1500 /** 1501 * Wrapper for subExact 1502 * 1503 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1504 * containing the result and the program point of the failure 1505 * 1506 * @param x first term 1507 * @param y second term 1508 * @param programPoint program point id 1509 * @return the result 1510 * @throws UnwarrantedOptimismException if overflow occurs 1511 */ 1512 public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1513 try { 1514 return Math.subtractExact(x, y); 1515 } catch (final ArithmeticException e) { 1516 throw new UnwarrantedOptimismException((double)x - (double)y, programPoint); 1517 } 1518 } 1519 1520 /** 1521 * Wrapper for mulExact 1522 * 1523 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1524 * containing the result and the program point of the failure 1525 * 1526 * @param x first term 1527 * @param y second term 1528 * @param programPoint program point id 1529 * @return the result 1530 * @throws UnwarrantedOptimismException if overflow occurs 1531 */ 1532 public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1533 try { 1534 return Math.multiplyExact(x, y); 1535 } catch (final ArithmeticException e) { 1536 throw new UnwarrantedOptimismException((long)x * (long)y, programPoint); 1537 } 1538 } 1539 1540 /** 1541 * Wrapper for mulExact 1542 * 1543 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1544 * containing the result and the program point of the failure 1545 * 1546 * @param x first term 1547 * @param y second term 1548 * @param programPoint program point id 1549 * @return the result 1550 * @throws UnwarrantedOptimismException if overflow occurs 1551 */ 1552 public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1553 try { 1554 return Math.multiplyExact(x, y); 1555 } catch (final ArithmeticException e) { 1556 throw new UnwarrantedOptimismException((double)x * (double)y, programPoint); 1557 } 1558 } 1559 1560 /** 1561 * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as 1562 * int. 1563 * 1564 * @param x first term 1565 * @param y second term 1566 * @param programPoint program point id 1567 * @return the result 1568 * @throws UnwarrantedOptimismException if the result of the division can't be represented as int. 1569 */ 1570 public static int divExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1571 final int res; 1572 try { 1573 res = x / y; 1574 } catch (final ArithmeticException e) { 1575 assert y == 0; // Only div by zero anticipated 1607 1608 /** 1609 * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. 1610 * 1611 * @param x first term 1612 * @param y second term 1613 * @param programPoint program point id 1614 * @return the result 1615 * @throws UnwarrantedOptimismException if the modulo can't be represented as int. 1616 */ 1617 public static int remExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1618 try { 1619 return x % y; 1620 } catch (final ArithmeticException e) { 1621 assert y == 0; // Only mod by zero anticipated 1622 throw new UnwarrantedOptimismException(Double.NaN, programPoint); 1623 } 1624 } 1625 1626 /** 1627 * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as 1628 * long. 1629 * 1630 * @param x first term 1631 * @param y second term 1632 * @param programPoint program point id 1633 * @return the result 1634 * @throws UnwarrantedOptimismException if the result of the division can't be represented as long. 1635 */ 1636 public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1637 final long res; 1638 try { 1639 res = x / y; 1640 } catch (final ArithmeticException e) { 1641 assert y == 0L; // Only div by zero anticipated 1642 throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); 1643 } 1644 final long rem = x % y; 1645 if (rem == 0L) { 1646 return res; 1647 } 1648 throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); 1649 } 1650 1651 /** 1652 * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs 1653 * is coerced to long. 1654 * @param x the dividend 1655 * @param y the divisor 1656 * @return the result 1657 */ 1658 public static long divZero(final long x, final long y) { 1659 return y == 0L ? 0L : x / y; 1660 } 1661 1662 /** 1663 * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs 1664 * is coerced to long. 1665 * @param x the dividend 1666 * @param y the divisor 1667 * @return the remainder 1668 */ 1669 public static long remZero(final long x, final long y) { 1670 return y == 0L ? 0L : x % y; 1671 } 1672 1673 /** 1674 * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. 1675 * 1676 * @param x first term 1677 * @param y second term 1678 * @param programPoint program point id 1679 * @return the result 1680 * @throws UnwarrantedOptimismException if the modulo can't be represented as int. 1681 */ 1682 public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1683 try { 1684 return x % y; 1685 } catch (final ArithmeticException e) { 1686 assert y == 0L; // Only mod by zero anticipated 1687 throw new UnwarrantedOptimismException(Double.NaN, programPoint); 1688 } 1689 } 1690 1691 /** 1692 * Wrapper for decrementExact 1693 * 1694 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1695 * containing the result and the program point of the failure 1696 * 1697 * @param x number to negate 1698 * @param programPoint program point id 1699 * @return the result 1700 * @throws UnwarrantedOptimismException if overflow occurs 1701 */ 1702 public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1703 try { 1704 return Math.decrementExact(x); 1705 } catch (final ArithmeticException e) { 1706 throw new UnwarrantedOptimismException((long)x - 1, programPoint); 1707 } 1708 } 1709 1710 /** 1711 * Wrapper for decrementExact 1712 * 1713 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1714 * containing the result and the program point of the failure 1715 * 1716 * @param x number to negate 1717 * @param programPoint program point id 1718 * @return the result 1719 * @throws UnwarrantedOptimismException if overflow occurs 1720 */ 1721 public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1722 try { 1723 return Math.decrementExact(x); 1724 } catch (final ArithmeticException e) { 1725 throw new UnwarrantedOptimismException((double)x - 1L, programPoint); 1726 } 1727 } 1728 1729 /** 1730 * Wrapper for incrementExact 1731 * 1732 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1733 * containing the result and the program point of the failure 1734 * 1735 * @param x the number to increment 1736 * @param programPoint program point id 1737 * @return the result 1738 * @throws UnwarrantedOptimismException if overflow occurs 1739 */ 1740 public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1741 try { 1742 return Math.incrementExact(x); 1743 } catch (final ArithmeticException e) { 1744 throw new UnwarrantedOptimismException((long)x + 1, programPoint); 1745 } 1746 } 1747 1748 /** 1749 * Wrapper for incrementExact 1750 * 1751 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1752 * containing the result and the program point of the failure 1753 * 1754 * @param x the number to increment 1755 * @param programPoint program point id 1756 * @return the result 1757 * @throws UnwarrantedOptimismException if overflow occurs 1758 */ 1759 public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1760 try { 1761 return Math.incrementExact(x); 1762 } catch (final ArithmeticException e) { 1763 throw new UnwarrantedOptimismException((double)x + 1L, programPoint); 1764 } 1765 } 1766 1767 /** 1768 * Wrapper for negateExact 1769 * 1770 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1771 * containing the result and the program point of the failure 1772 * 1773 * @param x the number to negate 1774 * @param programPoint program point id 1775 * @return the result 1776 * @throws UnwarrantedOptimismException if overflow occurs 1777 */ 1778 public static int negateExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1779 try { 1780 if (x == 0) { 1781 throw new UnwarrantedOptimismException(-0.0, programPoint); 1782 } 1783 return Math.negateExact(x); 1784 } catch (final ArithmeticException e) { 1785 throw new UnwarrantedOptimismException(-(long)x, programPoint); 1786 } 1787 } 1788 1789 /** 1790 * Wrapper for negateExact 1791 * 1792 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1793 * containing the result and the program point of the failure 1794 * 1795 * @param x the number to negate 1796 * @param programPoint program point id 1797 * @return the result 1798 * @throws UnwarrantedOptimismException if overflow occurs 1799 */ 1800 public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1801 try { 1802 if (x == 0L) { 1803 throw new UnwarrantedOptimismException(-0.0, programPoint); 1804 } 1805 return Math.negateExact(x); 1806 } catch (final ArithmeticException e) { 1807 throw new UnwarrantedOptimismException(-(double)x, programPoint); 1808 } 1809 } 1810 1811 /** 1812 * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1813 * 1814 * @param type the type 1815 * 1816 * @return the accessor index, or -1 if no accessor of this type exists 1817 */ 1818 public static int getAccessorTypeIndex(final Type type) { 1819 return getAccessorTypeIndex(type.getTypeClass()); 1820 } 1821 1822 /** 1823 * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1824 * 1825 * Note that this is hardcoded with respect to the dynamic contents of the accessor 1826 * types array for speed. Hotspot got stuck with this as 5% of the runtime in 1827 * a benchmark when it looped over values and increased an index counter. :-( 1828 * 1829 * @param type the type 1830 * 1831 * @return the accessor index, or -1 if no accessor of this type exists 1832 */ 1833 public static int getAccessorTypeIndex(final Class<?> type) { 1834 if (type == null) { 1835 return TYPE_UNDEFINED_INDEX; 1836 } else if (type == int.class) { 1837 return TYPE_INT_INDEX; 1838 } else if (type == long.class) { 1839 return TYPE_LONG_INDEX; 1840 } else if (type == double.class) { 1841 return TYPE_DOUBLE_INDEX; 1842 } else if (!type.isPrimitive()) { 1843 return TYPE_OBJECT_INDEX; 1844 } 1845 return -1; 1846 } 1847 1848 /** 1849 * Return the accessor type based on its index in [0..getNumberOfAccessorTypes()) 1850 * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always 1851 * go to a type of higher index 1852 * 1853 * @param index accessor type index 1854 * 1855 * @return a type corresponding to the index. 1856 */ 1857 1858 public static Type getAccessorType(final int index) { 1859 return ACCESSOR_TYPES.get(index); 1920 } 1921 1922 private static Object invoke(final MethodHandle mh, final Object arg) { 1923 try { 1924 return mh.invoke(arg); 1925 } catch (final RuntimeException | Error e) { 1926 throw e; 1927 } catch (final Throwable t) { 1928 throw new RuntimeException(t); 1929 } 1930 } 1931 1932 /** 1933 * Returns the boxed version of a primitive class 1934 * @param clazz the class 1935 * @return the boxed type of clazz, or unchanged if not primitive 1936 */ 1937 public static Class<?> getBoxedClass(final Class<?> clazz) { 1938 if (clazz == int.class) { 1939 return Integer.class; 1940 } else if (clazz == long.class) { 1941 return Long.class; 1942 } else if (clazz == double.class) { 1943 return Double.class; 1944 } 1945 assert !clazz.isPrimitive(); 1946 return clazz; 1947 } 1948 1949 /** 1950 * Create a method handle constant of the correct primitive type 1951 * for a constant object 1952 * @param o object 1953 * @return constant function that returns object 1954 */ 1955 public static MethodHandle unboxConstant(final Object o) { 1956 if (o != null) { 1957 if (o.getClass() == Integer.class) { 1958 return MH.constant(int.class, ((Integer)o).intValue()); 1959 } else if (o.getClass() == Long.class) { 1960 return MH.constant(long.class, ((Long)o).longValue()); 1961 } else if (o.getClass() == Double.class) { 1962 return MH.constant(double.class, ((Double)o).doubleValue()); 1963 } 1964 } 1965 return MH.constant(Object.class, o); 1966 } 1967 1968 /** 1969 * Get the unboxed (primitive) type for an object 1970 * @param o object 1971 * @return primitive type or Object.class if not primitive 1972 */ 1973 public static Class<?> unboxedFieldType(final Object o) { 1974 if (o == null) { 1975 return Object.class; 1976 } else if (o.getClass() == Integer.class) { 1977 return int.class; 1978 } else if (o.getClass() == Long.class) { 1979 return long.class; 1980 } else if (o.getClass() == Double.class) { 1981 return double.class; 1982 } else { 1983 return Object.class; 1984 } 1985 } 1986 1987 private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) { 1988 return Collections.unmodifiableList(Arrays.asList(methodHandles)); 1989 } 1990 } | 98 99 /** JavaScript compliant conversion function from Object to number with type check */ 100 public static final Call TO_NUMBER_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumberOptimistic", double.class, Object.class, int.class); 101 102 /** JavaScript compliant conversion function from Object to String */ 103 public static final Call TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, Object.class); 104 105 /** JavaScript compliant conversion function from Object to int32 */ 106 public static final Call TO_INT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, Object.class); 107 108 /** JavaScript compliant conversion function from Object to int32 */ 109 public static final Call TO_INT32_L = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, long.class); 110 111 /** JavaScript compliant conversion function from Object to int32 with type check */ 112 public static final Call TO_INT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32Optimistic", int.class, Object.class, int.class); 113 114 /** JavaScript compliant conversion function from double to int32 */ 115 public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class); 116 117 /** JavaScript compliant conversion function from int to uint32 */ 118 public static final Call TO_UINT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Optimistic", int.class, int.class, int.class); 119 120 /** JavaScript compliant conversion function from int to uint32 */ 121 public static final Call TO_UINT32_DOUBLE = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Double", double.class, int.class); 122 123 /** JavaScript compliant conversion function from Object to uint32 */ 124 public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class); 125 126 /** JavaScript compliant conversion function from number to uint32 */ 127 public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class); 128 129 /** JavaScript compliant conversion function from number to String */ 130 public static final Call TO_STRING_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, double.class); 131 132 /** Combined call to toPrimitive followed by toString. */ 133 public static final Call TO_PRIMITIVE_TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToString", String.class, Object.class); 134 135 /** Combined call to toPrimitive followed by toCharSequence. */ 136 public static final Call TO_PRIMITIVE_TO_CHARSEQUENCE = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToCharSequence", CharSequence.class, Object.class); 137 138 /** Throw an unwarranted optimism exception */ 139 public static final Call THROW_UNWARRANTED = staticCall(JSTYPE_LOOKUP, JSType.class, "throwUnwarrantedOptimismException", Object.class, Object.class, int.class); 140 141 /** Add exact wrapper for potentially overflowing integer operations */ 142 public static final Call ADD_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", int.class, int.class, int.class, int.class); 143 144 /** Sub exact wrapper for potentially overflowing integer operations */ 145 public static final Call SUB_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", int.class, int.class, int.class, int.class); 151 public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class); 152 153 /** Div zero wrapper for integer division that handles (0/0)|0 == 0 */ 154 public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class); 155 156 /** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */ 157 public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class); 158 159 /** Mod exact wrapper for potentially integer remainders that turns into float point */ 160 public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class); 161 162 /** Decrement exact wrapper for potentially overflowing integer operations */ 163 public static final Call DECREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", int.class, int.class, int.class); 164 165 /** Increment exact wrapper for potentially overflowing integer operations */ 166 public static final Call INCREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", int.class, int.class, int.class); 167 168 /** Negate exact exact wrapper for potentially overflowing integer operations */ 169 public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class); 170 171 /** Method handle to convert a JS Object to a Java array. */ 172 public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class); 173 174 /** Method handle for void returns. */ 175 public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); 176 177 /** 178 * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide 179 * in the dual--fields world 180 */ 181 private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList( 182 Arrays.asList( 183 Type.INT, 184 Type.NUMBER, 185 Type.OBJECT)); 186 187 /** table index for undefined type - hard coded so it can be used in switches at compile time */ 188 public static final int TYPE_UNDEFINED_INDEX = -1; 189 /** table index for integer type - hard coded so it can be used in switches at compile time */ 190 public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); 191 /** table index for double type - hard coded so it can be used in switches at compile time */ 192 public static final int TYPE_DOUBLE_INDEX = 1; //getAccessorTypeIndex(double.class); 193 /** table index for object type - hard coded so it can be used in switches at compile time */ 194 public static final int TYPE_OBJECT_INDEX = 2; //getAccessorTypeIndex(Object.class); 195 196 /** object conversion quickies with JS semantics - used for return value and parameter filter */ 197 public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList( 198 JSType.TO_INT32.methodHandle(), 199 JSType.TO_NUMBER.methodHandle(), 200 null 201 ); 202 203 /** 204 * object conversion quickies with JS semantics - used for return value and parameter filter, optimistic 205 * throws exception upon incompatible type (asking for a narrower one than the storage) 206 */ 207 public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList( 208 JSType.TO_INT32_OPTIMISTIC.methodHandle(), 209 JSType.TO_NUMBER_OPTIMISTIC.methodHandle(), 210 null 211 ); 212 213 /** The value of Undefined cast to an int32 */ 214 public static final int UNDEFINED_INT = 0; 215 /** The value of Undefined cast to a long */ 216 public static final long UNDEFINED_LONG = 0L; 217 /** The value of Undefined cast to a double */ 218 public static final double UNDEFINED_DOUBLE = Double.NaN; 219 220 // Minimum and maximum range between which every long value can be precisely represented as a double. 221 private static final long MAX_PRECISE_DOUBLE = 1L << 53; 222 private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; 223 224 /** 225 * Method handles for getters that return undefined coerced 226 * to the appropriate type 227 */ 228 public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList( 229 MH.constant(int.class, UNDEFINED_INT), 230 MH.constant(double.class, UNDEFINED_DOUBLE), 231 MH.constant(Object.class, Undefined.getUndefined()) 232 ); 233 234 private static final double INT32_LIMIT = 4294967296.0; 235 236 /** 237 * Constructor 238 * 239 * @param typeName the type name 240 */ 241 private JSType(final String typeName) { 242 this.typeName = typeName; 243 } 244 245 /** 246 * The external type name as returned by ECMAScript "typeof" operator 247 * 248 * @return type name for this type 249 */ 367 public static boolean isStrictlyRepresentableAsInt(final double number) { 368 return isRepresentableAsInt(number) && isNotNegativeZero(number); 369 } 370 371 /** 372 * Returns true if Object can be represented as an int 373 * 374 * @param obj an object to inspect 375 * 376 * @return true for int representable objects 377 */ 378 public static boolean isRepresentableAsInt(final Object obj) { 379 if (obj instanceof Number) { 380 return isRepresentableAsInt(((Number)obj).doubleValue()); 381 } 382 return false; 383 } 384 385 /** 386 * Returns true if double number can be represented as a long. Note that it returns true for negative 387 * zero. 388 * 389 * @param number a double to inspect 390 * @return true for long representable doubles 391 */ 392 public static boolean isRepresentableAsLong(final double number) { 393 return (long)number == number; 394 } 395 396 /** 397 * Returns true if long number can be represented as double without loss of precision. 398 * @param number a long number 399 * @return true if the double representation does not lose precision 400 */ 401 public static boolean isRepresentableAsDouble(final long number) { 402 return MAX_PRECISE_DOUBLE >= number && number >= MIN_PRECISE_DOUBLE; 403 } 404 405 /** 406 * Returns true if the number is not the negative zero ({@code -0.0d}). 407 * @param number the number to test 408 * @return true if it is not the negative zero, false otherwise. 409 */ 410 private static boolean isNotNegativeZero(final double number) { 411 return Double.doubleToRawLongBits(number) != 0x8000000000000000L; 412 } 413 414 /** 415 * Check whether an object is primitive 416 * 417 * @param obj an object 418 * 419 * @return true if object is primitive (includes null and undefined) 420 */ 421 public static boolean isPrimitive(final Object obj) { 422 return obj == null || 562 */ 563 public static String toString(final Object obj) { 564 return toStringImpl(obj, false); 565 } 566 567 /** 568 * If obj is an instance of {@link ConsString} cast to CharSequence, else return 569 * result of {@link #toString(Object)}. 570 * 571 * @param obj an object 572 * @return an instance of String or ConsString 573 */ 574 public static CharSequence toCharSequence(final Object obj) { 575 if (obj instanceof ConsString) { 576 return (CharSequence) obj; 577 } 578 return toString(obj); 579 } 580 581 /** 582 * Returns true if object represents a primitive JavaScript string value. 583 * @param obj the object 584 * @return true if the object represents a primitive JavaScript string value. 585 */ 586 public static boolean isString(final Object obj) { 587 return obj instanceof String || obj instanceof ConsString; 588 } 589 590 /** 591 * JavaScript compliant conversion of integer to String 592 * 593 * @param num an integer 594 * 595 * @return a string 596 */ 597 public static String toString(final int num) { 598 return Integer.toString(num); 599 } 600 601 /** 927 * caller's responsibility to handle such values correctly.</p> 928 * 929 * @param obj an object 930 * @return a long 931 */ 932 public static long toLong(final Object obj) { 933 return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj)); 934 } 935 936 /** 937 * Converts a double to long. 938 * 939 * @param num the double to convert 940 * @return the converted long value 941 */ 942 public static long toLong(final double num) { 943 return (long)num; 944 } 945 946 /** 947 * JavaScript compliant Object to int32 conversion 948 * See ECMA 9.5 ToInt32 949 * 950 * @param obj an object 951 * @return an int32 952 */ 953 public static int toInt32(final Object obj) { 954 return toInt32(toNumber(obj)); 955 } 956 957 /** 958 * Optimistic int conversion - throws UnwarrantedOptimismException if double, long or Object 959 * 960 * @param obj object to convert 961 * @param programPoint program point 962 * @return double 963 */ 964 public static int toInt32Optimistic(final Object obj, final int programPoint) { 965 if (obj != null && obj.getClass() == Integer.class) { 966 return ((Integer)obj).intValue(); 967 } 968 throw new UnwarrantedOptimismException(obj, programPoint); 969 } 970 971 /** 972 * Object to int conversion that delegates to either {@link #toInt32(Object)} or to 973 * {@link #toInt32Optimistic(Object, int)} depending on whether the program point is valid or not. 974 * @param obj the object to convert 975 * @param programPoint the program point; can be invalid. 976 * @return the value converted to int 977 * @throws UnwarrantedOptimismException if the value can't be represented as int and the program point is valid. 978 */ 979 public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) { 980 return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj); 981 } 982 983 /** 984 * JavaScript compliant long to int32 conversion 985 * 986 * @param num a long 987 * @return an int32 988 */ 989 public static int toInt32(final long num) { 990 return (int)(num >= MIN_PRECISE_DOUBLE && num <= MAX_PRECISE_DOUBLE ? num : (long)(num % INT32_LIMIT)); 991 } 992 993 994 /** 995 * JavaScript compliant number to int32 conversion 996 * 997 * @param num a number 998 * @return an int32 999 */ 1000 public static int toInt32(final double num) { 1001 return (int)doubleToInt32(num); 1002 } 1015 * JavaScript compliant number to uint32 conversion 1016 * 1017 * @param num a number 1018 * @return a uint32 1019 */ 1020 public static long toUint32(final double num) { 1021 return doubleToInt32(num) & MAX_UINT; 1022 } 1023 1024 /** 1025 * JavaScript compliant int to uint32 conversion 1026 * 1027 * @param num an int 1028 * @return a uint32 1029 */ 1030 public static long toUint32(final int num) { 1031 return num & MAX_UINT; 1032 } 1033 1034 /** 1035 * Optimistic JavaScript compliant int to uint32 conversion 1036 * @param num an int 1037 * @param pp the program point 1038 * @return the uint32 value if it can be represented by an int 1039 * @throws UnwarrantedOptimismException if uint32 value cannot be represented by an int 1040 */ 1041 public static int toUint32Optimistic(final int num, final int pp) { 1042 if (num >= 0) { 1043 return num; 1044 } 1045 throw new UnwarrantedOptimismException(toUint32Double(num), pp, Type.NUMBER); 1046 } 1047 1048 /** 1049 * JavaScript compliant int to uint32 conversion with double return type 1050 * @param num an int 1051 * @return the uint32 value as double 1052 */ 1053 public static double toUint32Double(final int num) { 1054 return (double) toUint32(num); 1055 } 1056 1057 /** 1058 * JavaScript compliant Object to uint16 conversion 1059 * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) 1060 * 1061 * @param obj an object 1062 * @return a uint16 1063 */ 1064 public static int toUint16(final Object obj) { 1065 return toUint16(toNumber(obj)); 1066 } 1067 1068 /** 1069 * JavaScript compliant number to uint16 conversion 1070 * 1071 * @param num a number 1072 * @return a uint16 1073 */ 1074 public static int toUint16(final int num) { 1075 return num & 0xffff; 1076 } 1077 1361 private static Object throwUnwarrantedOptimismException(final Object value, final int programPoint) { 1362 throw new UnwarrantedOptimismException(value, programPoint); 1363 } 1364 1365 /** 1366 * Wrapper for addExact 1367 * 1368 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1369 * containing the result and the program point of the failure 1370 * 1371 * @param x first term 1372 * @param y second term 1373 * @param programPoint program point id 1374 * @return the result 1375 * @throws UnwarrantedOptimismException if overflow occurs 1376 */ 1377 public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1378 try { 1379 return Math.addExact(x, y); 1380 } catch (final ArithmeticException e) { 1381 throw new UnwarrantedOptimismException((double)x + (double)y, programPoint); 1382 } 1383 } 1384 1385 /** 1386 * Wrapper for subExact 1387 * 1388 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1389 * containing the result and the program point of the failure 1390 * 1391 * @param x first term 1392 * @param y second term 1393 * @param programPoint program point id 1394 * @return the result 1395 * @throws UnwarrantedOptimismException if overflow occurs 1396 */ 1397 public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1398 try { 1399 return Math.subtractExact(x, y); 1400 } catch (final ArithmeticException e) { 1401 throw new UnwarrantedOptimismException((double)x - (double)y, programPoint); 1402 } 1403 } 1404 1405 /** 1406 * Wrapper for mulExact 1407 * 1408 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1409 * containing the result and the program point of the failure 1410 * 1411 * @param x first term 1412 * @param y second term 1413 * @param programPoint program point id 1414 * @return the result 1415 * @throws UnwarrantedOptimismException if overflow occurs 1416 */ 1417 public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1418 try { 1419 return Math.multiplyExact(x, y); 1420 } catch (final ArithmeticException e) { 1421 throw new UnwarrantedOptimismException((double)x * (double)y, programPoint); 1422 } 1423 } 1424 1425 /** 1426 * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as 1427 * int. 1428 * 1429 * @param x first term 1430 * @param y second term 1431 * @param programPoint program point id 1432 * @return the result 1433 * @throws UnwarrantedOptimismException if the result of the division can't be represented as int. 1434 */ 1435 public static int divExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1436 final int res; 1437 try { 1438 res = x / y; 1439 } catch (final ArithmeticException e) { 1440 assert y == 0; // Only div by zero anticipated 1472 1473 /** 1474 * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. 1475 * 1476 * @param x first term 1477 * @param y second term 1478 * @param programPoint program point id 1479 * @return the result 1480 * @throws UnwarrantedOptimismException if the modulo can't be represented as int. 1481 */ 1482 public static int remExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1483 try { 1484 return x % y; 1485 } catch (final ArithmeticException e) { 1486 assert y == 0; // Only mod by zero anticipated 1487 throw new UnwarrantedOptimismException(Double.NaN, programPoint); 1488 } 1489 } 1490 1491 /** 1492 * Wrapper for decrementExact 1493 * 1494 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1495 * containing the result and the program point of the failure 1496 * 1497 * @param x number to negate 1498 * @param programPoint program point id 1499 * @return the result 1500 * @throws UnwarrantedOptimismException if overflow occurs 1501 */ 1502 public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1503 try { 1504 return Math.decrementExact(x); 1505 } catch (final ArithmeticException e) { 1506 throw new UnwarrantedOptimismException((double)x - 1, programPoint); 1507 } 1508 } 1509 1510 /** 1511 * Wrapper for incrementExact 1512 * 1513 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1514 * containing the result and the program point of the failure 1515 * 1516 * @param x the number to increment 1517 * @param programPoint program point id 1518 * @return the result 1519 * @throws UnwarrantedOptimismException if overflow occurs 1520 */ 1521 public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1522 try { 1523 return Math.incrementExact(x); 1524 } catch (final ArithmeticException e) { 1525 throw new UnwarrantedOptimismException((double)x + 1, programPoint); 1526 } 1527 } 1528 1529 /** 1530 * Wrapper for negateExact 1531 * 1532 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1533 * containing the result and the program point of the failure 1534 * 1535 * @param x the number to negate 1536 * @param programPoint program point id 1537 * @return the result 1538 * @throws UnwarrantedOptimismException if overflow occurs 1539 */ 1540 public static int negateExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1541 try { 1542 if (x == 0) { 1543 throw new UnwarrantedOptimismException(-0.0, programPoint); 1544 } 1545 return Math.negateExact(x); 1546 } catch (final ArithmeticException e) { 1547 throw new UnwarrantedOptimismException(-(double)x, programPoint); 1548 } 1549 } 1550 1551 /** 1552 * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1553 * 1554 * @param type the type 1555 * 1556 * @return the accessor index, or -1 if no accessor of this type exists 1557 */ 1558 public static int getAccessorTypeIndex(final Type type) { 1559 return getAccessorTypeIndex(type.getTypeClass()); 1560 } 1561 1562 /** 1563 * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1564 * 1565 * Note that this is hardcoded with respect to the dynamic contents of the accessor 1566 * types array for speed. Hotspot got stuck with this as 5% of the runtime in 1567 * a benchmark when it looped over values and increased an index counter. :-( 1568 * 1569 * @param type the type 1570 * 1571 * @return the accessor index, or -1 if no accessor of this type exists 1572 */ 1573 public static int getAccessorTypeIndex(final Class<?> type) { 1574 if (type == null) { 1575 return TYPE_UNDEFINED_INDEX; 1576 } else if (type == int.class) { 1577 return TYPE_INT_INDEX; 1578 } else if (type == double.class) { 1579 return TYPE_DOUBLE_INDEX; 1580 } else if (!type.isPrimitive()) { 1581 return TYPE_OBJECT_INDEX; 1582 } 1583 return -1; 1584 } 1585 1586 /** 1587 * Return the accessor type based on its index in [0..getNumberOfAccessorTypes()) 1588 * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always 1589 * go to a type of higher index 1590 * 1591 * @param index accessor type index 1592 * 1593 * @return a type corresponding to the index. 1594 */ 1595 1596 public static Type getAccessorType(final int index) { 1597 return ACCESSOR_TYPES.get(index); 1658 } 1659 1660 private static Object invoke(final MethodHandle mh, final Object arg) { 1661 try { 1662 return mh.invoke(arg); 1663 } catch (final RuntimeException | Error e) { 1664 throw e; 1665 } catch (final Throwable t) { 1666 throw new RuntimeException(t); 1667 } 1668 } 1669 1670 /** 1671 * Returns the boxed version of a primitive class 1672 * @param clazz the class 1673 * @return the boxed type of clazz, or unchanged if not primitive 1674 */ 1675 public static Class<?> getBoxedClass(final Class<?> clazz) { 1676 if (clazz == int.class) { 1677 return Integer.class; 1678 } else if (clazz == double.class) { 1679 return Double.class; 1680 } 1681 assert !clazz.isPrimitive(); 1682 return clazz; 1683 } 1684 1685 /** 1686 * Create a method handle constant of the correct primitive type 1687 * for a constant object 1688 * @param o object 1689 * @return constant function that returns object 1690 */ 1691 public static MethodHandle unboxConstant(final Object o) { 1692 if (o != null) { 1693 if (o.getClass() == Integer.class) { 1694 return MH.constant(int.class, ((Integer)o).intValue()); 1695 } else if (o.getClass() == Double.class) { 1696 return MH.constant(double.class, ((Double)o).doubleValue()); 1697 } 1698 } 1699 return MH.constant(Object.class, o); 1700 } 1701 1702 /** 1703 * Get the unboxed (primitive) type for an object 1704 * @param o object 1705 * @return primitive type or Object.class if not primitive 1706 */ 1707 public static Class<?> unboxedFieldType(final Object o) { 1708 if (o == null) { 1709 return Object.class; 1710 } else if (o.getClass() == Integer.class) { 1711 return int.class; 1712 } else if (o.getClass() == Double.class) { 1713 return double.class; 1714 } else { 1715 return Object.class; 1716 } 1717 } 1718 1719 private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) { 1720 return Collections.unmodifiableList(Arrays.asList(methodHandles)); 1721 } 1722 } |