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 #ifndef V8_CONVERSIONS_INL_H_
      6 #define V8_CONVERSIONS_INL_H_
      7 
      8 #include <float.h>         // Required for DBL_MAX and on Win32 for finite()
      9 #include <limits.h>        // Required for INT_MAX etc.
     10 #include <stdarg.h>
     11 #include <cmath>
     12 #include "src/globals.h"       // Required for V8_INFINITY
     13 #include "src/unicode-cache-inl.h"
     14 
     15 // ----------------------------------------------------------------------------
     16 // Extra POSIX/ANSI functions for Win32/MSVC.
     17 
     18 #include "src/base/bits.h"
     19 #include "src/base/platform/platform.h"
     20 #include "src/conversions.h"
     21 #include "src/double.h"
     22 #include "src/objects-inl.h"
     23 #include "src/strtod.h"
     24 
     25 namespace v8 {
     26 namespace internal {
     27 
     28 inline double JunkStringValue() {
     29   return bit_cast<double, uint64_t>(kQuietNaNMask);
     30 }
     31 
     32 
     33 inline double SignedZero(bool negative) {
     34   return negative ? uint64_to_double(Double::kSignMask) : 0.0;
     35 }
     36 
     37 
     38 // The fast double-to-unsigned-int conversion routine does not guarantee
     39 // rounding towards zero, or any reasonable value if the argument is larger
     40 // than what fits in an unsigned 32-bit integer.
     41 inline unsigned int FastD2UI(double x) {
     42   // There is no unsigned version of lrint, so there is no fast path
     43   // in this function as there is in FastD2I. Using lrint doesn't work
     44   // for values of 2^31 and above.
     45 
     46   // Convert "small enough" doubles to uint32_t by fixing the 32
     47   // least significant non-fractional bits in the low 32 bits of the
     48   // double, and reading them from there.
     49   const double k2Pow52 = 4503599627370496.0;
     50   bool negative = x < 0;
     51   if (negative) {
     52     x = -x;
     53   }
     54   if (x < k2Pow52) {
     55     x += k2Pow52;
     56     uint32_t result;
     57 #ifndef V8_TARGET_BIG_ENDIAN
     58     Address mantissa_ptr = reinterpret_cast<Address>(&x);
     59 #else
     60     Address mantissa_ptr = reinterpret_cast<Address>(&x) + kInt32Size;
     61 #endif
     62     // Copy least significant 32 bits of mantissa.
     63     memcpy(&result, mantissa_ptr, sizeof(result));
     64     return negative ? ~result + 1 : result;
     65   }
     66   // Large number (outside uint32 range), Infinity or NaN.
     67   return 0x80000000u;  // Return integer indefinite.
     68 }
     69 
     70 
     71 inline float DoubleToFloat32(double x) {
     72   // TODO(yangguo): This static_cast is implementation-defined behaviour in C++,
     73   // so we may need to do the conversion manually instead to match the spec.
     74   volatile float f = static_cast<float>(x);
     75   return f;
     76 }
     77 
     78 
     79 inline double DoubleToInteger(double x) {
     80   if (std::isnan(x)) return 0;
     81   if (!std::isfinite(x) || x == 0) return x;
     82   return (x >= 0) ? std::floor(x) : std::ceil(x);
     83 }
     84 
     85 
     86 int32_t DoubleToInt32(double x) {
     87   int32_t i = FastD2I(x);
     88   if (FastI2D(i) == x) return i;
     89   Double d(x);
     90   int exponent = d.Exponent();
     91   if (exponent < 0) {
     92     if (exponent <= -Double::kSignificandSize) return 0;
     93     return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
     94   } else {
     95     if (exponent > 31) return 0;
     96     return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
     97   }
     98 }
     99 
    100 bool DoubleToSmiInteger(double value, int* smi_int_value) {
    101   if (IsMinusZero(value)) return false;
    102   int i = FastD2IChecked(value);
    103   if (value != i || !Smi::IsValid(i)) return false;
    104   *smi_int_value = i;
    105   return true;
    106 }
    107 
    108 bool IsSmiDouble(double value) {
    109   return !IsMinusZero(value) && value >= Smi::kMinValue &&
    110          value <= Smi::kMaxValue && value == FastI2D(FastD2I(value));
    111 }
    112 
    113 
    114 bool IsInt32Double(double value) {
    115   return !IsMinusZero(value) && value >= kMinInt && value <= kMaxInt &&
    116          value == FastI2D(FastD2I(value));
    117 }
    118 
    119 
    120 bool IsUint32Double(double value) {
    121   return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
    122          value == FastUI2D(FastD2UI(value));
    123 }
    124 
    125 bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value) {
    126   const double k2Pow52 = 4503599627370496.0;
    127   const uint32_t kValidTopBits = 0x43300000;
    128   const uint64_t kBottomBitMask = V8_2PART_UINT64_C(0x00000000, FFFFFFFF);
    129 
    130   // Add 2^52 to the double, to place valid uint32 values in the low-significant
    131   // bits of the exponent, by effectively setting the (implicit) top bit of the
    132   // significand. Note that this addition also normalises 0.0 and -0.0.
    133   double shifted_value = value + k2Pow52;
    134 
    135   // At this point, a valid uint32 valued double will be represented as:
    136   //
    137   // sign = 0
    138   // exponent = 52
    139   // significand = 1. 00...00 <value>
    140   //       implicit^          ^^^^^^^ 32 bits
    141   //                  ^^^^^^^^^^^^^^^ 52 bits
    142   //
    143   // Therefore, we can first check the top 32 bits to make sure that the sign,
    144   // exponent and remaining significand bits are valid, and only then check the
    145   // value in the bottom 32 bits.
    146 
    147   uint64_t result = bit_cast<uint64_t>(shifted_value);
    148   if ((result >> 32) == kValidTopBits) {
    149     *uint32_value = result & kBottomBitMask;
    150     return FastUI2D(result & kBottomBitMask) == value;
    151   }
    152   return false;
    153 }
    154 
    155 int32_t NumberToInt32(Object* number) {
    156   if (number->IsSmi()) return Smi::cast(number)->value();
    157   return DoubleToInt32(number->Number());
    158 }
    159 
    160 uint32_t NumberToUint32(Object* number) {
    161   if (number->IsSmi()) return Smi::cast(number)->value();
    162   return DoubleToUint32(number->Number());
    163 }
    164 
    165 uint32_t PositiveNumberToUint32(Object* number) {
    166   if (number->IsSmi()) {
    167     int value = Smi::cast(number)->value();
    168     if (value <= 0) return 0;
    169     return value;
    170   }
    171   DCHECK(number->IsHeapNumber());
    172   double value = number->Number();
    173   // Catch all values smaller than 1 and use the double-negation trick for NANs.
    174   if (!(value >= 1)) return 0;
    175   uint32_t max = std::numeric_limits<uint32_t>::max();
    176   if (value < max) return static_cast<uint32_t>(value);
    177   return max;
    178 }
    179 
    180 int64_t NumberToInt64(Object* number) {
    181   if (number->IsSmi()) return Smi::cast(number)->value();
    182   return static_cast<int64_t>(number->Number());
    183 }
    184 
    185 bool TryNumberToSize(Object* number, size_t* result) {
    186   // Do not create handles in this function! Don't use SealHandleScope because
    187   // the function can be used concurrently.
    188   if (number->IsSmi()) {
    189     int value = Smi::cast(number)->value();
    190     DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
    191            std::numeric_limits<size_t>::max());
    192     if (value >= 0) {
    193       *result = static_cast<size_t>(value);
    194       return true;
    195     }
    196     return false;
    197   } else {
    198     DCHECK(number->IsHeapNumber());
    199     double value = HeapNumber::cast(number)->value();
    200     // If value is compared directly to the limit, the limit will be
    201     // casted to a double and could end up as limit + 1,
    202     // because a double might not have enough mantissa bits for it.
    203     // So we might as well cast the limit first, and use < instead of <=.
    204     double maxSize = static_cast<double>(std::numeric_limits<size_t>::max());
    205     if (value >= 0 && value < maxSize) {
    206       *result = static_cast<size_t>(value);
    207       return true;
    208     } else {
    209       return false;
    210     }
    211   }
    212 }
    213 
    214 size_t NumberToSize(Object* number) {
    215   size_t result = 0;
    216   bool is_valid = TryNumberToSize(number, &result);
    217   CHECK(is_valid);
    218   return result;
    219 }
    220 
    221 
    222 uint32_t DoubleToUint32(double x) {
    223   return static_cast<uint32_t>(DoubleToInt32(x));
    224 }
    225 
    226 
    227 template <class Iterator, class EndMark>
    228 bool SubStringEquals(Iterator* current,
    229                      EndMark end,
    230                      const char* substring) {
    231   DCHECK(**current == *substring);
    232   for (substring++; *substring != '\0'; substring++) {
    233     ++*current;
    234     if (*current == end || **current != *substring) return false;
    235   }
    236   ++*current;
    237   return true;
    238 }
    239 
    240 
    241 // Returns true if a nonspace character has been found and false if the
    242 // end was been reached before finding a nonspace character.
    243 template <class Iterator, class EndMark>
    244 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
    245                               Iterator* current,
    246                               EndMark end) {
    247   while (*current != end) {
    248     if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true;
    249     ++*current;
    250   }
    251   return false;
    252 }
    253 
    254 
    255 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
    256 template <int radix_log_2, class Iterator, class EndMark>
    257 double InternalStringToIntDouble(UnicodeCache* unicode_cache,
    258                                  Iterator current,
    259                                  EndMark end,
    260                                  bool negative,
    261                                  bool allow_trailing_junk) {
    262   DCHECK(current != end);
    263 
    264   // Skip leading 0s.
    265   while (*current == '0') {
    266     ++current;
    267     if (current == end) return SignedZero(negative);
    268   }
    269 
    270   int64_t number = 0;
    271   int exponent = 0;
    272   const int radix = (1 << radix_log_2);
    273 
    274   do {
    275     int digit;
    276     if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
    277       digit = static_cast<char>(*current) - '0';
    278     } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
    279       digit = static_cast<char>(*current) - 'a' + 10;
    280     } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
    281       digit = static_cast<char>(*current) - 'A' + 10;
    282     } else {
    283       if (allow_trailing_junk ||
    284           !AdvanceToNonspace(unicode_cache, &current, end)) {
    285         break;
    286       } else {
    287         return JunkStringValue();
    288       }
    289     }
    290 
    291     number = number * radix + digit;
    292     int overflow = static_cast<int>(number >> 53);
    293     if (overflow != 0) {
    294       // Overflow occurred. Need to determine which direction to round the
    295       // result.
    296       int overflow_bits_count = 1;
    297       while (overflow > 1) {
    298         overflow_bits_count++;
    299         overflow >>= 1;
    300       }
    301 
    302       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
    303       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
    304       number >>= overflow_bits_count;
    305       exponent = overflow_bits_count;
    306 
    307       bool zero_tail = true;
    308       while (true) {
    309         ++current;
    310         if (current == end || !isDigit(*current, radix)) break;
    311         zero_tail = zero_tail && *current == '0';
    312         exponent += radix_log_2;
    313       }
    314 
    315       if (!allow_trailing_junk &&
    316           AdvanceToNonspace(unicode_cache, &current, end)) {
    317         return JunkStringValue();
    318       }
    319 
    320       int middle_value = (1 << (overflow_bits_count - 1));
    321       if (dropped_bits > middle_value) {
    322         number++;  // Rounding up.
    323       } else if (dropped_bits == middle_value) {
    324         // Rounding to even to consistency with decimals: half-way case rounds
    325         // up if significant part is odd and down otherwise.
    326         if ((number & 1) != 0 || !zero_tail) {
    327           number++;  // Rounding up.
    328         }
    329       }
    330 
    331       // Rounding up may cause overflow.
    332       if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
    333         exponent++;
    334         number >>= 1;
    335       }
    336       break;
    337     }
    338     ++current;
    339   } while (current != end);
    340 
    341   DCHECK(number < ((int64_t)1 << 53));
    342   DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
    343 
    344   if (exponent == 0) {
    345     if (negative) {
    346       if (number == 0) return -0.0;
    347       number = -number;
    348     }
    349     return static_cast<double>(number);
    350   }
    351 
    352   DCHECK(number != 0);
    353   return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
    354 }
    355 
    356 // ES6 18.2.5 parseInt(string, radix)
    357 template <class Iterator, class EndMark>
    358 double InternalStringToInt(UnicodeCache* unicode_cache,
    359                            Iterator current,
    360                            EndMark end,
    361                            int radix) {
    362   const bool allow_trailing_junk = true;
    363   const double empty_string_val = JunkStringValue();
    364 
    365   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    366     return empty_string_val;
    367   }
    368 
    369   bool negative = false;
    370   bool leading_zero = false;
    371 
    372   if (*current == '+') {
    373     // Ignore leading sign; skip following spaces.
    374     ++current;
    375     if (current == end) {
    376       return JunkStringValue();
    377     }
    378   } else if (*current == '-') {
    379     ++current;
    380     if (current == end) {
    381       return JunkStringValue();
    382     }
    383     negative = true;
    384   }
    385 
    386   if (radix == 0) {
    387     // Radix detection.
    388     radix = 10;
    389     if (*current == '0') {
    390       ++current;
    391       if (current == end) return SignedZero(negative);
    392       if (*current == 'x' || *current == 'X') {
    393         radix = 16;
    394         ++current;
    395         if (current == end) return JunkStringValue();
    396       } else {
    397         leading_zero = true;
    398       }
    399     }
    400   } else if (radix == 16) {
    401     if (*current == '0') {
    402       // Allow "0x" prefix.
    403       ++current;
    404       if (current == end) return SignedZero(negative);
    405       if (*current == 'x' || *current == 'X') {
    406         ++current;
    407         if (current == end) return JunkStringValue();
    408       } else {
    409         leading_zero = true;
    410       }
    411     }
    412   }
    413 
    414   if (radix < 2 || radix > 36) return JunkStringValue();
    415 
    416   // Skip leading zeros.
    417   while (*current == '0') {
    418     leading_zero = true;
    419     ++current;
    420     if (current == end) return SignedZero(negative);
    421   }
    422 
    423   if (!leading_zero && !isDigit(*current, radix)) {
    424     return JunkStringValue();
    425   }
    426 
    427   if (base::bits::IsPowerOfTwo32(radix)) {
    428     switch (radix) {
    429       case 2:
    430         return InternalStringToIntDouble<1>(
    431             unicode_cache, current, end, negative, allow_trailing_junk);
    432       case 4:
    433         return InternalStringToIntDouble<2>(
    434             unicode_cache, current, end, negative, allow_trailing_junk);
    435       case 8:
    436         return InternalStringToIntDouble<3>(
    437             unicode_cache, current, end, negative, allow_trailing_junk);
    438 
    439       case 16:
    440         return InternalStringToIntDouble<4>(
    441             unicode_cache, current, end, negative, allow_trailing_junk);
    442 
    443       case 32:
    444         return InternalStringToIntDouble<5>(
    445             unicode_cache, current, end, negative, allow_trailing_junk);
    446       default:
    447         UNREACHABLE();
    448     }
    449   }
    450 
    451   if (radix == 10) {
    452     // Parsing with strtod.
    453     const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
    454     // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
    455     // end.
    456     const int kBufferSize = kMaxSignificantDigits + 2;
    457     char buffer[kBufferSize];
    458     int buffer_pos = 0;
    459     while (*current >= '0' && *current <= '9') {
    460       if (buffer_pos <= kMaxSignificantDigits) {
    461         // If the number has more than kMaxSignificantDigits it will be parsed
    462         // as infinity.
    463         DCHECK(buffer_pos < kBufferSize);
    464         buffer[buffer_pos++] = static_cast<char>(*current);
    465       }
    466       ++current;
    467       if (current == end) break;
    468     }
    469 
    470     if (!allow_trailing_junk &&
    471         AdvanceToNonspace(unicode_cache, &current, end)) {
    472       return JunkStringValue();
    473     }
    474 
    475     SLOW_DCHECK(buffer_pos < kBufferSize);
    476     buffer[buffer_pos] = '\0';
    477     Vector<const char> buffer_vector(buffer, buffer_pos);
    478     return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
    479   }
    480 
    481   // The following code causes accumulating rounding error for numbers greater
    482   // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
    483   // 16, or 32, then mathInt may be an implementation-dependent approximation to
    484   // the mathematical integer value" (15.1.2.2).
    485 
    486   int lim_0 = '0' + (radix < 10 ? radix : 10);
    487   int lim_a = 'a' + (radix - 10);
    488   int lim_A = 'A' + (radix - 10);
    489 
    490   // NOTE: The code for computing the value may seem a bit complex at
    491   // first glance. It is structured to use 32-bit multiply-and-add
    492   // loops as long as possible to avoid loosing precision.
    493 
    494   double v = 0.0;
    495   bool done = false;
    496   do {
    497     // Parse the longest part of the string starting at index j
    498     // possible while keeping the multiplier, and thus the part
    499     // itself, within 32 bits.
    500     unsigned int part = 0, multiplier = 1;
    501     while (true) {
    502       int d;
    503       if (*current >= '0' && *current < lim_0) {
    504         d = *current - '0';
    505       } else if (*current >= 'a' && *current < lim_a) {
    506         d = *current - 'a' + 10;
    507       } else if (*current >= 'A' && *current < lim_A) {
    508         d = *current - 'A' + 10;
    509       } else {
    510         done = true;
    511         break;
    512       }
    513 
    514       // Update the value of the part as long as the multiplier fits
    515       // in 32 bits. When we can't guarantee that the next iteration
    516       // will not overflow the multiplier, we stop parsing the part
    517       // by leaving the loop.
    518       const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
    519       uint32_t m = multiplier * radix;
    520       if (m > kMaximumMultiplier) break;
    521       part = part * radix + d;
    522       multiplier = m;
    523       DCHECK(multiplier > part);
    524 
    525       ++current;
    526       if (current == end) {
    527         done = true;
    528         break;
    529       }
    530     }
    531 
    532     // Update the value and skip the part in the string.
    533     v = v * multiplier + part;
    534   } while (!done);
    535 
    536   if (!allow_trailing_junk &&
    537       AdvanceToNonspace(unicode_cache, &current, end)) {
    538     return JunkStringValue();
    539   }
    540 
    541   return negative ? -v : v;
    542 }
    543 
    544 
    545 // Converts a string to a double value. Assumes the Iterator supports
    546 // the following operations:
    547 // 1. current == end (other ops are not allowed), current != end.
    548 // 2. *current - gets the current character in the sequence.
    549 // 3. ++current (advances the position).
    550 template <class Iterator, class EndMark>
    551 double InternalStringToDouble(UnicodeCache* unicode_cache,
    552                               Iterator current,
    553                               EndMark end,
    554                               int flags,
    555                               double empty_string_val) {
    556   // To make sure that iterator dereferencing is valid the following
    557   // convention is used:
    558   // 1. Each '++current' statement is followed by check for equality to 'end'.
    559   // 2. If AdvanceToNonspace returned false then current == end.
    560   // 3. If 'current' becomes be equal to 'end' the function returns or goes to
    561   // 'parsing_done'.
    562   // 4. 'current' is not dereferenced after the 'parsing_done' label.
    563   // 5. Code before 'parsing_done' may rely on 'current != end'.
    564   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    565     return empty_string_val;
    566   }
    567 
    568   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
    569 
    570   // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
    571   const int kBufferSize = kMaxSignificantDigits + 10;
    572   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
    573   int buffer_pos = 0;
    574 
    575   // Exponent will be adjusted if insignificant digits of the integer part
    576   // or insignificant leading zeros of the fractional part are dropped.
    577   int exponent = 0;
    578   int significant_digits = 0;
    579   int insignificant_digits = 0;
    580   bool nonzero_digit_dropped = false;
    581 
    582   enum Sign {
    583     NONE,
    584     NEGATIVE,
    585     POSITIVE
    586   };
    587 
    588   Sign sign = NONE;
    589 
    590   if (*current == '+') {
    591     // Ignore leading sign.
    592     ++current;
    593     if (current == end) return JunkStringValue();
    594     sign = POSITIVE;
    595   } else if (*current == '-') {
    596     ++current;
    597     if (current == end) return JunkStringValue();
    598     sign = NEGATIVE;
    599   }
    600 
    601   static const char kInfinityString[] = "Infinity";
    602   if (*current == kInfinityString[0]) {
    603     if (!SubStringEquals(&current, end, kInfinityString)) {
    604       return JunkStringValue();
    605     }
    606 
    607     if (!allow_trailing_junk &&
    608         AdvanceToNonspace(unicode_cache, &current, end)) {
    609       return JunkStringValue();
    610     }
    611 
    612     DCHECK(buffer_pos == 0);
    613     return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
    614   }
    615 
    616   bool leading_zero = false;
    617   if (*current == '0') {
    618     ++current;
    619     if (current == end) return SignedZero(sign == NEGATIVE);
    620 
    621     leading_zero = true;
    622 
    623     // It could be hexadecimal value.
    624     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
    625       ++current;
    626       if (current == end || !isDigit(*current, 16) || sign != NONE) {
    627         return JunkStringValue();  // "0x".
    628       }
    629 
    630       return InternalStringToIntDouble<4>(unicode_cache,
    631                                           current,
    632                                           end,
    633                                           false,
    634                                           allow_trailing_junk);
    635 
    636     // It could be an explicit octal value.
    637     } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
    638       ++current;
    639       if (current == end || !isDigit(*current, 8) || sign != NONE) {
    640         return JunkStringValue();  // "0o".
    641       }
    642 
    643       return InternalStringToIntDouble<3>(unicode_cache,
    644                                           current,
    645                                           end,
    646                                           false,
    647                                           allow_trailing_junk);
    648 
    649     // It could be a binary value.
    650     } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
    651       ++current;
    652       if (current == end || !isBinaryDigit(*current) || sign != NONE) {
    653         return JunkStringValue();  // "0b".
    654       }
    655 
    656       return InternalStringToIntDouble<1>(unicode_cache,
    657                                           current,
    658                                           end,
    659                                           false,
    660                                           allow_trailing_junk);
    661     }
    662 
    663     // Ignore leading zeros in the integer part.
    664     while (*current == '0') {
    665       ++current;
    666       if (current == end) return SignedZero(sign == NEGATIVE);
    667     }
    668   }
    669 
    670   bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
    671 
    672   // Copy significant digits of the integer part (if any) to the buffer.
    673   while (*current >= '0' && *current <= '9') {
    674     if (significant_digits < kMaxSignificantDigits) {
    675       DCHECK(buffer_pos < kBufferSize);
    676       buffer[buffer_pos++] = static_cast<char>(*current);
    677       significant_digits++;
    678       // Will later check if it's an octal in the buffer.
    679     } else {
    680       insignificant_digits++;  // Move the digit into the exponential part.
    681       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    682     }
    683     octal = octal && *current < '8';
    684     ++current;
    685     if (current == end) goto parsing_done;
    686   }
    687 
    688   if (significant_digits == 0) {
    689     octal = false;
    690   }
    691 
    692   if (*current == '.') {
    693     if (octal && !allow_trailing_junk) return JunkStringValue();
    694     if (octal) goto parsing_done;
    695 
    696     ++current;
    697     if (current == end) {
    698       if (significant_digits == 0 && !leading_zero) {
    699         return JunkStringValue();
    700       } else {
    701         goto parsing_done;
    702       }
    703     }
    704 
    705     if (significant_digits == 0) {
    706       // octal = false;
    707       // Integer part consists of 0 or is absent. Significant digits start after
    708       // leading zeros (if any).
    709       while (*current == '0') {
    710         ++current;
    711         if (current == end) return SignedZero(sign == NEGATIVE);
    712         exponent--;  // Move this 0 into the exponent.
    713       }
    714     }
    715 
    716     // There is a fractional part.  We don't emit a '.', but adjust the exponent
    717     // instead.
    718     while (*current >= '0' && *current <= '9') {
    719       if (significant_digits < kMaxSignificantDigits) {
    720         DCHECK(buffer_pos < kBufferSize);
    721         buffer[buffer_pos++] = static_cast<char>(*current);
    722         significant_digits++;
    723         exponent--;
    724       } else {
    725         // Ignore insignificant digits in the fractional part.
    726         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    727       }
    728       ++current;
    729       if (current == end) goto parsing_done;
    730     }
    731   }
    732 
    733   if (!leading_zero && exponent == 0 && significant_digits == 0) {
    734     // If leading_zeros is true then the string contains zeros.
    735     // If exponent < 0 then string was [+-]\.0*...
    736     // If significant_digits != 0 the string is not equal to 0.
    737     // Otherwise there are no digits in the string.
    738     return JunkStringValue();
    739   }
    740 
    741   // Parse exponential part.
    742   if (*current == 'e' || *current == 'E') {
    743     if (octal) return JunkStringValue();
    744     ++current;
    745     if (current == end) {
    746       if (allow_trailing_junk) {
    747         goto parsing_done;
    748       } else {
    749         return JunkStringValue();
    750       }
    751     }
    752     char sign = '+';
    753     if (*current == '+' || *current == '-') {
    754       sign = static_cast<char>(*current);
    755       ++current;
    756       if (current == end) {
    757         if (allow_trailing_junk) {
    758           goto parsing_done;
    759         } else {
    760           return JunkStringValue();
    761         }
    762       }
    763     }
    764 
    765     if (current == end || *current < '0' || *current > '9') {
    766       if (allow_trailing_junk) {
    767         goto parsing_done;
    768       } else {
    769         return JunkStringValue();
    770       }
    771     }
    772 
    773     const int max_exponent = INT_MAX / 2;
    774     DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
    775     int num = 0;
    776     do {
    777       // Check overflow.
    778       int digit = *current - '0';
    779       if (num >= max_exponent / 10
    780           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
    781         num = max_exponent;
    782       } else {
    783         num = num * 10 + digit;
    784       }
    785       ++current;
    786     } while (current != end && *current >= '0' && *current <= '9');
    787 
    788     exponent += (sign == '-' ? -num : num);
    789   }
    790 
    791   if (!allow_trailing_junk &&
    792       AdvanceToNonspace(unicode_cache, &current, end)) {
    793     return JunkStringValue();
    794   }
    795 
    796   parsing_done:
    797   exponent += insignificant_digits;
    798 
    799   if (octal) {
    800     return InternalStringToIntDouble<3>(unicode_cache,
    801                                         buffer,
    802                                         buffer + buffer_pos,
    803                                         sign == NEGATIVE,
    804                                         allow_trailing_junk);
    805   }
    806 
    807   if (nonzero_digit_dropped) {
    808     buffer[buffer_pos++] = '1';
    809     exponent--;
    810   }
    811 
    812   SLOW_DCHECK(buffer_pos < kBufferSize);
    813   buffer[buffer_pos] = '\0';
    814 
    815   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
    816   return (sign == NEGATIVE) ? -converted : converted;
    817 }
    818 
    819 }  // namespace internal
    820 }  // namespace v8
    821 
    822 #endif  // V8_CONVERSIONS_INL_H_
    823