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