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