• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdarg.h>
29 #include <limits.h>
30 
31 #include "v8.h"
32 
33 #include "conversions-inl.h"
34 #include "dtoa.h"
35 #include "factory.h"
36 #include "scanner-base.h"
37 #include "strtod.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 namespace {
43 
44 // C++-style iterator adaptor for StringInputBuffer
45 // (unlike C++ iterators the end-marker has different type).
46 class StringInputBufferIterator {
47  public:
48   class EndMarker {};
49 
50   explicit StringInputBufferIterator(StringInputBuffer* buffer);
51 
52   int operator*() const;
53   void operator++();
operator ==(EndMarker const &) const54   bool operator==(EndMarker const&) const { return end_; }
operator !=(EndMarker const & m) const55   bool operator!=(EndMarker const& m) const { return !end_; }
56 
57  private:
58   StringInputBuffer* const buffer_;
59   int current_;
60   bool end_;
61 };
62 
63 
StringInputBufferIterator(StringInputBuffer * buffer)64 StringInputBufferIterator::StringInputBufferIterator(
65     StringInputBuffer* buffer) : buffer_(buffer) {
66   ++(*this);
67 }
68 
operator *() const69 int StringInputBufferIterator::operator*() const {
70   return current_;
71 }
72 
73 
operator ++()74 void StringInputBufferIterator::operator++() {
75   end_ = !buffer_->has_more();
76   if (!end_) {
77     current_ = buffer_->GetNext();
78   }
79 }
80 }
81 
82 
83 template <class Iterator, class EndMark>
SubStringEquals(Iterator * current,EndMark end,const char * substring)84 static bool SubStringEquals(Iterator* current,
85                             EndMark end,
86                             const char* substring) {
87   ASSERT(**current == *substring);
88   for (substring++; *substring != '\0'; substring++) {
89     ++*current;
90     if (*current == end || **current != *substring) return false;
91   }
92   ++*current;
93   return true;
94 }
95 
96 
97 // Maximum number of significant digits in decimal representation.
98 // The longest possible double in decimal representation is
99 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
100 // (768 digits). If we parse a number whose first digits are equal to a
101 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
102 // must be rounded to the bigger one unless the tail consists of zeros, so
103 // we don't need to preserve all the digits.
104 const int kMaxSignificantDigits = 772;
105 
106 
107 static const double JUNK_STRING_VALUE = OS::nan_value();
108 
109 
110 // Returns true if a nonspace found and false if the end has reached.
111 template <class Iterator, class EndMark>
AdvanceToNonspace(UnicodeCache * unicode_cache,Iterator * current,EndMark end)112 static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
113                                      Iterator* current,
114                                      EndMark end) {
115   while (*current != end) {
116     if (!unicode_cache->IsWhiteSpace(**current)) return true;
117     ++*current;
118   }
119   return false;
120 }
121 
122 
isDigit(int x,int radix)123 static bool isDigit(int x, int radix) {
124   return (x >= '0' && x <= '9' && x < '0' + radix)
125       || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
126       || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
127 }
128 
129 
SignedZero(bool negative)130 static double SignedZero(bool negative) {
131   return negative ? -0.0 : 0.0;
132 }
133 
134 
135 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
136 template <int radix_log_2, class Iterator, class EndMark>
InternalStringToIntDouble(UnicodeCache * unicode_cache,Iterator current,EndMark end,bool negative,bool allow_trailing_junk)137 static double InternalStringToIntDouble(UnicodeCache* unicode_cache,
138                                         Iterator current,
139                                         EndMark end,
140                                         bool negative,
141                                         bool allow_trailing_junk) {
142   ASSERT(current != end);
143 
144   // Skip leading 0s.
145   while (*current == '0') {
146     ++current;
147     if (current == end) return SignedZero(negative);
148   }
149 
150   int64_t number = 0;
151   int exponent = 0;
152   const int radix = (1 << radix_log_2);
153 
154   do {
155     int digit;
156     if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
157       digit = static_cast<char>(*current) - '0';
158     } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
159       digit = static_cast<char>(*current) - 'a' + 10;
160     } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
161       digit = static_cast<char>(*current) - 'A' + 10;
162     } else {
163       if (allow_trailing_junk ||
164           !AdvanceToNonspace(unicode_cache, &current, end)) {
165         break;
166       } else {
167         return JUNK_STRING_VALUE;
168       }
169     }
170 
171     number = number * radix + digit;
172     int overflow = static_cast<int>(number >> 53);
173     if (overflow != 0) {
174       // Overflow occurred. Need to determine which direction to round the
175       // result.
176       int overflow_bits_count = 1;
177       while (overflow > 1) {
178         overflow_bits_count++;
179         overflow >>= 1;
180       }
181 
182       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
183       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
184       number >>= overflow_bits_count;
185       exponent = overflow_bits_count;
186 
187       bool zero_tail = true;
188       while (true) {
189         ++current;
190         if (current == end || !isDigit(*current, radix)) break;
191         zero_tail = zero_tail && *current == '0';
192         exponent += radix_log_2;
193       }
194 
195       if (!allow_trailing_junk &&
196           AdvanceToNonspace(unicode_cache, &current, end)) {
197         return JUNK_STRING_VALUE;
198       }
199 
200       int middle_value = (1 << (overflow_bits_count - 1));
201       if (dropped_bits > middle_value) {
202         number++;  // Rounding up.
203       } else if (dropped_bits == middle_value) {
204         // Rounding to even to consistency with decimals: half-way case rounds
205         // up if significant part is odd and down otherwise.
206         if ((number & 1) != 0 || !zero_tail) {
207           number++;  // Rounding up.
208         }
209       }
210 
211       // Rounding up may cause overflow.
212       if ((number & ((int64_t)1 << 53)) != 0) {
213         exponent++;
214         number >>= 1;
215       }
216       break;
217     }
218     ++current;
219   } while (current != end);
220 
221   ASSERT(number < ((int64_t)1 << 53));
222   ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
223 
224   if (exponent == 0) {
225     if (negative) {
226       if (number == 0) return -0.0;
227       number = -number;
228     }
229     return static_cast<double>(number);
230   }
231 
232   ASSERT(number != 0);
233   // The double could be constructed faster from number (mantissa), exponent
234   // and sign. Assuming it's a rare case more simple code is used.
235   return static_cast<double>(negative ? -number : number) * pow(2.0, exponent);
236 }
237 
238 
239 template <class Iterator, class EndMark>
InternalStringToInt(UnicodeCache * unicode_cache,Iterator current,EndMark end,int radix)240 static double InternalStringToInt(UnicodeCache* unicode_cache,
241                                   Iterator current,
242                                   EndMark end,
243                                   int radix) {
244   const bool allow_trailing_junk = true;
245   const double empty_string_val = JUNK_STRING_VALUE;
246 
247   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
248     return empty_string_val;
249   }
250 
251   bool negative = false;
252   bool leading_zero = false;
253 
254   if (*current == '+') {
255     // Ignore leading sign; skip following spaces.
256     ++current;
257     if (!AdvanceToNonspace(unicode_cache, &current, end)) {
258       return JUNK_STRING_VALUE;
259     }
260   } else if (*current == '-') {
261     ++current;
262     if (!AdvanceToNonspace(unicode_cache, &current, end)) {
263       return JUNK_STRING_VALUE;
264     }
265     negative = true;
266   }
267 
268   if (radix == 0) {
269     // Radix detection.
270     if (*current == '0') {
271       ++current;
272       if (current == end) return SignedZero(negative);
273       if (*current == 'x' || *current == 'X') {
274         radix = 16;
275         ++current;
276         if (current == end) return JUNK_STRING_VALUE;
277       } else {
278         radix = 8;
279         leading_zero = true;
280       }
281     } else {
282       radix = 10;
283     }
284   } else if (radix == 16) {
285     if (*current == '0') {
286       // Allow "0x" prefix.
287       ++current;
288       if (current == end) return SignedZero(negative);
289       if (*current == 'x' || *current == 'X') {
290         ++current;
291         if (current == end) return JUNK_STRING_VALUE;
292       } else {
293         leading_zero = true;
294       }
295     }
296   }
297 
298   if (radix < 2 || radix > 36) return JUNK_STRING_VALUE;
299 
300   // Skip leading zeros.
301   while (*current == '0') {
302     leading_zero = true;
303     ++current;
304     if (current == end) return SignedZero(negative);
305   }
306 
307   if (!leading_zero && !isDigit(*current, radix)) {
308     return JUNK_STRING_VALUE;
309   }
310 
311   if (IsPowerOf2(radix)) {
312     switch (radix) {
313       case 2:
314         return InternalStringToIntDouble<1>(
315             unicode_cache, current, end, negative, allow_trailing_junk);
316       case 4:
317         return InternalStringToIntDouble<2>(
318             unicode_cache, current, end, negative, allow_trailing_junk);
319       case 8:
320         return InternalStringToIntDouble<3>(
321             unicode_cache, current, end, negative, allow_trailing_junk);
322 
323       case 16:
324         return InternalStringToIntDouble<4>(
325             unicode_cache, current, end, negative, allow_trailing_junk);
326 
327       case 32:
328         return InternalStringToIntDouble<5>(
329             unicode_cache, current, end, negative, allow_trailing_junk);
330       default:
331         UNREACHABLE();
332     }
333   }
334 
335   if (radix == 10) {
336     // Parsing with strtod.
337     const int kMaxSignificantDigits = 309;  // Doubles are less than 1.8e308.
338     // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
339     // end.
340     const int kBufferSize = kMaxSignificantDigits + 2;
341     char buffer[kBufferSize];
342     int buffer_pos = 0;
343     while (*current >= '0' && *current <= '9') {
344       if (buffer_pos <= kMaxSignificantDigits) {
345         // If the number has more than kMaxSignificantDigits it will be parsed
346         // as infinity.
347         ASSERT(buffer_pos < kBufferSize);
348         buffer[buffer_pos++] = static_cast<char>(*current);
349       }
350       ++current;
351       if (current == end) break;
352     }
353 
354     if (!allow_trailing_junk &&
355         AdvanceToNonspace(unicode_cache, &current, end)) {
356       return JUNK_STRING_VALUE;
357     }
358 
359     ASSERT(buffer_pos < kBufferSize);
360     buffer[buffer_pos] = '\0';
361     Vector<const char> buffer_vector(buffer, buffer_pos);
362     return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
363   }
364 
365   // The following code causes accumulating rounding error for numbers greater
366   // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
367   // 16, or 32, then mathInt may be an implementation-dependent approximation to
368   // the mathematical integer value" (15.1.2.2).
369 
370   int lim_0 = '0' + (radix < 10 ? radix : 10);
371   int lim_a = 'a' + (radix - 10);
372   int lim_A = 'A' + (radix - 10);
373 
374   // NOTE: The code for computing the value may seem a bit complex at
375   // first glance. It is structured to use 32-bit multiply-and-add
376   // loops as long as possible to avoid loosing precision.
377 
378   double v = 0.0;
379   bool done = false;
380   do {
381     // Parse the longest part of the string starting at index j
382     // possible while keeping the multiplier, and thus the part
383     // itself, within 32 bits.
384     unsigned int part = 0, multiplier = 1;
385     while (true) {
386       int d;
387       if (*current >= '0' && *current < lim_0) {
388         d = *current - '0';
389       } else if (*current >= 'a' && *current < lim_a) {
390         d = *current - 'a' + 10;
391       } else if (*current >= 'A' && *current < lim_A) {
392         d = *current - 'A' + 10;
393       } else {
394         done = true;
395         break;
396       }
397 
398       // Update the value of the part as long as the multiplier fits
399       // in 32 bits. When we can't guarantee that the next iteration
400       // will not overflow the multiplier, we stop parsing the part
401       // by leaving the loop.
402       const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
403       uint32_t m = multiplier * radix;
404       if (m > kMaximumMultiplier) break;
405       part = part * radix + d;
406       multiplier = m;
407       ASSERT(multiplier > part);
408 
409       ++current;
410       if (current == end) {
411         done = true;
412         break;
413       }
414     }
415 
416     // Update the value and skip the part in the string.
417     v = v * multiplier + part;
418   } while (!done);
419 
420   if (!allow_trailing_junk &&
421       AdvanceToNonspace(unicode_cache, &current, end)) {
422     return JUNK_STRING_VALUE;
423   }
424 
425   return negative ? -v : v;
426 }
427 
428 
429 // Converts a string to a double value. Assumes the Iterator supports
430 // the following operations:
431 // 1. current == end (other ops are not allowed), current != end.
432 // 2. *current - gets the current character in the sequence.
433 // 3. ++current (advances the position).
434 template <class Iterator, class EndMark>
InternalStringToDouble(UnicodeCache * unicode_cache,Iterator current,EndMark end,int flags,double empty_string_val)435 static double InternalStringToDouble(UnicodeCache* unicode_cache,
436                                      Iterator current,
437                                      EndMark end,
438                                      int flags,
439                                      double empty_string_val) {
440   // To make sure that iterator dereferencing is valid the following
441   // convention is used:
442   // 1. Each '++current' statement is followed by check for equality to 'end'.
443   // 2. If AdvanceToNonspace returned false then current == end.
444   // 3. If 'current' becomes be equal to 'end' the function returns or goes to
445   // 'parsing_done'.
446   // 4. 'current' is not dereferenced after the 'parsing_done' label.
447   // 5. Code before 'parsing_done' may rely on 'current != end'.
448   if (!AdvanceToNonspace(unicode_cache, &current, end)) {
449     return empty_string_val;
450   }
451 
452   const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
453 
454   // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
455   const int kBufferSize = kMaxSignificantDigits + 10;
456   char buffer[kBufferSize];  // NOLINT: size is known at compile time.
457   int buffer_pos = 0;
458 
459   // Exponent will be adjusted if insignificant digits of the integer part
460   // or insignificant leading zeros of the fractional part are dropped.
461   int exponent = 0;
462   int significant_digits = 0;
463   int insignificant_digits = 0;
464   bool nonzero_digit_dropped = false;
465   bool fractional_part = false;
466 
467   bool negative = false;
468 
469   if (*current == '+') {
470     // Ignore leading sign.
471     ++current;
472     if (current == end) return JUNK_STRING_VALUE;
473   } else if (*current == '-') {
474     ++current;
475     if (current == end) return JUNK_STRING_VALUE;
476     negative = true;
477   }
478 
479   static const char kInfinitySymbol[] = "Infinity";
480   if (*current == kInfinitySymbol[0]) {
481     if (!SubStringEquals(&current, end, kInfinitySymbol)) {
482       return JUNK_STRING_VALUE;
483     }
484 
485     if (!allow_trailing_junk &&
486         AdvanceToNonspace(unicode_cache, &current, end)) {
487       return JUNK_STRING_VALUE;
488     }
489 
490     ASSERT(buffer_pos == 0);
491     return negative ? -V8_INFINITY : V8_INFINITY;
492   }
493 
494   bool leading_zero = false;
495   if (*current == '0') {
496     ++current;
497     if (current == end) return SignedZero(negative);
498 
499     leading_zero = true;
500 
501     // It could be hexadecimal value.
502     if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
503       ++current;
504       if (current == end || !isDigit(*current, 16)) {
505         return JUNK_STRING_VALUE;  // "0x".
506       }
507 
508       return InternalStringToIntDouble<4>(unicode_cache,
509                                           current,
510                                           end,
511                                           negative,
512                                           allow_trailing_junk);
513     }
514 
515     // Ignore leading zeros in the integer part.
516     while (*current == '0') {
517       ++current;
518       if (current == end) return SignedZero(negative);
519     }
520   }
521 
522   bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
523 
524   // Copy significant digits of the integer part (if any) to the buffer.
525   while (*current >= '0' && *current <= '9') {
526     if (significant_digits < kMaxSignificantDigits) {
527       ASSERT(buffer_pos < kBufferSize);
528       buffer[buffer_pos++] = static_cast<char>(*current);
529       significant_digits++;
530       // Will later check if it's an octal in the buffer.
531     } else {
532       insignificant_digits++;  // Move the digit into the exponential part.
533       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
534     }
535     octal = octal && *current < '8';
536     ++current;
537     if (current == end) goto parsing_done;
538   }
539 
540   if (significant_digits == 0) {
541     octal = false;
542   }
543 
544   if (*current == '.') {
545     if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
546     if (octal) goto parsing_done;
547 
548     ++current;
549     if (current == end) {
550       if (significant_digits == 0 && !leading_zero) {
551         return JUNK_STRING_VALUE;
552       } else {
553         goto parsing_done;
554       }
555     }
556 
557     if (significant_digits == 0) {
558       // octal = false;
559       // Integer part consists of 0 or is absent. Significant digits start after
560       // leading zeros (if any).
561       while (*current == '0') {
562         ++current;
563         if (current == end) return SignedZero(negative);
564         exponent--;  // Move this 0 into the exponent.
565       }
566     }
567 
568     // We don't emit a '.', but adjust the exponent instead.
569     fractional_part = true;
570 
571     // There is a fractional part.
572     while (*current >= '0' && *current <= '9') {
573       if (significant_digits < kMaxSignificantDigits) {
574         ASSERT(buffer_pos < kBufferSize);
575         buffer[buffer_pos++] = static_cast<char>(*current);
576         significant_digits++;
577         exponent--;
578       } else {
579         // Ignore insignificant digits in the fractional part.
580         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
581       }
582       ++current;
583       if (current == end) goto parsing_done;
584     }
585   }
586 
587   if (!leading_zero && exponent == 0 && significant_digits == 0) {
588     // If leading_zeros is true then the string contains zeros.
589     // If exponent < 0 then string was [+-]\.0*...
590     // If significant_digits != 0 the string is not equal to 0.
591     // Otherwise there are no digits in the string.
592     return JUNK_STRING_VALUE;
593   }
594 
595   // Parse exponential part.
596   if (*current == 'e' || *current == 'E') {
597     if (octal) return JUNK_STRING_VALUE;
598     ++current;
599     if (current == end) {
600       if (allow_trailing_junk) {
601         goto parsing_done;
602       } else {
603         return JUNK_STRING_VALUE;
604       }
605     }
606     char sign = '+';
607     if (*current == '+' || *current == '-') {
608       sign = static_cast<char>(*current);
609       ++current;
610       if (current == end) {
611         if (allow_trailing_junk) {
612           goto parsing_done;
613         } else {
614           return JUNK_STRING_VALUE;
615         }
616       }
617     }
618 
619     if (current == end || *current < '0' || *current > '9') {
620       if (allow_trailing_junk) {
621         goto parsing_done;
622       } else {
623         return JUNK_STRING_VALUE;
624       }
625     }
626 
627     const int max_exponent = INT_MAX / 2;
628     ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
629     int num = 0;
630     do {
631       // Check overflow.
632       int digit = *current - '0';
633       if (num >= max_exponent / 10
634           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
635         num = max_exponent;
636       } else {
637         num = num * 10 + digit;
638       }
639       ++current;
640     } while (current != end && *current >= '0' && *current <= '9');
641 
642     exponent += (sign == '-' ? -num : num);
643   }
644 
645   if (!allow_trailing_junk &&
646       AdvanceToNonspace(unicode_cache, &current, end)) {
647     return JUNK_STRING_VALUE;
648   }
649 
650   parsing_done:
651   exponent += insignificant_digits;
652 
653   if (octal) {
654     return InternalStringToIntDouble<3>(unicode_cache,
655                                         buffer,
656                                         buffer + buffer_pos,
657                                         negative,
658                                         allow_trailing_junk);
659   }
660 
661   if (nonzero_digit_dropped) {
662     buffer[buffer_pos++] = '1';
663     exponent--;
664   }
665 
666   ASSERT(buffer_pos < kBufferSize);
667   buffer[buffer_pos] = '\0';
668 
669   double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
670   return negative ? -converted : converted;
671 }
672 
673 
StringToDouble(UnicodeCache * unicode_cache,String * str,int flags,double empty_string_val)674 double StringToDouble(UnicodeCache* unicode_cache,
675                       String* str, int flags, double empty_string_val) {
676   StringShape shape(str);
677   if (shape.IsSequentialAscii()) {
678     const char* begin = SeqAsciiString::cast(str)->GetChars();
679     const char* end = begin + str->length();
680     return InternalStringToDouble(unicode_cache, begin, end, flags,
681                                   empty_string_val);
682   } else if (shape.IsSequentialTwoByte()) {
683     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
684     const uc16* end = begin + str->length();
685     return InternalStringToDouble(unicode_cache, begin, end, flags,
686                                   empty_string_val);
687   } else {
688     StringInputBuffer buffer(str);
689     return InternalStringToDouble(unicode_cache,
690                                   StringInputBufferIterator(&buffer),
691                                   StringInputBufferIterator::EndMarker(),
692                                   flags,
693                                   empty_string_val);
694   }
695 }
696 
697 
StringToInt(UnicodeCache * unicode_cache,String * str,int radix)698 double StringToInt(UnicodeCache* unicode_cache,
699                    String* str,
700                    int radix) {
701   StringShape shape(str);
702   if (shape.IsSequentialAscii()) {
703     const char* begin = SeqAsciiString::cast(str)->GetChars();
704     const char* end = begin + str->length();
705     return InternalStringToInt(unicode_cache, begin, end, radix);
706   } else if (shape.IsSequentialTwoByte()) {
707     const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
708     const uc16* end = begin + str->length();
709     return InternalStringToInt(unicode_cache, begin, end, radix);
710   } else {
711     StringInputBuffer buffer(str);
712     return InternalStringToInt(unicode_cache,
713                                StringInputBufferIterator(&buffer),
714                                StringInputBufferIterator::EndMarker(),
715                                radix);
716   }
717 }
718 
719 
StringToDouble(UnicodeCache * unicode_cache,const char * str,int flags,double empty_string_val)720 double StringToDouble(UnicodeCache* unicode_cache,
721                       const char* str, int flags, double empty_string_val) {
722   const char* end = str + StrLength(str);
723   return InternalStringToDouble(unicode_cache, str, end, flags,
724                                 empty_string_val);
725 }
726 
727 
StringToDouble(UnicodeCache * unicode_cache,Vector<const char> str,int flags,double empty_string_val)728 double StringToDouble(UnicodeCache* unicode_cache,
729                       Vector<const char> str,
730                       int flags,
731                       double empty_string_val) {
732   const char* end = str.start() + str.length();
733   return InternalStringToDouble(unicode_cache, str.start(), end, flags,
734                                 empty_string_val);
735 }
736 
737 
DoubleToCString(double v,Vector<char> buffer)738 const char* DoubleToCString(double v, Vector<char> buffer) {
739   switch (fpclassify(v)) {
740     case FP_NAN: return "NaN";
741     case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
742     case FP_ZERO: return "0";
743     default: {
744       StringBuilder builder(buffer.start(), buffer.length());
745       int decimal_point;
746       int sign;
747       const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
748       char decimal_rep[kV8DtoaBufferCapacity];
749       int length;
750 
751       DoubleToAscii(v, DTOA_SHORTEST, 0,
752                     Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
753                     &sign, &length, &decimal_point);
754 
755       if (sign) builder.AddCharacter('-');
756 
757       if (length <= decimal_point && decimal_point <= 21) {
758         // ECMA-262 section 9.8.1 step 6.
759         builder.AddString(decimal_rep);
760         builder.AddPadding('0', decimal_point - length);
761 
762       } else if (0 < decimal_point && decimal_point <= 21) {
763         // ECMA-262 section 9.8.1 step 7.
764         builder.AddSubstring(decimal_rep, decimal_point);
765         builder.AddCharacter('.');
766         builder.AddString(decimal_rep + decimal_point);
767 
768       } else if (decimal_point <= 0 && decimal_point > -6) {
769         // ECMA-262 section 9.8.1 step 8.
770         builder.AddString("0.");
771         builder.AddPadding('0', -decimal_point);
772         builder.AddString(decimal_rep);
773 
774       } else {
775         // ECMA-262 section 9.8.1 step 9 and 10 combined.
776         builder.AddCharacter(decimal_rep[0]);
777         if (length != 1) {
778           builder.AddCharacter('.');
779           builder.AddString(decimal_rep + 1);
780         }
781         builder.AddCharacter('e');
782         builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
783         int exponent = decimal_point - 1;
784         if (exponent < 0) exponent = -exponent;
785         builder.AddFormatted("%d", exponent);
786       }
787     return builder.Finalize();
788     }
789   }
790 }
791 
792 
IntToCString(int n,Vector<char> buffer)793 const char* IntToCString(int n, Vector<char> buffer) {
794   bool negative = false;
795   if (n < 0) {
796     // We must not negate the most negative int.
797     if (n == kMinInt) return DoubleToCString(n, buffer);
798     negative = true;
799     n = -n;
800   }
801   // Build the string backwards from the least significant digit.
802   int i = buffer.length();
803   buffer[--i] = '\0';
804   do {
805     buffer[--i] = '0' + (n % 10);
806     n /= 10;
807   } while (n);
808   if (negative) buffer[--i] = '-';
809   return buffer.start() + i;
810 }
811 
812 
DoubleToFixedCString(double value,int f)813 char* DoubleToFixedCString(double value, int f) {
814   const int kMaxDigitsBeforePoint = 21;
815   const double kFirstNonFixed = 1e21;
816   const int kMaxDigitsAfterPoint = 20;
817   ASSERT(f >= 0);
818   ASSERT(f <= kMaxDigitsAfterPoint);
819 
820   bool negative = false;
821   double abs_value = value;
822   if (value < 0) {
823     abs_value = -value;
824     negative = true;
825   }
826 
827   // If abs_value has more than kMaxDigitsBeforePoint digits before the point
828   // use the non-fixed conversion routine.
829   if (abs_value >= kFirstNonFixed) {
830     char arr[100];
831     Vector<char> buffer(arr, ARRAY_SIZE(arr));
832     return StrDup(DoubleToCString(value, buffer));
833   }
834 
835   // Find a sufficiently precise decimal representation of n.
836   int decimal_point;
837   int sign;
838   // Add space for the '\0' byte.
839   const int kDecimalRepCapacity =
840       kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
841   char decimal_rep[kDecimalRepCapacity];
842   int decimal_rep_length;
843   DoubleToAscii(value, DTOA_FIXED, f,
844                 Vector<char>(decimal_rep, kDecimalRepCapacity),
845                 &sign, &decimal_rep_length, &decimal_point);
846 
847   // Create a representation that is padded with zeros if needed.
848   int zero_prefix_length = 0;
849   int zero_postfix_length = 0;
850 
851   if (decimal_point <= 0) {
852     zero_prefix_length = -decimal_point + 1;
853     decimal_point = 1;
854   }
855 
856   if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
857     zero_postfix_length = decimal_point + f - decimal_rep_length -
858                           zero_prefix_length;
859   }
860 
861   unsigned rep_length =
862       zero_prefix_length + decimal_rep_length + zero_postfix_length;
863   StringBuilder rep_builder(rep_length + 1);
864   rep_builder.AddPadding('0', zero_prefix_length);
865   rep_builder.AddString(decimal_rep);
866   rep_builder.AddPadding('0', zero_postfix_length);
867   char* rep = rep_builder.Finalize();
868 
869   // Create the result string by appending a minus and putting in a
870   // decimal point if needed.
871   unsigned result_size = decimal_point + f + 2;
872   StringBuilder builder(result_size + 1);
873   if (negative) builder.AddCharacter('-');
874   builder.AddSubstring(rep, decimal_point);
875   if (f > 0) {
876     builder.AddCharacter('.');
877     builder.AddSubstring(rep + decimal_point, f);
878   }
879   DeleteArray(rep);
880   return builder.Finalize();
881 }
882 
883 
CreateExponentialRepresentation(char * decimal_rep,int exponent,bool negative,int significant_digits)884 static char* CreateExponentialRepresentation(char* decimal_rep,
885                                              int exponent,
886                                              bool negative,
887                                              int significant_digits) {
888   bool negative_exponent = false;
889   if (exponent < 0) {
890     negative_exponent = true;
891     exponent = -exponent;
892   }
893 
894   // Leave room in the result for appending a minus, for a period, the
895   // letter 'e', a minus or a plus depending on the exponent, and a
896   // three digit exponent.
897   unsigned result_size = significant_digits + 7;
898   StringBuilder builder(result_size + 1);
899 
900   if (negative) builder.AddCharacter('-');
901   builder.AddCharacter(decimal_rep[0]);
902   if (significant_digits != 1) {
903     builder.AddCharacter('.');
904     builder.AddString(decimal_rep + 1);
905     int rep_length = StrLength(decimal_rep);
906     builder.AddPadding('0', significant_digits - rep_length);
907   }
908 
909   builder.AddCharacter('e');
910   builder.AddCharacter(negative_exponent ? '-' : '+');
911   builder.AddFormatted("%d", exponent);
912   return builder.Finalize();
913 }
914 
915 
916 
DoubleToExponentialCString(double value,int f)917 char* DoubleToExponentialCString(double value, int f) {
918   const int kMaxDigitsAfterPoint = 20;
919   // f might be -1 to signal that f was undefined in JavaScript.
920   ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
921 
922   bool negative = false;
923   if (value < 0) {
924     value = -value;
925     negative = true;
926   }
927 
928   // Find a sufficiently precise decimal representation of n.
929   int decimal_point;
930   int sign;
931   // f corresponds to the digits after the point. There is always one digit
932   // before the point. The number of requested_digits equals hence f + 1.
933   // And we have to add one character for the null-terminator.
934   const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
935   // Make sure that the buffer is big enough, even if we fall back to the
936   // shortest representation (which happens when f equals -1).
937   ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
938   char decimal_rep[kV8DtoaBufferCapacity];
939   int decimal_rep_length;
940 
941   if (f == -1) {
942     DoubleToAscii(value, DTOA_SHORTEST, 0,
943                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
944                   &sign, &decimal_rep_length, &decimal_point);
945     f = decimal_rep_length - 1;
946   } else {
947     DoubleToAscii(value, DTOA_PRECISION, f + 1,
948                   Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
949                   &sign, &decimal_rep_length, &decimal_point);
950   }
951   ASSERT(decimal_rep_length > 0);
952   ASSERT(decimal_rep_length <= f + 1);
953 
954   int exponent = decimal_point - 1;
955   char* result =
956       CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
957 
958   return result;
959 }
960 
961 
DoubleToPrecisionCString(double value,int p)962 char* DoubleToPrecisionCString(double value, int p) {
963   const int kMinimalDigits = 1;
964   const int kMaximalDigits = 21;
965   ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
966   USE(kMinimalDigits);
967 
968   bool negative = false;
969   if (value < 0) {
970     value = -value;
971     negative = true;
972   }
973 
974   // Find a sufficiently precise decimal representation of n.
975   int decimal_point;
976   int sign;
977   // Add one for the terminating null character.
978   const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
979   char decimal_rep[kV8DtoaBufferCapacity];
980   int decimal_rep_length;
981 
982   DoubleToAscii(value, DTOA_PRECISION, p,
983                 Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
984                 &sign, &decimal_rep_length, &decimal_point);
985   ASSERT(decimal_rep_length <= p);
986 
987   int exponent = decimal_point - 1;
988 
989   char* result = NULL;
990 
991   if (exponent < -6 || exponent >= p) {
992     result =
993         CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
994   } else {
995     // Use fixed notation.
996     //
997     // Leave room in the result for appending a minus, a period and in
998     // the case where decimal_point is not positive for a zero in
999     // front of the period.
1000     unsigned result_size = (decimal_point <= 0)
1001         ? -decimal_point + p + 3
1002         : p + 2;
1003     StringBuilder builder(result_size + 1);
1004     if (negative) builder.AddCharacter('-');
1005     if (decimal_point <= 0) {
1006       builder.AddString("0.");
1007       builder.AddPadding('0', -decimal_point);
1008       builder.AddString(decimal_rep);
1009       builder.AddPadding('0', p - decimal_rep_length);
1010     } else {
1011       const int m = Min(decimal_rep_length, decimal_point);
1012       builder.AddSubstring(decimal_rep, m);
1013       builder.AddPadding('0', decimal_point - decimal_rep_length);
1014       if (decimal_point < p) {
1015         builder.AddCharacter('.');
1016         const int extra = negative ? 2 : 1;
1017         if (decimal_rep_length > decimal_point) {
1018           const int len = StrLength(decimal_rep + decimal_point);
1019           const int n = Min(len, p - (builder.position() - extra));
1020           builder.AddSubstring(decimal_rep + decimal_point, n);
1021         }
1022         builder.AddPadding('0', extra + (p - builder.position()));
1023       }
1024     }
1025     result = builder.Finalize();
1026   }
1027 
1028   return result;
1029 }
1030 
1031 
DoubleToRadixCString(double value,int radix)1032 char* DoubleToRadixCString(double value, int radix) {
1033   ASSERT(radix >= 2 && radix <= 36);
1034 
1035   // Character array used for conversion.
1036   static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1037 
1038   // Buffer for the integer part of the result. 1024 chars is enough
1039   // for max integer value in radix 2.  We need room for a sign too.
1040   static const int kBufferSize = 1100;
1041   char integer_buffer[kBufferSize];
1042   integer_buffer[kBufferSize - 1] = '\0';
1043 
1044   // Buffer for the decimal part of the result.  We only generate up
1045   // to kBufferSize - 1 chars for the decimal part.
1046   char decimal_buffer[kBufferSize];
1047   decimal_buffer[kBufferSize - 1] = '\0';
1048 
1049   // Make sure the value is positive.
1050   bool is_negative = value < 0.0;
1051   if (is_negative) value = -value;
1052 
1053   // Get the integer part and the decimal part.
1054   double integer_part = floor(value);
1055   double decimal_part = value - integer_part;
1056 
1057   // Convert the integer part starting from the back.  Always generate
1058   // at least one digit.
1059   int integer_pos = kBufferSize - 2;
1060   do {
1061     integer_buffer[integer_pos--] =
1062         chars[static_cast<int>(modulo(integer_part, radix))];
1063     integer_part /= radix;
1064   } while (integer_part >= 1.0);
1065   // Sanity check.
1066   ASSERT(integer_pos > 0);
1067   // Add sign if needed.
1068   if (is_negative) integer_buffer[integer_pos--] = '-';
1069 
1070   // Convert the decimal part.  Repeatedly multiply by the radix to
1071   // generate the next char.  Never generate more than kBufferSize - 1
1072   // chars.
1073   //
1074   // TODO(1093998): We will often generate a full decimal_buffer of
1075   // chars because hitting zero will often not happen.  The right
1076   // solution would be to continue until the string representation can
1077   // be read back and yield the original value.  To implement this
1078   // efficiently, we probably have to modify dtoa.
1079   int decimal_pos = 0;
1080   while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
1081     decimal_part *= radix;
1082     decimal_buffer[decimal_pos++] =
1083         chars[static_cast<int>(floor(decimal_part))];
1084     decimal_part -= floor(decimal_part);
1085   }
1086   decimal_buffer[decimal_pos] = '\0';
1087 
1088   // Compute the result size.
1089   int integer_part_size = kBufferSize - 2 - integer_pos;
1090   // Make room for zero termination.
1091   unsigned result_size = integer_part_size + decimal_pos;
1092   // If the number has a decimal part, leave room for the period.
1093   if (decimal_pos > 0) result_size++;
1094   // Allocate result and fill in the parts.
1095   StringBuilder builder(result_size + 1);
1096   builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
1097   if (decimal_pos > 0) builder.AddCharacter('.');
1098   builder.AddSubstring(decimal_buffer, decimal_pos);
1099   return builder.Finalize();
1100 }
1101 
1102 
1103 static Mutex* dtoa_lock_one = OS::CreateMutex();
1104 static Mutex* dtoa_lock_zero = OS::CreateMutex();
1105 
1106 
1107 } }  // namespace v8::internal
1108 
1109 
1110 extern "C" {
ACQUIRE_DTOA_LOCK(int n)1111 void ACQUIRE_DTOA_LOCK(int n) {
1112   ASSERT(n == 0 || n == 1);
1113   (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock();
1114 }
1115 
1116 
FREE_DTOA_LOCK(int n)1117 void FREE_DTOA_LOCK(int n) {
1118   ASSERT(n == 0 || n == 1);
1119   (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->
1120       Unlock();
1121 }
1122 }
1123