LCOV - code coverage report
Current view: top level - src - conversions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 489 507 96.4 %
Date: 2019-01-20 Functions: 44 60 73.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/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     1483607 :   return negative ? uint64_to_double(Double::kSignMask) : 0.0;
      38             : }
      39             : 
      40     1972284 : inline bool isDigit(int x, int radix) {
      41     3944680 :   return (x >= '0' && x <= '9' && x < '0' + radix) ||
      42     4492985 :          (radix > 10 && x >= 'a' && x < 'a' + radix - 10) ||
      43     1188707 :          (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
      44             : }
      45             : 
      46         201 : 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       76517 :   for (substring++; *substring != '\0'; substring++) {
      52       77425 :     ++*current;
      53       77425 :     if (*current == end || **current != *substring) return false;
      54             :   }
      55       10808 :   ++*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    13527200 : inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
      63    27068999 :   while (*current != end) {
      64    26115003 :     if (!IsWhiteSpaceOrLineTerminator(**current)) return true;
      65       14599 :     ++*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      786474 : double InternalStringToIntDouble(Iterator current, EndMark end, bool negative,
      73             :                                  bool allow_trailing_junk) {
      74             :   DCHECK(current != end);
      75             : 
      76             :   // Skip leading 0s.
      77     1654187 :   while (*current == '0') {
      78       90915 :     ++current;
      79      100591 :     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     2131467 :   do {
      91             :     int digit;
      92     2132047 :     if (*current >= '0' && *current < lim_0) {
      93     1561270 :       digit = static_cast<char>(*current) - '0';
      94      570777 :     } else if (*current >= 'a' && *current < lim_a) {
      95      549520 :       digit = static_cast<char>(*current) - 'a' + 10;
      96       21257 :     } else if (*current >= 'A' && *current < lim_A) {
      97       21051 :       digit = static_cast<char>(*current) - 'A' + 10;
      98             :     } else {
      99         206 :       if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
     100             :         break;
     101             :       } else {
     102             :         return JunkStringValue();
     103             :       }
     104             :     }
     105             : 
     106     2131841 :     number = number * radix + digit;
     107     2131841 :     int overflow = static_cast<int>(number >> 53);
     108     2131841 :     if (overflow != 0) {
     109             :       // Overflow occurred. Need to determine which direction to round the
     110             :       // result.
     111             :       int overflow_bits_count = 1;
     112        1407 :       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             :       while (true) {
     124       20560 :         ++current;
     125       20560 :         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       20186 :       break;
     151             :     }
     152     2131467 :     ++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      776741 :   if (exponent == 0) {
     159      776367 :     if (negative) {
     160           0 :       if (number == 0) return -0.0;
     161           0 :       number = -number;
     162             :     }
     163      776367 :     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     1341094 :       : 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        1134 :       : 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       22782 :       : isolate_(isolate), raw_one_byte_subject_(subject), length_(length) {}
     190           0 :   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       11201 :   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       12525 :     allow_binary_and_octal_prefixes_ = true;
     207             :   }
     208        1134 :   void set_disallow_trailing_junk() { allow_trailing_junk_ = false; }
     209             : 
     210     1522650 :   bool IsOneByte() const {
     211     3023491 :     return raw_one_byte_subject_ != nullptr ||
     212     3023491 :            String::IsOneByteRepresentationUnderneath(*subject_);
     213             :   }
     214             : 
     215      345009 :   Vector<const uint8_t> GetOneByteVector() {
     216      345009 :     if (raw_one_byte_subject_ != nullptr) {
     217       21809 :       return Vector<const uint8_t>(raw_one_byte_subject_, length_);
     218             :     }
     219             :     DisallowHeapAllocation no_gc;
     220      646400 :     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       11039 :   bool negative() { return sign_ == Sign::kNegative; }
     238             :   Sign sign() { return sign_; }
     239             :   State state() { return state_; }
     240     1342661 :   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     1353619 : void StringToIntHelper::ParseInt() {
     262             :   {
     263             :     DisallowHeapAllocation no_gc;
     264     1353619 :     if (IsOneByte()) {
     265      176365 :       Vector<const uint8_t> vector = GetOneByteVector();
     266      352730 :       DetectRadixInternal(vector.start(), vector.length());
     267             :     } else {
     268     1177254 :       Vector<const uc16> vector = GetTwoByteVector();
     269     2354508 :       DetectRadixInternal(vector.start(), vector.length());
     270             :     }
     271             :   }
     272     1353619 :   if (state_ != kRunning) return;
     273      169031 :   AllocateResult();
     274      169031 :   HandleSpecialCases();
     275      169031 :   if (state_ != kRunning) return;
     276             :   {
     277             :     DisallowHeapAllocation no_gc;
     278       11228 :     if (IsOneByte()) {
     279       11228 :       Vector<const uint8_t> vector = GetOneByteVector();
     280             :       DCHECK_EQ(length_, vector.length());
     281       11228 :       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     1353619 : void StringToIntHelper::DetectRadixInternal(Char current, int length) {
     293     1353619 :   Char start = current;
     294     1353619 :   length_ = length;
     295     1353619 :   Char end = start + length;
     296             : 
     297     1353619 :   if (!AdvanceToNonspace(&current, end)) {
     298             :     return set_state(kEmpty);
     299             :   }
     300             : 
     301     1353403 :   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     1353340 :   } 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     1353394 :   if (radix_ == 0) {
     317             :     // Radix detection.
     318     1352885 :     radix_ = 10;
     319     1352885 :     if (*current == '0') {
     320       23613 :       ++current;
     321       23613 :       if (current == end) return set_state(kZero);
     322       18666 :       if (*current == 'x' || *current == 'X') {
     323       18350 :         radix_ = 16;
     324       18350 :         ++current;
     325       18350 :         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     1348733 :   while (*current == '0') {
     355         331 :     leading_zero_ = true;
     356         331 :     ++current;
     357         331 :     if (current == end) return set_state(kZero);
     358             :   }
     359             : 
     360     1348402 :   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      169031 :   cursor_ = static_cast<int>(current - start);
     367             : }
     368             : 
     369             : template <class Char>
     370       11228 : void StringToIntHelper::ParseInternal(Char start) {
     371       11228 :   Char current = start + cursor_;
     372       11228 :   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       11228 :   int lim_0 = '0' + (radix_ < 10 ? radix_ : 10);
     380       11228 :   int lim_a = 'a' + (radix_ - 10);
     381       11228 :   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       34170 :   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      188958 :       if (*current >= '0' && *current < lim_0) {
     396      122481 :         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      188769 :       uint32_t m = multiplier * static_cast<uint32_t>(radix_);
     412      188769 :       if (m > kMaximumMultiplier) break;
     413      165827 :       part = part * radix_ + d;
     414             :       multiplier = m;
     415             :       DCHECK(multiplier > part);
     416             : 
     417      165827 :       ++current;
     418      165827 :       if (current == end) {
     419             :         done = true;
     420             :         break;
     421             :       }
     422             :     }
     423             : 
     424             :     // Update the value and skip the part in the string.
     425       34170 :     ResultMultiplyAdd(multiplier, part);
     426             :   } while (!done);
     427             : 
     428       11228 :   if (!allow_trailing_junk_ && AdvanceToNonspace(&current, end)) {
     429             :     return set_state(kJunk);
     430             :   }
     431             : 
     432             :   return set_state(kDone);
     433             : }
     434             : 
     435           0 : class NumberParseIntHelper : public StringToIntHelper {
     436             :  public:
     437             :   NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix)
     438     1341094 :       : StringToIntHelper(isolate, string, radix) {}
     439             : 
     440     1341094 :   double GetResult() {
     441     1502898 :     ParseInt();
     442     1341094 :     switch (state()) {
     443             :       case kJunk:
     444             :       case kEmpty:
     445             :         return JunkStringValue();
     446             :       case kZero:
     447        3974 :         return SignedZero(negative());
     448             :       case kDone:
     449      157830 :         return negative() ? -result_ : result_;
     450             :       case kError:
     451             :       case kRunning:
     452             :         break;
     453             :     }
     454           0 :     UNREACHABLE();
     455             :   }
     456             : 
     457             :  protected:
     458      157830 :   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      157830 :   void HandleSpecialCases() override {
     465      157830 :     bool is_power_of_two = base::bits::IsPowerOfTwo(radix());
     466      315660 :     if (!is_power_of_two && radix() != 10) return;
     467             :     DisallowHeapAllocation no_gc;
     468      157803 :     if (IsOneByte()) {
     469      157416 :       Vector<const uint8_t> vector = GetOneByteVector();
     470             :       DCHECK_EQ(length(), vector.length());
     471             :       result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start())
     472      157416 :                                 : 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       28444 :     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      143581 :   double HandleBaseTenCase(Char start) {
     514             :     // Parsing with strtod.
     515      143581 :     Char current = start + cursor();
     516      143581 :     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     1199146 :     while (*current >= '0' && *current <= '9') {
     524     1054161 :       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     1053504 :         buffer[buffer_pos++] = static_cast<char>(*current);
     529             :       }
     530     1054161 :       ++current;
     531     1054161 :       if (current == end) break;
     532             :     }
     533             : 
     534             :     SLOW_DCHECK(buffer_pos < kBufferSize);
     535      143581 :     buffer[buffer_pos] = '\0';
     536      143581 :     Vector<const char> buffer_vector(buffer, buffer_pos);
     537      143581 :     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    12125589 : 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    12125589 :   if (!AdvanceToNonspace(&current, end)) {
     560             :     return empty_string_val;
     561             :   }
     562             : 
     563    11667791 :   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    11667791 :   if (*current == '+') {
     591             :     // Ignore leading sign.
     592        4993 :     ++current;
     593        4993 :     if (current == end) return JunkStringValue();
     594             :     sign = POSITIVE;
     595    11662798 :   } else if (*current == '-') {
     596       12408 :     ++current;
     597       12408 :     if (current == end) return JunkStringValue();
     598             :     sign = NEGATIVE;
     599             :   }
     600             : 
     601             :   static const char kInfinityString[] = "Infinity";
     602    11667654 :   if (*current == kInfinityString[0]) {
     603       11716 :     if (!SubStringEquals(&current, end, kInfinityString)) {
     604             :       return JunkStringValue();
     605             :     }
     606             : 
     607       10808 :     if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
     608             :       return JunkStringValue();
     609             :     }
     610             : 
     611             :     DCHECK_EQ(buffer_pos, 0);
     612       10785 :     return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
     613             :   }
     614             : 
     615             :   bool leading_zero = false;
     616    11655938 :   if (*current == '0') {
     617     2767321 :     ++current;
     618     4185541 :     if (current == end) return SignedZero(sign == NEGATIVE);
     619             : 
     620             :     leading_zero = true;
     621             : 
     622             :     // It could be hexadecimal value.
     623     1349101 :     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
     624      603761 :       ++current;
     625      603761 :       if (current == end || !isDigit(*current, 16) || sign != NONE) {
     626             :         return JunkStringValue();  // "0x".
     627             :       }
     628             : 
     629             :       return InternalStringToIntDouble<4>(current, end, false,
     630      603773 :                                           allow_trailing_junk);
     631             : 
     632             :       // It could be an explicit octal value.
     633      745340 :     } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
     634         224 :       ++current;
     635         224 :       if (current == end || !isDigit(*current, 8) || sign != NONE) {
     636             :         return JunkStringValue();  // "0o".
     637             :       }
     638             : 
     639             :       return InternalStringToIntDouble<3>(current, end, false,
     640         222 :                                           allow_trailing_junk);
     641             : 
     642             :       // It could be a binary value.
     643      745116 :     } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
     644         201 :       ++current;
     645         402 :       if (current == end || !isBinaryDigit(*current) || sign != NONE) {
     646             :         return JunkStringValue();  // "0b".
     647             :       }
     648             : 
     649             :       return InternalStringToIntDouble<1>(current, end, false,
     650         199 :                                           allow_trailing_junk);
     651             :     }
     652             : 
     653             :     // Ignore leading zeros in the integer part.
     654      745031 :     while (*current == '0') {
     655       24166 :       ++current;
     656       48216 :       if (current == end) return SignedZero(sign == NEGATIVE);
     657             :     }
     658             :   }
     659             : 
     660     9609482 :   bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
     661             : 
     662             :   // Copy significant digits of the integer part (if any) to the buffer.
     663    21854452 :   while (*current >= '0' && *current <= '9') {
     664     3824499 :     if (significant_digits < kMaxSignificantDigits) {
     665             :       DCHECK_LT(buffer_pos, kBufferSize);
     666     3822148 :       buffer[buffer_pos++] = static_cast<char>(*current);
     667     3822148 :       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     3824499 :     octal = octal && *current < '8';
     674     3824499 :     ++current;
     675     3824499 :     if (current == end) goto parsing_done;
     676             :   }
     677             : 
     678     8420471 :   if (significant_digits == 0) {
     679             :     octal = false;
     680             :   }
     681             : 
     682     8420471 :   if (*current == '.') {
     683      685932 :     if (octal && !allow_trailing_junk) return JunkStringValue();
     684      685924 :     if (octal) goto parsing_done;
     685             : 
     686      685917 :     ++current;
     687      685917 :     if (current == end) {
     688        1615 :       if (significant_digits == 0 && !leading_zero) {
     689             :         return JunkStringValue();
     690             :       } else {
     691             :         goto parsing_done;
     692             :       }
     693             :     }
     694             : 
     695      684302 :     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      578022 :       while (*current == '0') {
     700       46500 :         ++current;
     701       74187 :         if (current == end) return SignedZero(sign == NEGATIVE);
     702       18813 :         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     1005652 :     while (*current >= '0' && *current <= '9') {
     709      994715 :       if (significant_digits < kMaxSignificantDigits) {
     710             :         DCHECK_LT(buffer_pos, kBufferSize);
     711      992919 :         buffer[buffer_pos++] = static_cast<char>(*current);
     712      992919 :         significant_digits++;
     713      992919 :         exponent--;
     714             :       } else {
     715             :         // Ignore insignificant digits in the fractional part.
     716        1796 :         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
     717             :       }
     718      994715 :       ++current;
     719      994715 :       if (current == end) goto parsing_done;
     720             :     }
     721             :   }
     722             : 
     723     7745476 :   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       36219 :   if (*current == 'e' || *current == 'E') {
     733       13160 :     if (octal) return JunkStringValue();
     734       13150 :     ++current;
     735       13150 :     if (current == end) {
     736          23 :       if (allow_trailing_junk) {
     737             :         goto parsing_done;
     738             :       } else {
     739             :         return JunkStringValue();
     740             :       }
     741             :     }
     742             :     char sign = '+';
     743       13127 :     if (*current == '+' || *current == '-') {
     744        7198 :       sign = static_cast<char>(*current);
     745        7198 :       ++current;
     746        7198 :       if (current == end) {
     747           5 :         if (allow_trailing_junk) {
     748             :           goto parsing_done;
     749             :         } else {
     750             :           return JunkStringValue();
     751             :         }
     752             :       }
     753             :     }
     754             : 
     755       13122 :     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       20407 :     do {
     767             :       // Check overflow.
     768       20407 :       int digit = *current - '0';
     769       20407 :       if (num >= max_exponent / 10 &&
     770             :           !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
     771             :         num = max_exponent;
     772             :       } else {
     773       20405 :         num = num * 10 + digit;
     774             :       }
     775       20407 :       ++current;
     776             :     } while (current != end && *current >= '0' && *current <= '9');
     777             : 
     778       13096 :     exponent += (sign == '-' ? -num : num);
     779             :   }
     780             : 
     781       36155 :   if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
     782             :     return JunkStringValue();
     783             :   }
     784             : 
     785             : parsing_done:
     786     1849458 :   exponent += insignificant_digits;
     787             : 
     788     1849458 :   if (octal) {
     789             :     return InternalStringToIntDouble<3>(buffer, buffer + buffer_pos,
     790      168061 :                                         sign == NEGATIVE, allow_trailing_junk);
     791             :   }
     792             : 
     793     1681397 :   if (nonzero_digit_dropped) {
     794          16 :     buffer[buffer_pos++] = '1';
     795          16 :     exponent--;
     796             :   }
     797             : 
     798             :   SLOW_DCHECK(buffer_pos < kBufferSize);
     799     1681397 :   buffer[buffer_pos] = '\0';
     800             : 
     801     3362794 :   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
     802     1681396 :   return (sign == NEGATIVE) ? -converted : converted;
     803             : }
     804             : 
     805      368347 : 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      368347 :   const uint8_t* end = start + StrLength(str);
     810      368347 :   return InternalStringToDouble(start, end, flags, empty_string_val);
     811             : }
     812             : 
     813     2971906 : 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     2971906 :   const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
     818    13541426 :   const uint8_t* end = start + str.length();
     819    10569520 :   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     1187729 :   const uc16* end = str.start() + str.length();
     825     1187729 :   return InternalStringToDouble(str.start(), end, flags, empty_string_val);
     826             : }
     827             : 
     828     1341094 : double StringToInt(Isolate* isolate, Handle<String> string, int radix) {
     829             :   NumberParseIntHelper helper(isolate, string, radix);
     830     1341094 :   return helper.GetResult();
     831             : }
     832             : 
     833           0 : 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        2268 :         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       22782 :         behavior_(Behavior::kLiteral) {
     850             :     set_allow_binary_and_octal_prefixes();
     851             :   }
     852             : 
     853       12525 :   MaybeHandle<BigInt> GetResult() {
     854       50928 :     ParseInt();
     855       13839 :     if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone &&
     856             :         radix() != 10) {
     857          90 :       return MaybeHandle<BigInt>();
     858             :     }
     859       12435 :     if (state() == kEmpty) {
     860         198 :       if (behavior_ == Behavior::kStringToBigInt) {
     861             :         set_state(kZero);
     862             :       } else {
     863           0 :         UNREACHABLE();
     864             :       }
     865             :     }
     866       12435 :     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        1180 :         return BigInt::Zero(isolate());
     878             :       case kError:
     879             :         DCHECK_EQ(should_throw() == kThrowOnError,
     880             :                   isolate()->has_pending_exception());
     881           0 :         return MaybeHandle<BigInt>();
     882             :       case kDone:
     883       11039 :         return BigInt::Finalize(result_, negative());
     884             :       case kEmpty:
     885             :       case kRunning:
     886             :         break;
     887             :     }
     888           0 :     UNREACHABLE();
     889             :   }
     890             : 
     891             :  protected:
     892       11201 :   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       22402 :     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             :     PretenureFlag pretenure =
     901       11201 :         behavior_ == Behavior::kLiteral ? TENURED : NOT_TENURED;
     902             :     MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor(
     903       11201 :         isolate(), radix(), charcount, should_throw(), pretenure);
     904       22402 :     if (!maybe.ToHandle(&result_)) {
     905             :       set_state(kError);
     906             :     }
     907       11201 :   }
     908             : 
     909       34125 :   void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) override {
     910             :     BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier),
     911       34125 :                                static_cast<uintptr_t>(part));
     912       34125 :   }
     913             : 
     914             :  private:
     915             :   ShouldThrow should_throw() const { return kDontThrow; }
     916             : 
     917             :   Handle<FreshlyAllocatedBigInt> result_;
     918             :   Behavior behavior_;
     919             : };
     920             : 
     921        1134 : MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) {
     922        1134 :   string = String::Flatten(isolate, string);
     923             :   StringToBigIntHelper helper(isolate, string);
     924        1134 :   return helper.GetResult();
     925             : }
     926             : 
     927       11391 : MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) {
     928             :   StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string),
     929       11391 :                               static_cast<int>(strlen(string)));
     930       11391 :   return helper.GetResult();
     931             : }
     932             : 
     933     1409033 : const char* DoubleToCString(double v, Vector<char> buffer) {
     934     1409033 :   switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) {
     935             :     case FP_NAN: return "NaN";
     936        7733 :     case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
     937       60317 :     case FP_ZERO: return "0";
     938             :     default: {
     939     1324645 :       if (IsInt32Double(v)) {
     940             :         // This will trigger if v is -0 and -0.0 is stringified to "0".
     941             :         // (see ES section 7.1.12.1 #sec-tostring-applied-to-the-number-type)
     942      197817 :         return IntToCString(FastD2I(v), buffer);
     943             :       }
     944     2253656 :       SimpleStringBuilder builder(buffer.start(), buffer.length());
     945             :       int decimal_point;
     946             :       int sign;
     947             :       const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
     948             :       char decimal_rep[kV8DtoaBufferCapacity];
     949             :       int length;
     950             : 
     951             :       DoubleToAscii(v, DTOA_SHORTEST, 0,
     952             :                     Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
     953     1126828 :                     &sign, &length, &decimal_point);
     954             : 
     955     1126828 :       if (sign) builder.AddCharacter('-');
     956             : 
     957     1126828 :       if (length <= decimal_point && decimal_point <= 21) {
     958             :         // ECMA-262 section 9.8.1 step 6.
     959      126075 :         builder.AddString(decimal_rep);
     960      126075 :         builder.AddPadding('0', decimal_point - length);
     961             : 
     962     1000753 :       } else if (0 < decimal_point && decimal_point <= 21) {
     963             :         // ECMA-262 section 9.8.1 step 7.
     964      693926 :         builder.AddSubstring(decimal_rep, decimal_point);
     965             :         builder.AddCharacter('.');
     966      693926 :         builder.AddString(decimal_rep + decimal_point);
     967             : 
     968      306827 :       } else if (decimal_point <= 0 && decimal_point > -6) {
     969             :         // ECMA-262 section 9.8.1 step 8.
     970       20747 :         builder.AddString("0.");
     971       20747 :         builder.AddPadding('0', -decimal_point);
     972       20747 :         builder.AddString(decimal_rep);
     973             : 
     974             :       } else {
     975             :         // ECMA-262 section 9.8.1 step 9 and 10 combined.
     976      286080 :         builder.AddCharacter(decimal_rep[0]);
     977      286080 :         if (length != 1) {
     978             :           builder.AddCharacter('.');
     979      284247 :           builder.AddString(decimal_rep + 1);
     980             :         }
     981             :         builder.AddCharacter('e');
     982      286080 :         builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
     983      286080 :         int exponent = decimal_point - 1;
     984      286080 :         if (exponent < 0) exponent = -exponent;
     985      286080 :         builder.AddDecimalInteger(exponent);
     986             :       }
     987     1126828 :       return builder.Finalize();
     988             :     }
     989             :   }
     990             : }
     991             : 
     992             : 
     993    42099593 : const char* IntToCString(int n, Vector<char> buffer) {
     994             :   bool negative = true;
     995    42099593 :   if (n >= 0) {
     996    41934782 :     n = -n;
     997             :     negative = false;
     998             :   }
     999             :   // Build the string backwards from the least significant digit.
    1000    42099593 :   int i = buffer.length();
    1001    84199186 :   buffer[--i] = '\0';
    1002   183350673 :   do {
    1003             :     // We ensured n <= 0, so the subtraction does the right addition.
    1004   366701346 :     buffer[--i] = '0' - (n % 10);
    1005   183350673 :     n /= 10;
    1006             :   } while (n);
    1007    42264401 :   if (negative) buffer[--i] = '-';
    1008    42099593 :   return buffer.start() + i;
    1009             : }
    1010             : 
    1011             : 
    1012        2928 : char* DoubleToFixedCString(double value, int f) {
    1013             :   const int kMaxDigitsBeforePoint = 21;
    1014             :   const double kFirstNonFixed = 1e21;
    1015             :   DCHECK_GE(f, 0);
    1016             :   DCHECK_LE(f, kMaxFractionDigits);
    1017             : 
    1018             :   bool negative = false;
    1019             :   double abs_value = value;
    1020        2928 :   if (value < 0) {
    1021         927 :     abs_value = -value;
    1022             :     negative = true;
    1023             :   }
    1024             : 
    1025             :   // If abs_value has more than kMaxDigitsBeforePoint digits before the point
    1026             :   // use the non-fixed conversion routine.
    1027        2928 :   if (abs_value >= kFirstNonFixed) {
    1028             :     char arr[kMaxFractionDigits];
    1029             :     Vector<char> buffer(arr, arraysize(arr));
    1030          72 :     return StrDup(DoubleToCString(value, buffer));
    1031             :   }
    1032             : 
    1033             :   // Find a sufficiently precise decimal representation of n.
    1034             :   int decimal_point;
    1035             :   int sign;
    1036             :   // Add space for the '\0' byte.
    1037             :   const int kDecimalRepCapacity =
    1038             :       kMaxDigitsBeforePoint + kMaxFractionDigits + 1;
    1039             :   char decimal_rep[kDecimalRepCapacity];
    1040             :   int decimal_rep_length;
    1041             :   DoubleToAscii(value, DTOA_FIXED, f,
    1042             :                 Vector<char>(decimal_rep, kDecimalRepCapacity),
    1043        2856 :                 &sign, &decimal_rep_length, &decimal_point);
    1044             : 
    1045             :   // Create a representation that is padded with zeros if needed.
    1046             :   int zero_prefix_length = 0;
    1047             :   int zero_postfix_length = 0;
    1048             : 
    1049        2856 :   if (decimal_point <= 0) {
    1050        1080 :     zero_prefix_length = -decimal_point + 1;
    1051        1080 :     decimal_point = 1;
    1052             :   }
    1053             : 
    1054        2856 :   if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
    1055        1266 :     zero_postfix_length = decimal_point + f - decimal_rep_length -
    1056        1266 :                           zero_prefix_length;
    1057             :   }
    1058             : 
    1059             :   unsigned rep_length =
    1060        2856 :       zero_prefix_length + decimal_rep_length + zero_postfix_length;
    1061        2856 :   SimpleStringBuilder rep_builder(rep_length + 1);
    1062        2856 :   rep_builder.AddPadding('0', zero_prefix_length);
    1063        2856 :   rep_builder.AddString(decimal_rep);
    1064        2856 :   rep_builder.AddPadding('0', zero_postfix_length);
    1065        2856 :   char* rep = rep_builder.Finalize();
    1066             : 
    1067             :   // Create the result string by appending a minus and putting in a
    1068             :   // decimal point if needed.
    1069        2856 :   unsigned result_size = decimal_point + f + 2;
    1070        2856 :   SimpleStringBuilder builder(result_size + 1);
    1071        2856 :   if (negative) builder.AddCharacter('-');
    1072        2856 :   builder.AddSubstring(rep, decimal_point);
    1073        2856 :   if (f > 0) {
    1074             :     builder.AddCharacter('.');
    1075        2109 :     builder.AddSubstring(rep + decimal_point, f);
    1076             :   }
    1077             :   DeleteArray(rep);
    1078        2856 :   return builder.Finalize();
    1079             : }
    1080             : 
    1081             : 
    1082        5112 : static char* CreateExponentialRepresentation(char* decimal_rep,
    1083             :                                              int exponent,
    1084             :                                              bool negative,
    1085             :                                              int significant_digits) {
    1086             :   bool negative_exponent = false;
    1087        5112 :   if (exponent < 0) {
    1088             :     negative_exponent = true;
    1089        1971 :     exponent = -exponent;
    1090             :   }
    1091             : 
    1092             :   // Leave room in the result for appending a minus, for a period, the
    1093             :   // letter 'e', a minus or a plus depending on the exponent, and a
    1094             :   // three digit exponent.
    1095        5112 :   unsigned result_size = significant_digits + 7;
    1096        5112 :   SimpleStringBuilder builder(result_size + 1);
    1097             : 
    1098        5112 :   if (negative) builder.AddCharacter('-');
    1099        5112 :   builder.AddCharacter(decimal_rep[0]);
    1100        5112 :   if (significant_digits != 1) {
    1101             :     builder.AddCharacter('.');
    1102        4257 :     builder.AddString(decimal_rep + 1);
    1103             :     int rep_length = StrLength(decimal_rep);
    1104        4257 :     builder.AddPadding('0', significant_digits - rep_length);
    1105             :   }
    1106             : 
    1107             :   builder.AddCharacter('e');
    1108        5112 :   builder.AddCharacter(negative_exponent ? '-' : '+');
    1109        5112 :   builder.AddDecimalInteger(exponent);
    1110       10224 :   return builder.Finalize();
    1111             : }
    1112             : 
    1113             : 
    1114        4149 : char* DoubleToExponentialCString(double value, int f) {
    1115             :   // f might be -1 to signal that f was undefined in JavaScript.
    1116             :   DCHECK(f >= -1 && f <= kMaxFractionDigits);
    1117             : 
    1118             :   bool negative = false;
    1119        4149 :   if (value < 0) {
    1120        1872 :     value = -value;
    1121             :     negative = true;
    1122             :   }
    1123             : 
    1124             :   // Find a sufficiently precise decimal representation of n.
    1125             :   int decimal_point;
    1126             :   int sign;
    1127             :   // f corresponds to the digits after the point. There is always one digit
    1128             :   // before the point. The number of requested_digits equals hence f + 1.
    1129             :   // And we have to add one character for the null-terminator.
    1130             :   const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1;
    1131             :   // Make sure that the buffer is big enough, even if we fall back to the
    1132             :   // shortest representation (which happens when f equals -1).
    1133             :   DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1);
    1134             :   char decimal_rep[kV8DtoaBufferCapacity];
    1135             :   int decimal_rep_length;
    1136             : 
    1137        4149 :   if (f == -1) {
    1138             :     DoubleToAscii(value, DTOA_SHORTEST, 0,
    1139             :                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    1140        1296 :                   &sign, &decimal_rep_length, &decimal_point);
    1141        1296 :     f = decimal_rep_length - 1;
    1142             :   } else {
    1143             :     DoubleToAscii(value, DTOA_PRECISION, f + 1,
    1144             :                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    1145        2853 :                   &sign, &decimal_rep_length, &decimal_point);
    1146             :   }
    1147             :   DCHECK_GT(decimal_rep_length, 0);
    1148             :   DCHECK(decimal_rep_length <= f + 1);
    1149             : 
    1150        4149 :   int exponent = decimal_point - 1;
    1151             :   char* result =
    1152        4149 :       CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
    1153             : 
    1154        4149 :   return result;
    1155             : }
    1156             : 
    1157             : 
    1158        2939 : char* DoubleToPrecisionCString(double value, int p) {
    1159             :   const int kMinimalDigits = 1;
    1160             :   DCHECK(p >= kMinimalDigits && p <= kMaxFractionDigits);
    1161             :   USE(kMinimalDigits);
    1162             : 
    1163             :   bool negative = false;
    1164        2939 :   if (value < 0) {
    1165        1422 :     value = -value;
    1166             :     negative = true;
    1167             :   }
    1168             : 
    1169             :   // Find a sufficiently precise decimal representation of n.
    1170             :   int decimal_point;
    1171             :   int sign;
    1172             :   // Add one for the terminating null character.
    1173             :   const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1;
    1174             :   char decimal_rep[kV8DtoaBufferCapacity];
    1175             :   int decimal_rep_length;
    1176             : 
    1177             :   DoubleToAscii(value, DTOA_PRECISION, p,
    1178             :                 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
    1179        2939 :                 &sign, &decimal_rep_length, &decimal_point);
    1180             :   DCHECK(decimal_rep_length <= p);
    1181             : 
    1182        2939 :   int exponent = decimal_point - 1;
    1183             : 
    1184             :   char* result = nullptr;
    1185             : 
    1186        2939 :   if (exponent < -6 || exponent >= p) {
    1187             :     result =
    1188         963 :         CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
    1189             :   } else {
    1190             :     // Use fixed notation.
    1191             :     //
    1192             :     // Leave room in the result for appending a minus, a period and in
    1193             :     // the case where decimal_point is not positive for a zero in
    1194             :     // front of the period.
    1195             :     unsigned result_size = (decimal_point <= 0)
    1196         702 :         ? -decimal_point + p + 3
    1197        2678 :         : p + 2;
    1198        1976 :     SimpleStringBuilder builder(result_size + 1);
    1199        1976 :     if (negative) builder.AddCharacter('-');
    1200        1976 :     if (decimal_point <= 0) {
    1201         702 :       builder.AddString("0.");
    1202         702 :       builder.AddPadding('0', -decimal_point);
    1203         702 :       builder.AddString(decimal_rep);
    1204         702 :       builder.AddPadding('0', p - decimal_rep_length);
    1205             :     } else {
    1206        1274 :       const int m = Min(decimal_rep_length, decimal_point);
    1207        1274 :       builder.AddSubstring(decimal_rep, m);
    1208        1274 :       builder.AddPadding('0', decimal_point - decimal_rep_length);
    1209        1274 :       if (decimal_point < p) {
    1210             :         builder.AddCharacter('.');
    1211        1049 :         const int extra = negative ? 2 : 1;
    1212        1049 :         if (decimal_rep_length > decimal_point) {
    1213         851 :           const int len = StrLength(decimal_rep + decimal_point);
    1214         851 :           const int n = Min(len, p - (builder.position() - extra));
    1215         851 :           builder.AddSubstring(decimal_rep + decimal_point, n);
    1216             :         }
    1217        1049 :         builder.AddPadding('0', extra + (p - builder.position()));
    1218             :       }
    1219             :     }
    1220        1976 :     result = builder.Finalize();
    1221             :   }
    1222             : 
    1223        2939 :   return result;
    1224             : }
    1225             : 
    1226      174945 : char* DoubleToRadixCString(double value, int radix) {
    1227             :   DCHECK(radix >= 2 && radix <= 36);
    1228             :   DCHECK(std::isfinite(value));
    1229             :   DCHECK_NE(0.0, value);
    1230             :   // Character array used for conversion.
    1231             :   static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    1232             : 
    1233             :   // Temporary buffer for the result. We start with the decimal point in the
    1234             :   // middle and write to the left for the integer part and to the right for the
    1235             :   // fractional part. 1024 characters for the exponent and 52 for the mantissa
    1236             :   // either way, with additional space for sign, decimal point and string
    1237             :   // termination should be sufficient.
    1238             :   static const int kBufferSize = 2200;
    1239             :   char buffer[kBufferSize];
    1240             :   int integer_cursor = kBufferSize / 2;
    1241             :   int fraction_cursor = integer_cursor;
    1242             : 
    1243      174945 :   bool negative = value < 0;
    1244      174945 :   if (negative) value = -value;
    1245             : 
    1246             :   // Split the value into an integer part and a fractional part.
    1247      174945 :   double integer = std::floor(value);
    1248      174945 :   double fraction = value - integer;
    1249             :   // We only compute fractional digits up to the input double's precision.
    1250      174945 :   double delta = 0.5 * (Double(value).NextDouble() - value);
    1251      349890 :   delta = std::max(Double(0.0).NextDouble(), delta);
    1252             :   DCHECK_GT(delta, 0.0);
    1253      174945 :   if (fraction > delta) {
    1254             :     // Insert decimal point.
    1255        1485 :     buffer[fraction_cursor++] = '.';
    1256       34299 :     do {
    1257             :       // Shift up by one digit.
    1258       34560 :       fraction *= radix;
    1259       34560 :       delta *= radix;
    1260             :       // Write digit.
    1261       34560 :       int digit = static_cast<int>(fraction);
    1262       34560 :       buffer[fraction_cursor++] = chars[digit];
    1263             :       // Calculate remainder.
    1264       34560 :       fraction -= digit;
    1265             :       // Round to even.
    1266       34560 :       if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) {
    1267       11574 :         if (fraction + delta > 1) {
    1268             :           // We need to back trace already written digits in case of carry-over.
    1269             :           while (true) {
    1270         279 :             fraction_cursor--;
    1271         279 :             if (fraction_cursor == kBufferSize / 2) {
    1272           0 :               CHECK_EQ('.', buffer[fraction_cursor]);
    1273             :               // Carry over to the integer part.
    1274           0 :               integer += 1;
    1275           0 :               break;
    1276             :             }
    1277         279 :             char c = buffer[fraction_cursor];
    1278             :             // Reconstruct digit.
    1279         279 :             int digit = c > '9' ? (c - 'a' + 10) : (c - '0');
    1280         279 :             if (digit + 1 < radix) {
    1281         261 :               buffer[fraction_cursor++] = chars[digit + 1];
    1282         261 :               break;
    1283             :             }
    1284             :           }
    1285             :           break;
    1286             :         }
    1287             :       }
    1288             :     } while (fraction > delta);
    1289             :   }
    1290             : 
    1291             :   // Compute integer digits. Fill unrepresented digits with zero.
    1292      370788 :   while (Double(integer / radix).Exponent() > 0) {
    1293             :     integer /= radix;
    1294       10449 :     buffer[--integer_cursor] = '0';
    1295             :   }
    1296      678940 :   do {
    1297             :     double remainder = Modulo(integer, radix);
    1298      678940 :     buffer[--integer_cursor] = chars[static_cast<int>(remainder)];
    1299      678940 :     integer = (integer - remainder) / radix;
    1300             :   } while (integer > 0);
    1301             : 
    1302             :   // Add sign and terminate string.
    1303      174945 :   if (negative) buffer[--integer_cursor] = '-';
    1304      174945 :   buffer[fraction_cursor++] = '\0';
    1305             :   DCHECK_LT(fraction_cursor, kBufferSize);
    1306             :   DCHECK_LE(0, integer_cursor);
    1307             :   // Allocate new string as return value.
    1308      174945 :   char* result = NewArray<char>(fraction_cursor - integer_cursor);
    1309      174945 :   memcpy(result, buffer + integer_cursor, fraction_cursor - integer_cursor);
    1310      174945 :   return result;
    1311             : }
    1312             : 
    1313             : 
    1314             : // ES6 18.2.4 parseFloat(string)
    1315     8785081 : double StringToDouble(Isolate* isolate, Handle<String> string, int flags,
    1316             :                       double empty_string_val) {
    1317     8785081 :   Handle<String> flattened = String::Flatten(isolate, string);
    1318             :   {
    1319             :     DisallowHeapAllocation no_gc;
    1320     8785084 :     String::FlatContent flat = flattened->GetFlatContent(no_gc);
    1321             :     DCHECK(flat.IsFlat());
    1322     8785084 :     if (flat.IsOneByte()) {
    1323     7597613 :       return StringToDouble(flat.ToOneByteVector(), flags, empty_string_val);
    1324             :     } else {
    1325     1187470 :       return StringToDouble(flat.ToUC16Vector(), flags, empty_string_val);
    1326             :     }
    1327             :   }
    1328             : }
    1329             : 
    1330       84893 : bool IsSpecialIndex(String string) {
    1331             :   // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX
    1332             :   const int kBufferSize = 24;
    1333             :   const int length = string->length();
    1334       84893 :   if (length == 0 || length > kBufferSize) return false;
    1335             :   uint16_t buffer[kBufferSize];
    1336       84883 :   String::WriteToFlat(string, buffer, 0, length);
    1337             :   // If the first char is not a digit or a '-' or we can't match 'NaN' or
    1338             :   // '(-)Infinity', bailout immediately.
    1339             :   int offset = 0;
    1340      169766 :   if (!IsDecimalDigit(buffer[0])) {
    1341       84461 :     if (buffer[0] == '-') {
    1342         978 :       if (length == 1) return false;  // Just '-' is bad.
    1343        1946 :       if (!IsDecimalDigit(buffer[1])) {
    1344          41 :         if (buffer[1] == 'I' && length == 9) {
    1345             :           // Allow matching of '-Infinity' below.
    1346             :         } else {
    1347             :           return false;
    1348             :         }
    1349             :       }
    1350             :       offset++;
    1351       83483 :     } else if (buffer[0] == 'I' && length == 8) {
    1352             :       // Allow matching of 'Infinity' below.
    1353       83478 :     } else if (buffer[0] == 'N' && length == 3) {
    1354             :       // Match NaN.
    1355         122 :       return buffer[1] == 'a' && buffer[2] == 'N';
    1356             :     } else {
    1357             :       return false;
    1358             :     }
    1359             :   }
    1360             :   // Expected fast path: key is an integer.
    1361             :   static const int kRepresentableIntegerLength = 15;  // (-)XXXXXXXXXXXXXXX
    1362        1400 :   if (length - offset <= kRepresentableIntegerLength) {
    1363             :     const int initial_offset = offset;
    1364             :     bool matches = true;
    1365        3801 :     for (; offset < length; offset++) {
    1366        7602 :       matches &= IsDecimalDigit(buffer[offset]);
    1367             :     }
    1368        1365 :     if (matches) {
    1369             :       // Match 0 and -0.
    1370        1141 :       if (buffer[initial_offset] == '0') return initial_offset == length - 1;
    1371             :       return true;
    1372             :     }
    1373             :   }
    1374             :   // Slow path: test DoubleToString(StringToDouble(string)) == string.
    1375         259 :   Vector<const uint16_t> vector(buffer, length);
    1376             :   double d = StringToDouble(vector, NO_FLAGS);
    1377         259 :   if (std::isnan(d)) return false;
    1378             :   // Compute reverse string.
    1379             :   char reverse_buffer[kBufferSize + 1];  // Result will be /0 terminated.
    1380             :   Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
    1381         254 :   const char* reverse_string = DoubleToCString(d, reverse_vector);
    1382        1735 :   for (int i = 0; i < length; ++i) {
    1383        1528 :     if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false;
    1384             :   }
    1385             :   return true;
    1386             : }
    1387             : }  // namespace internal
    1388      183867 : }  // namespace v8

Generated by: LCOV version 1.10