Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <stdarg.h>
     29 #include <limits.h>
     30 
     31 #include "v8.h"
     32 
     33 #include "conversions-inl.h"
     34 #include "dtoa.h"
     35 #include "factory.h"
     36 #include "scanner-base.h"
     37 #include "strtod.h"
     38 
     39 namespace v8 {
     40 namespace internal {
     41 
     42 namespace {
     43 
     44 // C++-style iterator adaptor for StringInputBuffer
     45 // (unlike C++ iterators the end-marker has different type).
     46 class StringInputBufferIterator {
     47  public:
     48   class EndMarker {};
     49 
     50   explicit StringInputBufferIterator(StringInputBuffer* buffer);
     51 
     52   int operator*() const;
     53   void operator++();
     54   bool operator==(EndMarker const&) const { return end_; }
     55   bool operator!=(EndMarker const& m) const { return !end_; }
     56 
     57  private:
     58   StringInputBuffer* const buffer_;
     59   int current_;
     60   bool end_;
     61 };
     62 
     63 
     64 StringInputBufferIterator::StringInputBufferIterator(
     65     StringInputBuffer* buffer) : buffer_(buffer) {
     66   ++(*this);
     67 }
     68 
     69 int StringInputBufferIterator::operator*() const {
     70   return current_;
     71 }
     72 
     73 
     74 void StringInputBufferIterator::operator++() {
     75   end_ = !buffer_->has_more();
     76   if (!end_) {
     77     current_ = buffer_->GetNext();
     78   }
     79 }
     80 }
     81 
     82 
     83 template <class Iterator, class EndMark>
     84 static bool SubStringEquals(Iterator* current,
     85                             EndMark end,
     86                             const char* substring) {
     87   ASSERT(**current == *substring);
     88   for (substring++; *substring != '\0'; substring++) {
     89     ++*current;
     90     if (*current == end || **current != *substring) return false;
     91   }
     92   ++*current;
     93   return true;
     94 }
     95 
     96 
     97 // Maximum number of significant digits in decimal representation.
     98 // The longest possible double in decimal representation is
     99 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
    100 // (768 digits). If we parse a number whose first digits are equal to a
    101 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
    102 // must be rounded to the bigger one unless the tail consists of zeros, so
    103 // we don't need to preserve all the digits.
    104 const int kMaxSignificantDigits = 772;
    105 
    106 
    107 static const double JUNK_STRING_VALUE = OS::nan_value();
    108 
    109 
    110 // Returns true if a nonspace found and false if the end has reached.
    111 template <class Iterator, class EndMark>
    112 static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
    113                                      Iterator* current,
    114                                      EndMark end) {
    115   while (*current != end) {
    116     if (!unicode_cache->IsWhiteSpace(**current)) return true;
    117     ++*current;
    118   }
    119   return false;
    120 }
    121 
    122 
    123 static bool isDigit(int x, int radix) {
    124   return (x >= '0' && x <= '9' && x < '0' + radix)
    125       || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
    126       || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
    127 }
    128 
    129 
    130 static double SignedZero(bool negative) {
    131   return negative ? -0.0 : 0.0;
    132 }
    133 
    134 
    135 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
    136 template <int radix_log_2, class Iterator, class EndMark>
    137 static double InternalStringToIntDouble(UnicodeCache* unicode_cache,
    138                                         Iterator current,
    139                                         EndMark end,
    140                                         bool negative,
    141                                         bool allow_trailing_junk) {
    142   ASSERT(current != end);
    143 
    144   // Skip leading 0s.
    145   while (*current == '0') {
    146     ++current;
    147     if (current == end) return SignedZero(negative);
    148   }
    149 
    150   int64_t number = 0;
    151   int exponent = 0;
    152   const int radix = (1 << radix_log_2);
    153 
    154   do {
    155     int digit;
    156     if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
    157       digit = static_cast<char>(*current) - '0';
    158     } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
    159       digit = static_cast<char>(*current) - 'a' + 10;
    160     } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
    161       digit = static_cast<char>(*current) - 'A' + 10;
    162     } else {
    163       if (allow_trailing_junk ||
    164           !AdvanceToNonspace(unicode_cache, &current, end)) {
    165         break;
    166       } else {
    167         return JUNK_STRING_VALUE;
    168       }
    169     }
    170 
    171     number = number * radix + digit;
    172     int overflow = static_cast<int>(number >> 53);
    173     if (overflow != 0) {
    174       // Overflow occurred. Need to determine which direction to round the
    175       // result.
    176       int overflow_bits_count = 1;
    177       while (overflow > 1) {
    178         overflow_bits_count++;
    179         overflow >>= 1;
    180       }
    181 
    182       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
    183       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
    184       number >>= overflow_bits_count;
    185       exponent = overflow_bits_count;
    186 
    187       bool zero_tail = true;
    188       while (true) {
    189         ++current;
    190         if (current == end || !isDigit(*current, radix)) break;
    191         zero_tail = zero_tail && *current == '0';
    192         exponent += radix_log_2;
    193       }
    194 
    195       if (!allow_trailing_junk &&
    196           AdvanceToNonspace(unicode_cache, &current, end)) {
    197         return JUNK_STRING_VALUE;
    198       }
    199 
    200       int middle_value = (1 << (overflow_bits_count - 1));
    201       if (dropped_bits > middle_value) {
    202         number++;  // Rounding up.
    203       } else if (dropped_bits == middle_value) {
    204         // Rounding to even to consistency with decimals: half-way case rounds
    205         // up if significant part is odd and down otherwise.
    206         if ((number & 1) != 0 || !zero_tail) {
    207           number++;  // Rounding up.
    208         }
    209       }
    210 
    211       // Rounding up may cause overflow.
    212       if ((number & ((int64_t)1 << 53)) != 0) {
    213         exponent++;
    214         number >>= 1;
    215       }
    216       break;
    217     }
    218     ++current;
    219   } while (current != end);
    220 
    221   ASSERT(number < ((int64_t)1 << 53));
    222   ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
    223 
    224   if (exponent == 0) {
    225     if (negative) {
    226       if (number == 0) return -0.0;
    227       number = -number;
    228     }
    229     return static_cast<double>(number);
    230   }
    231 
    232   ASSERT(number != 0);
    233   // The double could be constructed faster from number (mantissa), exponent
    234   // and sign. Assuming it's a rare case more simple code is used.
    235   return static_cast<double>(negative ? -number : number) * pow(2.0, exponent);
    236 }
    237 
    238 
    239 template <class Iterator, class EndMark>
    240 static double InternalStringToInt(UnicodeCache* unicode_cache,
    241                                   Iterator current,
    242                                   EndMark end,
    243                                   int radix) {
    244   const bool allow_trailing_junk = true;
    245   const double empty_string_val = JUNK_STRING_VALUE;
    246 
    247   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    248     return empty_string_val;
    249   }
    250 
    251   bool negative = false;
    252   bool leading_zero = false;
    253 
    254   if (*current == '+') {
    255     // Ignore leading sign; skip following spaces.
    256     ++current;
    257     if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    258       return JUNK_STRING_VALUE;
    259     }
    260   } else if (*current == '-') {
    261     ++current;
    262     if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    263       return JUNK_STRING_VALUE;
    264     }
    265     negative = true;
    266   }
    267 
    268   if (radix == 0) {
    269     // Radix detection.
    270     if (*current == '0') {
    271       ++current;
    272       if (current == end) return SignedZero(negative);
    273       if (*current == 'x' || *current == 'X') {
    274         radix = 16;
    275         ++current;
    276         if (current == end) return JUNK_STRING_VALUE;
    277       } else {
    278         radix = 8;
    279         leading_zero = true;
    280       }
    281     } else {
    282       radix = 10;
    283     }
    284   } else if (radix == 16) {
    285     if (*current == '0') {
    286       // Allow "0x" prefix.
    287       ++current;
    288       if (current == end) return SignedZero(negative);
    289       if (*current == 'x' || *current == 'X') {
    290         ++current;
    291         if (current == end) return JUNK_STRING_VALUE;
    292       } else {
    293         leading_zero = true;
    294       }
    295     }
    296   }
    297 
    298   if (radix < 2 || radix > 36) return JUNK_STRING_VALUE;
    299 
    300   // Skip leading zeros.
    301   while (*current == '0') {
    302     leading_zero = true;
    303     ++current;
    304     if (current == end) return SignedZero(negative);
    305   }
    306 
    307   if (!leading_zero && !isDigit(*current, radix)) {
    308     return JUNK_STRING_VALUE;
    309   }
    310 
    311   if (IsPowerOf2(radix)) {
    312     switch (radix) {
    313       case 2:
    314         return InternalStringToIntDouble<1>(
    315             unicode_cache, current, end, negative, allow_trailing_junk);
    316       case 4:
    317         return InternalStringToIntDouble<2>(
    318             unicode_cache, current, end, negative, allow_trailing_junk);
    319       case 8:
    320         return InternalStringToIntDouble<3>(
    321             unicode_cache, current, end, negative, allow_trailing_junk);
    322 
    323       case 16:
    324         return InternalStringToIntDouble<4>(
    325             unicode_cache, current, end, negative, allow_trailing_junk);
    326 
    327       case 32:
    328         return InternalStringToIntDouble<5>(
    329             unicode_cache, current, end, negative, allow_trailing_junk);
    330       default:
    331         UNREACHABLE();
    332     }
    333   }
    334 
    335   if (radix == 10) {
    336     // Parsing with strtod.
    337     const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
    338     // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
    339     // end.
    340     const int kBufferSize = kMaxSignificantDigits + 2;
    341     char buffer[kBufferSize];
    342     int buffer_pos = 0;
    343     while (*current >= '0' && *current <= '9') {
    344       if (buffer_pos <= kMaxSignificantDigits) {
    345         // If the number has more than kMaxSignificantDigits it will be parsed
    346         // as infinity.
    347         ASSERT(buffer_pos < kBufferSize);
    348         buffer[buffer_pos++] = static_cast<char>(*current);
    349       }
    350       ++current;
    351       if (current == end) break;
    352     }
    353 
    354     if (!allow_trailing_junk &&
    355         AdvanceToNonspace(unicode_cache, &current, end)) {
    356       return JUNK_STRING_VALUE;
    357     }
    358 
    359     ASSERT(buffer_pos < kBufferSize);
    360     buffer[buffer_pos] = '\0';
    361     Vector<const char> buffer_vector(buffer, buffer_pos);
    362     return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
    363   }
    364 
    365   // The following code causes accumulating rounding error for numbers greater
    366   // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
    367   // 16, or 32, then mathInt may be an implementation-dependent approximation to
    368   // the mathematical integer value" (15.1.2.2).
    369 
    370   int lim_0 = '0' + (radix < 10 ? radix : 10);
    371   int lim_a = 'a' + (radix - 10);
    372   int lim_A = 'A' + (radix - 10);
    373 
    374   // NOTE: The code for computing the value may seem a bit complex at
    375   // first glance. It is structured to use 32-bit multiply-and-add
    376   // loops as long as possible to avoid loosing precision.
    377 
    378   double v = 0.0;
    379   bool done = false;
    380   do {
    381     // Parse the longest part of the string starting at index j
    382     // possible while keeping the multiplier, and thus the part
    383     // itself, within 32 bits.
    384     unsigned int part = 0, multiplier = 1;
    385     while (true) {
    386       int d;
    387       if (*current >= '0' && *current < lim_0) {
    388         d = *current - '0';
    389       } else if (*current >= 'a' && *current < lim_a) {
    390         d = *current - 'a' + 10;
    391       } else if (*current >= 'A' && *current < lim_A) {
    392         d = *current - 'A' + 10;
    393       } else {
    394         done = true;
    395         break;
    396       }
    397 
    398       // Update the value of the part as long as the multiplier fits
    399       // in 32 bits. When we can't guarantee that the next iteration
    400       // will not overflow the multiplier, we stop parsing the part
    401       // by leaving the loop.
    402       const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
    403       uint32_t m = multiplier * radix;
    404       if (m > kMaximumMultiplier) break;
    405       part = part * radix + d;
    406       multiplier = m;
    407       ASSERT(multiplier > part);
    408 
    409       ++current;
    410       if (current == end) {
    411         done = true;
    412         break;
    413       }
    414     }
    415 
    416     // Update the value and skip the part in the string.
    417     v = v * multiplier + part;
    418   } while (!done);
    419 
    420   if (!allow_trailing_junk &&
    421       AdvanceToNonspace(unicode_cache, &current, end)) {
    422     return JUNK_STRING_VALUE;
    423   }
    424 
    425   return negative ? -v : v;
    426 }
    427 
    428 
    429 // Converts a string to a double value. Assumes the Iterator supports
    430 // the following operations:
    431 // 1. current == end (other ops are not allowed), current != end.
    432 // 2. *current - gets the current character in the sequence.
    433 // 3. ++current (advances the position).
    434 template <class Iterator, class EndMark>
    435 static double InternalStringToDouble(UnicodeCache* unicode_cache,
    436                                      Iterator current,
    437                                      EndMark end,
    438                                      int flags,
    439                                      double empty_string_val) {
    440   // To make sure that iterator dereferencing is valid the following
    441   // convention is used:
    442   // 1. Each '++current' statement is followed by check for equality to 'end'.
    443   // 2. If AdvanceToNonspace returned false then current == end.
    444   // 3. If 'current' becomes be equal to 'end' the function returns or goes to
    445   // 'parsing_done'.
    446   // 4. 'current' is not dereferenced after the 'parsing_done' label.
    447   // 5. Code before 'parsing_done' may rely on 'current != end'.
    448   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    449     return empty_string_val;
    450   }
    451 
    452   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
    453 
    454   // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
    455   const int kBufferSize = kMaxSignificantDigits + 10;
    456   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
    457   int buffer_pos = 0;
    458 
    459   // Exponent will be adjusted if insignificant digits of the integer part
    460   // or insignificant leading zeros of the fractional part are dropped.
    461   int exponent = 0;
    462   int significant_digits = 0;
    463   int insignificant_digits = 0;
    464   bool nonzero_digit_dropped = false;
    465   bool fractional_part = false;
    466 
    467   bool negative = false;
    468 
    469   if (*current == '+') {
    470     // Ignore leading sign.
    471     ++current;
    472     if (current == end) return JUNK_STRING_VALUE;
    473   } else if (*current == '-') {
    474     ++current;
    475     if (current == end) return JUNK_STRING_VALUE;
    476     negative = true;
    477   }
    478 
    479   static const char kInfinitySymbol[] = "Infinity";
    480   if (*current == kInfinitySymbol[0]) {
    481     if (!SubStringEquals(&current, end, kInfinitySymbol)) {
    482       return JUNK_STRING_VALUE;
    483     }
    484 
    485     if (!allow_trailing_junk &&
    486         AdvanceToNonspace(unicode_cache, &current, end)) {
    487       return JUNK_STRING_VALUE;
    488     }
    489 
    490     ASSERT(buffer_pos == 0);
    491     return negative ? -V8_INFINITY : V8_INFINITY;
    492   }
    493 
    494   bool leading_zero = false;
    495   if (*current == '0') {
    496     ++current;
    497     if (current == end) return SignedZero(negative);
    498 
    499     leading_zero = true;
    500 
    501     // It could be hexadecimal value.
    502     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
    503       ++current;
    504       if (current == end || !isDigit(*current, 16)) {
    505         return JUNK_STRING_VALUE;  // "0x".
    506       }
    507 
    508       return InternalStringToIntDouble<4>(unicode_cache,
    509                                           current,
    510                                           end,
    511                                           negative,
    512                                           allow_trailing_junk);
    513     }
    514 
    515     // Ignore leading zeros in the integer part.
    516     while (*current == '0') {
    517       ++current;
    518       if (current == end) return SignedZero(negative);
    519     }
    520   }
    521 
    522   bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
    523 
    524   // Copy significant digits of the integer part (if any) to the buffer.
    525   while (*current >= '0' && *current <= '9') {
    526     if (significant_digits < kMaxSignificantDigits) {
    527       ASSERT(buffer_pos < kBufferSize);
    528       buffer[buffer_pos++] = static_cast<char>(*current);
    529       significant_digits++;
    530       // Will later check if it's an octal in the buffer.
    531     } else {
    532       insignificant_digits++;  // Move the digit into the exponential part.
    533       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    534     }
    535     octal = octal && *current < '8';
    536     ++current;
    537     if (current == end) goto parsing_done;
    538   }
    539 
    540   if (significant_digits == 0) {
    541     octal = false;
    542   }
    543 
    544   if (*current == '.') {
    545     if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
    546     if (octal) goto parsing_done;
    547 
    548     ++current;
    549     if (current == end) {
    550       if (significant_digits == 0 && !leading_zero) {
    551         return JUNK_STRING_VALUE;
    552       } else {
    553         goto parsing_done;
    554       }
    555     }
    556 
    557     if (significant_digits == 0) {
    558       // octal = false;
    559       // Integer part consists of 0 or is absent. Significant digits start after
    560       // leading zeros (if any).
    561       while (*current == '0') {
    562         ++current;
    563         if (current == end) return SignedZero(negative);
    564         exponent--;  // Move this 0 into the exponent.
    565       }
    566     }
    567 
    568     // We don't emit a '.', but adjust the exponent instead.
    569     fractional_part = true;
    570 
    571     // There is a fractional part.
    572     while (*current >= '0' && *current <= '9') {
    573       if (significant_digits < kMaxSignificantDigits) {
    574         ASSERT(buffer_pos < kBufferSize);
    575         buffer[buffer_pos++] = static_cast<char>(*current);
    576         significant_digits++;
    577         exponent--;
    578       } else {
    579         // Ignore insignificant digits in the fractional part.
    580         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    581       }
    582       ++current;
    583       if (current == end) goto parsing_done;
    584     }
    585   }
    586 
    587   if (!leading_zero && exponent == 0 && significant_digits == 0) {
    588     // If leading_zeros is true then the string contains zeros.
    589     // If exponent < 0 then string was [+-]\.0*...
    590     // If significant_digits != 0 the string is not equal to 0.
    591     // Otherwise there are no digits in the string.
    592     return JUNK_STRING_VALUE;
    593   }
    594 
    595   // Parse exponential part.
    596   if (*current == 'e' || *current == 'E') {
    597     if (octal) return JUNK_STRING_VALUE;
    598     ++current;
    599     if (current == end) {
    600       if (allow_trailing_junk) {
    601         goto parsing_done;
    602       } else {
    603         return JUNK_STRING_VALUE;
    604       }
    605     }
    606     char sign = '+';
    607     if (*current == '+' || *current == '-') {
    608       sign = static_cast<char>(*current);
    609       ++current;
    610       if (current == end) {
    611         if (allow_trailing_junk) {
    612           goto parsing_done;
    613         } else {
    614           return JUNK_STRING_VALUE;
    615         }
    616       }
    617     }
    618 
    619     if (current == end || *current < '0' || *current > '9') {
    620       if (allow_trailing_junk) {
    621         goto parsing_done;
    622       } else {
    623         return JUNK_STRING_VALUE;
    624       }
    625     }
    626 
    627     const int max_exponent = INT_MAX / 2;
    628     ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
    629     int num = 0;
    630     do {
    631       // Check overflow.
    632       int digit = *current - '0';
    633       if (num >= max_exponent / 10
    634           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
    635         num = max_exponent;
    636       } else {
    637         num = num * 10 + digit;
    638       }
    639       ++current;
    640     } while (current != end && *current >= '0' && *current <= '9');
    641 
    642     exponent += (sign == '-' ? -num : num);
    643   }
    644 
    645   if (!allow_trailing_junk &&
    646       AdvanceToNonspace(unicode_cache, &current, end)) {
    647     return JUNK_STRING_VALUE;
    648   }
    649 
    650   parsing_done:
    651   exponent += insignificant_digits;
    652 
    653   if (octal) {
    654     return InternalStringToIntDouble<3>(unicode_cache,
    655                                         buffer,
    656                                         buffer + buffer_pos,
    657                                         negative,
    658                                         allow_trailing_junk);
    659   }
    660 
    661   if (nonzero_digit_dropped) {
    662     buffer[buffer_pos++] = '1';
    663     exponent--;
    664   }
    665 
    666   ASSERT(buffer_pos < kBufferSize);
    667   buffer[buffer_pos] = '\0';
    668 
    669   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
    670   return negative ? -converted : converted;
    671 }
    672 
    673 
    674 double StringToDouble(UnicodeCache* unicode_cache,
    675                       String* str, int flags, double empty_string_val) {
    676   StringShape shape(str);
    677   if (shape.IsSequentialAscii()) {
    678     const char* begin = SeqAsciiString::cast(str)->GetChars();
    679     const char* end = begin + str->length();
    680     return InternalStringToDouble(unicode_cache, begin, end, flags,
    681                                   empty_string_val);
    682   } else if (shape.IsSequentialTwoByte()) {
    683     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
    684     const uc16* end = begin + str->length();
    685     return InternalStringToDouble(unicode_cache, begin, end, flags,
    686                                   empty_string_val);
    687   } else {
    688     StringInputBuffer buffer(str);
    689     return InternalStringToDouble(unicode_cache,
    690                                   StringInputBufferIterator(&buffer),
    691                                   StringInputBufferIterator::EndMarker(),
    692                                   flags,
    693                                   empty_string_val);
    694   }
    695 }
    696 
    697 
    698 double StringToInt(UnicodeCache* unicode_cache,
    699                    String* str,
    700                    int radix) {
    701   StringShape shape(str);
    702   if (shape.IsSequentialAscii()) {
    703     const char* begin = SeqAsciiString::cast(str)->GetChars();
    704     const char* end = begin + str->length();
    705     return InternalStringToInt(unicode_cache, begin, end, radix);
    706   } else if (shape.IsSequentialTwoByte()) {
    707     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
    708     const uc16* end = begin + str->length();
    709     return InternalStringToInt(unicode_cache, begin, end, radix);
    710   } else {
    711     StringInputBuffer buffer(str);
    712     return InternalStringToInt(unicode_cache,
    713                                StringInputBufferIterator(&buffer),
    714                                StringInputBufferIterator::EndMarker(),
    715                                radix);
    716   }
    717 }
    718 
    719 
    720 double StringToDouble(UnicodeCache* unicode_cache,
    721                       const char* str, int flags, double empty_string_val) {
    722   const char* end = str + StrLength(str);
    723   return InternalStringToDouble(unicode_cache, str, end, flags,
    724                                 empty_string_val);
    725 }
    726 
    727 
    728 double StringToDouble(UnicodeCache* unicode_cache,
    729                       Vector<const char> str,
    730                       int flags,
    731                       double empty_string_val) {
    732   const char* end = str.start() + str.length();
    733   return InternalStringToDouble(unicode_cache, str.start(), end, flags,
    734                                 empty_string_val);
    735 }
    736 
    737 
    738 const char* DoubleToCString(double v, Vector<char> buffer) {
    739   switch (fpclassify(v)) {
    740     case FP_NAN: return "NaN";
    741     case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
    742     case FP_ZERO: return "0";
    743     default: {
    744       StringBuilder builder(buffer.start(), buffer.length());
    745       int decimal_point;
    746       int sign;
    747       const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
    748       char decimal_rep[kV8DtoaBufferCapacity];
    749       int length;
    750 
    751       DoubleToAscii(v, DTOA_SHORTEST, 0,
    752                     Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    753                     &sign, &length, &decimal_point);
    754 
    755       if (sign) builder.AddCharacter('-');
    756 
    757       if (length <= decimal_point && decimal_point <= 21) {
    758         // ECMA-262 section 9.8.1 step 6.
    759         builder.AddString(decimal_rep);
    760         builder.AddPadding('0', decimal_point - length);
    761 
    762       } else if (0 < decimal_point && decimal_point <= 21) {
    763         // ECMA-262 section 9.8.1 step 7.
    764         builder.AddSubstring(decimal_rep, decimal_point);
    765         builder.AddCharacter('.');
    766         builder.AddString(decimal_rep + decimal_point);
    767 
    768       } else if (decimal_point <= 0 && decimal_point > -6) {
    769         // ECMA-262 section 9.8.1 step 8.
    770         builder.AddString("0.");
    771         builder.AddPadding('0', -decimal_point);
    772         builder.AddString(decimal_rep);
    773 
    774       } else {
    775         // ECMA-262 section 9.8.1 step 9 and 10 combined.
    776         builder.AddCharacter(decimal_rep[0]);
    777         if (length != 1) {
    778           builder.AddCharacter('.');
    779           builder.AddString(decimal_rep + 1);
    780         }
    781         builder.AddCharacter('e');
    782         builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
    783         int exponent = decimal_point - 1;
    784         if (exponent < 0) exponent = -exponent;
    785         builder.AddFormatted("%d", exponent);
    786       }
    787     return builder.Finalize();
    788     }
    789   }
    790 }
    791 
    792 
    793 const char* IntToCString(int n, Vector<char> buffer) {
    794   bool negative = false;
    795   if (n < 0) {
    796     // We must not negate the most negative int.
    797     if (n == kMinInt) return DoubleToCString(n, buffer);
    798     negative = true;
    799     n = -n;
    800   }
    801   // Build the string backwards from the least significant digit.
    802   int i = buffer.length();
    803   buffer[--i] = '\0';
    804   do {
    805     buffer[--i] = '0' + (n % 10);
    806     n /= 10;
    807   } while (n);
    808   if (negative) buffer[--i] = '-';
    809   return buffer.start() + i;
    810 }
    811 
    812 
    813 char* DoubleToFixedCString(double value, int f) {
    814   const int kMaxDigitsBeforePoint = 21;
    815   const double kFirstNonFixed = 1e21;
    816   const int kMaxDigitsAfterPoint = 20;
    817   ASSERT(f >= 0);
    818   ASSERT(f <= kMaxDigitsAfterPoint);
    819 
    820   bool negative = false;
    821   double abs_value = value;
    822   if (value < 0) {
    823     abs_value = -value;
    824     negative = true;
    825   }
    826 
    827   // If abs_value has more than kMaxDigitsBeforePoint digits before the point
    828   // use the non-fixed conversion routine.
    829   if (abs_value >= kFirstNonFixed) {
    830     char arr[100];
    831     Vector<char> buffer(arr, ARRAY_SIZE(arr));
    832     return StrDup(DoubleToCString(value, buffer));
    833   }
    834 
    835   // Find a sufficiently precise decimal representation of n.
    836   int decimal_point;
    837   int sign;
    838   // Add space for the '\0' byte.
    839   const int kDecimalRepCapacity =
    840       kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
    841   char decimal_rep[kDecimalRepCapacity];
    842   int decimal_rep_length;
    843   DoubleToAscii(value, DTOA_FIXED, f,
    844                 Vector<char>(decimal_rep, kDecimalRepCapacity),
    845                 &sign, &decimal_rep_length, &decimal_point);
    846 
    847   // Create a representation that is padded with zeros if needed.
    848   int zero_prefix_length = 0;
    849   int zero_postfix_length = 0;
    850 
    851   if (decimal_point <= 0) {
    852     zero_prefix_length = -decimal_point + 1;
    853     decimal_point = 1;
    854   }
    855 
    856   if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
    857     zero_postfix_length = decimal_point + f - decimal_rep_length -
    858                           zero_prefix_length;
    859   }
    860 
    861   unsigned rep_length =
    862       zero_prefix_length + decimal_rep_length + zero_postfix_length;
    863   StringBuilder rep_builder(rep_length + 1);
    864   rep_builder.AddPadding('0', zero_prefix_length);
    865   rep_builder.AddString(decimal_rep);
    866   rep_builder.AddPadding('0', zero_postfix_length);
    867   char* rep = rep_builder.Finalize();
    868 
    869   // Create the result string by appending a minus and putting in a
    870   // decimal point if needed.
    871   unsigned result_size = decimal_point + f + 2;
    872   StringBuilder builder(result_size + 1);
    873   if (negative) builder.AddCharacter('-');
    874   builder.AddSubstring(rep, decimal_point);
    875   if (f > 0) {
    876     builder.AddCharacter('.');
    877     builder.AddSubstring(rep + decimal_point, f);
    878   }
    879   DeleteArray(rep);
    880   return builder.Finalize();
    881 }
    882 
    883 
    884 static char* CreateExponentialRepresentation(char* decimal_rep,
    885                                              int exponent,
    886                                              bool negative,
    887                                              int significant_digits) {
    888   bool negative_exponent = false;
    889   if (exponent < 0) {
    890     negative_exponent = true;
    891     exponent = -exponent;
    892   }
    893 
    894   // Leave room in the result for appending a minus, for a period, the
    895   // letter 'e', a minus or a plus depending on the exponent, and a
    896   // three digit exponent.
    897   unsigned result_size = significant_digits + 7;
    898   StringBuilder builder(result_size + 1);
    899 
    900   if (negative) builder.AddCharacter('-');
    901   builder.AddCharacter(decimal_rep[0]);
    902   if (significant_digits != 1) {
    903     builder.AddCharacter('.');
    904     builder.AddString(decimal_rep + 1);
    905     int rep_length = StrLength(decimal_rep);
    906     builder.AddPadding('0', significant_digits - rep_length);
    907   }
    908 
    909   builder.AddCharacter('e');
    910   builder.AddCharacter(negative_exponent ? '-' : '+');
    911   builder.AddFormatted("%d", exponent);
    912   return builder.Finalize();
    913 }
    914 
    915 
    916 
    917 char* DoubleToExponentialCString(double value, int f) {
    918   const int kMaxDigitsAfterPoint = 20;
    919   // f might be -1 to signal that f was undefined in JavaScript.
    920   ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
    921 
    922   bool negative = false;
    923   if (value < 0) {
    924     value = -value;
    925     negative = true;
    926   }
    927 
    928   // Find a sufficiently precise decimal representation of n.
    929   int decimal_point;
    930   int sign;
    931   // f corresponds to the digits after the point. There is always one digit
    932   // before the point. The number of requested_digits equals hence f + 1.
    933   // And we have to add one character for the null-terminator.
    934   const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
    935   // Make sure that the buffer is big enough, even if we fall back to the
    936   // shortest representation (which happens when f equals -1).
    937   ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
    938   char decimal_rep[kV8DtoaBufferCapacity];
    939   int decimal_rep_length;
    940 
    941   if (f == -1) {
    942     DoubleToAscii(value, DTOA_SHORTEST, 0,
    943                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    944                   &sign, &decimal_rep_length, &decimal_point);
    945     f = decimal_rep_length - 1;
    946   } else {
    947     DoubleToAscii(value, DTOA_PRECISION, f + 1,
    948                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    949                   &sign, &decimal_rep_length, &decimal_point);
    950   }
    951   ASSERT(decimal_rep_length > 0);
    952   ASSERT(decimal_rep_length <= f + 1);
    953 
    954   int exponent = decimal_point - 1;
    955   char* result =
    956       CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
    957 
    958   return result;
    959 }
    960 
    961 
    962 char* DoubleToPrecisionCString(double value, int p) {
    963   const int kMinimalDigits = 1;
    964   const int kMaximalDigits = 21;
    965   ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
    966   USE(kMinimalDigits);
    967 
    968   bool negative = false;
    969   if (value < 0) {
    970     value = -value;
    971     negative = true;
    972   }
    973 
    974   // Find a sufficiently precise decimal representation of n.
    975   int decimal_point;
    976   int sign;
    977   // Add one for the terminating null character.
    978   const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
    979   char decimal_rep[kV8DtoaBufferCapacity];
    980   int decimal_rep_length;
    981 
    982   DoubleToAscii(value, DTOA_PRECISION, p,
    983                 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    984                 &sign, &decimal_rep_length, &decimal_point);
    985   ASSERT(decimal_rep_length <= p);
    986 
    987   int exponent = decimal_point - 1;
    988 
    989   char* result = NULL;
    990 
    991   if (exponent < -6 || exponent >= p) {
    992     result =
    993         CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
    994   } else {
    995     // Use fixed notation.
    996     //
    997     // Leave room in the result for appending a minus, a period and in
    998     // the case where decimal_point is not positive for a zero in
    999     // front of the period.
   1000     unsigned result_size = (decimal_point <= 0)
   1001         ? -decimal_point + p + 3
   1002         : p + 2;
   1003     StringBuilder builder(result_size + 1);
   1004     if (negative) builder.AddCharacter('-');
   1005     if (decimal_point <= 0) {
   1006       builder.AddString("0.");
   1007       builder.AddPadding('0', -decimal_point);
   1008       builder.AddString(decimal_rep);
   1009       builder.AddPadding('0', p - decimal_rep_length);
   1010     } else {
   1011       const int m = Min(decimal_rep_length, decimal_point);
   1012       builder.AddSubstring(decimal_rep, m);
   1013       builder.AddPadding('0', decimal_point - decimal_rep_length);
   1014       if (decimal_point < p) {
   1015         builder.AddCharacter('.');
   1016         const int extra = negative ? 2 : 1;
   1017         if (decimal_rep_length > decimal_point) {
   1018           const int len = StrLength(decimal_rep + decimal_point);
   1019           const int n = Min(len, p - (builder.position() - extra));
   1020           builder.AddSubstring(decimal_rep + decimal_point, n);
   1021         }
   1022         builder.AddPadding('0', extra + (p - builder.position()));
   1023       }
   1024     }
   1025     result = builder.Finalize();
   1026   }
   1027 
   1028   return result;
   1029 }
   1030 
   1031 
   1032 char* DoubleToRadixCString(double value, int radix) {
   1033   ASSERT(radix >= 2 && radix <= 36);
   1034 
   1035   // Character array used for conversion.
   1036   static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
   1037 
   1038   // Buffer for the integer part of the result. 1024 chars is enough
   1039   // for max integer value in radix 2.  We need room for a sign too.
   1040   static const int kBufferSize = 1100;
   1041   char integer_buffer[kBufferSize];
   1042   integer_buffer[kBufferSize - 1] = '\0';
   1043 
   1044   // Buffer for the decimal part of the result.  We only generate up
   1045   // to kBufferSize - 1 chars for the decimal part.
   1046   char decimal_buffer[kBufferSize];
   1047   decimal_buffer[kBufferSize - 1] = '\0';
   1048 
   1049   // Make sure the value is positive.
   1050   bool is_negative = value < 0.0;
   1051   if (is_negative) value = -value;
   1052 
   1053   // Get the integer part and the decimal part.
   1054   double integer_part = floor(value);
   1055   double decimal_part = value - integer_part;
   1056 
   1057   // Convert the integer part starting from the back.  Always generate
   1058   // at least one digit.
   1059   int integer_pos = kBufferSize - 2;
   1060   do {
   1061     integer_buffer[integer_pos--] =
   1062         chars[static_cast<int>(modulo(integer_part, radix))];
   1063     integer_part /= radix;
   1064   } while (integer_part >= 1.0);
   1065   // Sanity check.
   1066   ASSERT(integer_pos > 0);
   1067   // Add sign if needed.
   1068   if (is_negative) integer_buffer[integer_pos--] = '-';
   1069 
   1070   // Convert the decimal part.  Repeatedly multiply by the radix to
   1071   // generate the next char.  Never generate more than kBufferSize - 1
   1072   // chars.
   1073   //
   1074   // TODO(1093998): We will often generate a full decimal_buffer of
   1075   // chars because hitting zero will often not happen.  The right
   1076   // solution would be to continue until the string representation can
   1077   // be read back and yield the original value.  To implement this
   1078   // efficiently, we probably have to modify dtoa.
   1079   int decimal_pos = 0;
   1080   while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
   1081     decimal_part *= radix;
   1082     decimal_buffer[decimal_pos++] =
   1083         chars[static_cast<int>(floor(decimal_part))];
   1084     decimal_part -= floor(decimal_part);
   1085   }
   1086   decimal_buffer[decimal_pos] = '\0';
   1087 
   1088   // Compute the result size.
   1089   int integer_part_size = kBufferSize - 2 - integer_pos;
   1090   // Make room for zero termination.
   1091   unsigned result_size = integer_part_size + decimal_pos;
   1092   // If the number has a decimal part, leave room for the period.
   1093   if (decimal_pos > 0) result_size++;
   1094   // Allocate result and fill in the parts.
   1095   StringBuilder builder(result_size + 1);
   1096   builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
   1097   if (decimal_pos > 0) builder.AddCharacter('.');
   1098   builder.AddSubstring(decimal_buffer, decimal_pos);
   1099   return builder.Finalize();
   1100 }
   1101 
   1102 
   1103 static Mutex* dtoa_lock_one = OS::CreateMutex();
   1104 static Mutex* dtoa_lock_zero = OS::CreateMutex();
   1105 
   1106 
   1107 } }  // namespace v8::internal
   1108 
   1109 
   1110 extern "C" {
   1111 void ACQUIRE_DTOA_LOCK(int n) {
   1112   ASSERT(n == 0 || n == 1);
   1113   (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock();
   1114 }
   1115 
   1116 
   1117 void FREE_DTOA_LOCK(int n) {
   1118   ASSERT(n == 0 || n == 1);
   1119   (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->
   1120       Unlock();
   1121 }
   1122 }
   1123