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 }