Changeset 107625 in webkit for trunk/Source/JavaScriptCore/wtf


Ignore:
Timestamp:
Feb 13, 2012, 3:38:44 PM (13 years ago)
Author:
[email protected]
Message:

Replace old strtod with new strtod
https://bugs.webkit.org/show_bug.cgi?id=68044

Reviewed by Geoffrey Garen.

  • parser/Lexer.cpp: Added template argument. This version allows junk after numbers.

(JSC::::lex):

  • runtime/JSGlobalObjectFunctions.cpp: Ditto.

(JSC::parseInt):
(JSC::jsStrDecimalLiteral):

  • runtime/LiteralParser.cpp: Ditto.

(JSC::::Lexer::lexNumber):

  • wtf/dtoa.cpp: Replaced old strtod with a new version that uses the new StringToDoubleConverter.

It takes a template argument to allow clients to determine statically whether it should allow
junk after the numbers or not.
(WTF):
(WTF::strtod):

  • wtf/dtoa.h:

(WTF):

  • wtf/text/WTFString.cpp: Added template argument. This version does not allow junk after numbers.

(WTF::toDoubleType):

Location:
trunk/Source/JavaScriptCore/wtf
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/wtf/dtoa.cpp

    r101056 r107625  
    229229}
    230230
    231 static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9)
    232 {
    233     b.sign = 0;
    234     b.resize(1);
    235     b.words()[0] = y9;
    236 
    237     int i = 9;
    238     if (9 < nd0) {
    239         s += 9;
    240         do {
    241             multadd(b, 10, *s++ - '0');
    242         } while (++i < nd0);
    243         s++;
    244     } else
    245         s += 10;
    246     for (; i < nd; i++)
    247         multadd(b, 10, *s++ - '0');
    248 }
    249 
    250231static int hi0bits(uint32_t x)
    251232{
     
    604585}
    605586
    606 static double ulp(U *x)
    607 {
    608     register int32_t L;
    609     U u;
    610 
    611     L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
    612         word0(&u) = L;
    613         word1(&u) = 0;
    614     return dval(&u);
    615 }
    616 
    617 static double b2d(const BigInt& a, int* e)
    618 {
    619     const uint32_t* xa;
    620     const uint32_t* xa0;
    621     uint32_t w;
    622     uint32_t y;
    623     uint32_t z;
    624     int k;
    625     U d;
    626 
    627 #define d0 word0(&d)
    628 #define d1 word1(&d)
    629 
    630     xa0 = a.words();
    631     xa = xa0 + a.size();
    632     y = *--xa;
    633     ASSERT(y);
    634     k = hi0bits(y);
    635     *e = 32 - k;
    636     if (k < Ebits) {
    637         d0 = Exp_1 | (y >> (Ebits - k));
    638         w = xa > xa0 ? *--xa : 0;
    639         d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k));
    640         goto returnD;
    641     }
    642     z = xa > xa0 ? *--xa : 0;
    643     if (k -= Ebits) {
    644         d0 = Exp_1 | (y << k) | (z >> (32 - k));
    645         y = xa > xa0 ? *--xa : 0;
    646         d1 = (z << k) | (y >> (32 - k));
    647     } else {
    648         d0 = Exp_1 | y;
    649         d1 = z;
    650     }
    651 returnD:
    652 #undef d0
    653 #undef d1
    654     return dval(&d);
    655 }
    656 
    657587static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits)
    658588{
     
    702632#undef d1
    703633
    704 static double ratio(const BigInt& a, const BigInt& b)
    705 {
    706     U da, db;
    707     int k, ka, kb;
    708 
    709     dval(&da) = b2d(a, &ka);
    710     dval(&db) = b2d(b, &kb);
    711     k = ka - kb + 32 * (a.size() - b.size());
    712     if (k > 0)
    713         word0(&da) += k * Exp_msk1;
    714     else {
    715         k = -k;
    716         word0(&db) += k * Exp_msk1;
    717     }
    718     return dval(&da) / dval(&db);
    719 }
    720 
    721634static const double tens[] = {
    722635    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
     
    736649#define n_bigtens 5
    737650
     651template<AllowTrailingJunkTag allowTrailingJunk>
    738652double strtod(const char* s00, char** se)
    739653{
    740     int scale;
    741     int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
    742         e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
    743     const char *s, *s0, *s1;
    744     double aadj, aadj1;
    745     U aadj2, adj, rv, rv0;
    746     int32_t L;
    747     uint32_t y, z;
    748     BigInt bb, bb1, bd, bd0, bs, delta;
    749 
    750     sign = nz0 = nz = 0;
    751     dval(&rv) = 0;
    752     for (s = s00; ; s++) {
    753         switch (*s) {
    754         case '-':
    755             sign = 1;
    756             /* no break */
    757         case '+':
    758             if (*++s)
    759                 goto break2;
    760             /* no break */
    761         case 0:
    762             goto ret0;
    763         case '\t':
    764         case '\n':
    765         case '\v':
    766         case '\f':
    767         case '\r':
    768         case ' ':
    769             continue;
    770         default:
    771             goto break2;
    772         }
    773     }
    774 break2:
    775     if (*s == '0') {
    776         nz0 = 1;
    777         while (*++s == '0') { }
    778         if (!*s)
    779             goto ret;
    780     }
    781     s0 = s;
    782     y = z = 0;
    783     for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
    784         if (nd < 9)
    785             y = (10 * y) + c - '0';
    786         else if (nd < 16)
    787             z = (10 * z) + c - '0';
    788     nd0 = nd;
    789     if (c == '.') {
    790         c = *++s;
    791         if (!nd) {
    792             for (; c == '0'; c = *++s)
    793                 nz++;
    794             if (c > '0' && c <= '9') {
    795                 s0 = s;
    796                 nf += nz;
    797                 nz = 0;
    798                 goto haveDig;
    799             }
    800             goto digDone;
    801         }
    802         for (; c >= '0' && c <= '9'; c = *++s) {
    803 haveDig:
    804             nz++;
    805             if (c -= '0') {
    806                 nf += nz;
    807                 for (i = 1; i < nz; i++)
    808                     if (nd++ < 9)
    809                         y *= 10;
    810                     else if (nd <= DBL_DIG + 1)
    811                         z *= 10;
    812                 if (nd++ < 9)
    813                     y = (10 * y) + c;
    814                 else if (nd <= DBL_DIG + 1)
    815                     z = (10 * z) + c;
    816                 nz = 0;
    817             }
    818         }
    819     }
    820 digDone:
    821     e = 0;
    822     if (c == 'e' || c == 'E') {
    823         if (!nd && !nz && !nz0)
    824             goto ret0;
    825         s00 = s;
    826         esign = 0;
    827         switch (c = *++s) {
    828         case '-':
    829             esign = 1;
    830         case '+':
    831             c = *++s;
    832         }
    833         if (c >= '0' && c <= '9') {
    834             while (c == '0')
    835                 c = *++s;
    836             if (c > '0' && c <= '9') {
    837                 L = c - '0';
    838                 s1 = s;
    839                 while ((c = *++s) >= '0' && c <= '9')
    840                     L = (10 * L) + c - '0';
    841                 if (s - s1 > 8 || L > 19999)
    842                     /* Avoid confusion from exponents
    843                      * so large that e might overflow.
    844                      */
    845                     e = 19999; /* safe for 16 bit ints */
    846                 else
    847                     e = (int)L;
    848                 if (esign)
    849                     e = -e;
    850             } else
    851                 e = 0;
    852         } else
    853             s = s00;
    854     }
    855     if (!nd) {
    856         if (!nz && !nz0) {
    857 ret0:
    858             s = s00;
    859             sign = 0;
    860         }
    861         goto ret;
    862     }
    863     e1 = e -= nf;
    864 
    865     /* Now we have nd0 digits, starting at s0, followed by a
    866      * decimal point, followed by nd-nd0 digits.  The number we're
    867      * after is the integer represented by those digits times
    868      * 10**e */
    869 
    870     if (!nd0)
    871         nd0 = nd;
    872     k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
    873     dval(&rv) = y;
    874     if (k > 9)
    875         dval(&rv) = tens[k - 9] * dval(&rv) + z;
    876     if (nd <= DBL_DIG) {
    877         if (!e)
    878             goto ret;
    879         if (e > 0) {
    880             if (e <= Ten_pmax) {
    881                 /* rv = */ rounded_product(dval(&rv), tens[e]);
    882                 goto ret;
    883             }
    884             i = DBL_DIG - nd;
    885             if (e <= Ten_pmax + i) {
    886                 /* A fancier test would sometimes let us do
    887                  * this for larger i values.
    888                  */
    889                 e -= i;
    890                 dval(&rv) *= tens[i];
    891                 /* rv = */ rounded_product(dval(&rv), tens[e]);
    892                 goto ret;
    893             }
    894         } else if (e >= -Ten_pmax) {
    895             /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
    896             goto ret;
    897         }
    898     }
    899     e1 += nd - k;
    900 
    901     scale = 0;
    902 
    903     /* Get starting approximation = rv * 10**e1 */
    904 
    905     if (e1 > 0) {
    906         if ((i = e1 & 15))
    907             dval(&rv) *= tens[i];
    908         if (e1 &= ~15) {
    909             if (e1 > DBL_MAX_10_EXP) {
    910 ovfl:
    911 #if HAVE(ERRNO_H)
    912                 errno = ERANGE;
    913 #endif
    914                 /* Can't trust HUGE_VAL */
    915                 word0(&rv) = Exp_mask;
    916                 word1(&rv) = 0;
    917                 goto ret;
    918             }
    919             e1 >>= 4;
    920             for (j = 0; e1 > 1; j++, e1 >>= 1)
    921                 if (e1 & 1)
    922                     dval(&rv) *= bigtens[j];
    923         /* The last multiplication could overflow. */
    924             word0(&rv) -= P * Exp_msk1;
    925             dval(&rv) *= bigtens[j];
    926             if ((z = word0(&rv) & Exp_mask) > Exp_msk1 * (DBL_MAX_EXP + Bias - P))
    927                 goto ovfl;
    928             if (z > Exp_msk1 * (DBL_MAX_EXP + Bias - 1 - P)) {
    929                 /* set to largest number */
    930                 /* (Can't trust DBL_MAX) */
    931                 word0(&rv) = Big0;
    932                 word1(&rv) = Big1;
    933             } else
    934                 word0(&rv) += P * Exp_msk1;
    935         }
    936     } else if (e1 < 0) {
    937         e1 = -e1;
    938         if ((i = e1 & 15))
    939             dval(&rv) /= tens[i];
    940         if (e1 >>= 4) {
    941             if (e1 >= 1 << n_bigtens)
    942                 goto undfl;
    943             if (e1 & Scale_Bit)
    944                 scale = 2 * P;
    945             for (j = 0; e1 > 0; j++, e1 >>= 1)
    946                 if (e1 & 1)
    947                     dval(&rv) *= tinytens[j];
    948             if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) {
    949                 /* scaled rv is denormal; clear j low bits */
    950                 if (j >= 32) {
    951                     word1(&rv) = 0;
    952                     if (j >= 53)
    953                         word0(&rv) = (P + 2) * Exp_msk1;
    954                     else
    955                         word0(&rv) &= 0xffffffff << (j - 32);
    956                 } else
    957                     word1(&rv) &= 0xffffffff << j;
    958             }
    959                 if (!dval(&rv)) {
    960 undfl:
    961                     dval(&rv) = 0.;
    962 #if HAVE(ERRNO_H)
    963                     errno = ERANGE;
    964 #endif
    965                     goto ret;
    966                 }
    967         }
    968     }
    969 
    970     /* Now the hard part -- adjusting rv to the correct value.*/
    971 
    972     /* Put digits into bd: true value = bd * 10^e */
    973 
    974     s2b(bd0, s0, nd0, nd, y);
    975 
    976     for (;;) {
    977         bd = bd0;
    978         d2b(bb, &rv, &bbe, &bbbits);    /* rv = bb * 2^bbe */
    979         i2b(bs, 1);
    980 
    981         if (e >= 0) {
    982             bb2 = bb5 = 0;
    983             bd2 = bd5 = e;
    984         } else {
    985             bb2 = bb5 = -e;
    986             bd2 = bd5 = 0;
    987         }
    988         if (bbe >= 0)
    989             bb2 += bbe;
    990         else
    991             bd2 -= bbe;
    992         bs2 = bb2;
    993         j = bbe - scale;
    994         i = j + bbbits - 1;    /* logb(rv) */
    995         if (i < Emin)    /* denormal */
    996             j += P - Emin;
    997         else
    998             j = P + 1 - bbbits;
    999         bb2 += j;
    1000         bd2 += j;
    1001         bd2 += scale;
    1002         i = bb2 < bd2 ? bb2 : bd2;
    1003         if (i > bs2)
    1004             i = bs2;
    1005         if (i > 0) {
    1006             bb2 -= i;
    1007             bd2 -= i;
    1008             bs2 -= i;
    1009         }
    1010         if (bb5 > 0) {
    1011             pow5mult(bs, bb5);
    1012             mult(bb, bs);
    1013         }
    1014         if (bb2 > 0)
    1015             lshift(bb, bb2);
    1016         if (bd5 > 0)
    1017             pow5mult(bd, bd5);
    1018         if (bd2 > 0)
    1019             lshift(bd, bd2);
    1020         if (bs2 > 0)
    1021             lshift(bs, bs2);
    1022         diff(delta, bb, bd);
    1023         dsign = delta.sign;
    1024         delta.sign = 0;
    1025         i = cmp(delta, bs);
    1026 
    1027         if (i < 0) {
    1028             /* Error is less than half an ulp -- check for
    1029              * special case of mantissa a power of two.
    1030              */
    1031             if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
    1032              || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
    1033                 ) {
    1034                 break;
    1035             }
    1036             if (!delta.words()[0] && delta.size() <= 1) {
    1037                 /* exact result */
    1038                 break;
    1039             }
    1040             lshift(delta, Log2P);
    1041             if (cmp(delta, bs) > 0)
    1042                 goto dropDown;
    1043             break;
    1044         }
    1045         if (!i) {
    1046             /* exactly half-way between */
    1047             if (dsign) {
    1048                 if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
    1049                  &&  word1(&rv) == (
    1050             (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1)
    1051         ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) :
    1052                            0xffffffff)) {
    1053                     /*boundary case -- increment exponent*/
    1054                     word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1;
    1055                     word1(&rv) = 0;
    1056                     dsign = 0;
    1057                     break;
    1058                 }
    1059             } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
    1060 dropDown:
    1061                 /* boundary case -- decrement exponent */
    1062                 if (scale) {
    1063                     L = word0(&rv) & Exp_mask;
    1064                     if (L <= (2 * P + 1) * Exp_msk1) {
    1065                         if (L > (P + 2) * Exp_msk1)
    1066                             /* round even ==> */
    1067                             /* accept rv */
    1068                             break;
    1069                         /* rv = smallest denormal */
    1070                         goto undfl;
    1071                     }
    1072                 }
    1073                 L = (word0(&rv) & Exp_mask) - Exp_msk1;
    1074                 word0(&rv) = L | Bndry_mask1;
    1075                 word1(&rv) = 0xffffffff;
    1076                 break;
    1077             }
    1078             if (!(word1(&rv) & LSB))
    1079                 break;
    1080             if (dsign)
    1081                 dval(&rv) += ulp(&rv);
    1082             else {
    1083                 dval(&rv) -= ulp(&rv);
    1084                 if (!dval(&rv))
    1085                     goto undfl;
    1086             }
    1087             dsign = 1 - dsign;
    1088             break;
    1089         }
    1090         if ((aadj = ratio(delta, bs)) <= 2.) {
    1091             if (dsign)
    1092                 aadj = aadj1 = 1.;
    1093             else if (word1(&rv) || word0(&rv) & Bndry_mask) {
    1094                 if (word1(&rv) == Tiny1 && !word0(&rv))
    1095                     goto undfl;
    1096                 aadj = 1.;
    1097                 aadj1 = -1.;
    1098             } else {
    1099                 /* special case -- power of FLT_RADIX to be */
    1100                 /* rounded down... */
    1101 
    1102                 if (aadj < 2. / FLT_RADIX)
    1103                     aadj = 1. / FLT_RADIX;
    1104                 else
    1105                     aadj *= 0.5;
    1106                 aadj1 = -aadj;
    1107             }
    1108         } else {
    1109             aadj *= 0.5;
    1110             aadj1 = dsign ? aadj : -aadj;
    1111         }
    1112         y = word0(&rv) & Exp_mask;
    1113 
    1114         /* Check for overflow */
    1115 
    1116         if (y == Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) {
    1117             dval(&rv0) = dval(&rv);
    1118             word0(&rv) -= P * Exp_msk1;
    1119             adj.d = aadj1 * ulp(&rv);
    1120             dval(&rv) += adj.d;
    1121             if ((word0(&rv) & Exp_mask) >= Exp_msk1 * (DBL_MAX_EXP + Bias - P)) {
    1122                 if (word0(&rv0) == Big0 && word1(&rv0) == Big1)
    1123                     goto ovfl;
    1124                 word0(&rv) = Big0;
    1125                 word1(&rv) = Big1;
    1126                 goto cont;
    1127             }
    1128             word0(&rv) += P * Exp_msk1;
    1129         } else {
    1130             if (scale && y <= 2 * P * Exp_msk1) {
    1131                 if (aadj <= 0x7fffffff) {
    1132                     if ((z = (uint32_t)aadj) <= 0)
    1133                         z = 1;
    1134                     aadj = z;
    1135                     aadj1 = dsign ? aadj : -aadj;
    1136                 }
    1137                 dval(&aadj2) = aadj1;
    1138                 word0(&aadj2) += (2 * P + 1) * Exp_msk1 - y;
    1139                 aadj1 = dval(&aadj2);
    1140             }
    1141             adj.d = aadj1 * ulp(&rv);
    1142             dval(&rv) += adj.d;
    1143         }
    1144         z = word0(&rv) & Exp_mask;
    1145         if (!scale && y == z) {
    1146             /* Can we stop now? */
    1147             L = (int32_t)aadj;
    1148             aadj -= L;
    1149             /* The tolerances below are conservative. */
    1150             if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {
    1151                 if (aadj < .4999999 || aadj > .5000001)
    1152                     break;
    1153             } else if (aadj < .4999999 / FLT_RADIX)
    1154                 break;
    1155         }
    1156 cont:
    1157         {}
    1158     }
    1159     if (scale) {
    1160         word0(&rv0) = Exp_1 - 2 * P * Exp_msk1;
    1161         word1(&rv0) = 0;
    1162         dval(&rv) *= dval(&rv0);
    1163 #if HAVE(ERRNO_H)
    1164         /* try to avoid the bug of testing an 8087 register value */
    1165         if (!word0(&rv) && !word1(&rv))
    1166             errno = ERANGE;
    1167 #endif
    1168     }
    1169 ret:
     654    int length = strlen(s00);
     655    double_conversion::StringToDoubleConverter converter(
     656        (allowTrailingJunk ? double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK : 0) |
     657        double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES,
     658        0.0,
     659        (allowTrailingJunk ? std::numeric_limits<double>::quiet_NaN() : 0.0),
     660        "Infinity", "NaN");
     661    int processedCharacterCount = 0;
     662    double result = converter.StringToDouble(s00, length, &processedCharacterCount);
    1170663    if (se)
    1171         *se = const_cast<char*>(s);
    1172     return sign ? -dval(&rv) : dval(&rv);
    1173 }
     664        *se = const_cast<char*>(s00 + processedCharacterCount);
     665    return result;
     666}
     667
     668template double strtod<AllowTrailingJunk>(const char*, char**);
     669template double strtod<DisallowTrailingJunk>(const char*, char**);
    1174670
    1175671static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
  • trunk/Source/JavaScriptCore/wtf/dtoa.h

    r104900 r107625  
    3636WTF_EXPORT_PRIVATE void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
    3737
     38enum AllowTrailingJunkTag { DisallowTrailingJunk = 0, AllowTrailingJunk };
     39
    3840// s00: input string. Must not be 0 and must be terminated by 0.
    3941// se: *se will have the last consumed character position + 1.
    40 WTF_EXPORT_PRIVATE double strtod(const char* s00, char** se);
     42template<AllowTrailingJunkTag allowTrailingJunk>
     43double strtod(const char* s00, char** se);
    4144
    4245// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits.
  • trunk/Source/JavaScriptCore/wtf/text/WTFString.cpp

    r107499 r107625  
    2626#include <wtf/ASCIICType.h>
    2727#include <wtf/DataLog.h>
     28#include <wtf/MathExtras.h>
    2829#include <wtf/text/CString.h>
    2930#include <wtf/StringExtras.h>
     
    10531054    char* start = bytes.data();
    10541055    char* end;
    1055     double val = WTF::strtod(start, &end);
     1056    double val = WTF::strtod<WTF::DisallowTrailingJunk>(start, &end);
    10561057    if (ok)
    1057         *ok = (end == 0 || *end == '\0');
     1058        *ok = (end == 0 || *end == '\0') && !isnan(val);
    10581059    if (didReadNumber)
    10591060        *didReadNumber = end - start;
Note: See TracChangeset for help on using the changeset viewer.