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