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) + kIntSize;
     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 
    101 bool IsSmiDouble(double value) {
    102   return !IsMinusZero(value) && value >= Smi::kMinValue &&
    103          value <= Smi::kMaxValue && value == FastI2D(FastD2I(value));
    104 }
    105 
    106 
    107 bool IsInt32Double(double value) {
    108   return !IsMinusZero(value) && value >= kMinInt && value <= kMaxInt &&
    109          value == FastI2D(FastD2I(value));
    110 }
    111 
    112 
    113 bool IsUint32Double(double value) {
    114   return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
    115          value == FastUI2D(FastD2UI(value));
    116 }
    117 
    118 
    119 int32_t NumberToInt32(Object* number) {
    120   if (number->IsSmi()) return Smi::cast(number)->value();
    121   return DoubleToInt32(number->Number());
    122 }
    123 
    124 
    125 uint32_t NumberToUint32(Object* number) {
    126   if (number->IsSmi()) return Smi::cast(number)->value();
    127   return DoubleToUint32(number->Number());
    128 }
    129 
    130 int64_t NumberToInt64(Object* number) {
    131   if (number->IsSmi()) return Smi::cast(number)->value();
    132   return static_cast<int64_t>(number->Number());
    133 }
    134 
    135 bool TryNumberToSize(Isolate* isolate, Object* number, size_t* result) {
    136   SealHandleScope shs(isolate);
    137   if (number->IsSmi()) {
    138     int value = Smi::cast(number)->value();
    139     DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
    140            std::numeric_limits<size_t>::max());
    141     if (value >= 0) {
    142       *result = static_cast<size_t>(value);
    143       return true;
    144     }
    145     return false;
    146   } else {
    147     DCHECK(number->IsHeapNumber());
    148     double value = HeapNumber::cast(number)->value();
    149     if (value >= 0 && value <= std::numeric_limits<size_t>::max()) {
    150       *result = static_cast<size_t>(value);
    151       return true;
    152     } else {
    153       return false;
    154     }
    155   }
    156 }
    157 
    158 
    159 size_t NumberToSize(Isolate* isolate, Object* number) {
    160   size_t result = 0;
    161   bool is_valid = TryNumberToSize(isolate, number, &result);
    162   CHECK(is_valid);
    163   return result;
    164 }
    165 
    166 
    167 uint32_t DoubleToUint32(double x) {
    168   return static_cast<uint32_t>(DoubleToInt32(x));
    169 }
    170 
    171 
    172 template <class Iterator, class EndMark>
    173 bool SubStringEquals(Iterator* current,
    174                      EndMark end,
    175                      const char* substring) {
    176   DCHECK(**current == *substring);
    177   for (substring++; *substring != '\0'; substring++) {
    178     ++*current;
    179     if (*current == end || **current != *substring) return false;
    180   }
    181   ++*current;
    182   return true;
    183 }
    184 
    185 
    186 // Returns true if a nonspace character has been found and false if the
    187 // end was been reached before finding a nonspace character.
    188 template <class Iterator, class EndMark>
    189 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
    190                               Iterator* current,
    191                               EndMark end) {
    192   while (*current != end) {
    193     if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true;
    194     ++*current;
    195   }
    196   return false;
    197 }
    198 
    199 
    200 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
    201 template <int radix_log_2, class Iterator, class EndMark>
    202 double InternalStringToIntDouble(UnicodeCache* unicode_cache,
    203                                  Iterator current,
    204                                  EndMark end,
    205                                  bool negative,
    206                                  bool allow_trailing_junk) {
    207   DCHECK(current != end);
    208 
    209   // Skip leading 0s.
    210   while (*current == '0') {
    211     ++current;
    212     if (current == end) return SignedZero(negative);
    213   }
    214 
    215   int64_t number = 0;
    216   int exponent = 0;
    217   const int radix = (1 << radix_log_2);
    218 
    219   do {
    220     int digit;
    221     if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
    222       digit = static_cast<char>(*current) - '0';
    223     } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
    224       digit = static_cast<char>(*current) - 'a' + 10;
    225     } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
    226       digit = static_cast<char>(*current) - 'A' + 10;
    227     } else {
    228       if (allow_trailing_junk ||
    229           !AdvanceToNonspace(unicode_cache, &current, end)) {
    230         break;
    231       } else {
    232         return JunkStringValue();
    233       }
    234     }
    235 
    236     number = number * radix + digit;
    237     int overflow = static_cast<int>(number >> 53);
    238     if (overflow != 0) {
    239       // Overflow occurred. Need to determine which direction to round the
    240       // result.
    241       int overflow_bits_count = 1;
    242       while (overflow > 1) {
    243         overflow_bits_count++;
    244         overflow >>= 1;
    245       }
    246 
    247       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
    248       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
    249       number >>= overflow_bits_count;
    250       exponent = overflow_bits_count;
    251 
    252       bool zero_tail = true;
    253       while (true) {
    254         ++current;
    255         if (current == end || !isDigit(*current, radix)) break;
    256         zero_tail = zero_tail && *current == '0';
    257         exponent += radix_log_2;
    258       }
    259 
    260       if (!allow_trailing_junk &&
    261           AdvanceToNonspace(unicode_cache, &current, end)) {
    262         return JunkStringValue();
    263       }
    264 
    265       int middle_value = (1 << (overflow_bits_count - 1));
    266       if (dropped_bits > middle_value) {
    267         number++;  // Rounding up.
    268       } else if (dropped_bits == middle_value) {
    269         // Rounding to even to consistency with decimals: half-way case rounds
    270         // up if significant part is odd and down otherwise.
    271         if ((number & 1) != 0 || !zero_tail) {
    272           number++;  // Rounding up.
    273         }
    274       }
    275 
    276       // Rounding up may cause overflow.
    277       if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
    278         exponent++;
    279         number >>= 1;
    280       }
    281       break;
    282     }
    283     ++current;
    284   } while (current != end);
    285 
    286   DCHECK(number < ((int64_t)1 << 53));
    287   DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
    288 
    289   if (exponent == 0) {
    290     if (negative) {
    291       if (number == 0) return -0.0;
    292       number = -number;
    293     }
    294     return static_cast<double>(number);
    295   }
    296 
    297   DCHECK(number != 0);
    298   return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
    299 }
    300 
    301 // ES6 18.2.5 parseInt(string, radix)
    302 template <class Iterator, class EndMark>
    303 double InternalStringToInt(UnicodeCache* unicode_cache,
    304                            Iterator current,
    305                            EndMark end,
    306                            int radix) {
    307   const bool allow_trailing_junk = true;
    308   const double empty_string_val = JunkStringValue();
    309 
    310   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    311     return empty_string_val;
    312   }
    313 
    314   bool negative = false;
    315   bool leading_zero = false;
    316 
    317   if (*current == '+') {
    318     // Ignore leading sign; skip following spaces.
    319     ++current;
    320     if (current == end) {
    321       return JunkStringValue();
    322     }
    323   } else if (*current == '-') {
    324     ++current;
    325     if (current == end) {
    326       return JunkStringValue();
    327     }
    328     negative = true;
    329   }
    330 
    331   if (radix == 0) {
    332     // Radix detection.
    333     radix = 10;
    334     if (*current == '0') {
    335       ++current;
    336       if (current == end) return SignedZero(negative);
    337       if (*current == 'x' || *current == 'X') {
    338         radix = 16;
    339         ++current;
    340         if (current == end) return JunkStringValue();
    341       } else {
    342         leading_zero = true;
    343       }
    344     }
    345   } else if (radix == 16) {
    346     if (*current == '0') {
    347       // Allow "0x" prefix.
    348       ++current;
    349       if (current == end) return SignedZero(negative);
    350       if (*current == 'x' || *current == 'X') {
    351         ++current;
    352         if (current == end) return JunkStringValue();
    353       } else {
    354         leading_zero = true;
    355       }
    356     }
    357   }
    358 
    359   if (radix < 2 || radix > 36) return JunkStringValue();
    360 
    361   // Skip leading zeros.
    362   while (*current == '0') {
    363     leading_zero = true;
    364     ++current;
    365     if (current == end) return SignedZero(negative);
    366   }
    367 
    368   if (!leading_zero && !isDigit(*current, radix)) {
    369     return JunkStringValue();
    370   }
    371 
    372   if (base::bits::IsPowerOfTwo32(radix)) {
    373     switch (radix) {
    374       case 2:
    375         return InternalStringToIntDouble<1>(
    376             unicode_cache, current, end, negative, allow_trailing_junk);
    377       case 4:
    378         return InternalStringToIntDouble<2>(
    379             unicode_cache, current, end, negative, allow_trailing_junk);
    380       case 8:
    381         return InternalStringToIntDouble<3>(
    382             unicode_cache, current, end, negative, allow_trailing_junk);
    383 
    384       case 16:
    385         return InternalStringToIntDouble<4>(
    386             unicode_cache, current, end, negative, allow_trailing_junk);
    387 
    388       case 32:
    389         return InternalStringToIntDouble<5>(
    390             unicode_cache, current, end, negative, allow_trailing_junk);
    391       default:
    392         UNREACHABLE();
    393     }
    394   }
    395 
    396   if (radix == 10) {
    397     // Parsing with strtod.
    398     const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
    399     // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
    400     // end.
    401     const int kBufferSize = kMaxSignificantDigits + 2;
    402     char buffer[kBufferSize];
    403     int buffer_pos = 0;
    404     while (*current >= '0' && *current <= '9') {
    405       if (buffer_pos <= kMaxSignificantDigits) {
    406         // If the number has more than kMaxSignificantDigits it will be parsed
    407         // as infinity.
    408         DCHECK(buffer_pos < kBufferSize);
    409         buffer[buffer_pos++] = static_cast<char>(*current);
    410       }
    411       ++current;
    412       if (current == end) break;
    413     }
    414 
    415     if (!allow_trailing_junk &&
    416         AdvanceToNonspace(unicode_cache, &current, end)) {
    417       return JunkStringValue();
    418     }
    419 
    420     SLOW_DCHECK(buffer_pos < kBufferSize);
    421     buffer[buffer_pos] = '\0';
    422     Vector<const char> buffer_vector(buffer, buffer_pos);
    423     return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
    424   }
    425 
    426   // The following code causes accumulating rounding error for numbers greater
    427   // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
    428   // 16, or 32, then mathInt may be an implementation-dependent approximation to
    429   // the mathematical integer value" (15.1.2.2).
    430 
    431   int lim_0 = '0' + (radix < 10 ? radix : 10);
    432   int lim_a = 'a' + (radix - 10);
    433   int lim_A = 'A' + (radix - 10);
    434 
    435   // NOTE: The code for computing the value may seem a bit complex at
    436   // first glance. It is structured to use 32-bit multiply-and-add
    437   // loops as long as possible to avoid loosing precision.
    438 
    439   double v = 0.0;
    440   bool done = false;
    441   do {
    442     // Parse the longest part of the string starting at index j
    443     // possible while keeping the multiplier, and thus the part
    444     // itself, within 32 bits.
    445     unsigned int part = 0, multiplier = 1;
    446     while (true) {
    447       int d;
    448       if (*current >= '0' && *current < lim_0) {
    449         d = *current - '0';
    450       } else if (*current >= 'a' && *current < lim_a) {
    451         d = *current - 'a' + 10;
    452       } else if (*current >= 'A' && *current < lim_A) {
    453         d = *current - 'A' + 10;
    454       } else {
    455         done = true;
    456         break;
    457       }
    458 
    459       // Update the value of the part as long as the multiplier fits
    460       // in 32 bits. When we can't guarantee that the next iteration
    461       // will not overflow the multiplier, we stop parsing the part
    462       // by leaving the loop.
    463       const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
    464       uint32_t m = multiplier * radix;
    465       if (m > kMaximumMultiplier) break;
    466       part = part * radix + d;
    467       multiplier = m;
    468       DCHECK(multiplier > part);
    469 
    470       ++current;
    471       if (current == end) {
    472         done = true;
    473         break;
    474       }
    475     }
    476 
    477     // Update the value and skip the part in the string.
    478     v = v * multiplier + part;
    479   } while (!done);
    480 
    481   if (!allow_trailing_junk &&
    482       AdvanceToNonspace(unicode_cache, &current, end)) {
    483     return JunkStringValue();
    484   }
    485 
    486   return negative ? -v : v;
    487 }
    488 
    489 
    490 // Converts a string to a double value. Assumes the Iterator supports
    491 // the following operations:
    492 // 1. current == end (other ops are not allowed), current != end.
    493 // 2. *current - gets the current character in the sequence.
    494 // 3. ++current (advances the position).
    495 template <class Iterator, class EndMark>
    496 double InternalStringToDouble(UnicodeCache* unicode_cache,
    497                               Iterator current,
    498                               EndMark end,
    499                               int flags,
    500                               double empty_string_val) {
    501   // To make sure that iterator dereferencing is valid the following
    502   // convention is used:
    503   // 1. Each '++current' statement is followed by check for equality to 'end'.
    504   // 2. If AdvanceToNonspace returned false then current == end.
    505   // 3. If 'current' becomes be equal to 'end' the function returns or goes to
    506   // 'parsing_done'.
    507   // 4. 'current' is not dereferenced after the 'parsing_done' label.
    508   // 5. Code before 'parsing_done' may rely on 'current != end'.
    509   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
    510     return empty_string_val;
    511   }
    512 
    513   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
    514 
    515   // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
    516   const int kBufferSize = kMaxSignificantDigits + 10;
    517   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
    518   int buffer_pos = 0;
    519 
    520   // Exponent will be adjusted if insignificant digits of the integer part
    521   // or insignificant leading zeros of the fractional part are dropped.
    522   int exponent = 0;
    523   int significant_digits = 0;
    524   int insignificant_digits = 0;
    525   bool nonzero_digit_dropped = false;
    526 
    527   enum Sign {
    528     NONE,
    529     NEGATIVE,
    530     POSITIVE
    531   };
    532 
    533   Sign sign = NONE;
    534 
    535   if (*current == '+') {
    536     // Ignore leading sign.
    537     ++current;
    538     if (current == end) return JunkStringValue();
    539     sign = POSITIVE;
    540   } else if (*current == '-') {
    541     ++current;
    542     if (current == end) return JunkStringValue();
    543     sign = NEGATIVE;
    544   }
    545 
    546   static const char kInfinityString[] = "Infinity";
    547   if (*current == kInfinityString[0]) {
    548     if (!SubStringEquals(&current, end, kInfinityString)) {
    549       return JunkStringValue();
    550     }
    551 
    552     if (!allow_trailing_junk &&
    553         AdvanceToNonspace(unicode_cache, &current, end)) {
    554       return JunkStringValue();
    555     }
    556 
    557     DCHECK(buffer_pos == 0);
    558     return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
    559   }
    560 
    561   bool leading_zero = false;
    562   if (*current == '0') {
    563     ++current;
    564     if (current == end) return SignedZero(sign == NEGATIVE);
    565 
    566     leading_zero = true;
    567 
    568     // It could be hexadecimal value.
    569     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
    570       ++current;
    571       if (current == end || !isDigit(*current, 16) || sign != NONE) {
    572         return JunkStringValue();  // "0x".
    573       }
    574 
    575       return InternalStringToIntDouble<4>(unicode_cache,
    576                                           current,
    577                                           end,
    578                                           false,
    579                                           allow_trailing_junk);
    580 
    581     // It could be an explicit octal value.
    582     } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
    583       ++current;
    584       if (current == end || !isDigit(*current, 8) || sign != NONE) {
    585         return JunkStringValue();  // "0o".
    586       }
    587 
    588       return InternalStringToIntDouble<3>(unicode_cache,
    589                                           current,
    590                                           end,
    591                                           false,
    592                                           allow_trailing_junk);
    593 
    594     // It could be a binary value.
    595     } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
    596       ++current;
    597       if (current == end || !isBinaryDigit(*current) || sign != NONE) {
    598         return JunkStringValue();  // "0b".
    599       }
    600 
    601       return InternalStringToIntDouble<1>(unicode_cache,
    602                                           current,
    603                                           end,
    604                                           false,
    605                                           allow_trailing_junk);
    606     }
    607 
    608     // Ignore leading zeros in the integer part.
    609     while (*current == '0') {
    610       ++current;
    611       if (current == end) return SignedZero(sign == NEGATIVE);
    612     }
    613   }
    614 
    615   bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
    616 
    617   // Copy significant digits of the integer part (if any) to the buffer.
    618   while (*current >= '0' && *current <= '9') {
    619     if (significant_digits < kMaxSignificantDigits) {
    620       DCHECK(buffer_pos < kBufferSize);
    621       buffer[buffer_pos++] = static_cast<char>(*current);
    622       significant_digits++;
    623       // Will later check if it's an octal in the buffer.
    624     } else {
    625       insignificant_digits++;  // Move the digit into the exponential part.
    626       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    627     }
    628     octal = octal && *current < '8';
    629     ++current;
    630     if (current == end) goto parsing_done;
    631   }
    632 
    633   if (significant_digits == 0) {
    634     octal = false;
    635   }
    636 
    637   if (*current == '.') {
    638     if (octal && !allow_trailing_junk) return JunkStringValue();
    639     if (octal) goto parsing_done;
    640 
    641     ++current;
    642     if (current == end) {
    643       if (significant_digits == 0 && !leading_zero) {
    644         return JunkStringValue();
    645       } else {
    646         goto parsing_done;
    647       }
    648     }
    649 
    650     if (significant_digits == 0) {
    651       // octal = false;
    652       // Integer part consists of 0 or is absent. Significant digits start after
    653       // leading zeros (if any).
    654       while (*current == '0') {
    655         ++current;
    656         if (current == end) return SignedZero(sign == NEGATIVE);
    657         exponent--;  // Move this 0 into the exponent.
    658       }
    659     }
    660 
    661     // There is a fractional part.  We don't emit a '.', but adjust the exponent
    662     // instead.
    663     while (*current >= '0' && *current <= '9') {
    664       if (significant_digits < kMaxSignificantDigits) {
    665         DCHECK(buffer_pos < kBufferSize);
    666         buffer[buffer_pos++] = static_cast<char>(*current);
    667         significant_digits++;
    668         exponent--;
    669       } else {
    670         // Ignore insignificant digits in the fractional part.
    671         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
    672       }
    673       ++current;
    674       if (current == end) goto parsing_done;
    675     }
    676   }
    677 
    678   if (!leading_zero && exponent == 0 && significant_digits == 0) {
    679     // If leading_zeros is true then the string contains zeros.
    680     // If exponent < 0 then string was [+-]\.0*...
    681     // If significant_digits != 0 the string is not equal to 0.
    682     // Otherwise there are no digits in the string.
    683     return JunkStringValue();
    684   }
    685 
    686   // Parse exponential part.
    687   if (*current == 'e' || *current == 'E') {
    688     if (octal) return JunkStringValue();
    689     ++current;
    690     if (current == end) {
    691       if (allow_trailing_junk) {
    692         goto parsing_done;
    693       } else {
    694         return JunkStringValue();
    695       }
    696     }
    697     char sign = '+';
    698     if (*current == '+' || *current == '-') {
    699       sign = static_cast<char>(*current);
    700       ++current;
    701       if (current == end) {
    702         if (allow_trailing_junk) {
    703           goto parsing_done;
    704         } else {
    705           return JunkStringValue();
    706         }
    707       }
    708     }
    709 
    710     if (current == end || *current < '0' || *current > '9') {
    711       if (allow_trailing_junk) {
    712         goto parsing_done;
    713       } else {
    714         return JunkStringValue();
    715       }
    716     }
    717 
    718     const int max_exponent = INT_MAX / 2;
    719     DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
    720     int num = 0;
    721     do {
    722       // Check overflow.
    723       int digit = *current - '0';
    724       if (num >= max_exponent / 10
    725           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
    726         num = max_exponent;
    727       } else {
    728         num = num * 10 + digit;
    729       }
    730       ++current;
    731     } while (current != end && *current >= '0' && *current <= '9');
    732 
    733     exponent += (sign == '-' ? -num : num);
    734   }
    735 
    736   if (!allow_trailing_junk &&
    737       AdvanceToNonspace(unicode_cache, &current, end)) {
    738     return JunkStringValue();
    739   }
    740 
    741   parsing_done:
    742   exponent += insignificant_digits;
    743 
    744   if (octal) {
    745     return InternalStringToIntDouble<3>(unicode_cache,
    746                                         buffer,
    747                                         buffer + buffer_pos,
    748                                         sign == NEGATIVE,
    749                                         allow_trailing_junk);
    750   }
    751 
    752   if (nonzero_digit_dropped) {
    753     buffer[buffer_pos++] = '1';
    754     exponent--;
    755   }
    756 
    757   SLOW_DCHECK(buffer_pos < kBufferSize);
    758   buffer[buffer_pos] = '\0';
    759 
    760   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
    761   return (sign == NEGATIVE) ? -converted : converted;
    762 }
    763 
    764 }  // namespace internal
    765 }  // namespace v8
    766 
    767 #endif  // V8_CONVERSIONS_INL_H_
    768