1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code, released
17 : * March 31, 1998.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Netscape Communications Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 1998
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef jsnum_h___
41 : #define jsnum_h___
42 :
43 : #include <math.h>
44 :
45 : #include "jsobj.h"
46 :
47 : /*
48 : * JS number (IEEE double) interface.
49 : *
50 : * JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
51 : * but floating point literals, results that overflow 31 bits, and division and
52 : * modulus operands and results require a 64-bit IEEE double. These are GC'ed
53 : * and pointed to by 32-bit jsvals on the stack and in object properties.
54 : */
55 :
56 : /*
57 : * The ARM architecture supports two floating point models: VFP and FPA. When
58 : * targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
59 : * the high and low words are in big endian order).
60 : */
61 : #if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
62 : #if !defined(__VFP_FP__)
63 : #define FPU_IS_ARM_FPA
64 : #endif
65 : #endif
66 :
67 : /* Low-level floating-point predicates. See bug 640494. */
68 : #define JSDOUBLE_HI32_SIGNBIT 0x80000000
69 : #define JSDOUBLE_HI32_EXPMASK 0x7ff00000
70 : #define JSDOUBLE_HI32_MANTMASK 0x000fffff
71 : #define JSDOUBLE_HI32_NAN 0x7ff80000
72 : #define JSDOUBLE_LO32_NAN 0x00000000
73 :
74 : #define JSDOUBLE_HI32_EXPSHIFT 20
75 : #define JSDOUBLE_EXPBIAS 1023
76 :
77 : union jsdpun {
78 : struct {
79 : #if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
80 : uint32_t lo, hi;
81 : #else
82 : uint32_t hi, lo;
83 : #endif
84 : } s;
85 : uint64_t u64;
86 : double d;
87 : };
88 :
89 : static inline int
90 1302919 : JSDOUBLE_IS_NaN(double d)
91 : {
92 : jsdpun u;
93 1302919 : u.d = d;
94 : return (u.u64 & JSDOUBLE_EXPMASK) == JSDOUBLE_EXPMASK &&
95 1302919 : (u.u64 & JSDOUBLE_MANTMASK) != 0;
96 : }
97 :
98 : static inline int
99 1001753 : JSDOUBLE_IS_FINITE(double d)
100 : {
101 : /* -0 is finite. NaNs are not. */
102 : jsdpun u;
103 1001753 : u.d = d;
104 1001753 : return (u.u64 & JSDOUBLE_EXPMASK) != JSDOUBLE_EXPMASK;
105 : }
106 :
107 : static inline int
108 45 : JSDOUBLE_IS_INFINITE(double d)
109 : {
110 : jsdpun u;
111 45 : u.d = d;
112 45 : return (u.u64 & ~JSDOUBLE_SIGNBIT) == JSDOUBLE_EXPMASK;
113 : }
114 :
115 : static inline bool
116 3114 : JSDOUBLE_IS_NEG(double d)
117 : {
118 : jsdpun u;
119 3114 : u.d = d;
120 3114 : return (u.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
121 : }
122 :
123 : static inline uint32_t
124 : JS_HASH_DOUBLE(double d)
125 : {
126 : jsdpun u;
127 : u.d = d;
128 : return u.s.lo ^ u.s.hi;
129 : }
130 :
131 : extern double js_NaN;
132 : extern double js_PositiveInfinity;
133 : extern double js_NegativeInfinity;
134 :
135 : namespace js {
136 :
137 : extern bool
138 : InitRuntimeNumberState(JSRuntime *rt);
139 :
140 : extern void
141 : FinishRuntimeNumberState(JSRuntime *rt);
142 :
143 : } /* namespace js */
144 :
145 : /* Initialize the Number class, returning its prototype object. */
146 : extern JSObject *
147 : js_InitNumberClass(JSContext *cx, JSObject *obj);
148 :
149 : /*
150 : * String constants for global function names, used in jsapi.c and jsnum.c.
151 : */
152 : extern const char js_isNaN_str[];
153 : extern const char js_isFinite_str[];
154 : extern const char js_parseFloat_str[];
155 : extern const char js_parseInt_str[];
156 :
157 : class JSString;
158 : class JSFixedString;
159 :
160 : extern JSString * JS_FASTCALL
161 : js_IntToString(JSContext *cx, int i);
162 :
163 : /*
164 : * When base == 10, this function implements ToString() as specified by
165 : * ECMA-262-5 section 9.8.1; but note that it handles integers specially for
166 : * performance. See also js::NumberToCString().
167 : */
168 : extern JSString * JS_FASTCALL
169 : js_NumberToString(JSContext *cx, double d);
170 :
171 : namespace js {
172 :
173 : /*
174 : * Convert an integer or double (contained in the given value) to a string and
175 : * append to the given buffer.
176 : */
177 : extern bool JS_FASTCALL
178 : NumberValueToStringBuffer(JSContext *cx, const Value &v, StringBuffer &sb);
179 :
180 : /* Same as js_NumberToString, different signature. */
181 : extern JSFixedString *
182 : NumberToString(JSContext *cx, double d);
183 :
184 : extern JSFixedString *
185 : IndexToString(JSContext *cx, uint32_t index);
186 :
187 : /*
188 : * Usually a small amount of static storage is enough, but sometimes we need
189 : * to dynamically allocate much more. This struct encapsulates that.
190 : * Dynamically allocated memory will be freed when the object is destroyed.
191 : */
192 : struct ToCStringBuf
193 : {
194 : /*
195 : * The longest possible result that would need to fit in sbuf is
196 : * (-0x80000000).toString(2), which has length 33. Longer cases are
197 : * possible, but they'll go in dbuf.
198 : */
199 : static const size_t sbufSize = 34;
200 : char sbuf[sbufSize];
201 : char *dbuf;
202 :
203 : ToCStringBuf();
204 : ~ToCStringBuf();
205 : };
206 :
207 : /*
208 : * Convert a number to a C string. When base==10, this function implements
209 : * ToString() as specified by ECMA-262-5 section 9.8.1. It handles integral
210 : * values cheaply. Return NULL if we ran out of memory. See also
211 : * js_NumberToCString().
212 : */
213 : extern char *
214 : NumberToCString(JSContext *cx, ToCStringBuf *cbuf, double d, int base = 10);
215 :
216 : /*
217 : * The largest positive integer such that all positive integers less than it
218 : * may be precisely represented using the IEEE-754 double-precision format.
219 : */
220 : const double DOUBLE_INTEGRAL_PRECISION_LIMIT = uint64_t(1) << 53;
221 :
222 : /*
223 : * Compute the positive integer of the given base described immediately at the
224 : * start of the range [start, end) -- no whitespace-skipping, no magical
225 : * leading-"0" octal or leading-"0x" hex behavior, no "+"/"-" parsing, just
226 : * reading the digits of the integer. Return the index one past the end of the
227 : * digits of the integer in *endp, and return the integer itself in *dp. If
228 : * base is 10 or a power of two the returned integer is the closest possible
229 : * double; otherwise extremely large integers may be slightly inaccurate.
230 : *
231 : * If [start, end) does not begin with a number with the specified base,
232 : * *dp == 0 and *endp == start upon return.
233 : */
234 : extern bool
235 : GetPrefixInteger(JSContext *cx, const jschar *start, const jschar *end, int base,
236 : const jschar **endp, double *dp);
237 :
238 : /* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
239 : JS_ALWAYS_INLINE bool
240 4071867 : ToNumber(JSContext *cx, Value *vp)
241 : {
242 4071867 : if (vp->isNumber())
243 4053568 : return true;
244 : double d;
245 : extern bool ToNumberSlow(JSContext *cx, js::Value v, double *dp);
246 18299 : if (!ToNumberSlow(cx, *vp, &d))
247 0 : return false;
248 18299 : vp->setNumber(d);
249 18299 : return true;
250 : }
251 :
252 : /*
253 : * Convert a value to a uint32_t, according to the ECMA rules for
254 : * ToUint32. Return converted value in *out on success, !ok on
255 : * failure.
256 : */
257 :
258 : JS_ALWAYS_INLINE bool
259 157517 : ToUint32(JSContext *cx, const js::Value &v, uint32_t *out)
260 : {
261 157517 : if (v.isInt32()) {
262 155392 : *out = (uint32_t)v.toInt32();
263 155392 : return true;
264 : }
265 : extern bool ToUint32Slow(JSContext *cx, const js::Value &v, uint32_t *ip);
266 2125 : return ToUint32Slow(cx, v, out);
267 : }
268 :
269 : /*
270 : * Convert a value to a number, then to an int32_t if it fits by rounding to
271 : * nearest. Return converted value in *out on success, !ok on failure. As a
272 : * side effect, *vp will be mutated to match *out.
273 : */
274 : JS_ALWAYS_INLINE bool
275 405 : NonstandardToInt32(JSContext *cx, const js::Value &v, int32_t *out)
276 : {
277 405 : if (v.isInt32()) {
278 405 : *out = v.toInt32();
279 405 : return true;
280 : }
281 : extern bool NonstandardToInt32Slow(JSContext *cx, const js::Value &v, int32_t *ip);
282 0 : return NonstandardToInt32Slow(cx, v, out);
283 : }
284 :
285 : /*
286 : * Convert a value to a number, then to a uint16_t according to the ECMA rules
287 : * for ToUint16. Return converted value on success, !ok on failure. v must be a
288 : * copy of a rooted value.
289 : */
290 : JS_ALWAYS_INLINE bool
291 2394516 : ValueToUint16(JSContext *cx, const js::Value &v, uint16_t *out)
292 : {
293 2394516 : if (v.isInt32()) {
294 2393940 : *out = uint16_t(v.toInt32());
295 2393940 : return true;
296 : }
297 : extern bool ValueToUint16Slow(JSContext *cx, const js::Value &v, uint16_t *out);
298 576 : return ValueToUint16Slow(cx, v, out);
299 : }
300 :
301 : JSBool
302 : num_parseInt(JSContext *cx, unsigned argc, Value *vp);
303 :
304 : } /* namespace js */
305 :
306 : /*
307 : * Specialized ToInt32 and ToUint32 converters for doubles.
308 : */
309 : /*
310 : * From the ES3 spec, 9.5
311 : * 2. If Result(1) is NaN, +0, -0, +Inf, or -Inf, return +0.
312 : * 3. Compute sign(Result(1)) * floor(abs(Result(1))).
313 : * 4. Compute Result(3) modulo 2^32; that is, a finite integer value k of Number
314 : * type with positive sign and less than 2^32 in magnitude such the mathematical
315 : * difference of Result(3) and k is mathematically an integer multiple of 2^32.
316 : * 5. If Result(4) is greater than or equal to 2^31, return Result(4)- 2^32,
317 : * otherwise return Result(4).
318 : */
319 : static inline int32_t
320 1692867 : js_DoubleToECMAInt32(double d)
321 : {
322 : #if defined(__i386__) || defined(__i386) || defined(__x86_64__) || \
323 : defined(_M_IX86) || defined(_M_X64)
324 : jsdpun du, duh, two32;
325 : uint32_t di_h, u_tmp, expon, shift_amount;
326 : int32_t mask32;
327 :
328 : /*
329 : * Algorithm Outline
330 : * Step 1. If d is NaN, +/-Inf or |d|>=2^84 or |d|<1, then return 0
331 : * All of this is implemented based on an exponent comparison.
332 : * Step 2. If |d|<2^31, then return (int)d
333 : * The cast to integer (conversion in RZ mode) returns the correct result.
334 : * Step 3. If |d|>=2^32, d:=fmod(d, 2^32) is taken -- but without a call
335 : * Step 4. If |d|>=2^31, then the fractional bits are cleared before
336 : * applying the correction by 2^32: d - sign(d)*2^32
337 : * Step 5. Return (int)d
338 : */
339 :
340 1692867 : du.d = d;
341 1692867 : di_h = du.s.hi;
342 :
343 1692867 : u_tmp = (di_h & 0x7ff00000) - 0x3ff00000;
344 1692867 : if (u_tmp >= (0x45300000-0x3ff00000)) {
345 : // d is Nan, +/-Inf or +/-0, or |d|>=2^(32+52) or |d|<1, in which case result=0
346 319948 : return 0;
347 : }
348 :
349 1372919 : if (u_tmp < 0x01f00000) {
350 : // |d|<2^31
351 609804 : return int32_t(d);
352 : }
353 :
354 763115 : if (u_tmp > 0x01f00000) {
355 : // |d|>=2^32
356 534766 : expon = u_tmp >> 20;
357 534766 : shift_amount = expon - 21;
358 534766 : duh.u64 = du.u64;
359 534766 : mask32 = 0x80000000;
360 534766 : if (shift_amount < 32) {
361 534733 : mask32 >>= shift_amount;
362 534733 : duh.s.hi = du.s.hi & mask32;
363 534733 : duh.s.lo = 0;
364 : } else {
365 33 : mask32 >>= (shift_amount-32);
366 33 : duh.s.hi = du.s.hi;
367 33 : duh.s.lo = du.s.lo & mask32;
368 : }
369 534766 : du.d -= duh.d;
370 : }
371 :
372 763115 : di_h = du.s.hi;
373 :
374 : // eliminate fractional bits
375 763115 : u_tmp = (di_h & 0x7ff00000);
376 763115 : if (u_tmp >= 0x41e00000) {
377 : // |d|>=2^31
378 351456 : expon = u_tmp >> 20;
379 351456 : shift_amount = expon - (0x3ff - 11);
380 351456 : mask32 = 0x80000000;
381 351456 : if (shift_amount < 32) {
382 0 : mask32 >>= shift_amount;
383 0 : du.s.hi &= mask32;
384 0 : du.s.lo = 0;
385 : } else {
386 351456 : mask32 >>= (shift_amount-32);
387 351456 : du.s.lo &= mask32;
388 : }
389 351456 : two32.s.hi = 0x41f00000 ^ (du.s.hi & 0x80000000);
390 351456 : two32.s.lo = 0;
391 351456 : du.d -= two32.d;
392 : }
393 :
394 763115 : return int32_t(du.d);
395 : #elif defined (__arm__) && defined (__GNUC__)
396 : int32_t i;
397 : uint32_t tmp0;
398 : uint32_t tmp1;
399 : uint32_t tmp2;
400 : asm (
401 : // We use a pure integer solution here. In the 'softfp' ABI, the argument
402 : // will start in r0 and r1, and VFP can't do all of the necessary ECMA
403 : // conversions by itself so some integer code will be required anyway. A
404 : // hybrid solution is faster on A9, but this pure integer solution is
405 : // notably faster for A8.
406 :
407 : // %0 is the result register, and may alias either of the %[QR]1 registers.
408 : // %Q4 holds the lower part of the mantissa.
409 : // %R4 holds the sign, exponent, and the upper part of the mantissa.
410 : // %1, %2 and %3 are used as temporary values.
411 :
412 : // Extract the exponent.
413 : " mov %1, %R4, LSR #20\n"
414 : " bic %1, %1, #(1 << 11)\n" // Clear the sign.
415 :
416 : // Set the implicit top bit of the mantissa. This clobbers a bit of the
417 : // exponent, but we have already extracted that.
418 : " orr %R4, %R4, #(1 << 20)\n"
419 :
420 : // Special Cases
421 : // We should return zero in the following special cases:
422 : // - Exponent is 0x000 - 1023: +/-0 or subnormal.
423 : // - Exponent is 0x7ff - 1023: +/-INFINITY or NaN
424 : // - This case is implicitly handled by the standard code path anyway,
425 : // as shifting the mantissa up by the exponent will result in '0'.
426 : //
427 : // The result is composed of the mantissa, prepended with '1' and
428 : // bit-shifted left by the (decoded) exponent. Note that because the r1[20]
429 : // is the bit with value '1', r1 is effectively already shifted (left) by
430 : // 20 bits, and r0 is already shifted by 52 bits.
431 :
432 : // Adjust the exponent to remove the encoding offset. If the decoded
433 : // exponent is negative, quickly bail out with '0' as such values round to
434 : // zero anyway. This also catches +/-0 and subnormals.
435 : " sub %1, %1, #0xff\n"
436 : " subs %1, %1, #0x300\n"
437 : " bmi 8f\n"
438 :
439 : // %1 = (decoded) exponent >= 0
440 : // %R4 = upper mantissa and sign
441 :
442 : // ---- Lower Mantissa ----
443 : " subs %3, %1, #52\n" // Calculate exp-52
444 : " bmi 1f\n"
445 :
446 : // Shift r0 left by exp-52.
447 : // Ensure that we don't overflow ARM's 8-bit shift operand range.
448 : // We need to handle anything up to an 11-bit value here as we know that
449 : // 52 <= exp <= 1024 (0x400). Any shift beyond 31 bits results in zero
450 : // anyway, so as long as we don't touch the bottom 5 bits, we can use
451 : // a logical OR to push long shifts into the 32 <= (exp&0xff) <= 255 range.
452 : " bic %2, %3, #0xff\n"
453 : " orr %3, %3, %2, LSR #3\n"
454 : // We can now perform a straight shift, avoiding the need for any
455 : // conditional instructions or extra branches.
456 : " mov %Q4, %Q4, LSL %3\n"
457 : " b 2f\n"
458 : "1:\n" // Shift r0 right by 52-exp.
459 : // We know that 0 <= exp < 52, and we can shift up to 255 bits so 52-exp
460 : // will always be a valid shift and we can sk%3 the range check for this case.
461 : " rsb %3, %1, #52\n"
462 : " mov %Q4, %Q4, LSR %3\n"
463 :
464 : // %1 = (decoded) exponent
465 : // %R4 = upper mantissa and sign
466 : // %Q4 = partially-converted integer
467 :
468 : "2:\n"
469 : // ---- Upper Mantissa ----
470 : // This is much the same as the lower mantissa, with a few different
471 : // boundary checks and some masking to hide the exponent & sign bit in the
472 : // upper word.
473 : // Note that the upper mantissa is pre-shifted by 20 in %R4, but we shift
474 : // it left more to remove the sign and exponent so it is effectively
475 : // pre-shifted by 31 bits.
476 : " subs %3, %1, #31\n" // Calculate exp-31
477 : " mov %1, %R4, LSL #11\n" // Re-use %1 as a temporary register.
478 : " bmi 3f\n"
479 :
480 : // Shift %R4 left by exp-31.
481 : // Avoid overflowing the 8-bit shift range, as before.
482 : " bic %2, %3, #0xff\n"
483 : " orr %3, %3, %2, LSR #3\n"
484 : // Perform the shift.
485 : " mov %2, %1, LSL %3\n"
486 : " b 4f\n"
487 : "3:\n" // Shift r1 right by 31-exp.
488 : // We know that 0 <= exp < 31, and we can shift up to 255 bits so 31-exp
489 : // will always be a valid shift and we can skip the range check for this case.
490 : " rsb %3, %3, #0\n" // Calculate 31-exp from -(exp-31)
491 : " mov %2, %1, LSR %3\n" // Thumb-2 can't do "LSR %3" in "orr".
492 :
493 : // %Q4 = partially-converted integer (lower)
494 : // %R4 = upper mantissa and sign
495 : // %2 = partially-converted integer (upper)
496 :
497 : "4:\n"
498 : // Combine the converted parts.
499 : " orr %Q4, %Q4, %2\n"
500 : // Negate the result if we have to, and move it to %0 in the process. To
501 : // avoid conditionals, we can do this by inverting on %R4[31], then adding
502 : // %R4[31]>>31.
503 : " eor %Q4, %Q4, %R4, ASR #31\n"
504 : " add %0, %Q4, %R4, LSR #31\n"
505 : " b 9f\n"
506 : "8:\n"
507 : // +/-INFINITY, +/-0, subnormals, NaNs, and anything else out-of-range that
508 : // will result in a conversion of '0'.
509 : " mov %0, #0\n"
510 : "9:\n"
511 : : "=r" (i), "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2)
512 : : "r" (d)
513 : : "cc"
514 : );
515 : return i;
516 : #else
517 : int32_t i;
518 : double two32, two31;
519 :
520 : if (!JSDOUBLE_IS_FINITE(d))
521 : return 0;
522 :
523 : i = (int32_t) d;
524 : if ((double) i == d)
525 : return i;
526 :
527 : two32 = 4294967296.0;
528 : two31 = 2147483648.0;
529 : d = fmod(d, two32);
530 : d = (d >= 0) ? floor(d) : ceil(d) + two32;
531 : return (int32_t) (d >= two31 ? d - two32 : d);
532 : #endif
533 : }
534 :
535 : inline uint32_t
536 5160 : js_DoubleToECMAUint32(double d)
537 : {
538 5160 : return uint32_t(js_DoubleToECMAInt32(d));
539 : }
540 :
541 : /*
542 : * Convert a double to an integral number, stored in a double.
543 : * If d is NaN, return 0. If d is an infinity, return it without conversion.
544 : */
545 : static inline double
546 50253 : js_DoubleToInteger(double d)
547 : {
548 50253 : if (d == 0)
549 94 : return d;
550 :
551 50159 : if (!JSDOUBLE_IS_FINITE(d)) {
552 378 : if (JSDOUBLE_IS_NaN(d))
553 189 : return 0;
554 189 : return d;
555 : }
556 :
557 49781 : JSBool neg = (d < 0);
558 49781 : d = floor(neg ? -d : d);
559 :
560 49781 : return neg ? -d : d;
561 : }
562 :
563 : /*
564 : * Similar to strtod except that it replaces overflows with infinities of the
565 : * correct sign, and underflows with zeros of the correct sign. Guaranteed to
566 : * return the closest double number to the given input in dp.
567 : *
568 : * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
569 : * the appropriate sign. The case of the "Infinity" string must match exactly.
570 : * If the string does not contain a number, set *ep to s and return 0.0 in dp.
571 : * Return false if out of memory.
572 : */
573 : extern JSBool
574 : js_strtod(JSContext *cx, const jschar *s, const jschar *send,
575 : const jschar **ep, double *dp);
576 :
577 : extern JSBool
578 : js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp);
579 :
580 : namespace js {
581 :
582 : static JS_ALWAYS_INLINE bool
583 32474398 : ValueFitsInInt32(const Value &v, int32_t *pi)
584 : {
585 32474398 : if (v.isInt32()) {
586 18975361 : *pi = v.toInt32();
587 18975361 : return true;
588 : }
589 13499037 : return v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), pi);
590 : }
591 :
592 : /*
593 : * Returns true if the given value is definitely an index: that is, the value
594 : * is a number that's an unsigned 32-bit integer.
595 : *
596 : * This method prioritizes common-case speed over accuracy in every case. It
597 : * can produce false negatives (but not false positives): some values which are
598 : * indexes will be reported not to be indexes by this method. Users must
599 : * consider this possibility when using this method.
600 : */
601 : static JS_ALWAYS_INLINE bool
602 30132678 : IsDefinitelyIndex(const Value &v, uint32_t *indexp)
603 : {
604 30132678 : if (v.isInt32() && v.toInt32() >= 0) {
605 26925363 : *indexp = v.toInt32();
606 26925363 : return true;
607 : }
608 :
609 : int32_t i;
610 3207315 : if (v.isDouble() && JSDOUBLE_IS_INT32(v.toDouble(), &i) && i >= 0) {
611 4 : *indexp = uint32_t(i);
612 4 : return true;
613 : }
614 :
615 3207311 : return false;
616 : }
617 :
618 : /* ES5 9.4 ToInteger. */
619 : static inline bool
620 1103946 : ToInteger(JSContext *cx, const js::Value &v, double *dp)
621 : {
622 1103946 : if (v.isInt32()) {
623 1103463 : *dp = v.toInt32();
624 1103463 : return true;
625 : }
626 483 : if (v.isDouble()) {
627 474 : *dp = v.toDouble();
628 : } else {
629 : extern bool ToNumberSlow(JSContext *cx, Value v, double *dp);
630 9 : if (!ToNumberSlow(cx, v, dp))
631 0 : return false;
632 : }
633 483 : *dp = js_DoubleToInteger(*dp);
634 483 : return true;
635 : }
636 :
637 : } /* namespace js */
638 :
639 : #endif /* jsnum_h___ */
|