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