Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/conversions-inl.h

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/conversions.cc ('k') | src/cpu-profiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifndef V8_CONVERSIONS_INL_H_ 28 #ifndef V8_CONVERSIONS_INL_H_
29 #define V8_CONVERSIONS_INL_H_ 29 #define V8_CONVERSIONS_INL_H_
30 30
31 #include <limits.h> // Required for INT_MAX etc.
31 #include <math.h> 32 #include <math.h>
32 #include <float.h> // required for DBL_MAX and on Win32 for finite() 33 #include <float.h> // Required for DBL_MAX and on Win32 for finite()
33 #include <stdarg.h> 34 #include <stdarg.h>
34 35
35 // ---------------------------------------------------------------------------- 36 // ----------------------------------------------------------------------------
36 // Extra POSIX/ANSI functions for Win32/MSVC. 37 // Extra POSIX/ANSI functions for Win32/MSVC.
37 38
38 #include "conversions.h" 39 #include "conversions.h"
40 #include "strtod.h"
39 #include "platform.h" 41 #include "platform.h"
40 42
41 namespace v8 { 43 namespace v8 {
42 namespace internal { 44 namespace internal {
43 45
46 static inline double JunkStringValue() {
47 return std::numeric_limits<double>::quiet_NaN();
48 }
49
50
44 // The fast double-to-unsigned-int conversion routine does not guarantee 51 // The fast double-to-unsigned-int conversion routine does not guarantee
45 // rounding towards zero, or any reasonable value if the argument is larger 52 // rounding towards zero, or any reasonable value if the argument is larger
46 // than what fits in an unsigned 32-bit integer. 53 // than what fits in an unsigned 32-bit integer.
47 static inline unsigned int FastD2UI(double x) { 54 static inline unsigned int FastD2UI(double x) {
48 // There is no unsigned version of lrint, so there is no fast path 55 // There is no unsigned version of lrint, so there is no fast path
49 // in this function as there is in FastD2I. Using lrint doesn't work 56 // in this function as there is in FastD2I. Using lrint doesn't work
50 // for values of 2^31 and above. 57 // for values of 2^31 and above.
51 58
52 // Convert "small enough" doubles to uint32_t by fixing the 32 59 // Convert "small enough" doubles to uint32_t by fixing the 32
53 // least significant non-fractional bits in the low 32 bits of the 60 // least significant non-fractional bits in the low 32 bits of the
(...skipping 16 matching lines...) Expand all
70 } 77 }
71 78
72 79
73 static inline double DoubleToInteger(double x) { 80 static inline double DoubleToInteger(double x) {
74 if (isnan(x)) return 0; 81 if (isnan(x)) return 0;
75 if (!isfinite(x) || x == 0) return x; 82 if (!isfinite(x) || x == 0) return x;
76 return (x >= 0) ? floor(x) : ceil(x); 83 return (x >= 0) ? floor(x) : ceil(x);
77 } 84 }
78 85
79 86
80 int32_t NumberToInt32(Object* number) {
81 if (number->IsSmi()) return Smi::cast(number)->value();
82 return DoubleToInt32(number->Number());
83 }
84
85
86 uint32_t NumberToUint32(Object* number) {
87 if (number->IsSmi()) return Smi::cast(number)->value();
88 return DoubleToUint32(number->Number());
89 }
90
91
92 int32_t DoubleToInt32(double x) { 87 int32_t DoubleToInt32(double x) {
93 int32_t i = FastD2I(x); 88 int32_t i = FastD2I(x);
94 if (FastI2D(i) == x) return i; 89 if (FastI2D(i) == x) return i;
95 static const double two32 = 4294967296.0; 90 static const double two32 = 4294967296.0;
96 static const double two31 = 2147483648.0; 91 static const double two31 = 2147483648.0;
97 if (!isfinite(x) || x == 0) return 0; 92 if (!isfinite(x) || x == 0) return 0;
98 if (x < 0 || x >= two32) x = modulo(x, two32); 93 if (x < 0 || x >= two32) x = modulo(x, two32);
99 x = (x >= 0) ? floor(x) : ceil(x) + two32; 94 x = (x >= 0) ? floor(x) : ceil(x) + two32;
100 return (int32_t) ((x >= two31) ? x - two32 : x); 95 return (int32_t) ((x >= two31) ? x - two32 : x);
101 } 96 }
102 97
103 98
99 template <class Iterator, class EndMark>
100 static bool SubStringEquals(Iterator* current,
101 EndMark end,
102 const char* substring) {
103 ASSERT(**current == *substring);
104 for (substring++; *substring != '\0'; substring++) {
105 ++*current;
106 if (*current == end || **current != *substring) return false;
107 }
108 ++*current;
109 return true;
110 }
111
112
113 // Returns true if a nonspace character has been found and false if the
114 // end was been reached before finding a nonspace character.
115 template <class Iterator, class EndMark>
116 static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
117 Iterator* current,
118 EndMark end) {
119 while (*current != end) {
120 if (!unicode_cache->IsWhiteSpace(**current)) return true;
121 ++*current;
122 }
123 return false;
124 }
125
126
127 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
128 template <int radix_log_2, class Iterator, class EndMark>
129 static double InternalStringToIntDouble(UnicodeCache* unicode_cache,
130 Iterator current,
131 EndMark end,
132 bool negative,
133 bool allow_trailing_junk) {
134 ASSERT(current != end);
135
136 // Skip leading 0s.
137 while (*current == '0') {
138 ++current;
139 if (current == end) return SignedZero(negative);
140 }
141
142 int64_t number = 0;
143 int exponent = 0;
144 const int radix = (1 << radix_log_2);
145
146 do {
147 int digit;
148 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
149 digit = static_cast<char>(*current) - '0';
150 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
151 digit = static_cast<char>(*current) - 'a' + 10;
152 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
153 digit = static_cast<char>(*current) - 'A' + 10;
154 } else {
155 if (allow_trailing_junk ||
156 !AdvanceToNonspace(unicode_cache, &current, end)) {
157 break;
158 } else {
159 return JunkStringValue();
160 }
161 }
162
163 number = number * radix + digit;
164 int overflow = static_cast<int>(number >> 53);
165 if (overflow != 0) {
166 // Overflow occurred. Need to determine which direction to round the
167 // result.
168 int overflow_bits_count = 1;
169 while (overflow > 1) {
170 overflow_bits_count++;
171 overflow >>= 1;
172 }
173
174 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
175 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
176 number >>= overflow_bits_count;
177 exponent = overflow_bits_count;
178
179 bool zero_tail = true;
180 while (true) {
181 ++current;
182 if (current == end || !isDigit(*current, radix)) break;
183 zero_tail = zero_tail && *current == '0';
184 exponent += radix_log_2;
185 }
186
187 if (!allow_trailing_junk &&
188 AdvanceToNonspace(unicode_cache, &current, end)) {
189 return JunkStringValue();
190 }
191
192 int middle_value = (1 << (overflow_bits_count - 1));
193 if (dropped_bits > middle_value) {
194 number++; // Rounding up.
195 } else if (dropped_bits == middle_value) {
196 // Rounding to even to consistency with decimals: half-way case rounds
197 // up if significant part is odd and down otherwise.
198 if ((number & 1) != 0 || !zero_tail) {
199 number++; // Rounding up.
200 }
201 }
202
203 // Rounding up may cause overflow.
204 if ((number & ((int64_t)1 << 53)) != 0) {
205 exponent++;
206 number >>= 1;
207 }
208 break;
209 }
210 ++current;
211 } while (current != end);
212
213 ASSERT(number < ((int64_t)1 << 53));
214 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
215
216 if (exponent == 0) {
217 if (negative) {
218 if (number == 0) return -0.0;
219 number = -number;
220 }
221 return static_cast<double>(number);
222 }
223
224 ASSERT(number != 0);
225 // The double could be constructed faster from number (mantissa), exponent
226 // and sign. Assuming it's a rare case more simple code is used.
227 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent);
228 }
229
230
231 template <class Iterator, class EndMark>
232 static double InternalStringToInt(UnicodeCache* unicode_cache,
233 Iterator current,
234 EndMark end,
235 int radix) {
236 const bool allow_trailing_junk = true;
237 const double empty_string_val = JunkStringValue();
238
239 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
240 return empty_string_val;
241 }
242
243 bool negative = false;
244 bool leading_zero = false;
245
246 if (*current == '+') {
247 // Ignore leading sign; skip following spaces.
248 ++current;
249 if (current == end) {
250 return JunkStringValue();
251 }
252 } else if (*current == '-') {
253 ++current;
254 if (current == end) {
255 return JunkStringValue();
256 }
257 negative = true;
258 }
259
260 if (radix == 0) {
261 // Radix detection.
262 if (*current == '0') {
263 ++current;
264 if (current == end) return SignedZero(negative);
265 if (*current == 'x' || *current == 'X') {
266 radix = 16;
267 ++current;
268 if (current == end) return JunkStringValue();
269 } else {
270 radix = 8;
271 leading_zero = true;
272 }
273 } else {
274 radix = 10;
275 }
276 } else if (radix == 16) {
277 if (*current == '0') {
278 // Allow "0x" prefix.
279 ++current;
280 if (current == end) return SignedZero(negative);
281 if (*current == 'x' || *current == 'X') {
282 ++current;
283 if (current == end) return JunkStringValue();
284 } else {
285 leading_zero = true;
286 }
287 }
288 }
289
290 if (radix < 2 || radix > 36) return JunkStringValue();
291
292 // Skip leading zeros.
293 while (*current == '0') {
294 leading_zero = true;
295 ++current;
296 if (current == end) return SignedZero(negative);
297 }
298
299 if (!leading_zero && !isDigit(*current, radix)) {
300 return JunkStringValue();
301 }
302
303 if (IsPowerOf2(radix)) {
304 switch (radix) {
305 case 2:
306 return InternalStringToIntDouble<1>(
307 unicode_cache, current, end, negative, allow_trailing_junk);
308 case 4:
309 return InternalStringToIntDouble<2>(
310 unicode_cache, current, end, negative, allow_trailing_junk);
311 case 8:
312 return InternalStringToIntDouble<3>(
313 unicode_cache, current, end, negative, allow_trailing_junk);
314
315 case 16:
316 return InternalStringToIntDouble<4>(
317 unicode_cache, current, end, negative, allow_trailing_junk);
318
319 case 32:
320 return InternalStringToIntDouble<5>(
321 unicode_cache, current, end, negative, allow_trailing_junk);
322 default:
323 UNREACHABLE();
324 }
325 }
326
327 if (radix == 10) {
328 // Parsing with strtod.
329 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
330 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
331 // end.
332 const int kBufferSize = kMaxSignificantDigits + 2;
333 char buffer[kBufferSize];
334 int buffer_pos = 0;
335 while (*current >= '0' && *current <= '9') {
336 if (buffer_pos <= kMaxSignificantDigits) {
337 // If the number has more than kMaxSignificantDigits it will be parsed
338 // as infinity.
339 ASSERT(buffer_pos < kBufferSize);
340 buffer[buffer_pos++] = static_cast<char>(*current);
341 }
342 ++current;
343 if (current == end) break;
344 }
345
346 if (!allow_trailing_junk &&
347 AdvanceToNonspace(unicode_cache, &current, end)) {
348 return JunkStringValue();
349 }
350
351 ASSERT(buffer_pos < kBufferSize);
352 buffer[buffer_pos] = '\0';
353 Vector<const char> buffer_vector(buffer, buffer_pos);
354 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
355 }
356
357 // The following code causes accumulating rounding error for numbers greater
358 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
359 // 16, or 32, then mathInt may be an implementation-dependent approximation to
360 // the mathematical integer value" (15.1.2.2).
361
362 int lim_0 = '0' + (radix < 10 ? radix : 10);
363 int lim_a = 'a' + (radix - 10);
364 int lim_A = 'A' + (radix - 10);
365
366 // NOTE: The code for computing the value may seem a bit complex at
367 // first glance. It is structured to use 32-bit multiply-and-add
368 // loops as long as possible to avoid loosing precision.
369
370 double v = 0.0;
371 bool done = false;
372 do {
373 // Parse the longest part of the string starting at index j
374 // possible while keeping the multiplier, and thus the part
375 // itself, within 32 bits.
376 unsigned int part = 0, multiplier = 1;
377 while (true) {
378 int d;
379 if (*current >= '0' && *current < lim_0) {
380 d = *current - '0';
381 } else if (*current >= 'a' && *current < lim_a) {
382 d = *current - 'a' + 10;
383 } else if (*current >= 'A' && *current < lim_A) {
384 d = *current - 'A' + 10;
385 } else {
386 done = true;
387 break;
388 }
389
390 // Update the value of the part as long as the multiplier fits
391 // in 32 bits. When we can't guarantee that the next iteration
392 // will not overflow the multiplier, we stop parsing the part
393 // by leaving the loop.
394 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
395 uint32_t m = multiplier * radix;
396 if (m > kMaximumMultiplier) break;
397 part = part * radix + d;
398 multiplier = m;
399 ASSERT(multiplier > part);
400
401 ++current;
402 if (current == end) {
403 done = true;
404 break;
405 }
406 }
407
408 // Update the value and skip the part in the string.
409 v = v * multiplier + part;
410 } while (!done);
411
412 if (!allow_trailing_junk &&
413 AdvanceToNonspace(unicode_cache, &current, end)) {
414 return JunkStringValue();
415 }
416
417 return negative ? -v : v;
418 }
419
420
421 // Converts a string to a double value. Assumes the Iterator supports
422 // the following operations:
423 // 1. current == end (other ops are not allowed), current != end.
424 // 2. *current - gets the current character in the sequence.
425 // 3. ++current (advances the position).
426 template <class Iterator, class EndMark>
427 static double InternalStringToDouble(UnicodeCache* unicode_cache,
428 Iterator current,
429 EndMark end,
430 int flags,
431 double empty_string_val) {
432 // To make sure that iterator dereferencing is valid the following
433 // convention is used:
434 // 1. Each '++current' statement is followed by check for equality to 'end'.
435 // 2. If AdvanceToNonspace returned false then current == end.
436 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
437 // 'parsing_done'.
438 // 4. 'current' is not dereferenced after the 'parsing_done' label.
439 // 5. Code before 'parsing_done' may rely on 'current != end'.
440 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
441 return empty_string_val;
442 }
443
444 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
445
446 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
447 const int kBufferSize = kMaxSignificantDigits + 10;
448 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
449 int buffer_pos = 0;
450
451 // Exponent will be adjusted if insignificant digits of the integer part
452 // or insignificant leading zeros of the fractional part are dropped.
453 int exponent = 0;
454 int significant_digits = 0;
455 int insignificant_digits = 0;
456 bool nonzero_digit_dropped = false;
457 bool fractional_part = false;
458
459 bool negative = false;
460
461 if (*current == '+') {
462 // Ignore leading sign.
463 ++current;
464 if (current == end) return JunkStringValue();
465 } else if (*current == '-') {
466 ++current;
467 if (current == end) return JunkStringValue();
468 negative = true;
469 }
470
471 static const char kInfinitySymbol[] = "Infinity";
472 if (*current == kInfinitySymbol[0]) {
473 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
474 return JunkStringValue();
475 }
476
477 if (!allow_trailing_junk &&
478 AdvanceToNonspace(unicode_cache, &current, end)) {
479 return JunkStringValue();
480 }
481
482 ASSERT(buffer_pos == 0);
483 return negative ? -V8_INFINITY : V8_INFINITY;
484 }
485
486 bool leading_zero = false;
487 if (*current == '0') {
488 ++current;
489 if (current == end) return SignedZero(negative);
490
491 leading_zero = true;
492
493 // It could be hexadecimal value.
494 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
495 ++current;
496 if (current == end || !isDigit(*current, 16)) {
497 return JunkStringValue(); // "0x".
498 }
499
500 return InternalStringToIntDouble<4>(unicode_cache,
501 current,
502 end,
503 negative,
504 allow_trailing_junk);
505 }
506
507 // Ignore leading zeros in the integer part.
508 while (*current == '0') {
509 ++current;
510 if (current == end) return SignedZero(negative);
511 }
512 }
513
514 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
515
516 // Copy significant digits of the integer part (if any) to the buffer.
517 while (*current >= '0' && *current <= '9') {
518 if (significant_digits < kMaxSignificantDigits) {
519 ASSERT(buffer_pos < kBufferSize);
520 buffer[buffer_pos++] = static_cast<char>(*current);
521 significant_digits++;
522 // Will later check if it's an octal in the buffer.
523 } else {
524 insignificant_digits++; // Move the digit into the exponential part.
525 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
526 }
527 octal = octal && *current < '8';
528 ++current;
529 if (current == end) goto parsing_done;
530 }
531
532 if (significant_digits == 0) {
533 octal = false;
534 }
535
536 if (*current == '.') {
537 if (octal && !allow_trailing_junk) return JunkStringValue();
538 if (octal) goto parsing_done;
539
540 ++current;
541 if (current == end) {
542 if (significant_digits == 0 && !leading_zero) {
543 return JunkStringValue();
544 } else {
545 goto parsing_done;
546 }
547 }
548
549 if (significant_digits == 0) {
550 // octal = false;
551 // Integer part consists of 0 or is absent. Significant digits start after
552 // leading zeros (if any).
553 while (*current == '0') {
554 ++current;
555 if (current == end) return SignedZero(negative);
556 exponent--; // Move this 0 into the exponent.
557 }
558 }
559
560 // We don't emit a '.', but adjust the exponent instead.
561 fractional_part = true;
562
563 // There is a fractional part.
564 while (*current >= '0' && *current <= '9') {
565 if (significant_digits < kMaxSignificantDigits) {
566 ASSERT(buffer_pos < kBufferSize);
567 buffer[buffer_pos++] = static_cast<char>(*current);
568 significant_digits++;
569 exponent--;
570 } else {
571 // Ignore insignificant digits in the fractional part.
572 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
573 }
574 ++current;
575 if (current == end) goto parsing_done;
576 }
577 }
578
579 if (!leading_zero && exponent == 0 && significant_digits == 0) {
580 // If leading_zeros is true then the string contains zeros.
581 // If exponent < 0 then string was [+-]\.0*...
582 // If significant_digits != 0 the string is not equal to 0.
583 // Otherwise there are no digits in the string.
584 return JunkStringValue();
585 }
586
587 // Parse exponential part.
588 if (*current == 'e' || *current == 'E') {
589 if (octal) return JunkStringValue();
590 ++current;
591 if (current == end) {
592 if (allow_trailing_junk) {
593 goto parsing_done;
594 } else {
595 return JunkStringValue();
596 }
597 }
598 char sign = '+';
599 if (*current == '+' || *current == '-') {
600 sign = static_cast<char>(*current);
601 ++current;
602 if (current == end) {
603 if (allow_trailing_junk) {
604 goto parsing_done;
605 } else {
606 return JunkStringValue();
607 }
608 }
609 }
610
611 if (current == end || *current < '0' || *current > '9') {
612 if (allow_trailing_junk) {
613 goto parsing_done;
614 } else {
615 return JunkStringValue();
616 }
617 }
618
619 const int max_exponent = INT_MAX / 2;
620 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
621 int num = 0;
622 do {
623 // Check overflow.
624 int digit = *current - '0';
625 if (num >= max_exponent / 10
626 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
627 num = max_exponent;
628 } else {
629 num = num * 10 + digit;
630 }
631 ++current;
632 } while (current != end && *current >= '0' && *current <= '9');
633
634 exponent += (sign == '-' ? -num : num);
635 }
636
637 if (!allow_trailing_junk &&
638 AdvanceToNonspace(unicode_cache, &current, end)) {
639 return JunkStringValue();
640 }
641
642 parsing_done:
643 exponent += insignificant_digits;
644
645 if (octal) {
646 return InternalStringToIntDouble<3>(unicode_cache,
647 buffer,
648 buffer + buffer_pos,
649 negative,
650 allow_trailing_junk);
651 }
652
653 if (nonzero_digit_dropped) {
654 buffer[buffer_pos++] = '1';
655 exponent--;
656 }
657
658 ASSERT(buffer_pos < kBufferSize);
659 buffer[buffer_pos] = '\0';
660
661 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
662 return negative ? -converted : converted;
663 }
664
104 } } // namespace v8::internal 665 } } // namespace v8::internal
105 666
106 #endif // V8_CONVERSIONS_INL_H_ 667 #endif // V8_CONVERSIONS_INL_H_
OLDNEW
« no previous file with comments | « src/conversions.cc ('k') | src/cpu-profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698