| 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 |