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