v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
conversions.cc
Go to the documentation of this file.
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 #include <stdarg.h>
29 #include <math.h>
30 #include <limits.h>
31 
32 #include "conversions-inl.h"
33 #include "dtoa.h"
34 #include "strtod.h"
35 #include "utils.h"
36 
37 namespace v8 {
38 namespace internal {
39 
40 
41 double StringToDouble(UnicodeCache* unicode_cache,
42  const char* str, int flags, double empty_string_val) {
43  const char* end = str + StrLength(str);
44  return InternalStringToDouble(unicode_cache, str, end, flags,
45  empty_string_val);
46 }
47 
48 
49 double StringToDouble(UnicodeCache* unicode_cache,
51  int flags,
52  double empty_string_val) {
53  const char* end = str.start() + str.length();
54  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
55  empty_string_val);
56 }
57 
58 double StringToDouble(UnicodeCache* unicode_cache,
60  int flags,
61  double empty_string_val) {
62  const uc16* end = str.start() + str.length();
63  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
64  empty_string_val);
65 }
66 
67 
68 const char* DoubleToCString(double v, Vector<char> buffer) {
69  switch (fpclassify(v)) {
70  case FP_NAN: return "NaN";
71  case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
72  case FP_ZERO: return "0";
73  default: {
74  SimpleStringBuilder builder(buffer.start(), buffer.length());
75  int decimal_point;
76  int sign;
77  const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
78  char decimal_rep[kV8DtoaBufferCapacity];
79  int length;
80 
82  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
83  &sign, &length, &decimal_point);
84 
85  if (sign) builder.AddCharacter('-');
86 
87  if (length <= decimal_point && decimal_point <= 21) {
88  // ECMA-262 section 9.8.1 step 6.
89  builder.AddString(decimal_rep);
90  builder.AddPadding('0', decimal_point - length);
91 
92  } else if (0 < decimal_point && decimal_point <= 21) {
93  // ECMA-262 section 9.8.1 step 7.
94  builder.AddSubstring(decimal_rep, decimal_point);
95  builder.AddCharacter('.');
96  builder.AddString(decimal_rep + decimal_point);
97 
98  } else if (decimal_point <= 0 && decimal_point > -6) {
99  // ECMA-262 section 9.8.1 step 8.
100  builder.AddString("0.");
101  builder.AddPadding('0', -decimal_point);
102  builder.AddString(decimal_rep);
103 
104  } else {
105  // ECMA-262 section 9.8.1 step 9 and 10 combined.
106  builder.AddCharacter(decimal_rep[0]);
107  if (length != 1) {
108  builder.AddCharacter('.');
109  builder.AddString(decimal_rep + 1);
110  }
111  builder.AddCharacter('e');
112  builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
113  int exponent = decimal_point - 1;
114  if (exponent < 0) exponent = -exponent;
115  builder.AddDecimalInteger(exponent);
116  }
117  return builder.Finalize();
118  }
119  }
120 }
121 
122 
123 const char* IntToCString(int n, Vector<char> buffer) {
124  bool negative = false;
125  if (n < 0) {
126  // We must not negate the most negative int.
127  if (n == kMinInt) return DoubleToCString(n, buffer);
128  negative = true;
129  n = -n;
130  }
131  // Build the string backwards from the least significant digit.
132  int i = buffer.length();
133  buffer[--i] = '\0';
134  do {
135  buffer[--i] = '0' + (n % 10);
136  n /= 10;
137  } while (n);
138  if (negative) buffer[--i] = '-';
139  return buffer.start() + i;
140 }
141 
142 
143 char* DoubleToFixedCString(double value, int f) {
144  const int kMaxDigitsBeforePoint = 21;
145  const double kFirstNonFixed = 1e21;
146  const int kMaxDigitsAfterPoint = 20;
147  ASSERT(f >= 0);
148  ASSERT(f <= kMaxDigitsAfterPoint);
149 
150  bool negative = false;
151  double abs_value = value;
152  if (value < 0) {
153  abs_value = -value;
154  negative = true;
155  }
156 
157  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
158  // use the non-fixed conversion routine.
159  if (abs_value >= kFirstNonFixed) {
160  char arr[100];
161  Vector<char> buffer(arr, ARRAY_SIZE(arr));
162  return StrDup(DoubleToCString(value, buffer));
163  }
164 
165  // Find a sufficiently precise decimal representation of n.
166  int decimal_point;
167  int sign;
168  // Add space for the '\0' byte.
169  const int kDecimalRepCapacity =
170  kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
171  char decimal_rep[kDecimalRepCapacity];
172  int decimal_rep_length;
173  DoubleToAscii(value, DTOA_FIXED, f,
174  Vector<char>(decimal_rep, kDecimalRepCapacity),
175  &sign, &decimal_rep_length, &decimal_point);
176 
177  // Create a representation that is padded with zeros if needed.
178  int zero_prefix_length = 0;
179  int zero_postfix_length = 0;
180 
181  if (decimal_point <= 0) {
182  zero_prefix_length = -decimal_point + 1;
183  decimal_point = 1;
184  }
185 
186  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
187  zero_postfix_length = decimal_point + f - decimal_rep_length -
188  zero_prefix_length;
189  }
190 
191  unsigned rep_length =
192  zero_prefix_length + decimal_rep_length + zero_postfix_length;
193  SimpleStringBuilder rep_builder(rep_length + 1);
194  rep_builder.AddPadding('0', zero_prefix_length);
195  rep_builder.AddString(decimal_rep);
196  rep_builder.AddPadding('0', zero_postfix_length);
197  char* rep = rep_builder.Finalize();
198 
199  // Create the result string by appending a minus and putting in a
200  // decimal point if needed.
201  unsigned result_size = decimal_point + f + 2;
202  SimpleStringBuilder builder(result_size + 1);
203  if (negative) builder.AddCharacter('-');
204  builder.AddSubstring(rep, decimal_point);
205  if (f > 0) {
206  builder.AddCharacter('.');
207  builder.AddSubstring(rep + decimal_point, f);
208  }
209  DeleteArray(rep);
210  return builder.Finalize();
211 }
212 
213 
214 static char* CreateExponentialRepresentation(char* decimal_rep,
215  int exponent,
216  bool negative,
217  int significant_digits) {
218  bool negative_exponent = false;
219  if (exponent < 0) {
220  negative_exponent = true;
221  exponent = -exponent;
222  }
223 
224  // Leave room in the result for appending a minus, for a period, the
225  // letter 'e', a minus or a plus depending on the exponent, and a
226  // three digit exponent.
227  unsigned result_size = significant_digits + 7;
228  SimpleStringBuilder builder(result_size + 1);
229 
230  if (negative) builder.AddCharacter('-');
231  builder.AddCharacter(decimal_rep[0]);
232  if (significant_digits != 1) {
233  builder.AddCharacter('.');
234  builder.AddString(decimal_rep + 1);
235  int rep_length = StrLength(decimal_rep);
236  builder.AddPadding('0', significant_digits - rep_length);
237  }
238 
239  builder.AddCharacter('e');
240  builder.AddCharacter(negative_exponent ? '-' : '+');
241  builder.AddDecimalInteger(exponent);
242  return builder.Finalize();
243 }
244 
245 
246 
247 char* DoubleToExponentialCString(double value, int f) {
248  const int kMaxDigitsAfterPoint = 20;
249  // f might be -1 to signal that f was undefined in JavaScript.
250  ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
251 
252  bool negative = false;
253  if (value < 0) {
254  value = -value;
255  negative = true;
256  }
257 
258  // Find a sufficiently precise decimal representation of n.
259  int decimal_point;
260  int sign;
261  // f corresponds to the digits after the point. There is always one digit
262  // before the point. The number of requested_digits equals hence f + 1.
263  // And we have to add one character for the null-terminator.
264  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
265  // Make sure that the buffer is big enough, even if we fall back to the
266  // shortest representation (which happens when f equals -1).
267  ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
268  char decimal_rep[kV8DtoaBufferCapacity];
269  int decimal_rep_length;
270 
271  if (f == -1) {
272  DoubleToAscii(value, DTOA_SHORTEST, 0,
273  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
274  &sign, &decimal_rep_length, &decimal_point);
275  f = decimal_rep_length - 1;
276  } else {
277  DoubleToAscii(value, DTOA_PRECISION, f + 1,
278  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
279  &sign, &decimal_rep_length, &decimal_point);
280  }
281  ASSERT(decimal_rep_length > 0);
282  ASSERT(decimal_rep_length <= f + 1);
283 
284  int exponent = decimal_point - 1;
285  char* result =
286  CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
287 
288  return result;
289 }
290 
291 
292 char* DoubleToPrecisionCString(double value, int p) {
293  const int kMinimalDigits = 1;
294  const int kMaximalDigits = 21;
295  ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
296  USE(kMinimalDigits);
297 
298  bool negative = false;
299  if (value < 0) {
300  value = -value;
301  negative = true;
302  }
303 
304  // Find a sufficiently precise decimal representation of n.
305  int decimal_point;
306  int sign;
307  // Add one for the terminating null character.
308  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
309  char decimal_rep[kV8DtoaBufferCapacity];
310  int decimal_rep_length;
311 
312  DoubleToAscii(value, DTOA_PRECISION, p,
313  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
314  &sign, &decimal_rep_length, &decimal_point);
315  ASSERT(decimal_rep_length <= p);
316 
317  int exponent = decimal_point - 1;
318 
319  char* result = NULL;
320 
321  if (exponent < -6 || exponent >= p) {
322  result =
323  CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
324  } else {
325  // Use fixed notation.
326  //
327  // Leave room in the result for appending a minus, a period and in
328  // the case where decimal_point is not positive for a zero in
329  // front of the period.
330  unsigned result_size = (decimal_point <= 0)
331  ? -decimal_point + p + 3
332  : p + 2;
333  SimpleStringBuilder builder(result_size + 1);
334  if (negative) builder.AddCharacter('-');
335  if (decimal_point <= 0) {
336  builder.AddString("0.");
337  builder.AddPadding('0', -decimal_point);
338  builder.AddString(decimal_rep);
339  builder.AddPadding('0', p - decimal_rep_length);
340  } else {
341  const int m = Min(decimal_rep_length, decimal_point);
342  builder.AddSubstring(decimal_rep, m);
343  builder.AddPadding('0', decimal_point - decimal_rep_length);
344  if (decimal_point < p) {
345  builder.AddCharacter('.');
346  const int extra = negative ? 2 : 1;
347  if (decimal_rep_length > decimal_point) {
348  const int len = StrLength(decimal_rep + decimal_point);
349  const int n = Min(len, p - (builder.position() - extra));
350  builder.AddSubstring(decimal_rep + decimal_point, n);
351  }
352  builder.AddPadding('0', extra + (p - builder.position()));
353  }
354  }
355  result = builder.Finalize();
356  }
357 
358  return result;
359 }
360 
361 
362 char* DoubleToRadixCString(double value, int radix) {
363  ASSERT(radix >= 2 && radix <= 36);
364 
365  // Character array used for conversion.
366  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
367 
368  // Buffer for the integer part of the result. 1024 chars is enough
369  // for max integer value in radix 2. We need room for a sign too.
370  static const int kBufferSize = 1100;
371  char integer_buffer[kBufferSize];
372  integer_buffer[kBufferSize - 1] = '\0';
373 
374  // Buffer for the decimal part of the result. We only generate up
375  // to kBufferSize - 1 chars for the decimal part.
376  char decimal_buffer[kBufferSize];
377  decimal_buffer[kBufferSize - 1] = '\0';
378 
379  // Make sure the value is positive.
380  bool is_negative = value < 0.0;
381  if (is_negative) value = -value;
382 
383  // Get the integer part and the decimal part.
384  double integer_part = floor(value);
385  double decimal_part = value - integer_part;
386 
387  // Convert the integer part starting from the back. Always generate
388  // at least one digit.
389  int integer_pos = kBufferSize - 2;
390  do {
391  integer_buffer[integer_pos--] =
392  chars[static_cast<int>(fmod(integer_part, radix))];
393  integer_part /= radix;
394  } while (integer_part >= 1.0);
395  // Sanity check.
396  ASSERT(integer_pos > 0);
397  // Add sign if needed.
398  if (is_negative) integer_buffer[integer_pos--] = '-';
399 
400  // Convert the decimal part. Repeatedly multiply by the radix to
401  // generate the next char. Never generate more than kBufferSize - 1
402  // chars.
403  //
404  // TODO(1093998): We will often generate a full decimal_buffer of
405  // chars because hitting zero will often not happen. The right
406  // solution would be to continue until the string representation can
407  // be read back and yield the original value. To implement this
408  // efficiently, we probably have to modify dtoa.
409  int decimal_pos = 0;
410  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
411  decimal_part *= radix;
412  decimal_buffer[decimal_pos++] =
413  chars[static_cast<int>(floor(decimal_part))];
414  decimal_part -= floor(decimal_part);
415  }
416  decimal_buffer[decimal_pos] = '\0';
417 
418  // Compute the result size.
419  int integer_part_size = kBufferSize - 2 - integer_pos;
420  // Make room for zero termination.
421  unsigned result_size = integer_part_size + decimal_pos;
422  // If the number has a decimal part, leave room for the period.
423  if (decimal_pos > 0) result_size++;
424  // Allocate result and fill in the parts.
425  SimpleStringBuilder builder(result_size + 1);
426  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
427  if (decimal_pos > 0) builder.AddCharacter('.');
428  builder.AddSubstring(decimal_buffer, decimal_pos);
429  return builder.Finalize();
430 }
431 
432 } } // namespace v8::internal
const int kMinInt
Definition: globals.h:225
void AddString(const char *s)
Definition: utils.cc:43
double InternalStringToDouble(UnicodeCache *unicode_cache, Iterator current, EndMark end, int flags, double empty_string_val)
Flag flags[]
Definition: flags.cc:1467
#define ASSERT(condition)
Definition: checks.h:270
int fpclassify(double x)
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:41
T * start() const
Definition: utils.h:389
const char * IntToCString(int n, Vector< char > buffer)
Definition: conversions.cc:123
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:68
int length() const
Definition: utils.h:383
int StrLength(const char *string)
Definition: utils.h:234
char * DoubleToPrecisionCString(double value, int p)
Definition: conversions.cc:292
void AddSubstring(const char *s, int n)
Definition: utils.cc:48
uint16_t uc16
Definition: globals.h:273
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void USE(T)
Definition: globals.h:303
void AddPadding(char c, int count)
Definition: utils.cc:56
char * StrDup(const char *str)
Definition: allocation.cc:85
char * DoubleToExponentialCString(double value, int f)
Definition: conversions.cc:247
void DoubleToAscii(double v, DtoaMode mode, int requested_digits, Vector< char > buffer, int *sign, int *length, int *point)
Definition: dtoa.cc:56
char * DoubleToRadixCString(double value, int radix)
Definition: conversions.cc:362
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:229
const int kBase10MaximalLength
Definition: dtoa.h:50
#define ARRAY_SIZE(a)
Definition: globals.h:295
char * DoubleToFixedCString(double value, int f)
Definition: conversions.cc:143