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