Thu, 12 Sep 2013 14:02:15 +0200
8024476: Octane regression on Richards
Reviewed-by: sundar, jlaskey
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 */
26 package jdk.nashorn.internal.runtime;
28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
31 import java.lang.invoke.MethodHandles;
32 import jdk.internal.dynalink.beans.StaticClass;
33 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
34 import jdk.nashorn.internal.parser.Lexer;
35 import jdk.nashorn.internal.runtime.linker.Bootstrap;
37 /**
38 * Representation for ECMAScript types - this maps directly to the ECMA script standard
39 */
40 public enum JSType {
41 /** The undefined type */
42 UNDEFINED("undefined"),
44 /** The null type */
45 NULL("object"),
47 /** The boolean type */
48 BOOLEAN("boolean"),
50 /** The number type */
51 NUMBER("number"),
53 /** The string type */
54 STRING("string"),
56 /** The object type */
57 OBJECT("object"),
59 /** The function type */
60 FUNCTION("function");
62 /** The type name as returned by ECMAScript "typeof" operator*/
63 private final String typeName;
65 /** Max value for an uint32 in JavaScript */
66 public static final long MAX_UINT = 0xFFFF_FFFFL;
68 private static final MethodHandles.Lookup myLookup = MethodHandles.lookup();
70 /** JavaScript compliant conversion function from Object to boolean */
71 public static final Call TO_BOOLEAN = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, Object.class);
73 /** JavaScript compliant conversion function from number to boolean */
74 public static final Call TO_BOOLEAN_D = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, double.class);
76 /** JavaScript compliant conversion function from Object to integer */
77 public static final Call TO_INTEGER = staticCall(myLookup, JSType.class, "toInteger", int.class, Object.class);
79 /** JavaScript compliant conversion function from Object to long */
80 public static final Call TO_LONG = staticCall(myLookup, JSType.class, "toLong", long.class, Object.class);
82 /** JavaScript compliant conversion function from Object to number */
83 public static final Call TO_NUMBER = staticCall(myLookup, JSType.class, "toNumber", double.class, Object.class);
85 /** JavaScript compliant conversion function from Object to int32 */
86 public static final Call TO_INT32 = staticCall(myLookup, JSType.class, "toInt32", int.class, Object.class);
88 /** JavaScript compliant conversion function from double to int32 */
89 public static final Call TO_INT32_D = staticCall(myLookup, JSType.class, "toInt32", int.class, double.class);
91 /** JavaScript compliant conversion function from Object to uint32 */
92 public static final Call TO_UINT32 = staticCall(myLookup, JSType.class, "toUint32", long.class, Object.class);
94 /** JavaScript compliant conversion function from number to uint32 */
95 public static final Call TO_UINT32_D = staticCall(myLookup, JSType.class, "toUint32", long.class, double.class);
97 /** JavaScript compliant conversion function from Object to int64 */
98 public static final Call TO_INT64 = staticCall(myLookup, JSType.class, "toInt64", long.class, Object.class);
100 /** JavaScript compliant conversion function from number to int64 */
101 public static final Call TO_INT64_D = staticCall(myLookup, JSType.class, "toInt64", long.class, double.class);
103 /** JavaScript compliant conversion function from Object to String */
104 public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class);
106 /** JavaScript compliant conversion function from number to String */
107 public static final Call TO_STRING_D = staticCall(myLookup, JSType.class, "toString", String.class, double.class);
109 /** JavaScript compliant conversion function from Object to primitive */
110 public static final Call TO_PRIMITIVE = staticCall(myLookup, JSType.class, "toPrimitive", Object.class, Object.class);
112 private static final double INT32_LIMIT = 4294967296.0;
114 /**
115 * Constructor
116 *
117 * @param typeName the type name
118 */
119 private JSType(final String typeName) {
120 this.typeName = typeName;
121 }
123 /**
124 * The external type name as returned by ECMAScript "typeof" operator
125 *
126 * @return type name for this type
127 */
128 public final String typeName() {
129 return this.typeName;
130 }
132 /**
133 * Return the JSType for a given object
134 *
135 * @param obj an object
136 *
137 * @return the JSType for the object
138 */
139 public static JSType of(final Object obj) {
140 // Order of these statements is tuned for performance (see JDK-8024476)
141 if (obj == null) {
142 return JSType.NULL;
143 }
145 if (obj instanceof ScriptObject) {
146 return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT;
147 }
149 if (obj instanceof Boolean) {
150 return JSType.BOOLEAN;
151 }
153 if (obj instanceof String || obj instanceof ConsString) {
154 return JSType.STRING;
155 }
157 if (obj instanceof Number) {
158 return JSType.NUMBER;
159 }
161 if (obj == ScriptRuntime.UNDEFINED) {
162 return JSType.UNDEFINED;
163 }
165 return Bootstrap.isCallable(obj) ? JSType.FUNCTION : JSType.OBJECT;
166 }
168 /**
169 * Returns true if double number can be represented as an int
170 *
171 * @param number a long to inspect
172 *
173 * @return true for int representable longs
174 */
175 public static boolean isRepresentableAsInt(final long number) {
176 return (int)number == number;
177 }
179 /**
180 * Returns true if double number can be represented as an int
181 *
182 * @param number a double to inspect
183 *
184 * @return true for int representable doubles
185 */
186 public static boolean isRepresentableAsInt(final double number) {
187 return (int)number == number;
188 }
190 /**
191 * Returns true if double number can be represented as a long
192 *
193 * @param number a double to inspect
194 * @return true for long representable doubles
195 */
196 public static boolean isRepresentableAsLong(final double number) {
197 return (long)number == number;
198 }
200 /**
201 * Get the smallest integer representation of a number. Returns an Integer
202 * for something that is int representable, and Long for something that
203 * is long representable. If the number needs to be a double, this is an
204 * identity function
205 *
206 * @param number number to check
207 *
208 * @return Number instanceof the narrowest possible integer representation for number
209 */
210 public static Number narrowestIntegerRepresentation(final double number) {
211 if (isRepresentableAsInt(number)) {
212 return (int)number;
213 } else if (isRepresentableAsLong(number)) {
214 return (long)number;
215 } else {
216 return number;
217 }
218 }
220 /**
221 * Check whether an object is primitive
222 *
223 * @param obj an object
224 *
225 * @return true if object is primitive (includes null and undefined)
226 */
227 public static boolean isPrimitive(final Object obj) {
228 return obj == null ||
229 obj == ScriptRuntime.UNDEFINED ||
230 obj instanceof Boolean ||
231 obj instanceof Number ||
232 obj instanceof String ||
233 obj instanceof ConsString;
234 }
236 /**
237 * Primitive converter for an object
238 *
239 * @param obj an object
240 *
241 * @return primitive form of the object
242 */
243 public static Object toPrimitive(final Object obj) {
244 return toPrimitive(obj, null);
245 }
247 /**
248 * Primitive converter for an object including type hint
249 * See ECMA 9.1 ToPrimitive
250 *
251 * @param obj an object
252 * @param hint a type hint
253 *
254 * @return the primitive form of the object
255 */
256 public static Object toPrimitive(final Object obj, final Class<?> hint) {
257 if (!(obj instanceof ScriptObject)) {
258 return obj;
259 }
261 final ScriptObject sobj = (ScriptObject)obj;
262 final Object result = sobj.getDefaultValue(hint);
264 if (!isPrimitive(result)) {
265 throw typeError("bad.default.value", result.toString());
266 }
268 return result;
269 }
271 /**
272 * JavaScript compliant conversion of number to boolean
273 *
274 * @param num a number
275 *
276 * @return a boolean
277 */
278 public static boolean toBoolean(final double num) {
279 return num != 0 && !Double.isNaN(num);
280 }
282 /**
283 * JavaScript compliant conversion of Object to boolean
284 * See ECMA 9.2 ToBoolean
285 *
286 * @param obj an object
287 *
288 * @return a boolean
289 */
290 public static boolean toBoolean(final Object obj) {
291 if (obj instanceof Boolean) {
292 return (Boolean)obj;
293 }
295 if (nullOrUndefined(obj)) {
296 return false;
297 }
299 if (obj instanceof Number) {
300 final double num = ((Number)obj).doubleValue();
301 return num != 0 && !Double.isNaN(num);
302 }
304 if (obj instanceof String || obj instanceof ConsString) {
305 return ((CharSequence)obj).length() > 0;
306 }
308 return true;
309 }
312 /**
313 * JavaScript compliant converter of Object to String
314 * See ECMA 9.8 ToString
315 *
316 * @param obj an object
317 *
318 * @return a string
319 */
320 public static String toString(final Object obj) {
321 return toStringImpl(obj, false);
322 }
324 /**
325 * If obj is an instance of {@link ConsString} cast to CharSequence, else return
326 * result of {@link #toString(Object)}.
327 *
328 * @param obj an object
329 * @return an instance of String or ConsString
330 */
331 public static CharSequence toCharSequence(final Object obj) {
332 if (obj instanceof ConsString) {
333 return (CharSequence) obj;
334 }
335 return toString(obj);
336 }
338 /**
339 * Check whether a string is representable as a JavaScript number
340 *
341 * @param str a string
342 *
343 * @return true if string can be represented as a number
344 */
345 public static boolean isNumber(final String str) {
346 try {
347 Double.parseDouble(str);
348 return true;
349 } catch (final NumberFormatException e) {
350 return false;
351 }
352 }
354 /**
355 * JavaScript compliant conversion of integer to String
356 *
357 * @param num an integer
358 *
359 * @return a string
360 */
361 public static String toString(final int num) {
362 return Integer.toString(num);
363 }
365 /**
366 * JavaScript compliant conversion of number to String
367 * See ECMA 9.8.1
368 *
369 * @param num a number
370 *
371 * @return a string
372 */
373 public static String toString(final double num) {
374 if (isRepresentableAsInt(num)) {
375 return Integer.toString((int)num);
376 }
378 if (num == Double.POSITIVE_INFINITY) {
379 return "Infinity";
380 }
382 if (num == Double.NEGATIVE_INFINITY) {
383 return "-Infinity";
384 }
386 if (Double.isNaN(num)) {
387 return "NaN";
388 }
390 return NumberToString.stringFor(num);
391 }
393 /**
394 * JavaScript compliant conversion of number to String
395 *
396 * @param num a number
397 * @param radix a radix for the conversion
398 *
399 * @return a string
400 */
401 public static String toString(final double num, final int radix) {
402 assert radix >= 2 && radix <= 36 : "invalid radix";
404 if (isRepresentableAsInt(num)) {
405 return Integer.toString((int)num, radix);
406 }
408 if (num == Double.POSITIVE_INFINITY) {
409 return "Infinity";
410 }
412 if (num == Double.NEGATIVE_INFINITY) {
413 return "-Infinity";
414 }
416 if (Double.isNaN(num)) {
417 return "NaN";
418 }
420 if (num == 0.0) {
421 return "0";
422 }
424 final String chars = "0123456789abcdefghijklmnopqrstuvwxyz";
425 final StringBuilder sb = new StringBuilder();
427 final boolean negative = num < 0.0;
428 final double signedNum = negative ? -num : num;
430 double intPart = Math.floor(signedNum);
431 double decPart = signedNum - intPart;
433 // encode integer part from least significant digit, then reverse
434 do {
435 sb.append(chars.charAt((int) (intPart % radix)));
436 intPart /= radix;
437 } while (intPart >= 1.0);
439 if (negative) {
440 sb.append('-');
441 }
442 sb.reverse();
444 // encode decimal part
445 if (decPart > 0.0) {
446 final int dot = sb.length();
447 sb.append('.');
448 do {
449 decPart *= radix;
450 final double d = Math.floor(decPart);
451 sb.append(chars.charAt((int)d));
452 decPart -= d;
453 } while (decPart > 0.0 && sb.length() - dot < 1100);
454 // somewhat arbitrarily use same limit as V8
455 }
457 return sb.toString();
458 }
460 /**
461 * JavaScript compliant conversion of Object to number
462 * See ECMA 9.3 ToNumber
463 *
464 * @param obj an object
465 *
466 * @return a number
467 */
468 public static double toNumber(final Object obj) {
469 if (obj instanceof Number) {
470 return ((Number)obj).doubleValue();
471 }
472 return toNumberGeneric(obj);
473 }
475 /**
476 * Digit representation for a character
477 *
478 * @param ch a character
479 * @param radix radix
480 *
481 * @return the digit for this character
482 */
483 public static int digit(final char ch, final int radix) {
484 return digit(ch, radix, false);
485 }
487 /**
488 * Digit representation for a character
489 *
490 * @param ch a character
491 * @param radix radix
492 * @param onlyIsoLatin1 iso latin conversion only
493 *
494 * @return the digit for this character
495 */
496 public static int digit(final char ch, final int radix, final boolean onlyIsoLatin1) {
497 final char maxInRadix = (char)('a' + (radix - 1) - 10);
498 final char c = Character.toLowerCase(ch);
500 if (c >= 'a' && c <= maxInRadix) {
501 return Character.digit(ch, radix);
502 }
504 if (Character.isDigit(ch)) {
505 if (!onlyIsoLatin1 || ch >= '0' && ch <= '9') {
506 return Character.digit(ch, radix);
507 }
508 }
510 return -1;
511 }
513 /**
514 * JavaScript compliant String to number conversion
515 *
516 * @param str a string
517 *
518 * @return a number
519 */
520 public static double toNumber(final String str) {
521 int end = str.length();
522 if (end == 0) {
523 return 0.0; // Empty string
524 }
526 int start = 0;
527 char f = str.charAt(0);
529 while (Lexer.isJSWhitespace(f)) {
530 if (++start == end) {
531 return 0.0d; // All whitespace string
532 }
533 f = str.charAt(start);
534 }
536 // Guaranteed to terminate even without start >= end check, as the previous loop found at least one
537 // non-whitespace character.
538 while (Lexer.isJSWhitespace(str.charAt(end - 1))) {
539 end--;
540 }
542 final boolean negative;
543 if (f == '-') {
544 if(++start == end) {
545 return Double.NaN; // Single-char "-" string
546 }
547 f = str.charAt(start);
548 negative = true;
549 } else {
550 if (f == '+') {
551 if (++start == end) {
552 return Double.NaN; // Single-char "+" string
553 }
554 f = str.charAt(start);
555 }
556 negative = false;
557 }
559 final double value;
560 if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') {
561 //decode hex string
562 value = parseRadix(str.toCharArray(), start + 2, end, 16);
563 } else {
564 // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or
565 // "N" to allow for parsing "NaN" and "Infinity" correctly.
566 if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') {
567 return Double.NaN;
568 }
569 try {
570 value = Double.parseDouble(str.substring(start, end));
571 } catch (final NumberFormatException e) {
572 return Double.NaN;
573 }
574 }
576 return negative ? -value : value;
577 }
579 /**
580 * JavaScript compliant Object to integer conversion. See ECMA 9.4 ToInteger
581 *
582 * <p>Note that this returns {@link java.lang.Integer#MAX_VALUE} or {@link java.lang.Integer#MIN_VALUE}
583 * for double values that exceed the int range, including positive and negative Infinity. It is the
584 * caller's responsibility to handle such values correctly.</p>
585 *
586 * @param obj an object
587 * @return an integer
588 */
589 public static int toInteger(final Object obj) {
590 return (int)toNumber(obj);
591 }
593 /**
594 * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger
595 *
596 * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE}
597 * for double values that exceed the long range, including positive and negative Infinity. It is the
598 * caller's responsibility to handle such values correctly.</p>
599 *
600 * @param obj an object
601 * @return a long
602 */
603 public static long toLong(final Object obj) {
604 return (long)toNumber(obj);
605 }
607 /**
608 * JavaScript compliant Object to int32 conversion
609 * See ECMA 9.5 ToInt32
610 *
611 * @param obj an object
612 * @return an int32
613 */
614 public static int toInt32(final Object obj) {
615 return toInt32(toNumber(obj));
616 }
618 /**
619 * JavaScript compliant long to int32 conversion
620 *
621 * @param num a long
622 * @return an int32
623 */
624 public static int toInt32(final long num) {
625 return (int)num;
626 }
628 /**
629 * JavaScript compliant number to int32 conversion
630 *
631 * @param num a number
632 * @return an int32
633 */
634 public static int toInt32(final double num) {
635 return (int)doubleToInt32(num);
636 }
638 /**
639 * JavaScript compliant Object to int64 conversion
640 *
641 * @param obj an object
642 * @return an int64
643 */
644 public static long toInt64(final Object obj) {
645 return toInt64(toNumber(obj));
646 }
648 /**
649 * JavaScript compliant number to int64 conversion
650 *
651 * @param num a number
652 * @return an int64
653 */
654 public static long toInt64(final double num) {
655 if (Double.isInfinite(num)) {
656 return 0L;
657 }
658 return (long)num;
659 }
661 /**
662 * JavaScript compliant Object to uint32 conversion
663 *
664 * @param obj an object
665 * @return a uint32
666 */
667 public static long toUint32(final Object obj) {
668 return toUint32(toNumber(obj));
669 }
671 /**
672 * JavaScript compliant number to uint32 conversion
673 *
674 * @param num a number
675 * @return a uint32
676 */
677 public static long toUint32(final double num) {
678 return doubleToInt32(num) & MAX_UINT;
679 }
681 /**
682 * JavaScript compliant Object to uint16 conversion
683 * ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
684 *
685 * @param obj an object
686 * @return a uint16
687 */
688 public static int toUint16(final Object obj) {
689 return toUint16(toNumber(obj));
690 }
692 /**
693 * JavaScript compliant number to uint16 conversion
694 *
695 * @param num a number
696 * @return a uint16
697 */
698 public static int toUint16(final int num) {
699 return num & 0xffff;
700 }
702 /**
703 * JavaScript compliant number to uint16 conversion
704 *
705 * @param num a number
706 * @return a uint16
707 */
708 public static int toUint16(final long num) {
709 return ((int)num) & 0xffff;
710 }
712 /**
713 * JavaScript compliant number to uint16 conversion
714 *
715 * @param num a number
716 * @return a uint16
717 */
718 public static int toUint16(final double num) {
719 return ((int)doubleToInt32(num)) & 0xffff;
720 }
722 private static long doubleToInt32(final double num) {
723 final int exponent = Math.getExponent(num);
724 if (exponent < 31) {
725 return (long) num; // Fits into 32 bits
726 }
727 if (exponent >= 84) {
728 // Either infinite or NaN or so large that shift / modulo will produce 0
729 // (52 bit mantissa + 32 bit target width).
730 return 0;
731 }
732 // This is rather slow and could probably be sped up using bit-fiddling.
733 final double d = (num >= 0) ? Math.floor(num) : Math.ceil(num);
734 return (long)(d % INT32_LIMIT);
735 }
737 /**
738 * Check whether a number is finite
739 *
740 * @param num a number
741 * @return true if finite
742 */
743 public static boolean isFinite(final double num) {
744 return !Double.isInfinite(num) && !Double.isNaN(num);
745 }
747 /**
748 * Convert a primitive to a double
749 *
750 * @param num a double
751 * @return a boxed double
752 */
753 public static Double toDouble(final double num) {
754 return num;
755 }
757 /**
758 * Convert a primitive to a double
759 *
760 * @param num a long
761 * @return a boxed double
762 */
763 public static Double toDouble(final long num) {
764 return (double)num;
765 }
767 /**
768 * Convert a primitive to a double
769 *
770 * @param num an int
771 * @return a boxed double
772 */
773 public static Double toDouble(final int num) {
774 return (double)num;
775 }
777 /**
778 * Convert a boolean to an Object
779 *
780 * @param bool a boolean
781 * @return a boxed boolean, its Object representation
782 */
783 public static Object toObject(final boolean bool) {
784 return bool;
785 }
787 /**
788 * Convert a number to an Object
789 *
790 * @param num an integer
791 * @return the boxed number
792 */
793 public static Object toObject(final int num) {
794 return num;
795 }
797 /**
798 * Convert a number to an Object
799 *
800 * @param num a long
801 * @return the boxed number
802 */
803 public static Object toObject(final long num) {
804 return num;
805 }
807 /**
808 * Convert a number to an Object
809 *
810 * @param num a double
811 * @return the boxed number
812 */
813 public static Object toObject(final double num) {
814 return num;
815 }
817 /**
818 * Identity converter for objects.
819 *
820 * @param obj an object
821 * @return the boxed number
822 */
823 public static Object toObject(final Object obj) {
824 return obj;
825 }
827 /**
828 * Object conversion. This is used to convert objects and numbers to their corresponding
829 * NativeObject type
830 * See ECMA 9.9 ToObject
831 *
832 * @param obj the object to convert
833 *
834 * @return the wrapped object
835 */
836 public static Object toScriptObject(final Object obj) {
837 return toScriptObject(Context.getGlobalTrusted(), obj);
838 }
840 /**
841 * Object conversion. This is used to convert objects and numbers to their corresponding
842 * NativeObject type
843 * See ECMA 9.9 ToObject
844 *
845 * @param global the global object
846 * @param obj the object to convert
847 *
848 * @return the wrapped object
849 */
850 public static Object toScriptObject(final ScriptObject global, final Object obj) {
851 if (nullOrUndefined(obj)) {
852 throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj));
853 }
855 if (obj instanceof ScriptObject) {
856 return obj;
857 }
859 return ((GlobalObject)global).wrapAsObject(obj);
860 }
862 /**
863 * Check if an object is null or undefined
864 *
865 * @param obj object to check
866 *
867 * @return true if null or undefined
868 */
869 public static boolean nullOrUndefined(final Object obj) {
870 return obj == null || obj == ScriptRuntime.UNDEFINED;
871 }
873 static String toStringImpl(final Object obj, final boolean safe) {
874 if (obj instanceof String) {
875 return (String)obj;
876 }
878 if (obj instanceof Number) {
879 return toString(((Number)obj).doubleValue());
880 }
882 if (obj == ScriptRuntime.UNDEFINED) {
883 return "undefined";
884 }
886 if (obj == null) {
887 return "null";
888 }
890 if (obj instanceof ScriptObject) {
891 if (safe) {
892 final ScriptObject sobj = (ScriptObject)obj;
893 final GlobalObject gobj = (GlobalObject)Context.getGlobalTrusted();
894 return gobj.isError(sobj) ?
895 ECMAException.safeToString(sobj) :
896 sobj.safeToString();
897 }
899 return toString(toPrimitive(obj, String.class));
900 }
902 if (obj instanceof StaticClass) {
903 return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]";
904 }
906 return obj.toString();
907 }
909 // trim from left for JS whitespaces.
910 static String trimLeft(final String str) {
911 int start = 0;
913 while (start < str.length() && Lexer.isJSWhitespace(str.charAt(start))) {
914 start++;
915 }
917 return str.substring(start);
918 }
920 private static double parseRadix(final char chars[], final int start, final int length, final int radix) {
921 int pos = 0;
923 for (int i = start; i < length ; i++) {
924 if (digit(chars[i], radix) == -1) {
925 return Double.NaN;
926 }
927 pos++;
928 }
930 if (pos == 0) {
931 return Double.NaN;
932 }
934 double value = 0.0;
935 for (int i = start; i < start + pos; i++) {
936 value *= radix;
937 value += digit(chars[i], radix);
938 }
940 return value;
941 }
943 private static double toNumberGeneric(final Object obj) {
944 if (obj == null) {
945 return +0.0;
946 }
948 if (obj instanceof String) {
949 return toNumber((String)obj);
950 }
952 if (obj instanceof ConsString) {
953 return toNumber(obj.toString());
954 }
956 if (obj instanceof Boolean) {
957 return (Boolean)obj ? 1 : +0.0;
958 }
960 if (obj instanceof ScriptObject) {
961 return toNumber(toPrimitive(obj, Number.class));
962 }
964 return Double.NaN;
965 }
967 }