OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_CONVERSIONS_INL_H_ | 5 #ifndef V8_CONVERSIONS_INL_H_ |
6 #define V8_CONVERSIONS_INL_H_ | 6 #define V8_CONVERSIONS_INL_H_ |
7 | 7 |
8 #include <float.h> // Required for DBL_MAX and on Win32 for finite() | 8 #include <float.h> // Required for DBL_MAX and on Win32 for finite() |
9 #include <limits.h> // Required for INT_MAX etc. | 9 #include <limits.h> // Required for INT_MAX etc. |
10 #include <stdarg.h> | 10 #include <stdarg.h> |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 if (exponent > 31) return 0; | 85 if (exponent > 31) return 0; |
86 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent); | 86 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent); |
87 } | 87 } |
88 } | 88 } |
89 | 89 |
90 | 90 |
91 template <class Iterator, class EndMark> | 91 template <class Iterator, class EndMark> |
92 bool SubStringEquals(Iterator* current, | 92 bool SubStringEquals(Iterator* current, |
93 EndMark end, | 93 EndMark end, |
94 const char* substring) { | 94 const char* substring) { |
95 ASSERT(**current == *substring); | 95 DCHECK(**current == *substring); |
96 for (substring++; *substring != '\0'; substring++) { | 96 for (substring++; *substring != '\0'; substring++) { |
97 ++*current; | 97 ++*current; |
98 if (*current == end || **current != *substring) return false; | 98 if (*current == end || **current != *substring) return false; |
99 } | 99 } |
100 ++*current; | 100 ++*current; |
101 return true; | 101 return true; |
102 } | 102 } |
103 | 103 |
104 | 104 |
105 // Returns true if a nonspace character has been found and false if the | 105 // Returns true if a nonspace character has been found and false if the |
(...skipping 10 matching lines...) Expand all Loading... |
116 } | 116 } |
117 | 117 |
118 | 118 |
119 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. | 119 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
120 template <int radix_log_2, class Iterator, class EndMark> | 120 template <int radix_log_2, class Iterator, class EndMark> |
121 double InternalStringToIntDouble(UnicodeCache* unicode_cache, | 121 double InternalStringToIntDouble(UnicodeCache* unicode_cache, |
122 Iterator current, | 122 Iterator current, |
123 EndMark end, | 123 EndMark end, |
124 bool negative, | 124 bool negative, |
125 bool allow_trailing_junk) { | 125 bool allow_trailing_junk) { |
126 ASSERT(current != end); | 126 DCHECK(current != end); |
127 | 127 |
128 // Skip leading 0s. | 128 // Skip leading 0s. |
129 while (*current == '0') { | 129 while (*current == '0') { |
130 ++current; | 130 ++current; |
131 if (current == end) return SignedZero(negative); | 131 if (current == end) return SignedZero(negative); |
132 } | 132 } |
133 | 133 |
134 int64_t number = 0; | 134 int64_t number = 0; |
135 int exponent = 0; | 135 int exponent = 0; |
136 const int radix = (1 << radix_log_2); | 136 const int radix = (1 << radix_log_2); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 // Rounding up may cause overflow. | 195 // Rounding up may cause overflow. |
196 if ((number & (static_cast<int64_t>(1) << 53)) != 0) { | 196 if ((number & (static_cast<int64_t>(1) << 53)) != 0) { |
197 exponent++; | 197 exponent++; |
198 number >>= 1; | 198 number >>= 1; |
199 } | 199 } |
200 break; | 200 break; |
201 } | 201 } |
202 ++current; | 202 ++current; |
203 } while (current != end); | 203 } while (current != end); |
204 | 204 |
205 ASSERT(number < ((int64_t)1 << 53)); | 205 DCHECK(number < ((int64_t)1 << 53)); |
206 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); | 206 DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number); |
207 | 207 |
208 if (exponent == 0) { | 208 if (exponent == 0) { |
209 if (negative) { | 209 if (negative) { |
210 if (number == 0) return -0.0; | 210 if (number == 0) return -0.0; |
211 number = -number; | 211 number = -number; |
212 } | 212 } |
213 return static_cast<double>(number); | 213 return static_cast<double>(number); |
214 } | 214 } |
215 | 215 |
216 ASSERT(number != 0); | 216 DCHECK(number != 0); |
217 return std::ldexp(static_cast<double>(negative ? -number : number), exponent); | 217 return std::ldexp(static_cast<double>(negative ? -number : number), exponent); |
218 } | 218 } |
219 | 219 |
220 | 220 |
221 template <class Iterator, class EndMark> | 221 template <class Iterator, class EndMark> |
222 double InternalStringToInt(UnicodeCache* unicode_cache, | 222 double InternalStringToInt(UnicodeCache* unicode_cache, |
223 Iterator current, | 223 Iterator current, |
224 EndMark end, | 224 EndMark end, |
225 int radix) { | 225 int radix) { |
226 const bool allow_trailing_junk = true; | 226 const bool allow_trailing_junk = true; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. | 317 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. |
318 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero | 318 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero |
319 // end. | 319 // end. |
320 const int kBufferSize = kMaxSignificantDigits + 2; | 320 const int kBufferSize = kMaxSignificantDigits + 2; |
321 char buffer[kBufferSize]; | 321 char buffer[kBufferSize]; |
322 int buffer_pos = 0; | 322 int buffer_pos = 0; |
323 while (*current >= '0' && *current <= '9') { | 323 while (*current >= '0' && *current <= '9') { |
324 if (buffer_pos <= kMaxSignificantDigits) { | 324 if (buffer_pos <= kMaxSignificantDigits) { |
325 // If the number has more than kMaxSignificantDigits it will be parsed | 325 // If the number has more than kMaxSignificantDigits it will be parsed |
326 // as infinity. | 326 // as infinity. |
327 ASSERT(buffer_pos < kBufferSize); | 327 DCHECK(buffer_pos < kBufferSize); |
328 buffer[buffer_pos++] = static_cast<char>(*current); | 328 buffer[buffer_pos++] = static_cast<char>(*current); |
329 } | 329 } |
330 ++current; | 330 ++current; |
331 if (current == end) break; | 331 if (current == end) break; |
332 } | 332 } |
333 | 333 |
334 if (!allow_trailing_junk && | 334 if (!allow_trailing_junk && |
335 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 335 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
336 return JunkStringValue(); | 336 return JunkStringValue(); |
337 } | 337 } |
338 | 338 |
339 SLOW_ASSERT(buffer_pos < kBufferSize); | 339 SLOW_DCHECK(buffer_pos < kBufferSize); |
340 buffer[buffer_pos] = '\0'; | 340 buffer[buffer_pos] = '\0'; |
341 Vector<const char> buffer_vector(buffer, buffer_pos); | 341 Vector<const char> buffer_vector(buffer, buffer_pos); |
342 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); | 342 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); |
343 } | 343 } |
344 | 344 |
345 // The following code causes accumulating rounding error for numbers greater | 345 // The following code causes accumulating rounding error for numbers greater |
346 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, | 346 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, |
347 // 16, or 32, then mathInt may be an implementation-dependent approximation to | 347 // 16, or 32, then mathInt may be an implementation-dependent approximation to |
348 // the mathematical integer value" (15.1.2.2). | 348 // the mathematical integer value" (15.1.2.2). |
349 | 349 |
(...skipping 27 matching lines...) Expand all Loading... |
377 | 377 |
378 // Update the value of the part as long as the multiplier fits | 378 // Update the value of the part as long as the multiplier fits |
379 // in 32 bits. When we can't guarantee that the next iteration | 379 // in 32 bits. When we can't guarantee that the next iteration |
380 // will not overflow the multiplier, we stop parsing the part | 380 // will not overflow the multiplier, we stop parsing the part |
381 // by leaving the loop. | 381 // by leaving the loop. |
382 const unsigned int kMaximumMultiplier = 0xffffffffU / 36; | 382 const unsigned int kMaximumMultiplier = 0xffffffffU / 36; |
383 uint32_t m = multiplier * radix; | 383 uint32_t m = multiplier * radix; |
384 if (m > kMaximumMultiplier) break; | 384 if (m > kMaximumMultiplier) break; |
385 part = part * radix + d; | 385 part = part * radix + d; |
386 multiplier = m; | 386 multiplier = m; |
387 ASSERT(multiplier > part); | 387 DCHECK(multiplier > part); |
388 | 388 |
389 ++current; | 389 ++current; |
390 if (current == end) { | 390 if (current == end) { |
391 done = true; | 391 done = true; |
392 break; | 392 break; |
393 } | 393 } |
394 } | 394 } |
395 | 395 |
396 // Update the value and skip the part in the string. | 396 // Update the value and skip the part in the string. |
397 v = v * multiplier + part; | 397 v = v * multiplier + part; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 if (*current == kInfinityString[0]) { | 466 if (*current == kInfinityString[0]) { |
467 if (!SubStringEquals(¤t, end, kInfinityString)) { | 467 if (!SubStringEquals(¤t, end, kInfinityString)) { |
468 return JunkStringValue(); | 468 return JunkStringValue(); |
469 } | 469 } |
470 | 470 |
471 if (!allow_trailing_junk && | 471 if (!allow_trailing_junk && |
472 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 472 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
473 return JunkStringValue(); | 473 return JunkStringValue(); |
474 } | 474 } |
475 | 475 |
476 ASSERT(buffer_pos == 0); | 476 DCHECK(buffer_pos == 0); |
477 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY; | 477 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY; |
478 } | 478 } |
479 | 479 |
480 bool leading_zero = false; | 480 bool leading_zero = false; |
481 if (*current == '0') { | 481 if (*current == '0') { |
482 ++current; | 482 ++current; |
483 if (current == end) return SignedZero(sign == NEGATIVE); | 483 if (current == end) return SignedZero(sign == NEGATIVE); |
484 | 484 |
485 leading_zero = true; | 485 leading_zero = true; |
486 | 486 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 ++current; | 529 ++current; |
530 if (current == end) return SignedZero(sign == NEGATIVE); | 530 if (current == end) return SignedZero(sign == NEGATIVE); |
531 } | 531 } |
532 } | 532 } |
533 | 533 |
534 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0; | 534 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0; |
535 | 535 |
536 // Copy significant digits of the integer part (if any) to the buffer. | 536 // Copy significant digits of the integer part (if any) to the buffer. |
537 while (*current >= '0' && *current <= '9') { | 537 while (*current >= '0' && *current <= '9') { |
538 if (significant_digits < kMaxSignificantDigits) { | 538 if (significant_digits < kMaxSignificantDigits) { |
539 ASSERT(buffer_pos < kBufferSize); | 539 DCHECK(buffer_pos < kBufferSize); |
540 buffer[buffer_pos++] = static_cast<char>(*current); | 540 buffer[buffer_pos++] = static_cast<char>(*current); |
541 significant_digits++; | 541 significant_digits++; |
542 // Will later check if it's an octal in the buffer. | 542 // Will later check if it's an octal in the buffer. |
543 } else { | 543 } else { |
544 insignificant_digits++; // Move the digit into the exponential part. | 544 insignificant_digits++; // Move the digit into the exponential part. |
545 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; | 545 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
546 } | 546 } |
547 octal = octal && *current < '8'; | 547 octal = octal && *current < '8'; |
548 ++current; | 548 ++current; |
549 if (current == end) goto parsing_done; | 549 if (current == end) goto parsing_done; |
(...skipping 24 matching lines...) Expand all Loading... |
574 ++current; | 574 ++current; |
575 if (current == end) return SignedZero(sign == NEGATIVE); | 575 if (current == end) return SignedZero(sign == NEGATIVE); |
576 exponent--; // Move this 0 into the exponent. | 576 exponent--; // Move this 0 into the exponent. |
577 } | 577 } |
578 } | 578 } |
579 | 579 |
580 // There is a fractional part. We don't emit a '.', but adjust the exponent | 580 // There is a fractional part. We don't emit a '.', but adjust the exponent |
581 // instead. | 581 // instead. |
582 while (*current >= '0' && *current <= '9') { | 582 while (*current >= '0' && *current <= '9') { |
583 if (significant_digits < kMaxSignificantDigits) { | 583 if (significant_digits < kMaxSignificantDigits) { |
584 ASSERT(buffer_pos < kBufferSize); | 584 DCHECK(buffer_pos < kBufferSize); |
585 buffer[buffer_pos++] = static_cast<char>(*current); | 585 buffer[buffer_pos++] = static_cast<char>(*current); |
586 significant_digits++; | 586 significant_digits++; |
587 exponent--; | 587 exponent--; |
588 } else { | 588 } else { |
589 // Ignore insignificant digits in the fractional part. | 589 // Ignore insignificant digits in the fractional part. |
590 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; | 590 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
591 } | 591 } |
592 ++current; | 592 ++current; |
593 if (current == end) goto parsing_done; | 593 if (current == end) goto parsing_done; |
594 } | 594 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 628 |
629 if (current == end || *current < '0' || *current > '9') { | 629 if (current == end || *current < '0' || *current > '9') { |
630 if (allow_trailing_junk) { | 630 if (allow_trailing_junk) { |
631 goto parsing_done; | 631 goto parsing_done; |
632 } else { | 632 } else { |
633 return JunkStringValue(); | 633 return JunkStringValue(); |
634 } | 634 } |
635 } | 635 } |
636 | 636 |
637 const int max_exponent = INT_MAX / 2; | 637 const int max_exponent = INT_MAX / 2; |
638 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); | 638 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); |
639 int num = 0; | 639 int num = 0; |
640 do { | 640 do { |
641 // Check overflow. | 641 // Check overflow. |
642 int digit = *current - '0'; | 642 int digit = *current - '0'; |
643 if (num >= max_exponent / 10 | 643 if (num >= max_exponent / 10 |
644 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { | 644 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { |
645 num = max_exponent; | 645 num = max_exponent; |
646 } else { | 646 } else { |
647 num = num * 10 + digit; | 647 num = num * 10 + digit; |
648 } | 648 } |
(...skipping 17 matching lines...) Expand all Loading... |
666 buffer + buffer_pos, | 666 buffer + buffer_pos, |
667 sign == NEGATIVE, | 667 sign == NEGATIVE, |
668 allow_trailing_junk); | 668 allow_trailing_junk); |
669 } | 669 } |
670 | 670 |
671 if (nonzero_digit_dropped) { | 671 if (nonzero_digit_dropped) { |
672 buffer[buffer_pos++] = '1'; | 672 buffer[buffer_pos++] = '1'; |
673 exponent--; | 673 exponent--; |
674 } | 674 } |
675 | 675 |
676 SLOW_ASSERT(buffer_pos < kBufferSize); | 676 SLOW_DCHECK(buffer_pos < kBufferSize); |
677 buffer[buffer_pos] = '\0'; | 677 buffer[buffer_pos] = '\0'; |
678 | 678 |
679 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); | 679 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
680 return (sign == NEGATIVE) ? -converted : converted; | 680 return (sign == NEGATIVE) ? -converted : converted; |
681 } | 681 } |
682 | 682 |
683 } } // namespace v8::internal | 683 } } // namespace v8::internal |
684 | 684 |
685 #endif // V8_CONVERSIONS_INL_H_ | 685 #endif // V8_CONVERSIONS_INL_H_ |
OLD | NEW |