LCOV - code coverage report
Current view: top level - src - conversions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 498 512 97.3 %
Date: 2019-04-17 Functions: 42 56 75.0 %

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

Generated by: LCOV version 1.10