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