LCOV - code coverage report
Current view: top level - src - conversions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 486 504 96.4 %
Date: 2017-10-20 Functions: 45 59 76.3 %

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

Generated by: LCOV version 1.10