1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.runtime; 27 28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; 29 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; 30 import static jdk.nashorn.internal.lookup.Lookup.MH; 31 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 32 import java.lang.invoke.MethodHandle; 33 import java.lang.invoke.MethodHandles; 34 import java.lang.reflect.Array; 35 import java.util.Arrays; 36 import java.util.Collections; 37 import java.util.Deque; 38 import java.util.List; 39 import jdk.internal.dynalink.beans.StaticClass; 40 import jdk.nashorn.api.scripting.JSObject; 41 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 42 import jdk.nashorn.internal.codegen.types.Type; 43 import jdk.nashorn.internal.objects.Global; 44 import jdk.nashorn.internal.parser.Lexer; 45 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 46 import jdk.nashorn.internal.runtime.linker.Bootstrap; 47 48 /** 49 * Representation for ECMAScript types - this maps directly to the ECMA script standard 50 */ 51 public enum JSType { 52 /** The undefined type */ 53 UNDEFINED("undefined"), 54 55 /** The null type */ 56 NULL("object"), 57 58 /** The boolean type */ 59 BOOLEAN("boolean"), 60 61 /** The number type */ 62 NUMBER("number"), 63 64 /** The string type */ 65 STRING("string"), 66 67 /** The object type */ 68 OBJECT("object"), 69 70 /** The function type */ 71 FUNCTION("function"); 72 73 /** The type name as returned by ECMAScript "typeof" operator*/ 74 private final String typeName; 75 76 /** Max value for an uint32 in JavaScript */ 77 public static final long MAX_UINT = 0xFFFF_FFFFL; 78 79 private static final MethodHandles.Lookup JSTYPE_LOOKUP = MethodHandles.lookup(); 80 81 /** JavaScript compliant conversion function from Object to boolean */ 82 public static final Call TO_BOOLEAN = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, Object.class); 83 84 /** JavaScript compliant conversion function from number to boolean */ 85 public static final Call TO_BOOLEAN_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, double.class); 86 87 /** JavaScript compliant conversion function from Object to integer */ 88 public static final Call TO_INTEGER = staticCall(JSTYPE_LOOKUP, JSType.class, "toInteger", int.class, Object.class); 89 90 /** JavaScript compliant conversion function from Object to long */ 91 public static final Call TO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, Object.class); 92 93 /** JavaScript compliant conversion function from double to long */ 94 public static final Call TO_LONG_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, double.class); 95 96 /** JavaScript compliant conversion function from Object to number */ 97 public static final Call TO_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumber", double.class, Object.class); 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); 146 147 /** Multiply exact wrapper for potentially overflowing integer operations */ 148 public static final Call MUL_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", int.class, int.class, int.class, int.class); 149 150 /** Div exact wrapper for potentially integer division that turns into float point */ 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 to convert a JS Object to a Java List. */ 205 public static final Call TO_JAVA_LIST = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaList", List.class, Object.class); 206 207 /** Method handle to convert a JS Object to a Java deque. */ 208 public static final Call TO_JAVA_DEQUE = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaDeque", Deque.class, Object.class); 209 210 /** Method handle for void returns. */ 211 public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class); 212 213 214 /** 215 * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide 216 * in the dual--fields world 217 */ 218 private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList( 219 Arrays.asList( 220 Type.INT, 221 Type.LONG, 222 Type.NUMBER, 223 Type.OBJECT)); 224 225 /** table index for undefined type - hard coded so it can be used in switches at compile time */ 226 public static final int TYPE_UNDEFINED_INDEX = -1; 227 /** table index for integer type - hard coded so it can be used in switches at compile time */ 228 public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); 229 /** table index for long type - hard coded so it can be used in switches at compile time */ 230 public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); 231 /** table index for double type - hard coded so it can be used in switches at compile time */ 232 public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); 233 /** table index for object type - hard coded so it can be used in switches at compile time */ 234 public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); 235 236 /** object conversion quickies with JS semantics - used for return value and parameter filter */ 237 public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList( 238 JSType.TO_INT32.methodHandle(), 239 JSType.TO_UINT32.methodHandle(), 240 JSType.TO_NUMBER.methodHandle(), 241 null 242 ); 243 244 /** 245 * object conversion quickies with JS semantics - used for return value and parameter filter, optimistic 246 * throws exception upon incompatible type (asking for a narrower one than the storage) 247 */ 248 public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList( 249 JSType.TO_INT32_OPTIMISTIC.methodHandle(), 250 JSType.TO_LONG_OPTIMISTIC.methodHandle(), 251 JSType.TO_NUMBER_OPTIMISTIC.methodHandle(), 252 null 253 ); 254 255 /** The value of Undefined cast to an int32 */ 256 public static final int UNDEFINED_INT = 0; 257 /** The value of Undefined cast to a long */ 258 public static final long UNDEFINED_LONG = 0L; 259 /** The value of Undefined cast to a double */ 260 public static final double UNDEFINED_DOUBLE = Double.NaN; 261 262 /** 263 * Method handles for getters that return undefined coerced 264 * to the appropriate type 265 */ 266 public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList( 267 MH.constant(int.class, UNDEFINED_INT), 268 MH.constant(long.class, UNDEFINED_LONG), 269 MH.constant(double.class, UNDEFINED_DOUBLE), 270 MH.constant(Object.class, Undefined.getUndefined()) 271 ); 272 273 private static final double INT32_LIMIT = 4294967296.0; 274 275 /** 276 * Constructor 277 * 278 * @param typeName the type name 279 */ 280 private JSType(final String typeName) { 281 this.typeName = typeName; 282 } 283 284 /** 285 * The external type name as returned by ECMAScript "typeof" operator 286 * 287 * @return type name for this type 288 */ 289 public final String typeName() { 290 return this.typeName; 291 } 292 293 /** 294 * Return the JSType for a given object 295 * 296 * @param obj an object 297 * 298 * @return the JSType for the object 299 */ 300 public static JSType of(final Object obj) { 301 // Order of these statements is tuned for performance (see JDK-8024476) 302 if (obj == null) { 303 return JSType.NULL; 304 } 305 306 if (obj instanceof ScriptObject) { 307 return obj instanceof ScriptFunction ? JSType.FUNCTION : JSType.OBJECT; 308 } 309 310 if (obj instanceof Boolean) { 311 return JSType.BOOLEAN; 312 } 313 314 if (obj instanceof String || obj instanceof ConsString) { 315 return JSType.STRING; 316 } 317 318 if (obj instanceof Number) { 319 return JSType.NUMBER; 320 } 321 322 if (obj == ScriptRuntime.UNDEFINED) { 323 return JSType.UNDEFINED; 324 } 325 326 return Bootstrap.isCallable(obj) ? JSType.FUNCTION : JSType.OBJECT; 327 } 328 329 /** 330 * Similar to {@link #of(Object)}, but does not distinguish between {@link #FUNCTION} and {@link #OBJECT}, returning 331 * {@link #OBJECT} in both cases. The distinction is costly, and the EQ and STRICT_EQ predicates don't care about it 332 * so we maintain this version for their use. 333 * 334 * @param obj an object 335 * 336 * @return the JSType for the object; returns {@link #OBJECT} instead of {@link #FUNCTION} for functions. 337 */ 338 public static JSType ofNoFunction(final Object obj) { 339 // Order of these statements is tuned for performance (see JDK-8024476) 340 if (obj == null) { 341 return JSType.NULL; 342 } 343 344 if (obj instanceof ScriptObject) { 345 return JSType.OBJECT; 346 } 347 348 if (obj instanceof Boolean) { 349 return JSType.BOOLEAN; 350 } 351 352 if (obj instanceof String || obj instanceof ConsString) { 353 return JSType.STRING; 354 } 355 356 if (obj instanceof Number) { 357 return JSType.NUMBER; 358 } 359 360 if (obj == ScriptRuntime.UNDEFINED) { 361 return JSType.UNDEFINED; 362 } 363 364 return JSType.OBJECT; 365 } 366 367 /** 368 * Void return method handle glue 369 */ 370 public static void voidReturn() { 371 //empty 372 //TODO: fix up SetMethodCreator better so we don't need this stupid thing 373 } 374 375 /** 376 * Returns true if double number can be represented as an int 377 * 378 * @param number a long to inspect 379 * 380 * @return true for int representable longs 381 */ 382 public static boolean isRepresentableAsInt(final long number) { 383 return (int)number == number; 384 } 385 386 /** 387 * Returns true if double number can be represented as an int. Note that it returns true for negative zero. If you 388 * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}. 389 * 390 * @param number a double to inspect 391 * 392 * @return true for int representable doubles 393 */ 394 public static boolean isRepresentableAsInt(final double number) { 395 return (int)number == number; 396 } 397 398 /** 399 * Returns true if Object can be represented as an int 400 * 401 * @param obj an object to inspect 402 * 403 * @return true for int representable objects 404 */ 405 public static boolean isRepresentableAsInt(final Object obj) { 406 if (obj instanceof Number) { 407 return isRepresentableAsInt(((Number)obj).doubleValue()); 408 } 409 return false; 410 } 411 412 /** 413 * Returns true if double number can be represented as a long. Note that it returns true for negative zero. If you 414 * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}. 415 * 416 * @param number a double to inspect 417 * @return true for long representable doubles 418 */ 419 public static boolean isRepresentableAsLong(final double number) { 420 return (long)number == number; 421 } 422 423 /** 424 * Returns true if Object can be represented as a long 425 * 426 * @param obj an object to inspect 427 * 428 * @return true for long representable objects 429 */ 430 public static boolean isRepresentableAsLong(final Object obj) { 431 if (obj instanceof Number) { 432 return isRepresentableAsLong(((Number)obj).doubleValue()); 433 } 434 return false; 435 } 436 437 /** 438 * Returns true if the number is the negative zero ({@code -0.0d}). 439 * @param number the number to test 440 * @return true if it is the negative zero, false otherwise. 441 */ 442 public static boolean isNegativeZero(final double number) { 443 return number == 0.0d && Double.doubleToRawLongBits(number) == 0x8000000000000000L; 444 } 445 446 /** 447 * Check whether an object is primitive 448 * 449 * @param obj an object 450 * 451 * @return true if object is primitive (includes null and undefined) 452 */ 453 public static boolean isPrimitive(final Object obj) { 454 return obj == null || 455 obj == ScriptRuntime.UNDEFINED || 456 obj instanceof Boolean || 457 obj instanceof Number || 458 obj instanceof String || 459 obj instanceof ConsString; 460 } 461 462 /** 463 * Primitive converter for an object 464 * 465 * @param obj an object 466 * 467 * @return primitive form of the object 468 */ 469 public static Object toPrimitive(final Object obj) { 470 return toPrimitive(obj, null); 471 } 472 473 /** 474 * Primitive converter for an object including type hint 475 * See ECMA 9.1 ToPrimitive 476 * 477 * @param obj an object 478 * @param hint a type hint 479 * 480 * @return the primitive form of the object 481 */ 482 public static Object toPrimitive(final Object obj, final Class<?> hint) { 483 return obj instanceof ScriptObject ? toPrimitive((ScriptObject)obj, hint) : obj; 484 } 485 486 private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) { 487 final Object result = sobj.getDefaultValue(hint); 488 489 if (!isPrimitive(result)) { 490 throw typeError("bad.default.value", result.toString()); 491 } 492 493 return result; 494 } 495 496 /** 497 * Combines a hintless toPrimitive and a toString call. 498 * 499 * @param obj an object 500 * 501 * @return the string form of the primitive form of the object 502 */ 503 public static String toPrimitiveToString(final Object obj) { 504 return toString(toPrimitive(obj)); 505 } 506 507 /** 508 * Like {@link #toPrimitiveToString(Object)}, but avoids conversion of ConsString to String. 509 * 510 * @param obj an object 511 * @return the CharSequence form of the primitive form of the object 512 */ 513 public static CharSequence toPrimitiveToCharSequence(final Object obj) { 514 return toCharSequence(toPrimitive(obj)); 515 } 516 517 /** 518 * JavaScript compliant conversion of number to boolean 519 * 520 * @param num a number 521 * 522 * @return a boolean 523 */ 524 public static boolean toBoolean(final double num) { 525 return num != 0 && !Double.isNaN(num); 526 } 527 528 /** 529 * JavaScript compliant conversion of Object to boolean 530 * See ECMA 9.2 ToBoolean 531 * 532 * @param obj an object 533 * 534 * @return a boolean 535 */ 536 public static boolean toBoolean(final Object obj) { 537 if (obj instanceof Boolean) { 538 return (Boolean)obj; 539 } 540 541 if (nullOrUndefined(obj)) { 542 return false; 543 } 544 545 if (obj instanceof Number) { 546 final double num = ((Number)obj).doubleValue(); 547 return num != 0 && !Double.isNaN(num); 548 } 549 550 if (obj instanceof String || obj instanceof ConsString) { 551 return ((CharSequence)obj).length() > 0; 552 } 553 554 return true; 555 } 556 557 558 /** 559 * JavaScript compliant converter of Object to String 560 * See ECMA 9.8 ToString 561 * 562 * @param obj an object 563 * 564 * @return a string 565 */ 566 public static String toString(final Object obj) { 567 return toStringImpl(obj, false); 568 } 569 570 /** 571 * If obj is an instance of {@link ConsString} cast to CharSequence, else return 572 * result of {@link #toString(Object)}. 573 * 574 * @param obj an object 575 * @return an instance of String or ConsString 576 */ 577 public static CharSequence toCharSequence(final Object obj) { 578 if (obj instanceof ConsString) { 579 return (CharSequence) obj; 580 } 581 return toString(obj); 582 } 583 584 /** 585 * Check whether a string is representable as a JavaScript number 586 * 587 * @param str a string 588 * 589 * @return true if string can be represented as a number 590 */ 591 public static boolean isNumber(final String str) { 592 try { 593 Double.parseDouble(str); 594 return true; 595 } catch (final NumberFormatException e) { 596 return false; 597 } 598 } 599 600 /** 601 * JavaScript compliant conversion of integer to String 602 * 603 * @param num an integer 604 * 605 * @return a string 606 */ 607 public static String toString(final int num) { 608 return Integer.toString(num); 609 } 610 611 /** 612 * JavaScript compliant conversion of number to String 613 * See ECMA 9.8.1 614 * 615 * @param num a number 616 * 617 * @return a string 618 */ 619 public static String toString(final double num) { 620 if (isRepresentableAsInt(num)) { 621 return Integer.toString((int)num); 622 } 623 624 if (num == Double.POSITIVE_INFINITY) { 625 return "Infinity"; 626 } 627 628 if (num == Double.NEGATIVE_INFINITY) { 629 return "-Infinity"; 630 } 631 632 if (Double.isNaN(num)) { 633 return "NaN"; 634 } 635 636 return NumberToString.stringFor(num); 637 } 638 639 /** 640 * JavaScript compliant conversion of number to String 641 * 642 * @param num a number 643 * @param radix a radix for the conversion 644 * 645 * @return a string 646 */ 647 public static String toString(final double num, final int radix) { 648 assert radix >= 2 && radix <= 36 : "invalid radix"; 649 650 if (isRepresentableAsInt(num)) { 651 return Integer.toString((int)num, radix); 652 } 653 654 if (num == Double.POSITIVE_INFINITY) { 655 return "Infinity"; 656 } 657 658 if (num == Double.NEGATIVE_INFINITY) { 659 return "-Infinity"; 660 } 661 662 if (Double.isNaN(num)) { 663 return "NaN"; 664 } 665 666 if (num == 0.0) { 667 return "0"; 668 } 669 670 final String chars = "0123456789abcdefghijklmnopqrstuvwxyz"; 671 final StringBuilder sb = new StringBuilder(); 672 673 final boolean negative = num < 0.0; 674 final double signedNum = negative ? -num : num; 675 676 double intPart = Math.floor(signedNum); 677 double decPart = signedNum - intPart; 678 679 // encode integer part from least significant digit, then reverse 680 do { 681 final double remainder = intPart % radix; 682 sb.append(chars.charAt((int) remainder)); 683 intPart -= remainder; 684 intPart /= radix; 685 } while (intPart >= 1.0); 686 687 if (negative) { 688 sb.append('-'); 689 } 690 sb.reverse(); 691 692 // encode decimal part 693 if (decPart > 0.0) { 694 final int dot = sb.length(); 695 sb.append('.'); 696 do { 697 decPart *= radix; 698 final double d = Math.floor(decPart); 699 sb.append(chars.charAt((int)d)); 700 decPart -= d; 701 } while (decPart > 0.0 && sb.length() - dot < 1100); 702 // somewhat arbitrarily use same limit as V8 703 } 704 705 return sb.toString(); 706 } 707 708 /** 709 * JavaScript compliant conversion of Object to number 710 * See ECMA 9.3 ToNumber 711 * 712 * @param obj an object 713 * 714 * @return a number 715 */ 716 public static double toNumber(final Object obj) { 717 if (obj instanceof Double) { 718 return (Double)obj; 719 } 720 if (obj instanceof Number) { 721 return ((Number)obj).doubleValue(); 722 } 723 return toNumberGeneric(obj); 724 } 725 726 727 /** 728 * JavaScript compliant conversion of Object to number 729 * See ECMA 9.3 ToNumber 730 * 731 * @param obj an object 732 * 733 * @return a number 734 */ 735 public static double toNumber(final ScriptObject obj) { 736 return toNumber(toPrimitive(obj, Number.class)); 737 } 738 739 /** 740 * Optimistic number conversion - throws UnwarrantedOptimismException if Object 741 * 742 * @param obj object to convert 743 * @param programPoint program point 744 * @return double 745 */ 746 public static double toNumberOptimistic(final Object obj, final int programPoint) { 747 if (obj != null) { 748 final Class<?> clz = obj.getClass(); 749 if (clz == Double.class || clz == Integer.class || clz == Long.class) { 750 return ((Number)obj).doubleValue(); 751 } 752 } 753 throw new UnwarrantedOptimismException(obj, programPoint); 754 } 755 756 /** 757 * Object to number conversion that delegates to either {@link #toNumber(Object)} or to 758 * {@link #toNumberOptimistic(Object, int)} depending on whether the program point is valid or not. 759 * @param obj the object to convert 760 * @param programPoint the program point; can be invalid. 761 * @return the value converted to a number 762 * @throws UnwarrantedOptimismException if the value can't be represented as a number and the program point is valid. 763 */ 764 public static double toNumberMaybeOptimistic(final Object obj, final int programPoint) { 765 return UnwarrantedOptimismException.isValid(programPoint) ? toNumberOptimistic(obj, programPoint) : toNumber(obj); 766 } 767 768 /** 769 * Digit representation for a character 770 * 771 * @param ch a character 772 * @param radix radix 773 * 774 * @return the digit for this character 775 */ 776 public static int digit(final char ch, final int radix) { 777 return digit(ch, radix, false); 778 } 779 780 /** 781 * Digit representation for a character 782 * 783 * @param ch a character 784 * @param radix radix 785 * @param onlyIsoLatin1 iso latin conversion only 786 * 787 * @return the digit for this character 788 */ 789 public static int digit(final char ch, final int radix, final boolean onlyIsoLatin1) { 790 final char maxInRadix = (char)('a' + (radix - 1) - 10); 791 final char c = Character.toLowerCase(ch); 792 793 if (c >= 'a' && c <= maxInRadix) { 794 return Character.digit(ch, radix); 795 } 796 797 if (Character.isDigit(ch)) { 798 if (!onlyIsoLatin1 || ch >= '0' && ch <= '9') { 799 return Character.digit(ch, radix); 800 } 801 } 802 803 return -1; 804 } 805 806 /** 807 * JavaScript compliant String to number conversion 808 * 809 * @param str a string 810 * 811 * @return a number 812 */ 813 public static double toNumber(final String str) { 814 int end = str.length(); 815 if (end == 0) { 816 return 0.0; // Empty string 817 } 818 819 int start = 0; 820 char f = str.charAt(0); 821 822 while (Lexer.isJSWhitespace(f)) { 823 if (++start == end) { 824 return 0.0d; // All whitespace string 825 } 826 f = str.charAt(start); 827 } 828 829 // Guaranteed to terminate even without start >= end check, as the previous loop found at least one 830 // non-whitespace character. 831 while (Lexer.isJSWhitespace(str.charAt(end - 1))) { 832 end--; 833 } 834 835 final boolean negative; 836 if (f == '-') { 837 if(++start == end) { 838 return Double.NaN; // Single-char "-" string 839 } 840 f = str.charAt(start); 841 negative = true; 842 } else { 843 if (f == '+') { 844 if (++start == end) { 845 return Double.NaN; // Single-char "+" string 846 } 847 f = str.charAt(start); 848 } 849 negative = false; 850 } 851 852 final double value; 853 if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') { 854 //decode hex string 855 value = parseRadix(str.toCharArray(), start + 2, end, 16); 856 } else { 857 // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or 858 // "N" to allow for parsing "NaN" and "Infinity" correctly. 859 if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') { 860 return Double.NaN; 861 } 862 try { 863 value = Double.parseDouble(str.substring(start, end)); 864 } catch (final NumberFormatException e) { 865 return Double.NaN; 866 } 867 } 868 869 return negative ? -value : value; 870 } 871 872 /** 873 * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger 874 * 875 * <p>Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE} 876 * for double values that exceed the int range, including positive and negative Infinity. It is the 877 * caller's responsibility to handle such values correctly.</p> 878 * 879 * @param obj an object 880 * @return an integer 881 */ 882 public static int toInteger(final Object obj) { 883 return (int)toNumber(obj); 884 } 885 886 /** 887 * Converts an Object to long. 888 * 889 * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE} 890 * for double values that exceed the long range, including positive and negative Infinity. It is the 891 * caller's responsibility to handle such values correctly.</p> 892 * 893 * @param obj an object 894 * @return a long 895 */ 896 public static long toLong(final Object obj) { 897 return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj)); 898 } 899 900 /** 901 * Converts a double to long. 902 * 903 * @param num the double to convert 904 * @return the converted long value 905 */ 906 public static long toLong(final double num) { 907 return (long)num; 908 } 909 910 /** 911 * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object 912 * 913 * @param obj object to convert 914 * @param programPoint program point 915 * @return long 916 */ 917 public static long toLongOptimistic(final Object obj, final int programPoint) { 918 if (obj != null) { 919 final Class<?> clz = obj.getClass(); 920 if (clz == Long.class || clz == Integer.class) { 921 return ((Number)obj).longValue(); 922 } 923 } 924 throw new UnwarrantedOptimismException(obj, programPoint); 925 } 926 927 /** 928 * Object to int conversion that delegates to either {@link #toLong(Object)} or to 929 * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not. 930 * @param obj the object to convert 931 * @param programPoint the program point; can be invalid. 932 * @return the value converted to long 933 * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid. 934 */ 935 public static long toLongMaybeOptimistic(final Object obj, final int programPoint) { 936 return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj); 937 } 938 939 /** 940 * JavaScript compliant Object to int32 conversion 941 * See ECMA 9.5 ToInt32 942 * 943 * @param obj an object 944 * @return an int32 945 */ 946 public static int toInt32(final Object obj) { 947 return toInt32(toNumber(obj)); 948 } 949 950 /** 951 * Optimistic int conversion - throws UnwarrantedOptimismException if double, long or Object 952 * 953 * @param obj object to convert 954 * @param programPoint program point 955 * @return double 956 */ 957 public static int toInt32Optimistic(final Object obj, final int programPoint) { 958 if (obj != null && obj.getClass() == Integer.class) { 959 return ((Integer)obj).intValue(); 960 } 961 throw new UnwarrantedOptimismException(obj, programPoint); 962 } 963 964 /** 965 * Object to int conversion that delegates to either {@link #toInt32(Object)} or to 966 * {@link #toInt32Optimistic(Object, int)} depending on whether the program point is valid or not. 967 * @param obj the object to convert 968 * @param programPoint the program point; can be invalid. 969 * @return the value converted to int 970 * @throws UnwarrantedOptimismException if the value can't be represented as int and the program point is valid. 971 */ 972 public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) { 973 return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj); 974 } 975 976 // Minimum and maximum range between which every long value can be precisely represented as a double. 977 private static final long MAX_PRECISE_DOUBLE = 1L << 53; 978 private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE; 979 980 /** 981 * JavaScript compliant long to int32 conversion 982 * 983 * @param num a long 984 * @return an int32 985 */ 986 public static int toInt32(final long num) { 987 return (int)(num >= MIN_PRECISE_DOUBLE && num <= MAX_PRECISE_DOUBLE ? num : (long)(num % INT32_LIMIT)); 988 } 989 990 991 /** 992 * JavaScript compliant number to int32 conversion 993 * 994 * @param num a number 995 * @return an int32 996 */ 997 public static int toInt32(final double num) { 998 return (int)doubleToInt32(num); 999 } 1000 1001 /** 1002 * JavaScript compliant Object to uint32 conversion 1003 * 1004 * @param obj an object 1005 * @return a uint32 1006 */ 1007 public static long toUint32(final Object obj) { 1008 return toUint32(toNumber(obj)); 1009 } 1010 1011 /** 1012 * JavaScript compliant number to uint32 conversion 1013 * 1014 * @param num a number 1015 * @return a uint32 1016 */ 1017 public static long toUint32(final double num) { 1018 return doubleToInt32(num) & MAX_UINT; 1019 } 1020 1021 /** 1022 * JavaScript compliant int to uint32 conversion 1023 * 1024 * @param num an int 1025 * @return a uint32 1026 */ 1027 public static long toUint32(final int num) { 1028 return num & MAX_UINT; 1029 } 1030 1031 /** 1032 * JavaScript compliant Object to uint16 conversion 1033 * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer) 1034 * 1035 * @param obj an object 1036 * @return a uint16 1037 */ 1038 public static int toUint16(final Object obj) { 1039 return toUint16(toNumber(obj)); 1040 } 1041 1042 /** 1043 * JavaScript compliant number to uint16 conversion 1044 * 1045 * @param num a number 1046 * @return a uint16 1047 */ 1048 public static int toUint16(final int num) { 1049 return num & 0xffff; 1050 } 1051 1052 /** 1053 * JavaScript compliant number to uint16 conversion 1054 * 1055 * @param num a number 1056 * @return a uint16 1057 */ 1058 public static int toUint16(final long num) { 1059 return (int)num & 0xffff; 1060 } 1061 1062 /** 1063 * JavaScript compliant number to uint16 conversion 1064 * 1065 * @param num a number 1066 * @return a uint16 1067 */ 1068 public static int toUint16(final double num) { 1069 return (int)doubleToInt32(num) & 0xffff; 1070 } 1071 1072 private static long doubleToInt32(final double num) { 1073 final int exponent = Math.getExponent(num); 1074 if (exponent < 31) { 1075 return (long) num; // Fits into 32 bits 1076 } 1077 if (exponent >= 84) { 1078 // Either infinite or NaN or so large that shift / modulo will produce 0 1079 // (52 bit mantissa + 32 bit target width). 1080 return 0; 1081 } 1082 // This is rather slow and could probably be sped up using bit-fiddling. 1083 final double d = num >= 0 ? Math.floor(num) : Math.ceil(num); 1084 return (long)(d % INT32_LIMIT); 1085 } 1086 1087 /** 1088 * Check whether a number is finite 1089 * 1090 * @param num a number 1091 * @return true if finite 1092 */ 1093 public static boolean isFinite(final double num) { 1094 return !Double.isInfinite(num) && !Double.isNaN(num); 1095 } 1096 1097 /** 1098 * Convert a primitive to a double 1099 * 1100 * @param num a double 1101 * @return a boxed double 1102 */ 1103 public static Double toDouble(final double num) { 1104 return num; 1105 } 1106 1107 /** 1108 * Convert a primitive to a double 1109 * 1110 * @param num a long 1111 * @return a boxed double 1112 */ 1113 public static Double toDouble(final long num) { 1114 return (double)num; 1115 } 1116 1117 /** 1118 * Convert a primitive to a double 1119 * 1120 * @param num an int 1121 * @return a boxed double 1122 */ 1123 public static Double toDouble(final int num) { 1124 return (double)num; 1125 } 1126 1127 /** 1128 * Convert a boolean to an Object 1129 * 1130 * @param bool a boolean 1131 * @return a boxed boolean, its Object representation 1132 */ 1133 public static Object toObject(final boolean bool) { 1134 return bool; 1135 } 1136 1137 /** 1138 * Convert a number to an Object 1139 * 1140 * @param num an integer 1141 * @return the boxed number 1142 */ 1143 public static Object toObject(final int num) { 1144 return num; 1145 } 1146 1147 /** 1148 * Convert a number to an Object 1149 * 1150 * @param num a long 1151 * @return the boxed number 1152 */ 1153 public static Object toObject(final long num) { 1154 return num; 1155 } 1156 1157 /** 1158 * Convert a number to an Object 1159 * 1160 * @param num a double 1161 * @return the boxed number 1162 */ 1163 public static Object toObject(final double num) { 1164 return num; 1165 } 1166 1167 /** 1168 * Identity converter for objects. 1169 * 1170 * @param obj an object 1171 * @return the boxed number 1172 */ 1173 public static Object toObject(final Object obj) { 1174 return obj; 1175 } 1176 1177 /** 1178 * Object conversion. This is used to convert objects and numbers to their corresponding 1179 * NativeObject type 1180 * See ECMA 9.9 ToObject 1181 * 1182 * @param obj the object to convert 1183 * 1184 * @return the wrapped object 1185 */ 1186 public static Object toScriptObject(final Object obj) { 1187 return toScriptObject(Context.getGlobal(), obj); 1188 } 1189 1190 /** 1191 * Object conversion. This is used to convert objects and numbers to their corresponding 1192 * NativeObject type 1193 * See ECMA 9.9 ToObject 1194 * 1195 * @param global the global object 1196 * @param obj the object to convert 1197 * 1198 * @return the wrapped object 1199 */ 1200 public static Object toScriptObject(final Global global, final Object obj) { 1201 if (nullOrUndefined(obj)) { 1202 throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj)); 1203 } 1204 1205 if (obj instanceof ScriptObject) { 1206 return obj; 1207 } 1208 1209 return global.wrapAsObject(obj); 1210 } 1211 1212 /** 1213 * Script object to Java array conversion. 1214 * 1215 * @param obj script object to be converted to Java array 1216 * @param componentType component type of the destination array required 1217 * @return converted Java array 1218 */ 1219 public static Object toJavaArray(final Object obj, final Class<?> componentType) { 1220 if (obj instanceof ScriptObject) { 1221 return ((ScriptObject)obj).getArray().asArrayOfType(componentType); 1222 } else if (obj instanceof JSObject) { 1223 final ArrayLikeIterator<?> itr = ArrayLikeIterator.arrayLikeIterator(obj); 1224 final int len = (int) itr.getLength(); 1225 final Object[] res = new Object[len]; 1226 int idx = 0; 1227 while (itr.hasNext()) { 1228 res[idx++] = itr.next(); 1229 } 1230 return convertArray(res, componentType); 1231 } else if(obj == null) { 1232 return null; 1233 } else { 1234 throw new IllegalArgumentException("not a script object"); 1235 } 1236 } 1237 1238 /** 1239 * Java array to java array conversion - but using type conversions implemented by linker. 1240 * 1241 * @param src source array 1242 * @param componentType component type of the destination array required 1243 * @return converted Java array 1244 */ 1245 public static Object convertArray(final Object[] src, final Class<?> componentType) { 1246 if(componentType == Object.class) { 1247 for(int i = 0; i < src.length; ++i) { 1248 final Object e = src[i]; 1249 if(e instanceof ConsString) { 1250 src[i] = e.toString(); 1251 } 1252 } 1253 } 1254 1255 final int l = src.length; 1256 final Object dst = Array.newInstance(componentType, l); 1257 final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType); 1258 try { 1259 for (int i = 0; i < src.length; i++) { 1260 Array.set(dst, i, invoke(converter, src[i])); 1261 } 1262 } catch (final RuntimeException | Error e) { 1263 throw e; 1264 } catch (final Throwable t) { 1265 throw new RuntimeException(t); 1266 } 1267 return dst; 1268 } 1269 1270 /** 1271 * Converts a JavaScript object to a Java List. See {@link ListAdapter} for details. 1272 * @param obj the object to convert. Can be any array-like object. 1273 * @return a List that is live-backed by the JavaScript object. 1274 */ 1275 public static List<?> toJavaList(final Object obj) { 1276 return ListAdapter.create(obj); 1277 } 1278 1279 /** 1280 * Converts a JavaScript object to a Java Deque. See {@link ListAdapter} for details. 1281 * @param obj the object to convert. Can be any array-like object. 1282 * @return a Deque that is live-backed by the JavaScript object. 1283 */ 1284 public static Deque<?> toJavaDeque(final Object obj) { 1285 return ListAdapter.create(obj); 1286 } 1287 1288 /** 1289 * Check if an object is null or undefined 1290 * 1291 * @param obj object to check 1292 * 1293 * @return true if null or undefined 1294 */ 1295 public static boolean nullOrUndefined(final Object obj) { 1296 return obj == null || obj == ScriptRuntime.UNDEFINED; 1297 } 1298 1299 static String toStringImpl(final Object obj, final boolean safe) { 1300 if (obj instanceof String) { 1301 return (String)obj; 1302 } 1303 1304 if (obj instanceof Number) { 1305 return toString(((Number)obj).doubleValue()); 1306 } 1307 1308 if (obj == ScriptRuntime.UNDEFINED) { 1309 return "undefined"; 1310 } 1311 1312 if (obj == null) { 1313 return "null"; 1314 } 1315 1316 if (obj instanceof ScriptObject) { 1317 if (safe) { 1318 final ScriptObject sobj = (ScriptObject)obj; 1319 final Global gobj = Context.getGlobal(); 1320 return gobj.isError(sobj) ? 1321 ECMAException.safeToString(sobj) : 1322 sobj.safeToString(); 1323 } 1324 1325 return toString(toPrimitive(obj, String.class)); 1326 } 1327 1328 if (obj instanceof StaticClass) { 1329 return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]"; 1330 } 1331 1332 return obj.toString(); 1333 } 1334 1335 // trim from left for JS whitespaces. 1336 static String trimLeft(final String str) { 1337 int start = 0; 1338 1339 while (start < str.length() && Lexer.isJSWhitespace(str.charAt(start))) { 1340 start++; 1341 } 1342 1343 return str.substring(start); 1344 } 1345 1346 /** 1347 * Throw an unwarranted optimism exception for a program point 1348 * @param value real return value 1349 * @param programPoint program point 1350 * @return 1351 */ 1352 @SuppressWarnings("unused") 1353 private static Object throwUnwarrantedOptimismException(final Object value, final int programPoint) { 1354 throw new UnwarrantedOptimismException(value, programPoint); 1355 } 1356 1357 /** 1358 * Wrapper for addExact 1359 * 1360 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1361 * containing the result and the program point of the failure 1362 * 1363 * @param x first term 1364 * @param y second term 1365 * @param programPoint program point id 1366 * @return the result 1367 * @throws UnwarrantedOptimismException if overflow occurs 1368 */ 1369 public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1370 try { 1371 return Math.addExact(x, y); 1372 } catch (final ArithmeticException e) { 1373 throw new UnwarrantedOptimismException((long)x + (long)y, programPoint); 1374 } 1375 } 1376 1377 /** 1378 * Wrapper for addExact 1379 * 1380 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1381 * containing the result and the program point of the failure 1382 * 1383 * @param x first term 1384 * @param y second term 1385 * @param programPoint program point id 1386 * @return the result 1387 * @throws UnwarrantedOptimismException if overflow occurs 1388 */ 1389 public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1390 try { 1391 return Math.addExact(x, y); 1392 } catch (final ArithmeticException e) { 1393 throw new UnwarrantedOptimismException((double)x + (double)y, programPoint); 1394 } 1395 } 1396 1397 /** 1398 * Wrapper for subExact 1399 * 1400 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1401 * containing the result and the program point of the failure 1402 * 1403 * @param x first term 1404 * @param y second term 1405 * @param programPoint program point id 1406 * @return the result 1407 * @throws UnwarrantedOptimismException if overflow occurs 1408 */ 1409 public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1410 try { 1411 return Math.subtractExact(x, y); 1412 } catch (final ArithmeticException e) { 1413 throw new UnwarrantedOptimismException((long)x - (long)y, programPoint); 1414 } 1415 } 1416 1417 /** 1418 * Wrapper for subExact 1419 * 1420 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1421 * containing the result and the program point of the failure 1422 * 1423 * @param x first term 1424 * @param y second term 1425 * @param programPoint program point id 1426 * @return the result 1427 * @throws UnwarrantedOptimismException if overflow occurs 1428 */ 1429 public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1430 try { 1431 return Math.subtractExact(x, y); 1432 } catch (final ArithmeticException e) { 1433 throw new UnwarrantedOptimismException((double)x - (double)y, programPoint); 1434 } 1435 } 1436 1437 /** 1438 * Wrapper for mulExact 1439 * 1440 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1441 * containing the result and the program point of the failure 1442 * 1443 * @param x first term 1444 * @param y second term 1445 * @param programPoint program point id 1446 * @return the result 1447 * @throws UnwarrantedOptimismException if overflow occurs 1448 */ 1449 public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1450 try { 1451 return Math.multiplyExact(x, y); 1452 } catch (final ArithmeticException e) { 1453 throw new UnwarrantedOptimismException((long)x * (long)y, programPoint); 1454 } 1455 } 1456 1457 /** 1458 * Wrapper for mulExact 1459 * 1460 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1461 * containing the result and the program point of the failure 1462 * 1463 * @param x first term 1464 * @param y second term 1465 * @param programPoint program point id 1466 * @return the result 1467 * @throws UnwarrantedOptimismException if overflow occurs 1468 */ 1469 public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1470 try { 1471 return Math.multiplyExact(x, y); 1472 } catch (final ArithmeticException e) { 1473 throw new UnwarrantedOptimismException((double)x * (double)y, programPoint); 1474 } 1475 } 1476 1477 /** 1478 * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as 1479 * int. 1480 * 1481 * @param x first term 1482 * @param y second term 1483 * @param programPoint program point id 1484 * @return the result 1485 * @throws UnwarrantedOptimismException if the result of the division can't be represented as int. 1486 */ 1487 public static int divExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1488 final int res; 1489 try { 1490 res = x / y; 1491 } catch (final ArithmeticException e) { 1492 assert y == 0; // Only div by zero anticipated 1493 throw new UnwarrantedOptimismException(x > 0 ? Double.POSITIVE_INFINITY : x < 0 ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); 1494 } 1495 final int rem = x % y; 1496 if (rem == 0) { 1497 return res; 1498 } 1499 // go directly to double here, as anything with non zero remainder is a floating point number in JavaScript 1500 throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); 1501 } 1502 1503 /** 1504 * Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to 1505 * {@code (x / y)|0} JavaScript expression (division of two ints coerced to int). 1506 * @param x the dividend 1507 * @param y the divisor 1508 * @return the result 1509 */ 1510 public static int divZero(final int x, final int y) { 1511 return y == 0 ? 0 : x / y; 1512 } 1513 1514 /** 1515 * Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to 1516 * {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int). 1517 * @param x the dividend 1518 * @param y the divisor 1519 * @return the remainder 1520 */ 1521 public static int remZero(final int x, final int y) { 1522 return y == 0 ? 0 : x % y; 1523 } 1524 1525 /** 1526 * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. 1527 * 1528 * @param x first term 1529 * @param y second term 1530 * @param programPoint program point id 1531 * @return the result 1532 * @throws UnwarrantedOptimismException if the modulo can't be represented as int. 1533 */ 1534 public static int remExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException { 1535 try { 1536 return x % y; 1537 } catch (final ArithmeticException e) { 1538 assert y == 0; // Only mod by zero anticipated 1539 throw new UnwarrantedOptimismException(Double.NaN, programPoint); 1540 } 1541 } 1542 1543 /** 1544 * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as 1545 * long. 1546 * 1547 * @param x first term 1548 * @param y second term 1549 * @param programPoint program point id 1550 * @return the result 1551 * @throws UnwarrantedOptimismException if the result of the division can't be represented as long. 1552 */ 1553 public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1554 final long res; 1555 try { 1556 res = x / y; 1557 } catch (final ArithmeticException e) { 1558 assert y == 0L; // Only div by zero anticipated 1559 throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); 1560 } 1561 final long rem = x % y; 1562 if (rem == 0L) { 1563 return res; 1564 } 1565 throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); 1566 } 1567 1568 /** 1569 * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs 1570 * is coerced to long. 1571 * @param x the dividend 1572 * @param y the divisor 1573 * @return the result 1574 */ 1575 public static long divZero(final long x, final long y) { 1576 return y == 0L ? 0L : x / y; 1577 } 1578 1579 /** 1580 * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs 1581 * is coerced to long. 1582 * @param x the dividend 1583 * @param y the divisor 1584 * @return the remainder 1585 */ 1586 public static long remZero(final long x, final long y) { 1587 return y == 0L ? 0L : x % y; 1588 } 1589 1590 /** 1591 * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int. 1592 * 1593 * @param x first term 1594 * @param y second term 1595 * @param programPoint program point id 1596 * @return the result 1597 * @throws UnwarrantedOptimismException if the modulo can't be represented as int. 1598 */ 1599 public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException { 1600 try { 1601 return x % y; 1602 } catch (final ArithmeticException e) { 1603 assert y == 0L; // Only mod by zero anticipated 1604 throw new UnwarrantedOptimismException(Double.NaN, programPoint); 1605 } 1606 } 1607 1608 /** 1609 * Wrapper for decrementExact 1610 * 1611 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1612 * containing the result and the program point of the failure 1613 * 1614 * @param x number to negate 1615 * @param programPoint program point id 1616 * @return the result 1617 * @throws UnwarrantedOptimismException if overflow occurs 1618 */ 1619 public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1620 try { 1621 return Math.decrementExact(x); 1622 } catch (final ArithmeticException e) { 1623 throw new UnwarrantedOptimismException((long)x - 1, programPoint); 1624 } 1625 } 1626 1627 /** 1628 * Wrapper for decrementExact 1629 * 1630 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1631 * containing the result and the program point of the failure 1632 * 1633 * @param x number to negate 1634 * @param programPoint program point id 1635 * @return the result 1636 * @throws UnwarrantedOptimismException if overflow occurs 1637 */ 1638 public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1639 try { 1640 return Math.decrementExact(x); 1641 } catch (final ArithmeticException e) { 1642 throw new UnwarrantedOptimismException((double)x - 1L, programPoint); 1643 } 1644 } 1645 1646 /** 1647 * Wrapper for incrementExact 1648 * 1649 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1650 * containing the result and the program point of the failure 1651 * 1652 * @param x the number to increment 1653 * @param programPoint program point id 1654 * @return the result 1655 * @throws UnwarrantedOptimismException if overflow occurs 1656 */ 1657 public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1658 try { 1659 return Math.incrementExact(x); 1660 } catch (final ArithmeticException e) { 1661 throw new UnwarrantedOptimismException((long)x + 1, programPoint); 1662 } 1663 } 1664 1665 /** 1666 * Wrapper for incrementExact 1667 * 1668 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1669 * containing the result and the program point of the failure 1670 * 1671 * @param x the number to increment 1672 * @param programPoint program point id 1673 * @return the result 1674 * @throws UnwarrantedOptimismException if overflow occurs 1675 */ 1676 public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1677 try { 1678 return Math.incrementExact(x); 1679 } catch (final ArithmeticException e) { 1680 throw new UnwarrantedOptimismException((double)x + 1L, programPoint); 1681 } 1682 } 1683 1684 /** 1685 * Wrapper for negateExact 1686 * 1687 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1688 * containing the result and the program point of the failure 1689 * 1690 * @param x the number to negate 1691 * @param programPoint program point id 1692 * @return the result 1693 * @throws UnwarrantedOptimismException if overflow occurs 1694 */ 1695 public static int negateExact(final int x, final int programPoint) throws UnwarrantedOptimismException { 1696 try { 1697 if (x == 0) { 1698 throw new UnwarrantedOptimismException(-0.0, programPoint); 1699 } 1700 return Math.negateExact(x); 1701 } catch (final ArithmeticException e) { 1702 throw new UnwarrantedOptimismException(-(long)x, programPoint); 1703 } 1704 } 1705 1706 /** 1707 * Wrapper for negateExact 1708 * 1709 * Catches ArithmeticException and rethrows as UnwarrantedOptimismException 1710 * containing the result and the program point of the failure 1711 * 1712 * @param x the number to negate 1713 * @param programPoint program point id 1714 * @return the result 1715 * @throws UnwarrantedOptimismException if overflow occurs 1716 */ 1717 public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException { 1718 try { 1719 if (x == 0L) { 1720 throw new UnwarrantedOptimismException(-0.0, programPoint); 1721 } 1722 return Math.negateExact(x); 1723 } catch (final ArithmeticException e) { 1724 throw new UnwarrantedOptimismException(-(double)x, programPoint); 1725 } 1726 } 1727 1728 /** 1729 * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1730 * 1731 * @param type the type 1732 * 1733 * @return the accessor index, or -1 if no accessor of this type exists 1734 */ 1735 public static int getAccessorTypeIndex(final Type type) { 1736 return getAccessorTypeIndex(type.getTypeClass()); 1737 } 1738 1739 /** 1740 * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes()) 1741 * 1742 * Note that this is hardcoded with respect to the dynamic contents of the accessor 1743 * types array for speed. Hotspot got stuck with this as 5% of the runtime in 1744 * a benchmark when it looped over values and increased an index counter. :-( 1745 * 1746 * @param type the type 1747 * 1748 * @return the accessor index, or -1 if no accessor of this type exists 1749 */ 1750 public static int getAccessorTypeIndex(final Class<?> type) { 1751 if (type == null) { 1752 return TYPE_UNDEFINED_INDEX; 1753 } else if (type == int.class) { 1754 return TYPE_INT_INDEX; 1755 } else if (type == long.class) { 1756 return TYPE_LONG_INDEX; 1757 } else if (type == double.class) { 1758 return TYPE_DOUBLE_INDEX; 1759 } else if (!type.isPrimitive()) { 1760 return TYPE_OBJECT_INDEX; 1761 } 1762 return -1; 1763 } 1764 1765 /** 1766 * Return the accessor type based on its index in [0..getNumberOfAccessorTypes()) 1767 * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always 1768 * go to a type of higher index 1769 * 1770 * @param index accessor type index 1771 * 1772 * @return a type corresponding to the index. 1773 */ 1774 1775 public static Type getAccessorType(final int index) { 1776 return ACCESSOR_TYPES.get(index); 1777 } 1778 1779 /** 1780 * Return the number of accessor types available. 1781 * 1782 * @return number of accessor types in system 1783 */ 1784 public static int getNumberOfAccessorTypes() { 1785 return ACCESSOR_TYPES.size(); 1786 } 1787 1788 private static double parseRadix(final char chars[], final int start, final int length, final int radix) { 1789 int pos = 0; 1790 1791 for (int i = start; i < length ; i++) { 1792 if (digit(chars[i], radix) == -1) { 1793 return Double.NaN; 1794 } 1795 pos++; 1796 } 1797 1798 if (pos == 0) { 1799 return Double.NaN; 1800 } 1801 1802 double value = 0.0; 1803 for (int i = start; i < start + pos; i++) { 1804 value *= radix; 1805 value += digit(chars[i], radix); 1806 } 1807 1808 return value; 1809 } 1810 1811 private static double toNumberGeneric(final Object obj) { 1812 if (obj == null) { 1813 return +0.0; 1814 } 1815 1816 if (obj instanceof String) { 1817 return toNumber((String)obj); 1818 } 1819 1820 if (obj instanceof ConsString) { 1821 return toNumber(obj.toString()); 1822 } 1823 1824 if (obj instanceof Boolean) { 1825 return (Boolean)obj ? 1 : +0.0; 1826 } 1827 1828 if (obj instanceof ScriptObject) { 1829 return toNumber((ScriptObject)obj); 1830 } 1831 1832 if (obj instanceof JSObject) { 1833 return ((JSObject)obj).toNumber(); 1834 } 1835 1836 return Double.NaN; 1837 } 1838 1839 private static Object invoke(final MethodHandle mh, final Object arg) { 1840 try { 1841 return mh.invoke(arg); 1842 } catch (final RuntimeException | Error e) { 1843 throw e; 1844 } catch (final Throwable t) { 1845 throw new RuntimeException(t); 1846 } 1847 } 1848 1849 /** 1850 * Returns the boxed version of a primitive class 1851 * @param clazz the class 1852 * @return the boxed type of clazz, or unchanged if not primitive 1853 */ 1854 public static Class<?> getBoxedClass(final Class<?> clazz) { 1855 if (clazz == int.class) { 1856 return Integer.class; 1857 } else if (clazz == long.class) { 1858 return Long.class; 1859 } else if (clazz == double.class) { 1860 return Double.class; 1861 } 1862 assert !clazz.isPrimitive(); 1863 return clazz; 1864 } 1865 1866 /** 1867 * Create a method handle constant of the correct primitive type 1868 * for a constant object 1869 * @param o object 1870 * @return constant function that returns object 1871 */ 1872 public static MethodHandle unboxConstant(final Object o) { 1873 if (o != null) { 1874 if (o.getClass() == Integer.class) { 1875 return MH.constant(int.class, ((Integer)o).intValue()); 1876 } else if (o.getClass() == Long.class) { 1877 return MH.constant(long.class, ((Long)o).longValue()); 1878 } else if (o.getClass() == Double.class) { 1879 return MH.constant(double.class, ((Double)o).doubleValue()); 1880 } 1881 } 1882 return MH.constant(Object.class, o); 1883 } 1884 1885 /** 1886 * Get the unboxed (primitive) type for an object 1887 * @param o object 1888 * @return primive type or Object.class if not primitive 1889 */ 1890 public static Class<?> unboxedFieldType(final Object o) { 1891 if (OBJECT_FIELDS_ONLY) { 1892 return Object.class; 1893 } 1894 1895 if (o == null) { 1896 return Object.class; 1897 } else if (o.getClass() == Integer.class) { 1898 return int.class; 1899 } else if (o.getClass() == Long.class) { 1900 return long.class; 1901 } else if (o.getClass() == Double.class) { 1902 return double.class; 1903 } else { 1904 return Object.class; 1905 } 1906 } 1907 1908 private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) { 1909 return Collections.unmodifiableList(Arrays.asList(methodHandles)); 1910 } 1911 }