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 |