18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h>
29589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include <math.h>
306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include <limits.h>
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "conversions-inl.h"
3325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#include "dtoa.h"
34f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "strtod.h"
353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "utils.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      const char* str, int flags, double empty_string_val) {
436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* end = str + StrLength(str);
448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return InternalStringToDouble(unicode_cache, str, end, flags,
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                empty_string_val);
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                      Vector<const char> str,
5180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                      int flags,
5280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                      double empty_string_val) {
5380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const char* end = str.start() + str.length();
548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                empty_string_val);
5680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
5780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochdouble StringToDouble(UnicodeCache* unicode_cache,
59257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      Vector<const uc16> str,
60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      int flags,
61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      double empty_string_val) {
62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  const uc16* end = str.start() + str.length();
63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                                empty_string_val);
65257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
66257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
6780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* DoubleToCString(double v, Vector<char> buffer) {
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (fpclassify(v)) {
701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_NAN: return "NaN";
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case FP_ZERO: return "0";
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      SimpleStringBuilder builder(buffer.start(), buffer.length());
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int decimal_point;
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int sign;
7725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen      const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      char decimal_rep[kV8DtoaBufferCapacity];
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int length;
8025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      DoubleToAscii(v, DTOA_SHORTEST, 0,
828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                    Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                    &sign, &length, &decimal_point);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (sign) builder.AddCharacter('-');
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (length <= decimal_point && decimal_point <= 21) {
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 6.
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', decimal_point - length);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (0 < decimal_point && decimal_point <= 21) {
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 7.
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddSubstring(decimal_rep, decimal_point);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('.');
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep + decimal_point);
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (decimal_point <= 0 && decimal_point > -6) {
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 8.
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString("0.");
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', -decimal_point);
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddString(decimal_rep);
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // ECMA-262 section 9.8.1 step 9 and 10 combined.
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter(decimal_rep[0]);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (length != 1) {
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddCharacter('.');
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddString(decimal_rep + 1);
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('e');
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int exponent = decimal_point - 1;
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (exponent < 0) exponent = -exponent;
1153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.AddDecimalInteger(exponent);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return builder.Finalize();
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* IntToCString(int n, Vector<char> buffer) {
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (n < 0) {
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We must not negate the most negative int.
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (n == kMinInt) return DoubleToCString(n, buffer);
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n = -n;
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Build the string backwards from the least significant digit.
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int i = buffer.length();
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[--i] = '\0';
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer[--i] = '0' + (n % 10);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n /= 10;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (n);
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) buffer[--i] = '-';
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return buffer.start() + i;
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToFixedCString(double value, int f) {
1443e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  const int kMaxDigitsBeforePoint = 21;
14525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const double kFirstNonFixed = 1e21;
14625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kMaxDigitsAfterPoint = 20;
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(f >= 0);
14825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  ASSERT(f <= kMaxDigitsAfterPoint);
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double abs_value = value;
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    abs_value = -value;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
15825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // use the non-fixed conversion routine.
15925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  if (abs_value >= kFirstNonFixed) {
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char arr[100];
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Vector<char> buffer(arr, ARRAY_SIZE(arr));
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return StrDup(DoubleToCString(value, buffer));
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
1683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Add space for the '\0' byte.
16925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  const int kDecimalRepCapacity =
1703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
17125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  char decimal_rep[kDecimalRepCapacity];
17225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  int decimal_rep_length;
1738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  DoubleToAscii(value, DTOA_FIXED, f,
1748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                Vector<char>(decimal_rep, kDecimalRepCapacity),
1758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                &sign, &decimal_rep_length, &decimal_point);
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a representation that is padded with zeros if needed.
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int zero_prefix_length = 0;
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int zero_postfix_length = 0;
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_point <= 0) {
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    zero_prefix_length = -decimal_point + 1;
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_point = 1;
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    zero_postfix_length = decimal_point + f - decimal_rep_length -
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          zero_prefix_length;
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned rep_length =
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      zero_prefix_length + decimal_rep_length + zero_postfix_length;
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder rep_builder(rep_length + 1);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddPadding('0', zero_prefix_length);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddString(decimal_rep);
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  rep_builder.AddPadding('0', zero_postfix_length);
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* rep = rep_builder.Finalize();
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create the result string by appending a minus and putting in a
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // decimal point if needed.
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = decimal_point + f + 2;
2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) builder.AddCharacter('-');
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(rep, decimal_point);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f > 0) {
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddCharacter('.');
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddSubstring(rep + decimal_point, f);
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(rep);
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic char* CreateExponentialRepresentation(char* decimal_rep,
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int exponent,
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             bool negative,
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             int significant_digits) {
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative_exponent = false;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (exponent < 0) {
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative_exponent = true;
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exponent = -exponent;
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave room in the result for appending a minus, for a period, the
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // letter 'e', a minus or a plus depending on the exponent, and a
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // three digit exponent.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = significant_digits + 7;
2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (negative) builder.AddCharacter('-');
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter(decimal_rep[0]);
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (significant_digits != 1) {
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddCharacter('.');
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    builder.AddString(decimal_rep + 1);
235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int rep_length = StrLength(decimal_rep);
236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    builder.AddPadding('0', significant_digits - rep_length);
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter('e');
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddCharacter(negative_exponent ? '-' : '+');
2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  builder.AddDecimalInteger(exponent);
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToExponentialCString(double value, int f) {
2480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMaxDigitsAfterPoint = 20;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // f might be -1 to signal that f was undefined in JavaScript.
2500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = -value;
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
2610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // f corresponds to the digits after the point. There is always one digit
2620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // before the point. The number of requested_digits equals hence f + 1.
2630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // And we have to add one character for the null-terminator.
2640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
2650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Make sure that the buffer is big enough, even if we fall back to the
2660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // shortest representation (which happens when f equals -1).
2670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
2688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  char decimal_rep[kV8DtoaBufferCapacity];
2690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int decimal_rep_length;
2700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (f == -1) {
2728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    DoubleToAscii(value, DTOA_SHORTEST, 0,
2738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
2748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  &sign, &decimal_rep_length, &decimal_point);
2758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    f = decimal_rep_length - 1;
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    DoubleToAscii(value, DTOA_PRECISION, f + 1,
2788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
2798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                  &sign, &decimal_rep_length, &decimal_point);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(decimal_rep_length > 0);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(decimal_rep_length <= f + 1);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int exponent = decimal_point - 1;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* result =
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToPrecisionCString(double value, int p) {
2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMinimalDigits = 1;
2940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kMaximalDigits = 21;
2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  USE(kMinimalDigits);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool negative = false;
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value < 0) {
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = -value;
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    negative = true;
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find a sufficiently precise decimal representation of n.
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_point;
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int sign;
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Add one for the terminating null character.
3080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
3098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  char decimal_rep[kV8DtoaBufferCapacity];
3100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int decimal_rep_length;
3110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
3128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  DoubleToAscii(value, DTOA_PRECISION, p,
3138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
3148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                &sign, &decimal_rep_length, &decimal_point);
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(decimal_rep_length <= p);
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int exponent = decimal_point - 1;
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* result = NULL;
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (exponent < -6 || exponent >= p) {
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result =
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Use fixed notation.
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Leave room in the result for appending a minus, a period and in
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the case where decimal_point is not positive for a zero in
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // front of the period.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unsigned result_size = (decimal_point <= 0)
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ? -decimal_point + p + 3
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        : p + 2;
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SimpleStringBuilder builder(result_size + 1);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (negative) builder.AddCharacter('-');
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (decimal_point <= 0) {
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddString("0.");
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', -decimal_point);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddString(decimal_rep);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', p - decimal_rep_length);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      const int m = Min(decimal_rep_length, decimal_point);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddSubstring(decimal_rep, m);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder.AddPadding('0', decimal_point - decimal_rep_length);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (decimal_point < p) {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddCharacter('.');
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        const int extra = negative ? 2 : 1;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (decimal_rep_length > decimal_point) {
348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          const int len = StrLength(decimal_rep + decimal_point);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          const int n = Min(len, p - (builder.position() - extra));
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder.AddSubstring(decimal_rep + decimal_point, n);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder.AddPadding('0', extra + (p - builder.position()));
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = builder.Finalize();
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* DoubleToRadixCString(double value, int radix) {
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(radix >= 2 && radix <= 36);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Character array used for conversion.
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Buffer for the integer part of the result. 1024 chars is enough
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for max integer value in radix 2.  We need room for a sign too.
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 1100;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char integer_buffer[kBufferSize];
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  integer_buffer[kBufferSize - 1] = '\0';
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Buffer for the decimal part of the result.  We only generate up
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to kBufferSize - 1 chars for the decimal part.
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char decimal_buffer[kBufferSize];
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  decimal_buffer[kBufferSize - 1] = '\0';
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the value is positive.
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_negative = value < 0.0;
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_negative) value = -value;
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the integer part and the decimal part.
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double integer_part = floor(value);
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  double decimal_part = value - integer_part;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the integer part starting from the back.  Always generate
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // at least one digit.
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int integer_pos = kBufferSize - 2;
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    integer_buffer[integer_pos--] =
392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        chars[static_cast<int>(fmod(integer_part, radix))];
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    integer_part /= radix;
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (integer_part >= 1.0);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Sanity check.
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(integer_pos > 0);
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add sign if needed.
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_negative) integer_buffer[integer_pos--] = '-';
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the decimal part.  Repeatedly multiply by the radix to
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // generate the next char.  Never generate more than kBufferSize - 1
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // chars.
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1093998): We will often generate a full decimal_buffer of
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // chars because hitting zero will often not happen.  The right
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // solution would be to continue until the string representation can
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // be read back and yield the original value.  To implement this
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // efficiently, we probably have to modify dtoa.
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int decimal_pos = 0;
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_part *= radix;
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_buffer[decimal_pos++] =
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        chars[static_cast<int>(floor(decimal_part))];
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    decimal_part -= floor(decimal_part);
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  decimal_buffer[decimal_pos] = '\0';
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the result size.
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int integer_part_size = kBufferSize - 2 - integer_pos;
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make room for zero termination.
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned result_size = integer_part_size + decimal_pos;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the number has a decimal part, leave room for the period.
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_pos > 0) result_size++;
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate result and fill in the parts.
4253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SimpleStringBuilder builder(result_size + 1);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (decimal_pos > 0) builder.AddCharacter('.');
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  builder.AddSubstring(decimal_buffer, decimal_pos);
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return builder.Finalize();
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
433