LCOV - app.info - js/src/jsnum.h

LCOV - code coverage report
| Current view: | directory - js/src - jsnum.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 106 | 100 | 94.3 %
| Date: | 2012-04-07 | Functions: | 14 | 14 | 100.0 %

           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___ */

Generated by: LCOV version 1.7