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