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
3 // found in the LICENSE file.
4
5 #ifndef V8_CONVERSIONS_INL_H_
6 #define V8_CONVERSIONS_INL_H_
7
8 #include <float.h> // Required for DBL_MAX and on Win32 for finite()
9 #include <limits.h> // Required for INT_MAX etc.
10 #include <stdarg.h>
11 #include <cmath>
12 #include "src/globals.h" // Required for V8_INFINITY
13 #include "src/unicode-cache-inl.h"
14
15 // ----------------------------------------------------------------------------
16 // Extra POSIX/ANSI functions for Win32/MSVC.
17
18 #include "src/base/bits.h"
19 #include "src/base/platform/platform.h"
20 #include "src/conversions.h"
21 #include "src/double.h"
22 #include "src/objects-inl.h"
23 #include "src/strtod.h"
24
25 namespace v8 {
26 namespace internal {
27
JunkStringValue()28 inline double JunkStringValue() {
29 return bit_cast<double, uint64_t>(kQuietNaNMask);
30 }
31
32
SignedZero(bool negative)33 inline double SignedZero(bool negative) {
34 return negative ? uint64_to_double(Double::kSignMask) : 0.0;
35 }
36
37
38 // The fast double-to-unsigned-int conversion routine does not guarantee
39 // rounding towards zero, or any reasonable value if the argument is larger
40 // than what fits in an unsigned 32-bit integer.
FastD2UI(double x)41 inline unsigned int FastD2UI(double x) {
42 // There is no unsigned version of lrint, so there is no fast path
43 // in this function as there is in FastD2I. Using lrint doesn't work
44 // for values of 2^31 and above.
45
46 // Convert "small enough" doubles to uint32_t by fixing the 32
47 // least significant non-fractional bits in the low 32 bits of the
48 // double, and reading them from there.
49 const double k2Pow52 = 4503599627370496.0;
50 bool negative = x < 0;
51 if (negative) {
52 x = -x;
53 }
54 if (x < k2Pow52) {
55 x += k2Pow52;
56 uint32_t result;
57 #ifndef V8_TARGET_BIG_ENDIAN
58 Address mantissa_ptr = reinterpret_cast<Address>(&x);
59 #else
60 Address mantissa_ptr = reinterpret_cast<Address>(&x) + kIntSize;
61 #endif
62 // Copy least significant 32 bits of mantissa.
63 memcpy(&result, mantissa_ptr, sizeof(result));
64 return negative ? ~result + 1 : result;
65 }
66 // Large number (outside uint32 range), Infinity or NaN.
67 return 0x80000000u; // Return integer indefinite.
68 }
69
70
DoubleToFloat32(double x)71 inline float DoubleToFloat32(double x) {
72 // TODO(yangguo): This static_cast is implementation-defined behaviour in C++,
73 // so we may need to do the conversion manually instead to match the spec.
74 volatile float f = static_cast<float>(x);
75 return f;
76 }
77
78
DoubleToInteger(double x)79 inline double DoubleToInteger(double x) {
80 if (std::isnan(x)) return 0;
81 if (!std::isfinite(x) || x == 0) return x;
82 return (x >= 0) ? std::floor(x) : std::ceil(x);
83 }
84
85
DoubleToInt32(double x)86 int32_t DoubleToInt32(double x) {
87 int32_t i = FastD2I(x);
88 if (FastI2D(i) == x) return i;
89 Double d(x);
90 int exponent = d.Exponent();
91 if (exponent < 0) {
92 if (exponent <= -Double::kSignificandSize) return 0;
93 return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
94 } else {
95 if (exponent > 31) return 0;
96 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
97 }
98 }
99
DoubleToSmiInteger(double value,int * smi_int_value)100 bool DoubleToSmiInteger(double value, int* smi_int_value) {
101 if (IsMinusZero(value)) return false;
102 int i = FastD2IChecked(value);
103 if (value != i || !Smi::IsValid(i)) return false;
104 *smi_int_value = i;
105 return true;
106 }
107
IsSmiDouble(double value)108 bool IsSmiDouble(double value) {
109 return !IsMinusZero(value) && value >= Smi::kMinValue &&
110 value <= Smi::kMaxValue && value == FastI2D(FastD2I(value));
111 }
112
113
IsInt32Double(double value)114 bool IsInt32Double(double value) {
115 return !IsMinusZero(value) && value >= kMinInt && value <= kMaxInt &&
116 value == FastI2D(FastD2I(value));
117 }
118
119
IsUint32Double(double value)120 bool IsUint32Double(double value) {
121 return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
122 value == FastUI2D(FastD2UI(value));
123 }
124
125
NumberToInt32(Object * number)126 int32_t NumberToInt32(Object* number) {
127 if (number->IsSmi()) return Smi::cast(number)->value();
128 return DoubleToInt32(number->Number());
129 }
130
131
NumberToUint32(Object * number)132 uint32_t NumberToUint32(Object* number) {
133 if (number->IsSmi()) return Smi::cast(number)->value();
134 return DoubleToUint32(number->Number());
135 }
136
NumberToInt64(Object * number)137 int64_t NumberToInt64(Object* number) {
138 if (number->IsSmi()) return Smi::cast(number)->value();
139 return static_cast<int64_t>(number->Number());
140 }
141
TryNumberToSize(Object * number,size_t * result)142 bool TryNumberToSize(Object* number, size_t* result) {
143 // Do not create handles in this function! Don't use SealHandleScope because
144 // the function can be used concurrently.
145 if (number->IsSmi()) {
146 int value = Smi::cast(number)->value();
147 DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
148 std::numeric_limits<size_t>::max());
149 if (value >= 0) {
150 *result = static_cast<size_t>(value);
151 return true;
152 }
153 return false;
154 } else {
155 DCHECK(number->IsHeapNumber());
156 double value = HeapNumber::cast(number)->value();
157 if (value >= 0 && value <= std::numeric_limits<size_t>::max()) {
158 *result = static_cast<size_t>(value);
159 return true;
160 } else {
161 return false;
162 }
163 }
164 }
165
NumberToSize(Object * number)166 size_t NumberToSize(Object* number) {
167 size_t result = 0;
168 bool is_valid = TryNumberToSize(number, &result);
169 CHECK(is_valid);
170 return result;
171 }
172
173
DoubleToUint32(double x)174 uint32_t DoubleToUint32(double x) {
175 return static_cast<uint32_t>(DoubleToInt32(x));
176 }
177
178
179 template <class Iterator, class EndMark>
SubStringEquals(Iterator * current,EndMark end,const char * substring)180 bool SubStringEquals(Iterator* current,
181 EndMark end,
182 const char* substring) {
183 DCHECK(**current == *substring);
184 for (substring++; *substring != '\0'; substring++) {
185 ++*current;
186 if (*current == end || **current != *substring) return false;
187 }
188 ++*current;
189 return true;
190 }
191
192
193 // Returns true if a nonspace character has been found and false if the
194 // end was been reached before finding a nonspace character.
195 template <class Iterator, class EndMark>
AdvanceToNonspace(UnicodeCache * unicode_cache,Iterator * current,EndMark end)196 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
197 Iterator* current,
198 EndMark end) {
199 while (*current != end) {
200 if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true;
201 ++*current;
202 }
203 return false;
204 }
205
206
207 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
208 template <int radix_log_2, class Iterator, class EndMark>
InternalStringToIntDouble(UnicodeCache * unicode_cache,Iterator current,EndMark end,bool negative,bool allow_trailing_junk)209 double InternalStringToIntDouble(UnicodeCache* unicode_cache,
210 Iterator current,
211 EndMark end,
212 bool negative,
213 bool allow_trailing_junk) {
214 DCHECK(current != end);
215
216 // Skip leading 0s.
217 while (*current == '0') {
218 ++current;
219 if (current == end) return SignedZero(negative);
220 }
221
222 int64_t number = 0;
223 int exponent = 0;
224 const int radix = (1 << radix_log_2);
225
226 do {
227 int digit;
228 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
229 digit = static_cast<char>(*current) - '0';
230 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
231 digit = static_cast<char>(*current) - 'a' + 10;
232 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
233 digit = static_cast<char>(*current) - 'A' + 10;
234 } else {
235 if (allow_trailing_junk ||
236 !AdvanceToNonspace(unicode_cache, ¤t, end)) {
237 break;
238 } else {
239 return JunkStringValue();
240 }
241 }
242
243 number = number * radix + digit;
244 int overflow = static_cast<int>(number >> 53);
245 if (overflow != 0) {
246 // Overflow occurred. Need to determine which direction to round the
247 // result.
248 int overflow_bits_count = 1;
249 while (overflow > 1) {
250 overflow_bits_count++;
251 overflow >>= 1;
252 }
253
254 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
255 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
256 number >>= overflow_bits_count;
257 exponent = overflow_bits_count;
258
259 bool zero_tail = true;
260 while (true) {
261 ++current;
262 if (current == end || !isDigit(*current, radix)) break;
263 zero_tail = zero_tail && *current == '0';
264 exponent += radix_log_2;
265 }
266
267 if (!allow_trailing_junk &&
268 AdvanceToNonspace(unicode_cache, ¤t, end)) {
269 return JunkStringValue();
270 }
271
272 int middle_value = (1 << (overflow_bits_count - 1));
273 if (dropped_bits > middle_value) {
274 number++; // Rounding up.
275 } else if (dropped_bits == middle_value) {
276 // Rounding to even to consistency with decimals: half-way case rounds
277 // up if significant part is odd and down otherwise.
278 if ((number & 1) != 0 || !zero_tail) {
279 number++; // Rounding up.
280 }
281 }
282
283 // Rounding up may cause overflow.
284 if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
285 exponent++;
286 number >>= 1;
287 }
288 break;
289 }
290 ++current;
291 } while (current != end);
292
293 DCHECK(number < ((int64_t)1 << 53));
294 DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
295
296 if (exponent == 0) {
297 if (negative) {
298 if (number == 0) return -0.0;
299 number = -number;
300 }
301 return static_cast<double>(number);
302 }
303
304 DCHECK(number != 0);
305 return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
306 }
307
308 // ES6 18.2.5 parseInt(string, radix)
309 template <class Iterator, class EndMark>
InternalStringToInt(UnicodeCache * unicode_cache,Iterator current,EndMark end,int radix)310 double InternalStringToInt(UnicodeCache* unicode_cache,
311 Iterator current,
312 EndMark end,
313 int radix) {
314 const bool allow_trailing_junk = true;
315 const double empty_string_val = JunkStringValue();
316
317 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) {
318 return empty_string_val;
319 }
320
321 bool negative = false;
322 bool leading_zero = false;
323
324 if (*current == '+') {
325 // Ignore leading sign; skip following spaces.
326 ++current;
327 if (current == end) {
328 return JunkStringValue();
329 }
330 } else if (*current == '-') {
331 ++current;
332 if (current == end) {
333 return JunkStringValue();
334 }
335 negative = true;
336 }
337
338 if (radix == 0) {
339 // Radix detection.
340 radix = 10;
341 if (*current == '0') {
342 ++current;
343 if (current == end) return SignedZero(negative);
344 if (*current == 'x' || *current == 'X') {
345 radix = 16;
346 ++current;
347 if (current == end) return JunkStringValue();
348 } else {
349 leading_zero = true;
350 }
351 }
352 } else if (radix == 16) {
353 if (*current == '0') {
354 // Allow "0x" prefix.
355 ++current;
356 if (current == end) return SignedZero(negative);
357 if (*current == 'x' || *current == 'X') {
358 ++current;
359 if (current == end) return JunkStringValue();
360 } else {
361 leading_zero = true;
362 }
363 }
364 }
365
366 if (radix < 2 || radix > 36) return JunkStringValue();
367
368 // Skip leading zeros.
369 while (*current == '0') {
370 leading_zero = true;
371 ++current;
372 if (current == end) return SignedZero(negative);
373 }
374
375 if (!leading_zero && !isDigit(*current, radix)) {
376 return JunkStringValue();
377 }
378
379 if (base::bits::IsPowerOfTwo32(radix)) {
380 switch (radix) {
381 case 2:
382 return InternalStringToIntDouble<1>(
383 unicode_cache, current, end, negative, allow_trailing_junk);
384 case 4:
385 return InternalStringToIntDouble<2>(
386 unicode_cache, current, end, negative, allow_trailing_junk);
387 case 8:
388 return InternalStringToIntDouble<3>(
389 unicode_cache, current, end, negative, allow_trailing_junk);
390
391 case 16:
392 return InternalStringToIntDouble<4>(
393 unicode_cache, current, end, negative, allow_trailing_junk);
394
395 case 32:
396 return InternalStringToIntDouble<5>(
397 unicode_cache, current, end, negative, allow_trailing_junk);
398 default:
399 UNREACHABLE();
400 }
401 }
402
403 if (radix == 10) {
404 // Parsing with strtod.
405 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
406 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
407 // end.
408 const int kBufferSize = kMaxSignificantDigits + 2;
409 char buffer[kBufferSize];
410 int buffer_pos = 0;
411 while (*current >= '0' && *current <= '9') {
412 if (buffer_pos <= kMaxSignificantDigits) {
413 // If the number has more than kMaxSignificantDigits it will be parsed
414 // as infinity.
415 DCHECK(buffer_pos < kBufferSize);
416 buffer[buffer_pos++] = static_cast<char>(*current);
417 }
418 ++current;
419 if (current == end) break;
420 }
421
422 if (!allow_trailing_junk &&
423 AdvanceToNonspace(unicode_cache, ¤t, end)) {
424 return JunkStringValue();
425 }
426
427 SLOW_DCHECK(buffer_pos < kBufferSize);
428 buffer[buffer_pos] = '\0';
429 Vector<const char> buffer_vector(buffer, buffer_pos);
430 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
431 }
432
433 // The following code causes accumulating rounding error for numbers greater
434 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
435 // 16, or 32, then mathInt may be an implementation-dependent approximation to
436 // the mathematical integer value" (15.1.2.2).
437
438 int lim_0 = '0' + (radix < 10 ? radix : 10);
439 int lim_a = 'a' + (radix - 10);
440 int lim_A = 'A' + (radix - 10);
441
442 // NOTE: The code for computing the value may seem a bit complex at
443 // first glance. It is structured to use 32-bit multiply-and-add
444 // loops as long as possible to avoid loosing precision.
445
446 double v = 0.0;
447 bool done = false;
448 do {
449 // Parse the longest part of the string starting at index j
450 // possible while keeping the multiplier, and thus the part
451 // itself, within 32 bits.
452 unsigned int part = 0, multiplier = 1;
453 while (true) {
454 int d;
455 if (*current >= '0' && *current < lim_0) {
456 d = *current - '0';
457 } else if (*current >= 'a' && *current < lim_a) {
458 d = *current - 'a' + 10;
459 } else if (*current >= 'A' && *current < lim_A) {
460 d = *current - 'A' + 10;
461 } else {
462 done = true;
463 break;
464 }
465
466 // Update the value of the part as long as the multiplier fits
467 // in 32 bits. When we can't guarantee that the next iteration
468 // will not overflow the multiplier, we stop parsing the part
469 // by leaving the loop.
470 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
471 uint32_t m = multiplier * radix;
472 if (m > kMaximumMultiplier) break;
473 part = part * radix + d;
474 multiplier = m;
475 DCHECK(multiplier > part);
476
477 ++current;
478 if (current == end) {
479 done = true;
480 break;
481 }
482 }
483
484 // Update the value and skip the part in the string.
485 v = v * multiplier + part;
486 } while (!done);
487
488 if (!allow_trailing_junk &&
489 AdvanceToNonspace(unicode_cache, ¤t, end)) {
490 return JunkStringValue();
491 }
492
493 return negative ? -v : v;
494 }
495
496
497 // Converts a string to a double value. Assumes the Iterator supports
498 // the following operations:
499 // 1. current == end (other ops are not allowed), current != end.
500 // 2. *current - gets the current character in the sequence.
501 // 3. ++current (advances the position).
502 template <class Iterator, class EndMark>
InternalStringToDouble(UnicodeCache * unicode_cache,Iterator current,EndMark end,int flags,double empty_string_val)503 double InternalStringToDouble(UnicodeCache* unicode_cache,
504 Iterator current,
505 EndMark end,
506 int flags,
507 double empty_string_val) {
508 // To make sure that iterator dereferencing is valid the following
509 // convention is used:
510 // 1. Each '++current' statement is followed by check for equality to 'end'.
511 // 2. If AdvanceToNonspace returned false then current == end.
512 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
513 // 'parsing_done'.
514 // 4. 'current' is not dereferenced after the 'parsing_done' label.
515 // 5. Code before 'parsing_done' may rely on 'current != end'.
516 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) {
517 return empty_string_val;
518 }
519
520 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
521
522 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
523 const int kBufferSize = kMaxSignificantDigits + 10;
524 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
525 int buffer_pos = 0;
526
527 // Exponent will be adjusted if insignificant digits of the integer part
528 // or insignificant leading zeros of the fractional part are dropped.
529 int exponent = 0;
530 int significant_digits = 0;
531 int insignificant_digits = 0;
532 bool nonzero_digit_dropped = false;
533
534 enum Sign {
535 NONE,
536 NEGATIVE,
537 POSITIVE
538 };
539
540 Sign sign = NONE;
541
542 if (*current == '+') {
543 // Ignore leading sign.
544 ++current;
545 if (current == end) return JunkStringValue();
546 sign = POSITIVE;
547 } else if (*current == '-') {
548 ++current;
549 if (current == end) return JunkStringValue();
550 sign = NEGATIVE;
551 }
552
553 static const char kInfinityString[] = "Infinity";
554 if (*current == kInfinityString[0]) {
555 if (!SubStringEquals(¤t, end, kInfinityString)) {
556 return JunkStringValue();
557 }
558
559 if (!allow_trailing_junk &&
560 AdvanceToNonspace(unicode_cache, ¤t, end)) {
561 return JunkStringValue();
562 }
563
564 DCHECK(buffer_pos == 0);
565 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
566 }
567
568 bool leading_zero = false;
569 if (*current == '0') {
570 ++current;
571 if (current == end) return SignedZero(sign == NEGATIVE);
572
573 leading_zero = true;
574
575 // It could be hexadecimal value.
576 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
577 ++current;
578 if (current == end || !isDigit(*current, 16) || sign != NONE) {
579 return JunkStringValue(); // "0x".
580 }
581
582 return InternalStringToIntDouble<4>(unicode_cache,
583 current,
584 end,
585 false,
586 allow_trailing_junk);
587
588 // It could be an explicit octal value.
589 } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
590 ++current;
591 if (current == end || !isDigit(*current, 8) || sign != NONE) {
592 return JunkStringValue(); // "0o".
593 }
594
595 return InternalStringToIntDouble<3>(unicode_cache,
596 current,
597 end,
598 false,
599 allow_trailing_junk);
600
601 // It could be a binary value.
602 } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
603 ++current;
604 if (current == end || !isBinaryDigit(*current) || sign != NONE) {
605 return JunkStringValue(); // "0b".
606 }
607
608 return InternalStringToIntDouble<1>(unicode_cache,
609 current,
610 end,
611 false,
612 allow_trailing_junk);
613 }
614
615 // Ignore leading zeros in the integer part.
616 while (*current == '0') {
617 ++current;
618 if (current == end) return SignedZero(sign == NEGATIVE);
619 }
620 }
621
622 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
623
624 // Copy significant digits of the integer part (if any) to the buffer.
625 while (*current >= '0' && *current <= '9') {
626 if (significant_digits < kMaxSignificantDigits) {
627 DCHECK(buffer_pos < kBufferSize);
628 buffer[buffer_pos++] = static_cast<char>(*current);
629 significant_digits++;
630 // Will later check if it's an octal in the buffer.
631 } else {
632 insignificant_digits++; // Move the digit into the exponential part.
633 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
634 }
635 octal = octal && *current < '8';
636 ++current;
637 if (current == end) goto parsing_done;
638 }
639
640 if (significant_digits == 0) {
641 octal = false;
642 }
643
644 if (*current == '.') {
645 if (octal && !allow_trailing_junk) return JunkStringValue();
646 if (octal) goto parsing_done;
647
648 ++current;
649 if (current == end) {
650 if (significant_digits == 0 && !leading_zero) {
651 return JunkStringValue();
652 } else {
653 goto parsing_done;
654 }
655 }
656
657 if (significant_digits == 0) {
658 // octal = false;
659 // Integer part consists of 0 or is absent. Significant digits start after
660 // leading zeros (if any).
661 while (*current == '0') {
662 ++current;
663 if (current == end) return SignedZero(sign == NEGATIVE);
664 exponent--; // Move this 0 into the exponent.
665 }
666 }
667
668 // There is a fractional part. We don't emit a '.', but adjust the exponent
669 // instead.
670 while (*current >= '0' && *current <= '9') {
671 if (significant_digits < kMaxSignificantDigits) {
672 DCHECK(buffer_pos < kBufferSize);
673 buffer[buffer_pos++] = static_cast<char>(*current);
674 significant_digits++;
675 exponent--;
676 } else {
677 // Ignore insignificant digits in the fractional part.
678 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
679 }
680 ++current;
681 if (current == end) goto parsing_done;
682 }
683 }
684
685 if (!leading_zero && exponent == 0 && significant_digits == 0) {
686 // If leading_zeros is true then the string contains zeros.
687 // If exponent < 0 then string was [+-]\.0*...
688 // If significant_digits != 0 the string is not equal to 0.
689 // Otherwise there are no digits in the string.
690 return JunkStringValue();
691 }
692
693 // Parse exponential part.
694 if (*current == 'e' || *current == 'E') {
695 if (octal) return JunkStringValue();
696 ++current;
697 if (current == end) {
698 if (allow_trailing_junk) {
699 goto parsing_done;
700 } else {
701 return JunkStringValue();
702 }
703 }
704 char sign = '+';
705 if (*current == '+' || *current == '-') {
706 sign = static_cast<char>(*current);
707 ++current;
708 if (current == end) {
709 if (allow_trailing_junk) {
710 goto parsing_done;
711 } else {
712 return JunkStringValue();
713 }
714 }
715 }
716
717 if (current == end || *current < '0' || *current > '9') {
718 if (allow_trailing_junk) {
719 goto parsing_done;
720 } else {
721 return JunkStringValue();
722 }
723 }
724
725 const int max_exponent = INT_MAX / 2;
726 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
727 int num = 0;
728 do {
729 // Check overflow.
730 int digit = *current - '0';
731 if (num >= max_exponent / 10
732 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
733 num = max_exponent;
734 } else {
735 num = num * 10 + digit;
736 }
737 ++current;
738 } while (current != end && *current >= '0' && *current <= '9');
739
740 exponent += (sign == '-' ? -num : num);
741 }
742
743 if (!allow_trailing_junk &&
744 AdvanceToNonspace(unicode_cache, ¤t, end)) {
745 return JunkStringValue();
746 }
747
748 parsing_done:
749 exponent += insignificant_digits;
750
751 if (octal) {
752 return InternalStringToIntDouble<3>(unicode_cache,
753 buffer,
754 buffer + buffer_pos,
755 sign == NEGATIVE,
756 allow_trailing_junk);
757 }
758
759 if (nonzero_digit_dropped) {
760 buffer[buffer_pos++] = '1';
761 exponent--;
762 }
763
764 SLOW_DCHECK(buffer_pos < kBufferSize);
765 buffer[buffer_pos] = '\0';
766
767 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
768 return (sign == NEGATIVE) ? -converted : converted;
769 }
770
771 } // namespace internal
772 } // namespace v8
773
774 #endif // V8_CONVERSIONS_INL_H_
775