Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 | 39 |
| 40 #include "conversions.h" | 40 #include "conversions.h" |
| 41 #include "double.h" | 41 #include "double.h" |
| 42 #include "platform.h" | 42 #include "platform.h" |
| 43 #include "scanner.h" | 43 #include "scanner.h" |
| 44 #include "strtod.h" | 44 #include "strtod.h" |
| 45 | 45 |
| 46 namespace v8 { | 46 namespace v8 { |
| 47 namespace internal { | 47 namespace internal { |
| 48 | 48 |
| 49 static inline double JunkStringValue() { | 49 inline double JunkStringValue() { |
| 50 return BitCast<double, uint64_t>(kQuietNaNMask); | 50 return BitCast<double, uint64_t>(kQuietNaNMask); |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 // The fast double-to-unsigned-int conversion routine does not guarantee | 54 // The fast double-to-unsigned-int conversion routine does not guarantee |
| 55 // rounding towards zero, or any reasonable value if the argument is larger | 55 // rounding towards zero, or any reasonable value if the argument is larger |
| 56 // than what fits in an unsigned 32-bit integer. | 56 // than what fits in an unsigned 32-bit integer. |
| 57 static inline unsigned int FastD2UI(double x) { | 57 inline unsigned int FastD2UI(double x) { |
| 58 // There is no unsigned version of lrint, so there is no fast path | 58 // There is no unsigned version of lrint, so there is no fast path |
| 59 // in this function as there is in FastD2I. Using lrint doesn't work | 59 // in this function as there is in FastD2I. Using lrint doesn't work |
| 60 // for values of 2^31 and above. | 60 // for values of 2^31 and above. |
| 61 | 61 |
| 62 // Convert "small enough" doubles to uint32_t by fixing the 32 | 62 // Convert "small enough" doubles to uint32_t by fixing the 32 |
| 63 // least significant non-fractional bits in the low 32 bits of the | 63 // least significant non-fractional bits in the low 32 bits of the |
| 64 // double, and reading them from there. | 64 // double, and reading them from there. |
| 65 const double k2Pow52 = 4503599627370496.0; | 65 const double k2Pow52 = 4503599627370496.0; |
| 66 bool negative = x < 0; | 66 bool negative = x < 0; |
| 67 if (negative) { | 67 if (negative) { |
| 68 x = -x; | 68 x = -x; |
| 69 } | 69 } |
| 70 if (x < k2Pow52) { | 70 if (x < k2Pow52) { |
| 71 x += k2Pow52; | 71 x += k2Pow52; |
| 72 uint32_t result; | 72 uint32_t result; |
| 73 Address mantissa_ptr = reinterpret_cast<Address>(&x); | 73 Address mantissa_ptr = reinterpret_cast<Address>(&x); |
| 74 // Copy least significant 32 bits of mantissa. | 74 // Copy least significant 32 bits of mantissa. |
| 75 memcpy(&result, mantissa_ptr, sizeof(result)); | 75 memcpy(&result, mantissa_ptr, sizeof(result)); |
| 76 return negative ? ~result + 1 : result; | 76 return negative ? ~result + 1 : result; |
| 77 } | 77 } |
| 78 // Large number (outside uint32 range), Infinity or NaN. | 78 // Large number (outside uint32 range), Infinity or NaN. |
| 79 return 0x80000000u; // Return integer indefinite. | 79 return 0x80000000u; // Return integer indefinite. |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 static inline double DoubleToInteger(double x) { | 83 inline double DoubleToInteger(double x) { |
| 84 if (isnan(x)) return 0; | 84 if (isnan(x)) return 0; |
| 85 if (!isfinite(x) || x == 0) return x; | 85 if (!isfinite(x) || x == 0) return x; |
| 86 return (x >= 0) ? floor(x) : ceil(x); | 86 return (x >= 0) ? floor(x) : ceil(x); |
| 87 } | 87 } |
| 88 | 88 |
| 89 | 89 |
| 90 int32_t DoubleToInt32(double x) { | 90 int32_t DoubleToInt32(double x) { |
| 91 int32_t i = FastD2I(x); | 91 int32_t i = FastD2I(x); |
| 92 if (FastI2D(i) == x) return i; | 92 if (FastI2D(i) == x) return i; |
| 93 Double d(x); | 93 Double d(x); |
| 94 int exponent = d.Exponent(); | 94 int exponent = d.Exponent(); |
| 95 if (exponent < 0) { | 95 if (exponent < 0) { |
| 96 if (exponent <= -Double::kSignificandSize) return 0; | 96 if (exponent <= -Double::kSignificandSize) return 0; |
| 97 return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent); | 97 return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent); |
| 98 } else { | 98 } else { |
| 99 if (exponent > 31) return 0; | 99 if (exponent > 31) return 0; |
| 100 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent); | 100 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent); |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 template <class Iterator, class EndMark> | 105 template <class Iterator, class EndMark> |
| 106 static bool SubStringEquals(Iterator* current, | 106 bool SubStringEquals(Iterator* current, |
| 107 EndMark end, | 107 EndMark end, |
|
Erik Corry
2011/11/29 09:34:56
Indentation.
Kevin Millikin (Chromium)
2011/11/29 10:10:34
Thanks.
| |
| 108 const char* substring) { | 108 const char* substring) { |
| 109 ASSERT(**current == *substring); | 109 ASSERT(**current == *substring); |
| 110 for (substring++; *substring != '\0'; substring++) { | 110 for (substring++; *substring != '\0'; substring++) { |
| 111 ++*current; | 111 ++*current; |
| 112 if (*current == end || **current != *substring) return false; | 112 if (*current == end || **current != *substring) return false; |
| 113 } | 113 } |
| 114 ++*current; | 114 ++*current; |
| 115 return true; | 115 return true; |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 // Returns true if a nonspace character has been found and false if the | 119 // Returns true if a nonspace character has been found and false if the |
| 120 // end was been reached before finding a nonspace character. | 120 // end was been reached before finding a nonspace character. |
| 121 template <class Iterator, class EndMark> | 121 template <class Iterator, class EndMark> |
| 122 static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache, | 122 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache, |
|
Erik Corry
2011/11/29 09:34:56
Indentation
| |
| 123 Iterator* current, | 123 Iterator* current, |
| 124 EndMark end) { | 124 EndMark end) { |
| 125 while (*current != end) { | 125 while (*current != end) { |
| 126 if (!unicode_cache->IsWhiteSpace(**current)) return true; | 126 if (!unicode_cache->IsWhiteSpace(**current)) return true; |
| 127 ++*current; | 127 ++*current; |
| 128 } | 128 } |
| 129 return false; | 129 return false; |
| 130 } | 130 } |
| 131 | 131 |
| 132 | 132 |
| 133 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. | 133 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
| 134 template <int radix_log_2, class Iterator, class EndMark> | 134 template <int radix_log_2, class Iterator, class EndMark> |
| 135 static double InternalStringToIntDouble(UnicodeCache* unicode_cache, | 135 double InternalStringToIntDouble(UnicodeCache* unicode_cache, |
| 136 Iterator current, | 136 Iterator current, |
| 137 EndMark end, | 137 EndMark end, |
| 138 bool negative, | 138 bool negative, |
| 139 bool allow_trailing_junk) { | 139 bool allow_trailing_junk) { |
| 140 ASSERT(current != end); | 140 ASSERT(current != end); |
| 141 | 141 |
| 142 // Skip leading 0s. | 142 // Skip leading 0s. |
| 143 while (*current == '0') { | 143 while (*current == '0') { |
| 144 ++current; | 144 ++current; |
| 145 if (current == end) return SignedZero(negative); | 145 if (current == end) return SignedZero(negative); |
| 146 } | 146 } |
| 147 | 147 |
| 148 int64_t number = 0; | 148 int64_t number = 0; |
| 149 int exponent = 0; | 149 int exponent = 0; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 } | 228 } |
| 229 | 229 |
| 230 ASSERT(number != 0); | 230 ASSERT(number != 0); |
| 231 // The double could be constructed faster from number (mantissa), exponent | 231 // The double could be constructed faster from number (mantissa), exponent |
| 232 // and sign. Assuming it's a rare case more simple code is used. | 232 // and sign. Assuming it's a rare case more simple code is used. |
| 233 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent); | 233 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent); |
| 234 } | 234 } |
| 235 | 235 |
| 236 | 236 |
| 237 template <class Iterator, class EndMark> | 237 template <class Iterator, class EndMark> |
| 238 static double InternalStringToInt(UnicodeCache* unicode_cache, | 238 double InternalStringToInt(UnicodeCache* unicode_cache, |
| 239 Iterator current, | 239 Iterator current, |
| 240 EndMark end, | 240 EndMark end, |
| 241 int radix) { | 241 int radix) { |
| 242 const bool allow_trailing_junk = true; | 242 const bool allow_trailing_junk = true; |
| 243 const double empty_string_val = JunkStringValue(); | 243 const double empty_string_val = JunkStringValue(); |
| 244 | 244 |
| 245 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { | 245 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { |
| 246 return empty_string_val; | 246 return empty_string_val; |
| 247 } | 247 } |
| 248 | 248 |
| 249 bool negative = false; | 249 bool negative = false; |
| 250 bool leading_zero = false; | 250 bool leading_zero = false; |
| 251 | 251 |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 return negative ? -v : v; | 423 return negative ? -v : v; |
| 424 } | 424 } |
| 425 | 425 |
| 426 | 426 |
| 427 // Converts a string to a double value. Assumes the Iterator supports | 427 // Converts a string to a double value. Assumes the Iterator supports |
| 428 // the following operations: | 428 // the following operations: |
| 429 // 1. current == end (other ops are not allowed), current != end. | 429 // 1. current == end (other ops are not allowed), current != end. |
| 430 // 2. *current - gets the current character in the sequence. | 430 // 2. *current - gets the current character in the sequence. |
| 431 // 3. ++current (advances the position). | 431 // 3. ++current (advances the position). |
| 432 template <class Iterator, class EndMark> | 432 template <class Iterator, class EndMark> |
| 433 static double InternalStringToDouble(UnicodeCache* unicode_cache, | 433 double InternalStringToDouble(UnicodeCache* unicode_cache, |
| 434 Iterator current, | 434 Iterator current, |
| 435 EndMark end, | 435 EndMark end, |
| 436 int flags, | 436 int flags, |
| 437 double empty_string_val) { | 437 double empty_string_val) { |
| 438 // To make sure that iterator dereferencing is valid the following | 438 // To make sure that iterator dereferencing is valid the following |
| 439 // convention is used: | 439 // convention is used: |
| 440 // 1. Each '++current' statement is followed by check for equality to 'end'. | 440 // 1. Each '++current' statement is followed by check for equality to 'end'. |
| 441 // 2. If AdvanceToNonspace returned false then current == end. | 441 // 2. If AdvanceToNonspace returned false then current == end. |
| 442 // 3. If 'current' becomes be equal to 'end' the function returns or goes to | 442 // 3. If 'current' becomes be equal to 'end' the function returns or goes to |
| 443 // 'parsing_done'. | 443 // 'parsing_done'. |
| 444 // 4. 'current' is not dereferenced after the 'parsing_done' label. | 444 // 4. 'current' is not dereferenced after the 'parsing_done' label. |
| 445 // 5. Code before 'parsing_done' may rely on 'current != end'. | 445 // 5. Code before 'parsing_done' may rely on 'current != end'. |
| 446 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { | 446 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { |
| 447 return empty_string_val; | 447 return empty_string_val; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 661 ASSERT(buffer_pos < kBufferSize); | 661 ASSERT(buffer_pos < kBufferSize); |
| 662 buffer[buffer_pos] = '\0'; | 662 buffer[buffer_pos] = '\0'; |
| 663 | 663 |
| 664 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); | 664 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
| 665 return negative ? -converted : converted; | 665 return negative ? -converted : converted; |
| 666 } | 666 } |
| 667 | 667 |
| 668 } } // namespace v8::internal | 668 } } // namespace v8::internal |
| 669 | 669 |
| 670 #endif // V8_CONVERSIONS_INL_H_ | 670 #endif // V8_CONVERSIONS_INL_H_ |
| OLD | NEW |