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.lookup.Lookup.MH; 30 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 31 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.List; 38 import jdk.internal.dynalink.beans.StaticClass; 39 import jdk.nashorn.api.scripting.JSObject; 40 import jdk.nashorn.internal.codegen.CompilerConstants.Call; 41 import jdk.nashorn.internal.codegen.types.Type; 42 import jdk.nashorn.internal.objects.Global; 43 import jdk.nashorn.internal.parser.Lexer; 44 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; 45 import jdk.nashorn.internal.runtime.doubleconv.DoubleConversion; 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 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 */ 282 public final String typeName() { 283 return this.typeName; 284 } 285 286 /** 287 * Return the JSType for a given object 288 * 289 * @param obj an object 290 * 291 * @return the JSType for the object 292 */ 293 public static JSType of(final Object obj) { 294 // Order of these statements is tuned for performance (see JDK-8024476) 295 if (obj == null) { 296 return JSType.NULL; 297 } 298 299 if (obj instanceof ScriptObject) { 300 return obj instanceof ScriptFunction ? JSType.FUNCTION : JSType.OBJECT; 301 } 302 303 if (obj instanceof Boolean) { 304 return JSType.BOOLEAN; 305 } 306 307 if (isString(obj)) { 308 return JSType.STRING; 309 } 310 311 if (obj instanceof Number) { 312 return JSType.NUMBER; 313 } 314 315 if (obj == ScriptRuntime.UNDEFINED) { 316 return JSType.UNDEFINED; 317 } 318 319 return Bootstrap.isCallable(obj) ? JSType.FUNCTION : JSType.OBJECT; 320 } 321 322 /** 323 * Similar to {@link #of(Object)}, but does not distinguish between {@link #FUNCTION} and {@link #OBJECT}, returning 324 * {@link #OBJECT} in both cases. The distinction is costly, and the EQ and STRICT_EQ predicates don't care about it 325 * so we maintain this version for their use. 326 * 327 * @param obj an object 328 * 329 * @return the JSType for the object; returns {@link #OBJECT} instead of {@link #FUNCTION} for functions. 330 */ 331 public static JSType ofNoFunction(final Object obj) { 332 // Order of these statements is tuned for performance (see JDK-8024476) 333 if (obj == null) { 334 return JSType.NULL; 335 } 336 337 if (obj instanceof ScriptObject) { 338 return JSType.OBJECT; 339 } 340 341 if (obj instanceof Boolean) { 342 return JSType.BOOLEAN; 343 } 344 345 if (isString(obj)) { 346 return JSType.STRING; 347 } 348 349 if (obj instanceof Number) { 350 return JSType.NUMBER; 351 } 352 353 if (obj == ScriptRuntime.UNDEFINED) { 354 return JSType.UNDEFINED; 355 } 356 357 return JSType.OBJECT; 358 } 359 360 /** 361 * Void return method handle glue 362 */ 363 public static void voidReturn() { 364 //empty 365 //TODO: fix up SetMethodCreator better so we don't need this stupid thing 366 } 367 368 /** 369 * Returns true if double number can be represented as an int 370 * 371 * @param number a long to inspect 372 * 373 * @return true for int representable longs 374 */ 375 public static boolean isRepresentableAsInt(final long number) { 376 return (int)number == number; 377 } 378 379 /** 380 * Returns true if double number can be represented as an int. Note that it returns true for negative 381 * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsInt(double)}. 382 * 383 * @param number a double to inspect 384 * 385 * @return true for int representable doubles 386 */ 387 public static boolean isRepresentableAsInt(final double number) { 388 return (int)number == number; 389 } 390 391 /** 392 * Returns true if double number can be represented as an int. Note that it returns false for negative 393 * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsInt(double)}. 394 * 395 * @param number a double to inspect 396 * 397 * @return true for int representable doubles 398 */ 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 || 472 obj == ScriptRuntime.UNDEFINED || 473 obj instanceof Boolean || 474 obj instanceof Number || 475 isString(obj); 476 } 477 478 /** 479 * Primitive converter for an object 480 * 481 * @param obj an object 482 * 483 * @return primitive form of the object 484 */ 485 public static Object toPrimitive(final Object obj) { 486 return toPrimitive(obj, null); 487 } 488 489 /** 490 * Primitive converter for an object including type hint 491 * See ECMA 9.1 ToPrimitive 492 * 493 * @param obj an object 494 * @param hint a type hint 495 * 496 * @return the primitive form of the object 497 */ 498 public static Object toPrimitive(final Object obj, final Class<?> hint) { 499 if (obj instanceof ScriptObject) { 500 return toPrimitive((ScriptObject)obj, hint); 501 } else if (isPrimitive(obj)) { 502 return obj; 503 } else if (obj instanceof JSObject) { 504 return toPrimitive((JSObject)obj, hint); 505 } else if (obj instanceof StaticClass) { 506 final String name = ((StaticClass)obj).getRepresentedClass().getName(); 507 return new StringBuilder(12 + name.length()).append("[JavaClass ").append(name).append(']').toString(); 508 } 509 return obj.toString(); 510 } 511 512 private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) { 513 return requirePrimitive(sobj.getDefaultValue(hint)); 514 } 515 516 private static Object requirePrimitive(final Object result) { 517 if (!isPrimitive(result)) { 518 throw typeError("bad.default.value", result.toString()); 519 } 520 return result; 521 } 522 523 /** 524 * Primitive converter for a {@link JSObject} including type hint. Invokes 525 * {@link JSObject#getDefaultValue(Class)} and translates any thrown {@link UnsupportedOperationException} 526 * to a ECMAScript {@code TypeError}. 527 * See ECMA 9.1 ToPrimitive 528 * 529 * @param jsobj a JSObject 530 * @param hint a type hint 531 * 532 * @return the primitive form of the JSObject 533 */ 534 public static Object toPrimitive(final JSObject jsobj, final Class<?> hint) { 535 try { 536 return requirePrimitive(jsobj.getDefaultValue(hint)); 537 } catch (final UnsupportedOperationException e) { 538 throw new ECMAException(Context.getGlobal().newTypeError(e.getMessage()), e); 539 } 540 } 541 542 /** 543 * Combines a hintless toPrimitive and a toString call. 544 * 545 * @param obj an object 546 * 547 * @return the string form of the primitive form of the object 548 */ 549 public static String toPrimitiveToString(final Object obj) { 550 return toString(toPrimitive(obj)); 551 } 552 553 /** 554 * Like {@link #toPrimitiveToString(Object)}, but avoids conversion of ConsString to String. 555 * 556 * @param obj an object 557 * @return the CharSequence form of the primitive form of the object 558 */ 559 public static CharSequence toPrimitiveToCharSequence(final Object obj) { 560 return toCharSequence(toPrimitive(obj)); 561 } 562 563 /** 564 * JavaScript compliant conversion of number to boolean 565 * 566 * @param num a number 567 * 568 * @return a boolean 569 */ 570 public static boolean toBoolean(final double num) { 571 return num != 0 && !Double.isNaN(num); 572 } 573 574 /** 575 * JavaScript compliant conversion of Object to boolean 576 * See ECMA 9.2 ToBoolean 577 * 578 * @param obj an object 579 * 580 * @return a boolean 581 */ 582 public static boolean toBoolean(final Object obj) { 583 if (obj instanceof Boolean) { 584 return (Boolean)obj; 585 } 586 587 if (nullOrUndefined(obj)) { 588 return false; 589 } 590 591 if (obj instanceof Number) { 592 final double num = ((Number)obj).doubleValue(); 593 return num != 0 && !Double.isNaN(num); 594 } 595 596 if (isString(obj)) { 597 return ((CharSequence)obj).length() > 0; 598 } 599 600 return true; 601 } 602 603 604 /** 605 * JavaScript compliant converter of Object to String 606 * See ECMA 9.8 ToString 607 * 608 * @param obj an object 609 * 610 * @return a string 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 /** 667 * JavaScript compliant conversion of number to String 668 * See ECMA 9.8.1 669 * 670 * @param num a number 671 * 672 * @return a string 673 */ 674 public static String toString(final double num) { 675 if (isRepresentableAsInt(num)) { 676 return Integer.toString((int)num); 677 } 678 679 if (num == Double.POSITIVE_INFINITY) { 680 return "Infinity"; 681 } 682 683 if (num == Double.NEGATIVE_INFINITY) { 684 return "-Infinity"; 685 } 686 687 if (Double.isNaN(num)) { 688 return "NaN"; 689 } 690 691 return DoubleConversion.toShortestString(num); 692 } 693 694 /** 695 * JavaScript compliant conversion of number to String 696 * 697 * @param num a number 698 * @param radix a radix for the conversion 699 * 700 * @return a string 701 */ 702 public static String toString(final double num, final int radix) { 703 assert radix >= 2 && radix <= 36 : "invalid radix"; 704 705 if (isRepresentableAsInt(num)) { 706 return Integer.toString((int)num, radix); 707 } 708 709 if (num == Double.POSITIVE_INFINITY) { 710 return "Infinity"; 711 } 712 713 if (num == Double.NEGATIVE_INFINITY) { 714 return "-Infinity"; 715 } 716 717 if (Double.isNaN(num)) { 718 return "NaN"; 719 } 720 721 if (num == 0.0) { 722 return "0"; 723 } 724 725 final String chars = "0123456789abcdefghijklmnopqrstuvwxyz"; 726 final StringBuilder sb = new StringBuilder(); 727 728 final boolean negative = num < 0.0; 729 final double signedNum = negative ? -num : num; 730 731 double intPart = Math.floor(signedNum); 732 double decPart = signedNum - intPart; 733 734 // encode integer part from least significant digit, then reverse 735 do { 736 final double remainder = intPart % radix; 737 sb.append(chars.charAt((int) remainder)); 738 intPart -= remainder; 739 intPart /= radix; 740 } while (intPart >= 1.0); 741 742 if (negative) { 743 sb.append('-'); 744 } 745 sb.reverse(); 746 747 // encode decimal part 748 if (decPart > 0.0) { 749 final int dot = sb.length(); 750 sb.append('.'); 751 do { 752 decPart *= radix; 753 final double d = Math.floor(decPart); 754 sb.append(chars.charAt((int)d)); 755 decPart -= d; 756 } while (decPart > 0.0 && sb.length() - dot < 1100); 757 // somewhat arbitrarily use same limit as V8 758 } 759 760 return sb.toString(); 761 } 762 763 /** 764 * JavaScript compliant conversion of Object to number 765 * See ECMA 9.3 ToNumber 766 * 767 * @param obj an object 768 * 769 * @return a number 770 */ 771 public static double toNumber(final Object obj) { 772 if (obj instanceof Double) { 773 return (Double)obj; 774 } 775 if (obj instanceof Number) { 776 return ((Number)obj).doubleValue(); 777 } 778 return toNumberGeneric(obj); 779 } 780 781 /** 782 * Converts an object for a comparison with a number. Almost identical to {@link #toNumber(Object)} but 783 * converts {@code null} to {@code NaN} instead of zero, so it won't compare equal to zero. 784 * 785 * @param obj an object 786 * 787 * @return a number 788 */ 789 public static double toNumberForEq(final Object obj) { 790 return obj == null ? Double.NaN : toNumber(obj); 791 } 792 793 /** 794 * Converts an object for strict comparison with a number. Returns {@code NaN} for any object that is not 795 * a {@link Number}, so only boxed numerics can compare strictly equal to numbers. 796 * 797 * @param obj an object 798 * 799 * @return a number 800 */ 801 public static double toNumberForStrictEq(final Object obj) { 802 if (obj instanceof Double) { 803 return (Double)obj; 804 } 805 if (obj instanceof Number) { 806 return ((Number)obj).doubleValue(); 807 } 808 return Double.NaN; 809 } 810 811 812 /** 813 * JavaScript compliant conversion of Boolean to number 814 * See ECMA 9.3 ToNumber 815 * 816 * @param b a boolean 817 * 818 * @return JS numeric value of the boolean: 1.0 or 0.0 819 */ 820 public static double toNumber(final Boolean b) { 821 return b ? 1d : +0d; 822 } 823 824 /** 825 * JavaScript compliant conversion of Object to number 826 * See ECMA 9.3 ToNumber 827 * 828 * @param obj an object 829 * 830 * @return a number 831 */ 832 public static double toNumber(final ScriptObject obj) { 833 return toNumber(toPrimitive(obj, Number.class)); 834 } 835 836 /** 837 * Optimistic number conversion - throws UnwarrantedOptimismException if Object 838 * 839 * @param obj object to convert 840 * @param programPoint program point 841 * @return double 842 */ 843 public static double toNumberOptimistic(final Object obj, final int programPoint) { 844 if (obj != null) { 845 final Class<?> clz = obj.getClass(); 846 if (clz == Double.class || clz == Integer.class || clz == Long.class) { 847 return ((Number)obj).doubleValue(); 848 } 849 } 850 throw new UnwarrantedOptimismException(obj, programPoint); 851 } 852 853 /** 854 * Object to number conversion that delegates to either {@link #toNumber(Object)} or to 855 * {@link #toNumberOptimistic(Object, int)} depending on whether the program point is valid or not. 856 * @param obj the object to convert 857 * @param programPoint the program point; can be invalid. 858 * @return the value converted to a number 859 * @throws UnwarrantedOptimismException if the value can't be represented as a number and the program point is valid. 860 */ 861 public static double toNumberMaybeOptimistic(final Object obj, final int programPoint) { 862 return UnwarrantedOptimismException.isValid(programPoint) ? toNumberOptimistic(obj, programPoint) : toNumber(obj); 863 } 864 865 /** 866 * Digit representation for a character 867 * 868 * @param ch a character 869 * @param radix radix 870 * 871 * @return the digit for this character 872 */ 873 public static int digit(final char ch, final int radix) { 874 return digit(ch, radix, false); 875 } 876 877 /** 878 * Digit representation for a character 879 * 880 * @param ch a character 881 * @param radix radix 882 * @param onlyIsoLatin1 iso latin conversion only 883 * 884 * @return the digit for this character 885 */ 886 public static int digit(final char ch, final int radix, final boolean onlyIsoLatin1) { 887 final char maxInRadix = (char)('a' + (radix - 1) - 10); 888 final char c = Character.toLowerCase(ch); 889 890 if (c >= 'a' && c <= maxInRadix) { 891 return Character.digit(ch, radix); 892 } 893 894 if (Character.isDigit(ch)) { 895 if (!onlyIsoLatin1 || ch >= '0' && ch <= '9') { 896 return Character.digit(ch, radix); 897 } 898 } 899 900 return -1; 901 } 902 903 /** 904 * JavaScript compliant String to number conversion 905 * 906 * @param str a string 907 * 908 * @return a number 909 */ 910 public static double toNumber(final String str) { 911 int end = str.length(); 912 if (end == 0) { 913 return 0.0; // Empty string 914 } 915 916 int start = 0; 917 char f = str.charAt(0); 918 919 while (Lexer.isJSWhitespace(f)) { 920 if (++start == end) { 921 return 0.0d; // All whitespace string 922 } 923 f = str.charAt(start); 924 } 925 926 // Guaranteed to terminate even without start >= end check, as the previous loop found at least one 927 // non-whitespace character. 928 while (Lexer.isJSWhitespace(str.charAt(end - 1))) { 929 end--; 930 } 931 932 final boolean negative; 933 if (f == '-') { 934 if(++start == end) { 935 return Double.NaN; // Single-char "-" string 936 } 937 f = str.charAt(start); 938 negative = true; 939 } else { 940 if (f == '+') { 941 if (++start == end) { 942 return Double.NaN; // Single-char "+" string 943 } 944 f = str.charAt(start); 945 } 946 negative = false; 947 } 948 949 final double value; 950 if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') { 951 //decode hex string 952 value = parseRadix(str.toCharArray(), start + 2, end, 16); 953 } else if (f == 'I' && end - start == 8 && str.regionMatches(start, "Infinity", 0, 8)) { 954 return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; 955 } else { 956 // Fast (no NumberFormatException) path to NaN for non-numeric strings. 957 for (int i = start; i < end; i++) { 958 f = str.charAt(i); 959 if ((f < '0' || f > '9') && f != '.' && f != 'e' && f != 'E' && f != '+' && f != '-') { 960 return Double.NaN; 961 } 962 } 963 try { 964 value = Double.parseDouble(str.substring(start, end)); 965 } catch (final NumberFormatException e) { 966 return Double.NaN; 967 } 968 } 969 970 return negative ? -value : value; 971 } 972 973 /** 974 * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger 975 * 976 * <p>Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE} 977 * for double values that exceed the int range, including positive and negative Infinity. It is the 978 * caller's responsibility to handle such values correctly.</p> 979 * 980 * @param obj an object 981 * @return an integer 982 */ 983 public static int toInteger(final Object obj) { 984 return (int)toNumber(obj); 985 } 986 987 /** 988 * Converts an Object to long. 989 * 990 * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE} 991 * for double values that exceed the long range, including positive and negative Infinity. It is the 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) : 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); 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 } 1101 1102 /** 1103 * JavaScript compliant Object to uint32 conversion 1104 * 1105 * @param obj an object 1106 * @return a uint32 1107 */ 1108 public static long toUint32(final Object obj) { 1109 return toUint32(toNumber(obj)); 1110 } 1111 1112 /** 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 1153 /** 1154 * JavaScript compliant number to uint16 conversion 1155 * 1156 * @param num a number 1157 * @return a uint16 1158 */ 1159 public static int toUint16(final long num) { 1160 return (int)num & 0xffff; 1161 } 1162 1163 /** 1164 * JavaScript compliant number to uint16 conversion 1165 * 1166 * @param num a number 1167 * @return a uint16 1168 */ 1169 public static int toUint16(final double num) { 1170 return (int)doubleToInt32(num) & 0xffff; 1171 } 1172 1173 private static long doubleToInt32(final double num) { 1174 final int exponent = Math.getExponent(num); 1175 if (exponent < 31) { 1176 return (long) num; // Fits into 32 bits 1177 } 1178 if (exponent >= 84) { 1179 // Either infinite or NaN or so large that shift / modulo will produce 0 1180 // (52 bit mantissa + 32 bit target width). 1181 return 0; 1182 } 1183 // This is rather slow and could probably be sped up using bit-fiddling. 1184 final double d = num >= 0 ? Math.floor(num) : Math.ceil(num); 1185 return (long)(d % INT32_LIMIT); 1186 } 1187 1188 /** 1189 * Check whether a number is finite 1190 * 1191 * @param num a number 1192 * @return true if finite 1193 */ 1194 public static boolean isFinite(final double num) { 1195 return !Double.isInfinite(num) && !Double.isNaN(num); 1196 } 1197 1198 /** 1199 * Convert a primitive to a double 1200 * 1201 * @param num a double 1202 * @return a boxed double 1203 */ 1204 public static Double toDouble(final double num) { 1205 return num; 1206 } 1207 1208 /** 1209 * Convert a primitive to a double 1210 * 1211 * @param num a long 1212 * @return a boxed double 1213 */ 1214 public static Double toDouble(final long num) { 1215 return (double)num; 1216 } 1217 1218 /** 1219 * Convert a primitive to a double 1220 * 1221 * @param num an int 1222 * @return a boxed double 1223 */ 1224 public static Double toDouble(final int num) { 1225 return (double)num; 1226 } 1227 1228 /** 1229 * Convert a boolean to an Object 1230 * 1231 * @param bool a boolean 1232 * @return a boxed boolean, its Object representation 1233 */ 1234 public static Object toObject(final boolean bool) { 1235 return bool; 1236 } 1237 1238 /** 1239 * Convert a number to an Object 1240 * 1241 * @param num an integer 1242 * @return the boxed number 1243 */ 1244 public static Object toObject(final int num) { 1245 return num; 1246 } 1247 1248 /** 1249 * Convert a number to an Object 1250 * 1251 * @param num a long 1252 * @return the boxed number 1253 */ 1254 public static Object toObject(final long num) { 1255 return num; 1256 } 1257 1258 /** 1259 * Convert a number to an Object 1260 * 1261 * @param num a double 1262 * @return the boxed number 1263 */ 1264 public static Object toObject(final double num) { 1265 return num; 1266 } 1267 1268 /** 1269 * Identity converter for objects. 1270 * 1271 * @param obj an object 1272 * @return the boxed number 1273 */ 1274 public static Object toObject(final Object obj) { 1275 return obj; 1276 } 1277 1278 /** 1279 * Object conversion. This is used to convert objects and numbers to their corresponding 1280 * NativeObject type 1281 * See ECMA 9.9 ToObject 1282 * 1283 * @param obj the object to convert 1284 * 1285 * @return the wrapped object 1286 */ 1287 public static Object toScriptObject(final Object obj) { 1288 return toScriptObject(Context.getGlobal(), obj); 1289 } 1290 1291 /** 1292 * Object conversion. This is used to convert objects and numbers to their corresponding 1293 * NativeObject type 1294 * See ECMA 9.9 ToObject 1295 * 1296 * @param global the global object 1297 * @param obj the object to convert 1298 * 1299 * @return the wrapped object 1300 */ 1301 public static Object toScriptObject(final Global global, final Object obj) { 1302 if (nullOrUndefined(obj)) { 1303 throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj)); 1304 } 1305 1306 if (obj instanceof ScriptObject) { 1307 return obj; 1308 } 1309 1310 return global.wrapAsObject(obj); 1311 } 1312 1313 /** 1314 * Script object to Java array conversion. 1315 * 1316 * @param obj script object to be converted to Java array 1317 * @param componentType component type of the destination array required 1318 * @return converted Java array 1319 */ 1320 public static Object toJavaArray(final Object obj, final Class<?> componentType) { 1321 if (obj instanceof ScriptObject) { 1322 return ((ScriptObject)obj).getArray().asArrayOfType(componentType); 1323 } else if (obj instanceof JSObject) { 1324 final ArrayLikeIterator<?> itr = ArrayLikeIterator.arrayLikeIterator(obj); 1325 final int len = (int) itr.getLength(); 1326 final Object[] res = new Object[len]; 1327 int idx = 0; 1328 while (itr.hasNext()) { 1329 res[idx++] = itr.next(); 1330 } 1331 return convertArray(res, componentType); 1332 } else if(obj == null) { 1333 return null; 1334 } else { 1335 throw new IllegalArgumentException("not a script object"); 1336 } 1337 } 1338 1339 /** 1340 * Java array to java array conversion - but using type conversions implemented by linker. 1341 * 1342 * @param src source array 1343 * @param componentType component type of the destination array required 1344 * @return converted Java array 1345 */ 1346 public static Object convertArray(final Object[] src, final Class<?> componentType) { 1347 if(componentType == Object.class) { 1348 for(int i = 0; i < src.length; ++i) { 1349 final Object e = src[i]; 1350 if(e instanceof ConsString) { 1351 src[i] = e.toString(); 1352 } 1353 } 1354 } 1355 1356 final int l = src.length; 1357 final Object dst = Array.newInstance(componentType, l); 1358 final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType); 1359 try { 1360 for (int i = 0; i < src.length; i++) { 1361 Array.set(dst, i, invoke(converter, src[i])); 1362 } 1363 } catch (final RuntimeException | Error e) { 1364 throw e; 1365 } catch (final Throwable t) { 1366 throw new RuntimeException(t); 1367 } 1368 return dst; 1369 } 1370 1371 /** 1372 * Check if an object is null or undefined 1373 * 1374 * @param obj object to check 1375 * 1376 * @return true if null or undefined 1377 */ 1378 public static boolean nullOrUndefined(final Object obj) { 1379 return obj == null || obj == ScriptRuntime.UNDEFINED; 1380 } 1381 1382 static String toStringImpl(final Object obj, final boolean safe) { 1383 if (obj instanceof String) { 1384 return (String)obj; 1385 } 1386 1387 if (obj instanceof ConsString) { 1388 return obj.toString(); 1389 } 1390 1391 if (obj instanceof Number) { 1392 return toString(((Number)obj).doubleValue()); 1393 } 1394 1395 if (obj == ScriptRuntime.UNDEFINED) { 1396 return "undefined"; 1397 } 1398 1399 if (obj == null) { 1400 return "null"; 1401 } 1402 1403 if (obj instanceof Boolean) { 1404 return obj.toString(); 1405 } 1406 1407 if (safe && obj instanceof ScriptObject) { 1408 final ScriptObject sobj = (ScriptObject)obj; 1409 final Global gobj = Context.getGlobal(); 1410 return gobj.isError(sobj) ? 1411 ECMAException.safeToString(sobj) : 1412 sobj.safeToString(); 1413 } 1414 1415 return toString(toPrimitive(obj, String.class)); 1416 } 1417 1418 // trim from left for JS whitespaces. 1419 static String trimLeft(final String str) { 1420 int start = 0; 1421 1422 while (start < str.length() && Lexer.isJSWhitespace(str.charAt(start))) { 1423 start++; 1424 } 1425 1426 return str.substring(start); 1427 } 1428 1429 /** 1430 * Throw an unwarranted optimism exception for a program point 1431 * @param value real return value 1432 * @param programPoint program point 1433 * @return 1434 */ 1435 @SuppressWarnings("unused") 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 1576 throw new UnwarrantedOptimismException(x > 0 ? Double.POSITIVE_INFINITY : x < 0 ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint); 1577 } 1578 final int rem = x % y; 1579 if (rem == 0) { 1580 return res; 1581 } 1582 // go directly to double here, as anything with non zero remainder is a floating point number in JavaScript 1583 throw new UnwarrantedOptimismException((double)x / (double)y, programPoint); 1584 } 1585 1586 /** 1587 * Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to 1588 * {@code (x / y)|0} JavaScript expression (division of two ints coerced to int). 1589 * @param x the dividend 1590 * @param y the divisor 1591 * @return the result 1592 */ 1593 public static int divZero(final int x, final int y) { 1594 return y == 0 ? 0 : x / y; 1595 } 1596 1597 /** 1598 * Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to 1599 * {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int). 1600 * @param x the dividend 1601 * @param y the divisor 1602 * @return the remainder 1603 */ 1604 public static int remZero(final int x, final int y) { 1605 return y == 0 ? 0 : x % y; 1606 } 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); 1860 } 1861 1862 /** 1863 * Return the number of accessor types available. 1864 * 1865 * @return number of accessor types in system 1866 */ 1867 public static int getNumberOfAccessorTypes() { 1868 return ACCESSOR_TYPES.size(); 1869 } 1870 1871 private static double parseRadix(final char chars[], final int start, final int length, final int radix) { 1872 int pos = 0; 1873 1874 for (int i = start; i < length ; i++) { 1875 if (digit(chars[i], radix) == -1) { 1876 return Double.NaN; 1877 } 1878 pos++; 1879 } 1880 1881 if (pos == 0) { 1882 return Double.NaN; 1883 } 1884 1885 double value = 0.0; 1886 for (int i = start; i < start + pos; i++) { 1887 value *= radix; 1888 value += digit(chars[i], radix); 1889 } 1890 1891 return value; 1892 } 1893 1894 private static double toNumberGeneric(final Object obj) { 1895 if (obj == null) { 1896 return +0.0; 1897 } 1898 1899 if (obj instanceof String) { 1900 return toNumber((String)obj); 1901 } 1902 1903 if (obj instanceof ConsString) { 1904 return toNumber(obj.toString()); 1905 } 1906 1907 if (obj instanceof Boolean) { 1908 return toNumber((Boolean)obj); 1909 } 1910 1911 if (obj instanceof ScriptObject) { 1912 return toNumber((ScriptObject)obj); 1913 } 1914 1915 if (obj instanceof Undefined) { 1916 return Double.NaN; 1917 } 1918 1919 return toNumber(toPrimitive(obj, Number.class)); 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)); 1959 } else if (o.getClass() == Long.class) { 1960 return MH.constant(long.class, ((Long)o)); 1961 } else if (o.getClass() == Double.class) { 1962 return MH.constant(double.class, ((Double)o)); 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 List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) { 1988 return Collections.unmodifiableList(Arrays.asList(methodHandles)); 1989 } 1990 }