Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/conversions.h"
      6 
      7 #include <limits.h>
      8 #include <stdarg.h>
      9 #include <cmath>
     10 
     11 #include "src/allocation.h"
     12 #include "src/assert-scope.h"
     13 #include "src/char-predicates-inl.h"
     14 #include "src/dtoa.h"
     15 #include "src/handles.h"
     16 #include "src/heap/factory.h"
     17 #include "src/objects-inl.h"
     18 #include "src/objects/bigint.h"
     19 #include "src/strtod.h"
     20 #include "src/unicode-cache-inl.h"
     21 #include "src/utils.h"
     22 
     23 #if defined(_STLP_VENDOR_CSTD)
     24 // STLPort doesn't import fpclassify into the std namespace.
     25 #define FPCLASSIFY_NAMESPACE
     26 #else
     27 #define FPCLASSIFY_NAMESPACE std
     28 #endif
     29 
     30 namespace v8 {
     31 namespace internal {
     32 
     33 namespace {
     34 
     35 inline double JunkStringValue() {
     36   return bit_cast<double, uint64_t>(kQuietNaNMask);
     37 }
     38 
     39 inline double SignedZero(bool negative) {
     40   return negative ? uint64_to_double(Double::kSignMask) : 0.0;
     41 }
     42 
     43 inline bool isDigit(int x, int radix) {
     44   return (x >= '0' && x <= '9' && x < '0' + radix) ||
     45          (radix > 10 && x >= 'a' && x < 'a' + radix - 10) ||
     46          (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
     47 }
     48 
     49 inline bool isBinaryDigit(int x) { return x == '0' || x == '1'; }
     50 
     51 template <class Iterator, class EndMark>
     52 bool SubStringEquals(Iterator* current, EndMark end, const char* substring) {
     53   DCHECK(**current == *substring);
     54   for (substring++; *substring != '\0'; substring++) {
     55     ++*current;
     56     if (*current == end || **current != *substring) return false;
     57   }
     58   ++*current;
     59   return true;
     60 }
     61 
     62 // Returns true if a nonspace character has been found and false if the
     63 // end was been reached before finding a nonspace character.
     64 template <class Iterator, class EndMark>
     65 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache, Iterator* current,
     66                               EndMark end) {
     67   while (*current != end) {
     68     if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true;
     69     ++*current;
     70   }
     71   return false;
     72 }
     73 
     74 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
     75 template <int radix_log_2, class Iterator, class EndMark>
     76 double InternalStringToIntDouble(UnicodeCache* unicode_cache, Iterator current,
     77                                  EndMark end, bool negative,
     78                                  bool allow_trailing_junk) {
     79   DCHECK(current != end);
     80 
     81   // Skip leading 0s.
     82   while (*current == '0') {
     83     ++current;
     84     if (current == end) return SignedZero(negative);
     85   }
     86 
     87   int64_t number = 0;
     88   int exponent = 0;
     89   const int radix = (1 << radix_log_2);
     90 
     91   int lim_0 = '0' + (radix < 10 ? radix : 10);
     92   int lim_a = 'a' + (radix - 10);
     93   int lim_A = 'A' + (radix - 10);
     94 
     95   do {
     96     int digit;
     97     if (*current >= '0' && *current < lim_0) {
     98       digit = static_cast<char>(*current) - '0';
     99     } else if (*current >= 'a' && *current < lim_a) {
    100       digit = static_cast<char>(*current) - 'a' + 10;
    101     } else if (*current >= 'A' && *current < lim_A) {
    102       digit = static_cast<char>(*current) - 'A' + 10;
    103     } else {
    104       if (allow_trailing_junk ||
    105           !AdvanceToNonspace(unicode_cache, &current, end)) {
    106         break;
    107       } else {
    108         return JunkStringValue();
    109       }
    110     }
    111 
    112     number = number * radix + digit;
    113     int overflow = static_cast<int>(number >> 53);
    114     if (overflow != 0) {
    115       // Overflow occurred. Need to determine which direction to round the
    116       // result.
    117       int overflow_bits_count = 1;
    118       while (overflow > 1) {
    119         overflow_bits_count++;
    120         overflow >>= 1;
    121       }
    122 
    123       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
    124       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
    125       number >>= overflow_bits_count;
    126       exponent = overflow_bits_count;
    127 
    128       bool zero_tail = true;
    129       while (true) {
    130         ++current;
    131         if (current == end || !isDigit(*current, radix)) break;
    132         zero_tail = zero_tail && *current == '0';
    133         exponent += radix_log_2;
    134       }
    135 
    136       if (!allow_trailing_junk &&
    137           AdvanceToNonspace(unicode_cache, &current, end)) {
    138         return JunkStringValue();
    139       }
    140 
    141       int middle_value = (1 << (overflow_bits_count - 1));
    142       if (dropped_bits > middle_value) {
    143         number++;  // Rounding up.
    144       } else if (dropped_bits == middle_value) {
    145         // Rounding to even to consistency with decimals: half-way case rounds
    146         // up if significant part is odd and down otherwise.
    147         if ((number & 1) != 0 || !zero_tail) {
    148           number++;  // Rounding up.
    149         }
    150       }
    151 
    152       // Rounding up may cause overflow.
    153       if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
    154         exponent++;
    155         number >>= 1;
    156       }
    157       break;
    158     }
    159     ++current;
    160   } while (current != end);
    161 
    162   DCHECK(number < ((int64_t)1 << 53));
    163   DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
    164 
    165   if (exponent == 0) {
    166     if (negative) {
    167       if (number == 0) return -0.0;
    168       number = -number;
    169     }
    170     return static_cast<double>(number);
    171   }
    172 
    173   DCHECK_NE(number, 0);
    174   return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
    175 }
    176 
    177 // ES6 18.2.5 parseInt(string, radix) (with NumberParseIntHelper subclass);
    178 // and BigInt parsing cases from https://tc39.github.io/proposal-bigint/
    179 // (with StringToBigIntHelper subclass).
    180 class StringToIntHelper {
    181  public:
    182   StringToIntHelper(Isolate* isolate, Handle<String> subject, int radix)
    183       : isolate_(isolate), subject_(subject), radix_(radix) {
    184     DCHECK(subject->IsFlat());
    185   }
    186 
    187   // Used for the StringToBigInt operation.
    188   StringToIntHelper(Isolate* isolate, Handle<String> subject)
    189       : isolate_(isolate), subject_(subject) {
    190     DCHECK(subject->IsFlat());
    191   }
    192 
    193   // Used for parsing BigInt literals, where the input is a Zone-allocated
    194   // buffer of one-byte digits, along with an optional radix prefix.
    195   StringToIntHelper(Isolate* isolate, const uint8_t* subject, int length)
    196       : isolate_(isolate), raw_one_byte_subject_(subject), length_(length) {}
    197   virtual ~StringToIntHelper() {}
    198 
    199  protected:
    200   // Subclasses must implement these:
    201   virtual void AllocateResult() = 0;
    202   virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) = 0;
    203 
    204   // Subclasses must call this to do all the work.
    205   void ParseInt();
    206 
    207   // Subclasses may override this.
    208   virtual void HandleSpecialCases() {}
    209 
    210   // Subclass constructors should call these for configuration before calling
    211   // ParseInt().
    212   void set_allow_binary_and_octal_prefixes() {
    213     allow_binary_and_octal_prefixes_ = true;
    214   }
    215   void set_disallow_trailing_junk() { allow_trailing_junk_ = false; }
    216 
    217   bool IsOneByte() const {
    218     return raw_one_byte_subject_ != nullptr ||
    219            subject_->IsOneByteRepresentationUnderneath();
    220   }
    221 
    222   Vector<const uint8_t> GetOneByteVector() {
    223     if (raw_one_byte_subject_ != nullptr) {
    224       return Vector<const uint8_t>(raw_one_byte_subject_, length_);
    225     }
    226     return subject_->GetFlatContent().ToOneByteVector();
    227   }
    228 
    229   Vector<const uc16> GetTwoByteVector() {
    230     return subject_->GetFlatContent().ToUC16Vector();
    231   }
    232 
    233   // Subclasses get access to internal state:
    234   enum State { kRunning, kError, kJunk, kEmpty, kZero, kDone };
    235 
    236   enum class Sign { kNegative, kPositive, kNone };
    237 
    238   Isolate* isolate() { return isolate_; }
    239   int radix() { return radix_; }
    240   int cursor() { return cursor_; }
    241   int length() { return length_; }
    242   bool negative() { return sign_ == Sign::kNegative; }
    243   Sign sign() { return sign_; }
    244   State state() { return state_; }
    245   void set_state(State state) { state_ = state; }
    246 
    247  private:
    248   template <class Char>
    249   void DetectRadixInternal(Char current, int length);
    250   template <class Char>
    251   void ParseInternal(Char start);
    252 
    253   Isolate* isolate_;
    254   Handle<String> subject_;
    255   const uint8_t* raw_one_byte_subject_ = nullptr;
    256   int radix_ = 0;
    257   int cursor_ = 0;
    258   int length_ = 0;
    259   Sign sign_ = Sign::kNone;
    260   bool leading_zero_ = false;
    261   bool allow_binary_and_octal_prefixes_ = false;
    262   bool allow_trailing_junk_ = true;
    263   State state_ = kRunning;
    264 };
    265 
    266 void StringToIntHelper::ParseInt() {
    267   {
    268     DisallowHeapAllocation no_gc;
    269     if (IsOneByte()) {
    270       Vector<const uint8_t> vector = GetOneByteVector();
    271       DetectRadixInternal(vector.start(), vector.length());
    272     } else {
    273       Vector<const uc16> vector = GetTwoByteVector();
    274       DetectRadixInternal(vector.start(), vector.length());
    275     }
    276   }
    277   if (state_ != kRunning) return;
    278   AllocateResult();
    279   HandleSpecialCases();
    280   if (state_ != kRunning) return;
    281   {
    282     DisallowHeapAllocation no_gc;
    283     if (IsOneByte()) {
    284       Vector<const uint8_t> vector = GetOneByteVector();
    285       DCHECK_EQ(length_, vector.length());
    286       ParseInternal(vector.start());
    287     } else {
    288       Vector<const uc16> vector = GetTwoByteVector();
    289       DCHECK_EQ(length_, vector.length());
    290       ParseInternal(vector.start());
    291     }
    292   }
    293   DCHECK_NE(state_, kRunning);
    294 }
    295 
    296 template <class Char>
    297 void StringToIntHelper::DetectRadixInternal(Char current, int length) {
    298   Char start = current;
    299   length_ = length;
    300   Char end = start + length;
    301   UnicodeCache* unicode_cache = isolate_->unicode_cache();
    302 
    303   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    304     return set_state(kEmpty);
    305   }
    306 
    307   if (*current == '+') {
    308     // Ignore leading sign; skip following spaces.
    309     ++current;
    310     if (current == end) {
    311       return set_state(kJunk);
    312     }
    313     sign_ = Sign::kPositive;
    314   } else if (*current == '-') {
    315     ++current;
    316     if (current == end) {
    317       return set_state(kJunk);
    318     }
    319     sign_ = Sign::kNegative;
    320   }
    321 
    322   if (radix_ == 0) {
    323     // Radix detection.
    324     radix_ = 10;
    325     if (*current == '0') {
    326       ++current;
    327       if (current == end) return set_state(kZero);
    328       if (*current == 'x' || *current == 'X') {
    329         radix_ = 16;
    330         ++current;
    331         if (current == end) return set_state(kJunk);
    332       } else if (allow_binary_and_octal_prefixes_ &&
    333                  (*current == 'o' || *current == 'O')) {
    334         radix_ = 8;
    335         ++current;
    336         if (current == end) return set_state(kJunk);
    337       } else if (allow_binary_and_octal_prefixes_ &&
    338                  (*current == 'b' || *current == 'B')) {
    339         radix_ = 2;
    340         ++current;
    341         if (current == end) return set_state(kJunk);
    342       } else {
    343         leading_zero_ = true;
    344       }
    345     }
    346   } else if (radix_ == 16) {
    347     if (*current == '0') {
    348       // Allow "0x" prefix.
    349       ++current;
    350       if (current == end) return set_state(kZero);
    351       if (*current == 'x' || *current == 'X') {
    352         ++current;
    353         if (current == end) return set_state(kJunk);
    354       } else {
    355         leading_zero_ = true;
    356       }
    357     }
    358   }
    359   // Skip leading zeros.
    360   while (*current == '0') {
    361     leading_zero_ = true;
    362     ++current;
    363     if (current == end) return set_state(kZero);
    364   }
    365 
    366   if (!leading_zero_ && !isDigit(*current, radix_)) {
    367     return set_state(kJunk);
    368   }
    369 
    370   DCHECK(radix_ >= 2 && radix_ <= 36);
    371   STATIC_ASSERT(String::kMaxLength <= INT_MAX);
    372   cursor_ = static_cast<int>(current - start);
    373 }
    374 
    375 template <class Char>
    376 void StringToIntHelper::ParseInternal(Char start) {
    377   Char current = start + cursor_;
    378   Char end = start + length_;
    379 
    380   // The following code causes accumulating rounding error for numbers greater
    381   // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
    382   // 16, or 32, then mathInt may be an implementation-dependent approximation to
    383   // the mathematical integer value" (15.1.2.2).
    384 
    385   int lim_0 = '0' + (radix_ < 10 ? radix_ : 10);
    386   int lim_a = 'a' + (radix_ - 10);
    387   int lim_A = 'A' + (radix_ - 10);
    388 
    389   // NOTE: The code for computing the value may seem a bit complex at
    390   // first glance. It is structured to use 32-bit multiply-and-add
    391   // loops as long as possible to avoid losing precision.
    392 
    393   bool done = false;
    394   do {
    395     // Parse the longest part of the string starting at {current}
    396     // possible while keeping the multiplier, and thus the part
    397     // itself, within 32 bits.
    398     uint32_t part = 0, multiplier = 1;
    399     while (true) {
    400       uint32_t d;
    401       if (*current >= '0' && *current < lim_0) {
    402         d = *current - '0';
    403       } else if (*current >= 'a' && *current < lim_a) {
    404         d = *current - 'a' + 10;
    405       } else if (*current >= 'A' && *current < lim_A) {
    406         d = *current - 'A' + 10;
    407       } else {
    408         done = true;
    409         break;
    410       }
    411 
    412       // Update the value of the part as long as the multiplier fits
    413       // in 32 bits. When we can't guarantee that the next iteration
    414       // will not overflow the multiplier, we stop parsing the part
    415       // by leaving the loop.
    416       const uint32_t kMaximumMultiplier = 0xFFFFFFFFU / 36;
    417       uint32_t m = multiplier * static_cast<uint32_t>(radix_);
    418       if (m > kMaximumMultiplier) break;
    419       part = part * radix_ + d;
    420       multiplier = m;
    421       DCHECK(multiplier > part);
    422 
    423       ++current;
    424       if (current == end) {
    425         done = true;
    426         break;
    427       }
    428     }
    429 
    430     // Update the value and skip the part in the string.
    431     ResultMultiplyAdd(multiplier, part);
    432   } while (!done);
    433 
    434   if (!allow_trailing_junk_ &&
    435       AdvanceToNonspace(isolate_->unicode_cache(), &current, end)) {
    436     return set_state(kJunk);
    437   }
    438 
    439   return set_state(kDone);
    440 }
    441 
    442 class NumberParseIntHelper : public StringToIntHelper {
    443  public:
    444   NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix)
    445       : StringToIntHelper(isolate, string, radix) {}
    446 
    447   double GetResult() {
    448     ParseInt();
    449     switch (state()) {
    450       case kJunk:
    451       case kEmpty:
    452         return JunkStringValue();
    453       case kZero:
    454         return SignedZero(negative());
    455       case kDone:
    456         return negative() ? -result_ : result_;
    457       case kError:
    458       case kRunning:
    459         break;
    460     }
    461     UNREACHABLE();
    462   }
    463 
    464  protected:
    465   virtual void AllocateResult() {}
    466   virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) {
    467     result_ = result_ * multiplier + part;
    468   }
    469 
    470  private:
    471   virtual void HandleSpecialCases() {
    472     bool is_power_of_two = base::bits::IsPowerOfTwo(radix());
    473     if (!is_power_of_two && radix() != 10) return;
    474     DisallowHeapAllocation no_gc;
    475     if (IsOneByte()) {
    476       Vector<const uint8_t> vector = GetOneByteVector();
    477       DCHECK_EQ(length(), vector.length());
    478       result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
    479                                 : HandleBaseTenCase(vector.start());
    480     } else {
    481       Vector<const uc16> vector = GetTwoByteVector();
    482       DCHECK_EQ(length(), vector.length());
    483       result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
    484                                 : HandleBaseTenCase(vector.start());
    485     }
    486     set_state(kDone);
    487   }
    488 
    489   template <class Char>
    490   double HandlePowerOfTwoCase(Char start) {
    491     Char current = start + cursor();
    492     Char end = start + length();
    493     UnicodeCache* unicode_cache = isolate()->unicode_cache();
    494     const bool allow_trailing_junk = true;
    495     // GetResult() will take care of the sign bit, so ignore it for now.
    496     const bool negative = false;
    497     switch (radix()) {
    498       case 2:
    499         return InternalStringToIntDouble<1>(unicode_cache, current, end,
    500                                             negative, allow_trailing_junk);
    501       case 4:
    502         return InternalStringToIntDouble<2>(unicode_cache, current, end,
    503                                             negative, allow_trailing_junk);
    504       case 8:
    505         return InternalStringToIntDouble<3>(unicode_cache, current, end,
    506                                             negative, allow_trailing_junk);
    507 
    508       case 16:
    509         return InternalStringToIntDouble<4>(unicode_cache, current, end,
    510                                             negative, allow_trailing_junk);
    511 
    512       case 32:
    513         return InternalStringToIntDouble<5>(unicode_cache, current, end,
    514                                             negative, allow_trailing_junk);
    515       default:
    516         UNREACHABLE();
    517     }
    518   }
    519 
    520   template <class Char>
    521   double HandleBaseTenCase(Char start) {
    522     // Parsing with strtod.
    523     Char current = start + cursor();
    524     Char end = start + length();
    525     const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
    526     // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
    527     // end.
    528     const int kBufferSize = kMaxSignificantDigits + 2;
    529     char buffer[kBufferSize];
    530     int buffer_pos = 0;
    531     while (*current >= '0' && *current <= '9') {
    532       if (buffer_pos <= kMaxSignificantDigits) {
    533         // If the number has more than kMaxSignificantDigits it will be parsed
    534         // as infinity.
    535         DCHECK_LT(buffer_pos, kBufferSize);
    536         buffer[buffer_pos++] = static_cast<char>(*current);
    537       }
    538       ++current;
    539       if (current == end) break;
    540     }
    541 
    542     SLOW_DCHECK(buffer_pos < kBufferSize);
    543     buffer[buffer_pos] = '\0';
    544     Vector<const char> buffer_vector(buffer, buffer_pos);
    545     return Strtod(buffer_vector, 0);
    546   }
    547 
    548   double result_ = 0;
    549 };
    550 
    551 // Converts a string to a double value. Assumes the Iterator supports
    552 // the following operations:
    553 // 1. current == end (other ops are not allowed), current != end.
    554 // 2. *current - gets the current character in the sequence.
    555 // 3. ++current (advances the position).
    556 template <class Iterator, class EndMark>
    557 double InternalStringToDouble(UnicodeCache* unicode_cache, Iterator current,
    558                               EndMark end, int flags, double empty_string_val) {
    559   // To make sure that iterator dereferencing is valid the following
    560   // convention is used:
    561   // 1. Each '++current' statement is followed by check for equality to 'end'.
    562   // 2. If AdvanceToNonspace returned false then current == end.
    563   // 3. If 'current' becomes be equal to 'end' the function returns or goes to
    564   // 'parsing_done'.
    565   // 4. 'current' is not dereferenced after the 'parsing_done' label.
    566   // 5. Code before 'parsing_done' may rely on 'current != end'.
    567   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    568     return empty_string_val;
    569   }
    570 
    571   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
    572 
    573   // Maximum number of significant digits in decimal representation.
    574   // The longest possible double in decimal representation is
    575   // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
    576   // (768 digits). If we parse a number whose first digits are equal to a
    577   // mean of 2 adjacent doubles (that could have up to 769 digits) the result
    578   // must be rounded to the bigger one unless the tail consists of zeros, so
    579   // we don't need to preserve all the digits.
    580   const int kMaxSignificantDigits = 772;
    581 
    582   // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
    583   const int kBufferSize = kMaxSignificantDigits + 10;
    584   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
    585   int buffer_pos = 0;
    586 
    587   // Exponent will be adjusted if insignificant digits of the integer part
    588   // or insignificant leading zeros of the fractional part are dropped.
    589   int exponent = 0;
    590   int significant_digits = 0;
    591   int insignificant_digits = 0;
    592   bool nonzero_digit_dropped = false;
    593 
    594   enum Sign { NONE, NEGATIVE, POSITIVE };
    595 
    596   Sign sign = NONE;
    597 
    598   if (*current == '+') {
    599     // Ignore leading sign.
    600     ++current;
    601     if (current == end) return JunkStringValue();
    602     sign = POSITIVE;
    603   } else if (*current == '-') {
    604     ++current;
    605     if (current == end) return JunkStringValue();
    606     sign = NEGATIVE;
    607   }
    608 
    609   static const char kInfinityString[] = "Infinity";
    610   if (*current == kInfinityString[0]) {
    611     if (!SubStringEquals(&current, end, kInfinityString)) {
    612       return JunkStringValue();
    613     }
    614 
    615     if (!allow_trailing_junk &&
    616         AdvanceToNonspace(unicode_cache, &current, end)) {
    617       return JunkStringValue();
    618     }
    619 
    620     DCHECK_EQ(buffer_pos, 0);
    621     return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
    622   }
    623 
    624   bool leading_zero = false;
    625   if (*current == '0') {
    626     ++current;
    627     if (current == end) return SignedZero(sign == NEGATIVE);
    628 
    629     leading_zero = true;
    630 
    631     // It could be hexadecimal value.
    632     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
    633       ++current;
    634       if (current == end || !isDigit(*current, 16) || sign != NONE) {
    635         return JunkStringValue();  // "0x".
    636       }
    637 
    638       return InternalStringToIntDouble<4>(unicode_cache, current, end, false,
    639                                           allow_trailing_junk);
    640 
    641       // It could be an explicit octal value.
    642     } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
    643       ++current;
    644       if (current == end || !isDigit(*current, 8) || sign != NONE) {
    645         return JunkStringValue();  // "0o".
    646       }
    647 
    648       return InternalStringToIntDouble<3>(unicode_cache, current, end, false,
    649                                           allow_trailing_junk);
    650 
    651       // It could be a binary value.
    652     } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
    653       ++current;
    654       if (current == end || !isBinaryDigit(*current) || sign != NONE) {
    655         return JunkStringValue();  // "0b".
    656       }
    657 
    658       return InternalStringToIntDouble<1>(unicode_cache, current, end, false,
    659                                           allow_trailing_junk);
    660     }
    661 
    662     // Ignore leading zeros in the integer part.
    663     while (*current == '0') {
    664       ++current;
    665       if (current == end) return SignedZero(sign == NEGATIVE);
    666     }
    667   }
    668 
    669   bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
    670 
    671   // Copy significant digits of the integer part (if any) to the buffer.
    672   while (*current >= '0' && *current <= '9') {
    673     if (significant_digits < kMaxSignificantDigits) {
    674       DCHECK_LT(buffer_pos, kBufferSize);
    675       buffer[buffer_pos++] = static_cast<char>(*current);
    676       significant_digits++;
    677       // Will later check if it's an octal in the buffer.
    678     } else {
    679       insignificant_digits++;  // Move the digit into the exponential part.
    680       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    681     }
    682     octal = octal && *current < '8';
    683     ++current;
    684     if (current == end) goto parsing_done;
    685   }
    686 
    687   if (significant_digits == 0) {
    688     octal = false;
    689   }
    690 
    691   if (*current == '.') {
    692     if (octal && !allow_trailing_junk) return JunkStringValue();
    693     if (octal) goto parsing_done;
    694 
    695     ++current;
    696     if (current == end) {
    697       if (significant_digits == 0 && !leading_zero) {
    698         return JunkStringValue();
    699       } else {
    700         goto parsing_done;
    701       }
    702     }
    703 
    704     if (significant_digits == 0) {
    705       // octal = false;
    706       // Integer part consists of 0 or is absent. Significant digits start after
    707       // leading zeros (if any).
    708       while (*current == '0') {
    709         ++current;
    710         if (current == end) return SignedZero(sign == NEGATIVE);
    711         exponent--;  // Move this 0 into the exponent.
    712       }
    713     }
    714 
    715     // There is a fractional part.  We don't emit a '.', but adjust the exponent
    716     // instead.
    717     while (*current >= '0' && *current <= '9') {
    718       if (significant_digits < kMaxSignificantDigits) {
    719         DCHECK_LT(buffer_pos, kBufferSize);
    720         buffer[buffer_pos++] = static_cast<char>(*current);
    721         significant_digits++;
    722         exponent--;
    723       } else {
    724         // Ignore insignificant digits in the fractional part.
    725         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    726       }
    727       ++current;
    728       if (current == end) goto parsing_done;
    729     }
    730   }
    731 
    732   if (!leading_zero && exponent == 0 && significant_digits == 0) {
    733     // If leading_zeros is true then the string contains zeros.
    734     // If exponent < 0 then string was [+-]\.0*...
    735     // If significant_digits != 0 the string is not equal to 0.
    736     // Otherwise there are no digits in the string.
    737     return JunkStringValue();
    738   }
    739 
    740   // Parse exponential part.
    741   if (*current == 'e' || *current == 'E') {
    742     if (octal) return JunkStringValue();
    743     ++current;
    744     if (current == end) {
    745       if (allow_trailing_junk) {
    746         goto parsing_done;
    747       } else {
    748         return JunkStringValue();
    749       }
    750     }
    751     char sign = '+';
    752     if (*current == '+' || *current == '-') {
    753       sign = static_cast<char>(*current);
    754       ++current;
    755       if (current == end) {
    756         if (allow_trailing_junk) {
    757           goto parsing_done;
    758         } else {
    759           return JunkStringValue();
    760         }
    761       }
    762     }
    763 
    764     if (current == end || *current < '0' || *current > '9') {
    765       if (allow_trailing_junk) {
    766         goto parsing_done;
    767       } else {
    768         return JunkStringValue();
    769       }
    770     }
    771 
    772     const int max_exponent = INT_MAX / 2;
    773     DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
    774     int num = 0;
    775     do {
    776       // Check overflow.
    777       int digit = *current - '0';
    778       if (num >= max_exponent / 10 &&
    779           !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
    780         num = max_exponent;
    781       } else {
    782         num = num * 10 + digit;
    783       }
    784       ++current;
    785     } while (current != end && *current >= '0' && *current <= '9');
    786 
    787     exponent += (sign == '-' ? -num : num);
    788   }
    789 
    790   if (!allow_trailing_junk && AdvanceToNonspace(unicode_cache, &current, end)) {
    791     return JunkStringValue();
    792   }
    793 
    794 parsing_done:
    795   exponent += insignificant_digits;
    796 
    797   if (octal) {
    798     return InternalStringToIntDouble<3>(unicode_cache, buffer,
    799                                         buffer + buffer_pos, sign == NEGATIVE,
    800                                         allow_trailing_junk);
    801   }
    802 
    803   if (nonzero_digit_dropped) {
    804     buffer[buffer_pos++] = '1';
    805     exponent--;
    806   }
    807 
    808   SLOW_DCHECK(buffer_pos < kBufferSize);
    809   buffer[buffer_pos] = '\0';
    810 
    811   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
    812   return (sign == NEGATIVE) ? -converted : converted;
    813 }
    814 
    815 }  // namespace
    816 
    817 double StringToDouble(UnicodeCache* unicode_cache,
    818                       const char* str, int flags, double empty_string_val) {
    819   // We cast to const uint8_t* here to avoid instantiating the
    820   // InternalStringToDouble() template for const char* as well.
    821   const uint8_t* start = reinterpret_cast<const uint8_t*>(str);
    822   const uint8_t* end = start + StrLength(str);
    823   return InternalStringToDouble(unicode_cache, start, end, flags,
    824                                 empty_string_val);
    825 }
    826 
    827 
    828 double StringToDouble(UnicodeCache* unicode_cache,
    829                       Vector<const uint8_t> str,
    830                       int flags,
    831                       double empty_string_val) {
    832   // We cast to const uint8_t* here to avoid instantiating the
    833   // InternalStringToDouble() template for const char* as well.
    834   const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
    835   const uint8_t* end = start + str.length();
    836   return InternalStringToDouble(unicode_cache, start, end, flags,
    837                                 empty_string_val);
    838 }
    839 
    840 
    841 double StringToDouble(UnicodeCache* unicode_cache,
    842                       Vector<const uc16> str,
    843                       int flags,
    844                       double empty_string_val) {
    845   const uc16* end = str.start() + str.length();
    846   return InternalStringToDouble(unicode_cache, str.start(), end, flags,
    847                                 empty_string_val);
    848 }
    849 
    850 double StringToInt(Isolate* isolate, Handle<String> string, int radix) {
    851   NumberParseIntHelper helper(isolate, string, radix);
    852   return helper.GetResult();
    853 }
    854 
    855 class StringToBigIntHelper : public StringToIntHelper {
    856  public:
    857   enum class Behavior { kStringToBigInt, kLiteral };
    858 
    859   // Used for StringToBigInt operation (BigInt constructor and == operator).
    860   StringToBigIntHelper(Isolate* isolate, Handle<String> string)
    861       : StringToIntHelper(isolate, string),
    862         behavior_(Behavior::kStringToBigInt) {
    863     set_allow_binary_and_octal_prefixes();
    864     set_disallow_trailing_junk();
    865   }
    866 
    867   // Used for parsing BigInt literals, where the input is a buffer of
    868   // one-byte ASCII digits, along with an optional radix prefix.
    869   StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length)
    870       : StringToIntHelper(isolate, string, length),
    871         behavior_(Behavior::kLiteral) {
    872     set_allow_binary_and_octal_prefixes();
    873   }
    874 
    875   MaybeHandle<BigInt> GetResult() {
    876     ParseInt();
    877     if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone &&
    878         radix() != 10) {
    879       return MaybeHandle<BigInt>();
    880     }
    881     if (state() == kEmpty) {
    882       if (behavior_ == Behavior::kStringToBigInt) {
    883         set_state(kZero);
    884       } else {
    885         UNREACHABLE();
    886       }
    887     }
    888     switch (state()) {
    889       case kJunk:
    890         if (should_throw() == kThrowOnError) {
    891           THROW_NEW_ERROR(isolate(),
    892                           NewSyntaxError(MessageTemplate::kBigIntInvalidString),
    893                           BigInt);
    894         } else {
    895           DCHECK_EQ(should_throw(), kDontThrow);
    896           return MaybeHandle<BigInt>();
    897         }
    898       case kZero:
    899         return BigInt::Zero(isolate());
    900       case kError:
    901         DCHECK_EQ(should_throw() == kThrowOnError,
    902                   isolate()->has_pending_exception());
    903         return MaybeHandle<BigInt>();
    904       case kDone:
    905         return BigInt::Finalize(result_, negative());
    906       case kEmpty:
    907       case kRunning:
    908         break;
    909     }
    910     UNREACHABLE();
    911   }
    912 
    913  protected:
    914   virtual void AllocateResult() {
    915     // We have to allocate a BigInt that's big enough to fit the result.
    916     // Conseratively assume that all remaining digits are significant.
    917     // Optimization opportunity: Would it makes sense to scan for trailing
    918     // junk before allocating the result?
    919     int charcount = length() - cursor();
    920     // For literals, we pretenure the allocated BigInt, since it's about
    921     // to be stored in the interpreter's constants array.
    922     PretenureFlag pretenure =
    923         behavior_ == Behavior::kLiteral ? TENURED : NOT_TENURED;
    924     MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
    925         isolate(), radix(), charcount, should_throw(), pretenure);
    926     if (!maybe.ToHandle(&result_)) {
    927       set_state(kError);
    928     }
    929   }
    930 
    931   virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) {
    932     BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier),
    933                                static_cast<uintptr_t>(part));
    934   }
    935 
    936  private:
    937   ShouldThrow should_throw() const { return kDontThrow; }
    938 
    939   Handle<FreshlyAllocatedBigInt> result_;
    940   Behavior behavior_;
    941 };
    942 
    943 MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) {
    944   string = String::Flatten(isolate, string);
    945   StringToBigIntHelper helper(isolate, string);
    946   return helper.GetResult();
    947 }
    948 
    949 MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) {
    950   StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string),
    951                               static_cast<int>(strlen(string)));
    952   return helper.GetResult();
    953 }
    954 
    955 const char* DoubleToCString(double v, Vector<char> buffer) {
    956   switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
    957     case FP_NAN: return "NaN";
    958     case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
    959     case FP_ZERO: return "0";
    960     default: {
    961       SimpleStringBuilder builder(buffer.start(), buffer.length());
    962       int decimal_point;
    963       int sign;
    964       const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
    965       char decimal_rep[kV8DtoaBufferCapacity];
    966       int length;
    967 
    968       DoubleToAscii(v, DTOA_SHORTEST, 0,
    969                     Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    970                     &sign, &length, &decimal_point);
    971 
    972       if (sign) builder.AddCharacter('-');
    973 
    974       if (length <= decimal_point && decimal_point <= 21) {
    975         // ECMA-262 section 9.8.1 step 6.
    976         builder.AddString(decimal_rep);
    977         builder.AddPadding('0', decimal_point - length);
    978 
    979       } else if (0 < decimal_point && decimal_point <= 21) {
    980         // ECMA-262 section 9.8.1 step 7.
    981         builder.AddSubstring(decimal_rep, decimal_point);
    982         builder.AddCharacter('.');
    983         builder.AddString(decimal_rep + decimal_point);
    984 
    985       } else if (decimal_point <= 0 && decimal_point > -6) {
    986         // ECMA-262 section 9.8.1 step 8.
    987         builder.AddString("0.");
    988         builder.AddPadding('0', -decimal_point);
    989         builder.AddString(decimal_rep);
    990 
    991       } else {
    992         // ECMA-262 section 9.8.1 step 9 and 10 combined.
    993         builder.AddCharacter(decimal_rep[0]);
    994         if (length != 1) {
    995           builder.AddCharacter('.');
    996           builder.AddString(decimal_rep + 1);
    997         }
    998         builder.AddCharacter('e');
    999         builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
   1000         int exponent = decimal_point - 1;
   1001         if (exponent < 0) exponent = -exponent;
   1002         builder.AddDecimalInteger(exponent);
   1003       }
   1004       return builder.Finalize();
   1005     }
   1006   }
   1007 }
   1008 
   1009 
   1010 const char* IntToCString(int n, Vector<char> buffer) {
   1011   bool negative = false;
   1012   if (n < 0) {
   1013     // We must not negate the most negative int.
   1014     if (n == kMinInt) return DoubleToCString(n, buffer);
   1015     negative = true;
   1016     n = -n;
   1017   }
   1018   // Build the string backwards from the least significant digit.
   1019   int i = buffer.length();
   1020   buffer[--i] = '\0';
   1021   do {
   1022     buffer[--i] = '0' + (n % 10);
   1023     n /= 10;
   1024   } while (n);
   1025   if (negative) buffer[--i] = '-';
   1026   return buffer.start() + i;
   1027 }
   1028 
   1029 
   1030 char* DoubleToFixedCString(double value, int f) {
   1031   const int kMaxDigitsBeforePoint = 21;
   1032   const double kFirstNonFixed = 1e21;
   1033   DCHECK_GE(f, 0);
   1034   DCHECK_LE(f, kMaxFractionDigits);
   1035 
   1036   bool negative = false;
   1037   double abs_value = value;
   1038   if (value < 0) {
   1039     abs_value = -value;
   1040     negative = true;
   1041   }
   1042 
   1043   // If abs_value has more than kMaxDigitsBeforePoint digits before the point
   1044   // use the non-fixed conversion routine.
   1045   if (abs_value >= kFirstNonFixed) {
   1046     char arr[kMaxFractionDigits];
   1047     Vector<char> buffer(arr, arraysize(arr));
   1048     return StrDup(DoubleToCString(value, buffer));
   1049   }
   1050 
   1051   // Find a sufficiently precise decimal representation of n.
   1052   int decimal_point;
   1053   int sign;
   1054   // Add space for the '\0' byte.
   1055   const int kDecimalRepCapacity =
   1056       kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
   1057   char decimal_rep[kDecimalRepCapacity];
   1058   int decimal_rep_length;
   1059   DoubleToAscii(value, DTOA_FIXED, f,
   1060                 Vector<char>(decimal_rep, kDecimalRepCapacity),
   1061                 &sign, &decimal_rep_length, &decimal_point);
   1062 
   1063   // Create a representation that is padded with zeros if needed.
   1064   int zero_prefix_length = 0;
   1065   int zero_postfix_length = 0;
   1066 
   1067   if (decimal_point <= 0) {
   1068     zero_prefix_length = -decimal_point + 1;
   1069     decimal_point = 1;
   1070   }
   1071 
   1072   if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
   1073     zero_postfix_length = decimal_point + f - decimal_rep_length -
   1074                           zero_prefix_length;
   1075   }
   1076 
   1077   unsigned rep_length =
   1078       zero_prefix_length + decimal_rep_length + zero_postfix_length;
   1079   SimpleStringBuilder rep_builder(rep_length + 1);
   1080   rep_builder.AddPadding('0', zero_prefix_length);
   1081   rep_builder.AddString(decimal_rep);
   1082   rep_builder.AddPadding('0', zero_postfix_length);
   1083   char* rep = rep_builder.Finalize();
   1084 
   1085   // Create the result string by appending a minus and putting in a
   1086   // decimal point if needed.
   1087   unsigned result_size = decimal_point + f + 2;
   1088   SimpleStringBuilder builder(result_size + 1);
   1089   if (negative) builder.AddCharacter('-');
   1090   builder.AddSubstring(rep, decimal_point);
   1091   if (f > 0) {
   1092     builder.AddCharacter('.');
   1093     builder.AddSubstring(rep + decimal_point, f);
   1094   }
   1095   DeleteArray(rep);
   1096   return builder.Finalize();
   1097 }
   1098 
   1099 
   1100 static char* CreateExponentialRepresentation(char* decimal_rep,
   1101                                              int exponent,
   1102                                              bool negative,
   1103                                              int significant_digits) {
   1104   bool negative_exponent = false;
   1105   if (exponent < 0) {
   1106     negative_exponent = true;
   1107     exponent = -exponent;
   1108   }
   1109 
   1110   // Leave room in the result for appending a minus, for a period, the
   1111   // letter 'e', a minus or a plus depending on the exponent, and a
   1112   // three digit exponent.
   1113   unsigned result_size = significant_digits + 7;
   1114   SimpleStringBuilder builder(result_size + 1);
   1115 
   1116   if (negative) builder.AddCharacter('-');
   1117   builder.AddCharacter(decimal_rep[0]);
   1118   if (significant_digits != 1) {
   1119     builder.AddCharacter('.');
   1120     builder.AddString(decimal_rep + 1);
   1121     int rep_length = StrLength(decimal_rep);
   1122     builder.AddPadding('0', significant_digits - rep_length);
   1123   }
   1124 
   1125   builder.AddCharacter('e');
   1126   builder.AddCharacter(negative_exponent ? '-' : '+');
   1127   builder.AddDecimalInteger(exponent);
   1128   return builder.Finalize();
   1129 }
   1130 
   1131 
   1132 char* DoubleToExponentialCString(double value, int f) {
   1133   // f might be -1 to signal that f was undefined in JavaScript.
   1134   DCHECK(f >= -1 && f <= kMaxFractionDigits);
   1135 
   1136   bool negative = false;
   1137   if (value < 0) {
   1138     value = -value;
   1139     negative = true;
   1140   }
   1141 
   1142   // Find a sufficiently precise decimal representation of n.
   1143   int decimal_point;
   1144   int sign;
   1145   // f corresponds to the digits after the point. There is always one digit
   1146   // before the point. The number of requested_digits equals hence f + 1.
   1147   // And we have to add one character for the null-terminator.
   1148   const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
   1149   // Make sure that the buffer is big enough, even if we fall back to the
   1150   // shortest representation (which happens when f equals -1).
   1151   DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1);
   1152   char decimal_rep[kV8DtoaBufferCapacity];
   1153   int decimal_rep_length;
   1154 
   1155   if (f == -1) {
   1156     DoubleToAscii(value, DTOA_SHORTEST, 0,
   1157                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
   1158                   &sign, &decimal_rep_length, &decimal_point);
   1159     f = decimal_rep_length - 1;
   1160   } else {
   1161     DoubleToAscii(value, DTOA_PRECISION, f + 1,
   1162                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
   1163                   &sign, &decimal_rep_length, &decimal_point);
   1164   }
   1165   DCHECK_GT(decimal_rep_length, 0);
   1166   DCHECK(decimal_rep_length <= f + 1);
   1167 
   1168   int exponent = decimal_point - 1;
   1169   char* result =
   1170       CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
   1171 
   1172   return result;
   1173 }
   1174 
   1175 
   1176 char* DoubleToPrecisionCString(double value, int p) {
   1177   const int kMinimalDigits = 1;
   1178   DCHECK(p >= kMinimalDigits && p <= kMaxFractionDigits);
   1179   USE(kMinimalDigits);
   1180 
   1181   bool negative = false;
   1182   if (value < 0) {
   1183     value = -value;
   1184     negative = true;
   1185   }
   1186 
   1187   // Find a sufficiently precise decimal representation of n.
   1188   int decimal_point;
   1189   int sign;
   1190   // Add one for the terminating null character.
   1191   const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1;
   1192   char decimal_rep[kV8DtoaBufferCapacity];
   1193   int decimal_rep_length;
   1194 
   1195   DoubleToAscii(value, DTOA_PRECISION, p,
   1196                 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
   1197                 &sign, &decimal_rep_length, &decimal_point);
   1198   DCHECK(decimal_rep_length <= p);
   1199 
   1200   int exponent = decimal_point - 1;
   1201 
   1202   char* result = nullptr;
   1203 
   1204   if (exponent < -6 || exponent >= p) {
   1205     result =
   1206         CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
   1207   } else {
   1208     // Use fixed notation.
   1209     //
   1210     // Leave room in the result for appending a minus, a period and in
   1211     // the case where decimal_point is not positive for a zero in
   1212     // front of the period.
   1213     unsigned result_size = (decimal_point <= 0)
   1214         ? -decimal_point + p + 3
   1215         : p + 2;
   1216     SimpleStringBuilder builder(result_size + 1);
   1217     if (negative) builder.AddCharacter('-');
   1218     if (decimal_point <= 0) {
   1219       builder.AddString("0.");
   1220       builder.AddPadding('0', -decimal_point);
   1221       builder.AddString(decimal_rep);
   1222       builder.AddPadding('0', p - decimal_rep_length);
   1223     } else {
   1224       const int m = Min(decimal_rep_length, decimal_point);
   1225       builder.AddSubstring(decimal_rep, m);
   1226       builder.AddPadding('0', decimal_point - decimal_rep_length);
   1227       if (decimal_point < p) {
   1228         builder.AddCharacter('.');
   1229         const int extra = negative ? 2 : 1;
   1230         if (decimal_rep_length > decimal_point) {
   1231           const int len = StrLength(decimal_rep + decimal_point);
   1232           const int n = Min(len, p - (builder.position() - extra));
   1233           builder.AddSubstring(decimal_rep + decimal_point, n);
   1234         }
   1235         builder.AddPadding('0', extra + (p - builder.position()));
   1236       }
   1237     }
   1238     result = builder.Finalize();
   1239   }
   1240 
   1241   return result;
   1242 }
   1243 
   1244 char* DoubleToRadixCString(double value, int radix) {
   1245   DCHECK(radix >= 2 && radix <= 36);
   1246   DCHECK(std::isfinite(value));
   1247   DCHECK_NE(0.0, value);
   1248   // Character array used for conversion.
   1249   static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
   1250 
   1251   // Temporary buffer for the result. We start with the decimal point in the
   1252   // middle and write to the left for the integer part and to the right for the
   1253   // fractional part. 1024 characters for the exponent and 52 for the mantissa
   1254   // either way, with additional space for sign, decimal point and string
   1255   // termination should be sufficient.
   1256   static const int kBufferSize = 2200;
   1257   char buffer[kBufferSize];
   1258   int integer_cursor = kBufferSize / 2;
   1259   int fraction_cursor = integer_cursor;
   1260 
   1261   bool negative = value < 0;
   1262   if (negative) value = -value;
   1263 
   1264   // Split the value into an integer part and a fractional part.
   1265   double integer = std::floor(value);
   1266   double fraction = value - integer;
   1267   // We only compute fractional digits up to the input double's precision.
   1268   double delta = 0.5 * (Double(value).NextDouble() - value);
   1269   delta = std::max(Double(0.0).NextDouble(), delta);
   1270   DCHECK_GT(delta, 0.0);
   1271   if (fraction > delta) {
   1272     // Insert decimal point.
   1273     buffer[fraction_cursor++] = '.';
   1274     do {
   1275       // Shift up by one digit.
   1276       fraction *= radix;
   1277       delta *= radix;
   1278       // Write digit.
   1279       int digit = static_cast<int>(fraction);
   1280       buffer[fraction_cursor++] = chars[digit];
   1281       // Calculate remainder.
   1282       fraction -= digit;
   1283       // Round to even.
   1284       if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
   1285         if (fraction + delta > 1) {
   1286           // We need to back trace already written digits in case of carry-over.
   1287           while (true) {
   1288             fraction_cursor--;
   1289             if (fraction_cursor == kBufferSize / 2) {
   1290               CHECK_EQ('.', buffer[fraction_cursor]);
   1291               // Carry over to the integer part.
   1292               integer += 1;
   1293               break;
   1294             }
   1295             char c = buffer[fraction_cursor];
   1296             // Reconstruct digit.
   1297             int digit = c > '9' ? (c - 'a' + 10) : (c - '0');
   1298             if (digit + 1 < radix) {
   1299               buffer[fraction_cursor++] = chars[digit + 1];
   1300               break;
   1301             }
   1302           }
   1303           break;
   1304         }
   1305       }
   1306     } while (fraction > delta);
   1307   }
   1308 
   1309   // Compute integer digits. Fill unrepresented digits with zero.
   1310   while (Double(integer / radix).Exponent() > 0) {
   1311     integer /= radix;
   1312     buffer[--integer_cursor] = '0';
   1313   }
   1314   do {
   1315     double remainder = Modulo(integer, radix);
   1316     buffer[--integer_cursor] = chars[static_cast<int>(remainder)];
   1317     integer = (integer - remainder) / radix;
   1318   } while (integer > 0);
   1319 
   1320   // Add sign and terminate string.
   1321   if (negative) buffer[--integer_cursor] = '-';
   1322   buffer[fraction_cursor++] = '\0';
   1323   DCHECK_LT(fraction_cursor, kBufferSize);
   1324   DCHECK_LE(0, integer_cursor);
   1325   // Allocate new string as return value.
   1326   char* result = NewArray<char>(fraction_cursor - integer_cursor);
   1327   memcpy(result, buffer + integer_cursor, fraction_cursor - integer_cursor);
   1328   return result;
   1329 }
   1330 
   1331 
   1332 // ES6 18.2.4 parseFloat(string)
   1333 double StringToDouble(Isolate* isolate, UnicodeCache* unicode_cache,
   1334                       Handle<String> string, int flags,
   1335                       double empty_string_val) {
   1336   Handle<String> flattened = String::Flatten(isolate, string);
   1337   {
   1338     DisallowHeapAllocation no_gc;
   1339     String::FlatContent flat = flattened->GetFlatContent();
   1340     DCHECK(flat.IsFlat());
   1341     if (flat.IsOneByte()) {
   1342       return StringToDouble(unicode_cache, flat.ToOneByteVector(), flags,
   1343                             empty_string_val);
   1344     } else {
   1345       return StringToDouble(unicode_cache, flat.ToUC16Vector(), flags,
   1346                             empty_string_val);
   1347     }
   1348   }
   1349 }
   1350 
   1351 
   1352 bool IsSpecialIndex(UnicodeCache* unicode_cache, String* string) {
   1353   // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX
   1354   const int kBufferSize = 24;
   1355   const int length = string->length();
   1356   if (length == 0 || length > kBufferSize) return false;
   1357   uint16_t buffer[kBufferSize];
   1358   String::WriteToFlat(string, buffer, 0, length);
   1359   // If the first char is not a digit or a '-' or we can't match 'NaN' or
   1360   // '(-)Infinity', bailout immediately.
   1361   int offset = 0;
   1362   if (!IsDecimalDigit(buffer[0])) {
   1363     if (buffer[0] == '-') {
   1364       if (length == 1) return false;  // Just '-' is bad.
   1365       if (!IsDecimalDigit(buffer[1])) {
   1366         if (buffer[1] == 'I' && length == 9) {
   1367           // Allow matching of '-Infinity' below.
   1368         } else {
   1369           return false;
   1370         }
   1371       }
   1372       offset++;
   1373     } else if (buffer[0] == 'I' && length == 8) {
   1374       // Allow matching of 'Infinity' below.
   1375     } else if (buffer[0] == 'N' && length == 3) {
   1376       // Match NaN.
   1377       return buffer[1] == 'a' && buffer[2] == 'N';
   1378     } else {
   1379       return false;
   1380     }
   1381   }
   1382   // Expected fast path: key is an integer.
   1383   static const int kRepresentableIntegerLength = 15;  // (-)XXXXXXXXXXXXXXX
   1384   if (length - offset <= kRepresentableIntegerLength) {
   1385     const int initial_offset = offset;
   1386     bool matches = true;
   1387     for (; offset < length; offset++) {
   1388       matches &= IsDecimalDigit(buffer[offset]);
   1389     }
   1390     if (matches) {
   1391       // Match 0 and -0.
   1392       if (buffer[initial_offset] == '0') return initial_offset == length - 1;
   1393       return true;
   1394     }
   1395   }
   1396   // Slow path: test DoubleToString(StringToDouble(string)) == string.
   1397   Vector<const uint16_t> vector(buffer, length);
   1398   double d = StringToDouble(unicode_cache, vector, NO_FLAGS);
   1399   if (std::isnan(d)) return false;
   1400   // Compute reverse string.
   1401   char reverse_buffer[kBufferSize + 1];  // Result will be /0 terminated.
   1402   Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
   1403   const char* reverse_string = DoubleToCString(d, reverse_vector);
   1404   for (int i = 0; i < length; ++i) {
   1405     if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false;
   1406   }
   1407   return true;
   1408 }
   1409 }  // namespace internal
   1410 }  // namespace v8
   1411