v8  3.25.30(node0.11.13)
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 <limits.h>
30 #include <cmath>
31 
32 #include "conversions-inl.h"
33 #include "dtoa.h"
34 #include "list-inl.h"
35 #include "strtod.h"
36 #include "utils.h"
37 
38 #ifndef _STLP_VENDOR_CSTD
39 // STLPort doesn't import fpclassify into the std namespace.
40 using std::fpclassify;
41 #endif
42 
43 namespace v8 {
44 namespace internal {
45 
46 
47 double StringToDouble(UnicodeCache* unicode_cache,
48  const char* str, int flags, double empty_string_val) {
49  // We cast to const uint8_t* here to avoid instantiating the
50  // InternalStringToDouble() template for const char* as well.
51  const uint8_t* start = reinterpret_cast<const uint8_t*>(str);
52  const uint8_t* end = start + StrLength(str);
53  return InternalStringToDouble(unicode_cache, start, end, flags,
54  empty_string_val);
55 }
56 
57 
58 double StringToDouble(UnicodeCache* unicode_cache,
60  int flags,
61  double empty_string_val) {
62  // We cast to const uint8_t* here to avoid instantiating the
63  // InternalStringToDouble() template for const char* as well.
64  const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start());
65  const uint8_t* end = start + str.length();
66  return InternalStringToDouble(unicode_cache, start, end, flags,
67  empty_string_val);
68 }
69 
70 
71 double StringToDouble(UnicodeCache* unicode_cache,
73  int flags,
74  double empty_string_val) {
75  const uc16* end = str.start() + str.length();
76  return InternalStringToDouble(unicode_cache, str.start(), end, flags,
77  empty_string_val);
78 }
79 
80 
81 const char* DoubleToCString(double v, Vector<char> buffer) {
82  switch (fpclassify(v)) {
83  case FP_NAN: return "NaN";
84  case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity");
85  case FP_ZERO: return "0";
86  default: {
87  SimpleStringBuilder builder(buffer.start(), buffer.length());
88  int decimal_point;
89  int sign;
90  const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
91  char decimal_rep[kV8DtoaBufferCapacity];
92  int length;
93 
95  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
96  &sign, &length, &decimal_point);
97 
98  if (sign) builder.AddCharacter('-');
99 
100  if (length <= decimal_point && decimal_point <= 21) {
101  // ECMA-262 section 9.8.1 step 6.
102  builder.AddString(decimal_rep);
103  builder.AddPadding('0', decimal_point - length);
104 
105  } else if (0 < decimal_point && decimal_point <= 21) {
106  // ECMA-262 section 9.8.1 step 7.
107  builder.AddSubstring(decimal_rep, decimal_point);
108  builder.AddCharacter('.');
109  builder.AddString(decimal_rep + decimal_point);
110 
111  } else if (decimal_point <= 0 && decimal_point > -6) {
112  // ECMA-262 section 9.8.1 step 8.
113  builder.AddString("0.");
114  builder.AddPadding('0', -decimal_point);
115  builder.AddString(decimal_rep);
116 
117  } else {
118  // ECMA-262 section 9.8.1 step 9 and 10 combined.
119  builder.AddCharacter(decimal_rep[0]);
120  if (length != 1) {
121  builder.AddCharacter('.');
122  builder.AddString(decimal_rep + 1);
123  }
124  builder.AddCharacter('e');
125  builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
126  int exponent = decimal_point - 1;
127  if (exponent < 0) exponent = -exponent;
128  builder.AddDecimalInteger(exponent);
129  }
130  return builder.Finalize();
131  }
132  }
133 }
134 
135 
136 const char* IntToCString(int n, Vector<char> buffer) {
137  bool negative = false;
138  if (n < 0) {
139  // We must not negate the most negative int.
140  if (n == kMinInt) return DoubleToCString(n, buffer);
141  negative = true;
142  n = -n;
143  }
144  // Build the string backwards from the least significant digit.
145  int i = buffer.length();
146  buffer[--i] = '\0';
147  do {
148  buffer[--i] = '0' + (n % 10);
149  n /= 10;
150  } while (n);
151  if (negative) buffer[--i] = '-';
152  return buffer.start() + i;
153 }
154 
155 
156 char* DoubleToFixedCString(double value, int f) {
157  const int kMaxDigitsBeforePoint = 21;
158  const double kFirstNonFixed = 1e21;
159  const int kMaxDigitsAfterPoint = 20;
160  ASSERT(f >= 0);
161  ASSERT(f <= kMaxDigitsAfterPoint);
162 
163  bool negative = false;
164  double abs_value = value;
165  if (value < 0) {
166  abs_value = -value;
167  negative = true;
168  }
169 
170  // If abs_value has more than kMaxDigitsBeforePoint digits before the point
171  // use the non-fixed conversion routine.
172  if (abs_value >= kFirstNonFixed) {
173  char arr[100];
174  Vector<char> buffer(arr, ARRAY_SIZE(arr));
175  return StrDup(DoubleToCString(value, buffer));
176  }
177 
178  // Find a sufficiently precise decimal representation of n.
179  int decimal_point;
180  int sign;
181  // Add space for the '\0' byte.
182  const int kDecimalRepCapacity =
183  kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1;
184  char decimal_rep[kDecimalRepCapacity];
185  int decimal_rep_length;
186  DoubleToAscii(value, DTOA_FIXED, f,
187  Vector<char>(decimal_rep, kDecimalRepCapacity),
188  &sign, &decimal_rep_length, &decimal_point);
189 
190  // Create a representation that is padded with zeros if needed.
191  int zero_prefix_length = 0;
192  int zero_postfix_length = 0;
193 
194  if (decimal_point <= 0) {
195  zero_prefix_length = -decimal_point + 1;
196  decimal_point = 1;
197  }
198 
199  if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
200  zero_postfix_length = decimal_point + f - decimal_rep_length -
201  zero_prefix_length;
202  }
203 
204  unsigned rep_length =
205  zero_prefix_length + decimal_rep_length + zero_postfix_length;
206  SimpleStringBuilder rep_builder(rep_length + 1);
207  rep_builder.AddPadding('0', zero_prefix_length);
208  rep_builder.AddString(decimal_rep);
209  rep_builder.AddPadding('0', zero_postfix_length);
210  char* rep = rep_builder.Finalize();
211 
212  // Create the result string by appending a minus and putting in a
213  // decimal point if needed.
214  unsigned result_size = decimal_point + f + 2;
215  SimpleStringBuilder builder(result_size + 1);
216  if (negative) builder.AddCharacter('-');
217  builder.AddSubstring(rep, decimal_point);
218  if (f > 0) {
219  builder.AddCharacter('.');
220  builder.AddSubstring(rep + decimal_point, f);
221  }
222  DeleteArray(rep);
223  return builder.Finalize();
224 }
225 
226 
227 static char* CreateExponentialRepresentation(char* decimal_rep,
228  int exponent,
229  bool negative,
230  int significant_digits) {
231  bool negative_exponent = false;
232  if (exponent < 0) {
233  negative_exponent = true;
234  exponent = -exponent;
235  }
236 
237  // Leave room in the result for appending a minus, for a period, the
238  // letter 'e', a minus or a plus depending on the exponent, and a
239  // three digit exponent.
240  unsigned result_size = significant_digits + 7;
241  SimpleStringBuilder builder(result_size + 1);
242 
243  if (negative) builder.AddCharacter('-');
244  builder.AddCharacter(decimal_rep[0]);
245  if (significant_digits != 1) {
246  builder.AddCharacter('.');
247  builder.AddString(decimal_rep + 1);
248  int rep_length = StrLength(decimal_rep);
249  builder.AddPadding('0', significant_digits - rep_length);
250  }
251 
252  builder.AddCharacter('e');
253  builder.AddCharacter(negative_exponent ? '-' : '+');
254  builder.AddDecimalInteger(exponent);
255  return builder.Finalize();
256 }
257 
258 
259 
260 char* DoubleToExponentialCString(double value, int f) {
261  const int kMaxDigitsAfterPoint = 20;
262  // f might be -1 to signal that f was undefined in JavaScript.
263  ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
264 
265  bool negative = false;
266  if (value < 0) {
267  value = -value;
268  negative = true;
269  }
270 
271  // Find a sufficiently precise decimal representation of n.
272  int decimal_point;
273  int sign;
274  // f corresponds to the digits after the point. There is always one digit
275  // before the point. The number of requested_digits equals hence f + 1.
276  // And we have to add one character for the null-terminator.
277  const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
278  // Make sure that the buffer is big enough, even if we fall back to the
279  // shortest representation (which happens when f equals -1).
280  ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
281  char decimal_rep[kV8DtoaBufferCapacity];
282  int decimal_rep_length;
283 
284  if (f == -1) {
285  DoubleToAscii(value, DTOA_SHORTEST, 0,
286  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
287  &sign, &decimal_rep_length, &decimal_point);
288  f = decimal_rep_length - 1;
289  } else {
290  DoubleToAscii(value, DTOA_PRECISION, f + 1,
291  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
292  &sign, &decimal_rep_length, &decimal_point);
293  }
294  ASSERT(decimal_rep_length > 0);
295  ASSERT(decimal_rep_length <= f + 1);
296 
297  int exponent = decimal_point - 1;
298  char* result =
299  CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
300 
301  return result;
302 }
303 
304 
305 char* DoubleToPrecisionCString(double value, int p) {
306  const int kMinimalDigits = 1;
307  const int kMaximalDigits = 21;
308  ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
309  USE(kMinimalDigits);
310 
311  bool negative = false;
312  if (value < 0) {
313  value = -value;
314  negative = true;
315  }
316 
317  // Find a sufficiently precise decimal representation of n.
318  int decimal_point;
319  int sign;
320  // Add one for the terminating null character.
321  const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
322  char decimal_rep[kV8DtoaBufferCapacity];
323  int decimal_rep_length;
324 
325  DoubleToAscii(value, DTOA_PRECISION, p,
326  Vector<char>(decimal_rep, kV8DtoaBufferCapacity),
327  &sign, &decimal_rep_length, &decimal_point);
328  ASSERT(decimal_rep_length <= p);
329 
330  int exponent = decimal_point - 1;
331 
332  char* result = NULL;
333 
334  if (exponent < -6 || exponent >= p) {
335  result =
336  CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
337  } else {
338  // Use fixed notation.
339  //
340  // Leave room in the result for appending a minus, a period and in
341  // the case where decimal_point is not positive for a zero in
342  // front of the period.
343  unsigned result_size = (decimal_point <= 0)
344  ? -decimal_point + p + 3
345  : p + 2;
346  SimpleStringBuilder builder(result_size + 1);
347  if (negative) builder.AddCharacter('-');
348  if (decimal_point <= 0) {
349  builder.AddString("0.");
350  builder.AddPadding('0', -decimal_point);
351  builder.AddString(decimal_rep);
352  builder.AddPadding('0', p - decimal_rep_length);
353  } else {
354  const int m = Min(decimal_rep_length, decimal_point);
355  builder.AddSubstring(decimal_rep, m);
356  builder.AddPadding('0', decimal_point - decimal_rep_length);
357  if (decimal_point < p) {
358  builder.AddCharacter('.');
359  const int extra = negative ? 2 : 1;
360  if (decimal_rep_length > decimal_point) {
361  const int len = StrLength(decimal_rep + decimal_point);
362  const int n = Min(len, p - (builder.position() - extra));
363  builder.AddSubstring(decimal_rep + decimal_point, n);
364  }
365  builder.AddPadding('0', extra + (p - builder.position()));
366  }
367  }
368  result = builder.Finalize();
369  }
370 
371  return result;
372 }
373 
374 
375 char* DoubleToRadixCString(double value, int radix) {
376  ASSERT(radix >= 2 && radix <= 36);
377 
378  // Character array used for conversion.
379  static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
380 
381  // Buffer for the integer part of the result. 1024 chars is enough
382  // for max integer value in radix 2. We need room for a sign too.
383  static const int kBufferSize = 1100;
384  char integer_buffer[kBufferSize];
385  integer_buffer[kBufferSize - 1] = '\0';
386 
387  // Buffer for the decimal part of the result. We only generate up
388  // to kBufferSize - 1 chars for the decimal part.
389  char decimal_buffer[kBufferSize];
390  decimal_buffer[kBufferSize - 1] = '\0';
391 
392  // Make sure the value is positive.
393  bool is_negative = value < 0.0;
394  if (is_negative) value = -value;
395 
396  // Get the integer part and the decimal part.
397  double integer_part = std::floor(value);
398  double decimal_part = value - integer_part;
399 
400  // Convert the integer part starting from the back. Always generate
401  // at least one digit.
402  int integer_pos = kBufferSize - 2;
403  do {
404  double remainder = std::fmod(integer_part, radix);
405  integer_buffer[integer_pos--] = chars[static_cast<int>(remainder)];
406  integer_part -= remainder;
407  integer_part /= radix;
408  } while (integer_part >= 1.0);
409  // Sanity check.
410  ASSERT(integer_pos > 0);
411  // Add sign if needed.
412  if (is_negative) integer_buffer[integer_pos--] = '-';
413 
414  // Convert the decimal part. Repeatedly multiply by the radix to
415  // generate the next char. Never generate more than kBufferSize - 1
416  // chars.
417  //
418  // TODO(1093998): We will often generate a full decimal_buffer of
419  // chars because hitting zero will often not happen. The right
420  // solution would be to continue until the string representation can
421  // be read back and yield the original value. To implement this
422  // efficiently, we probably have to modify dtoa.
423  int decimal_pos = 0;
424  while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
425  decimal_part *= radix;
426  decimal_buffer[decimal_pos++] =
427  chars[static_cast<int>(std::floor(decimal_part))];
428  decimal_part -= std::floor(decimal_part);
429  }
430  decimal_buffer[decimal_pos] = '\0';
431 
432  // Compute the result size.
433  int integer_part_size = kBufferSize - 2 - integer_pos;
434  // Make room for zero termination.
435  unsigned result_size = integer_part_size + decimal_pos;
436  // If the number has a decimal part, leave room for the period.
437  if (decimal_pos > 0) result_size++;
438  // Allocate result and fill in the parts.
439  SimpleStringBuilder builder(result_size + 1);
440  builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
441  if (decimal_pos > 0) builder.AddCharacter('.');
442  builder.AddSubstring(decimal_buffer, decimal_pos);
443  return builder.Finalize();
444 }
445 
446 } } // namespace v8::internal
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
const int kMinInt
Definition: globals.h:249
int fpclassify(double x)
void AddString(const char *s)
Definition: utils.cc:44
double InternalStringToDouble(UnicodeCache *unicode_cache, Iterator current, EndMark end, int flags, double empty_string_val)
#define ASSERT(condition)
Definition: checks.h:329
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:47
T * start() const
Definition: utils.h:426
const char * IntToCString(int n, Vector< char > buffer)
Definition: conversions.cc:136
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
Definition: flags.cc:665
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:81
int length() const
Definition: utils.h:420
int StrLength(const char *string)
Definition: utils.h:253
char * DoubleToPrecisionCString(double value, int p)
Definition: conversions.cc:305
void AddSubstring(const char *s, int n)
Definition: utils.cc:49
uint16_t uc16
Definition: globals.h:309
void USE(T)
Definition: globals.h:341
void AddPadding(char c, int count)
Definition: utils.cc:57
char * StrDup(const char *str)
Definition: allocation.cc:89
char * DoubleToExponentialCString(double value, int f)
Definition: conversions.cc:260
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:375
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:234
const int kBase10MaximalLength
Definition: dtoa.h:50
#define ARRAY_SIZE(a)
Definition: globals.h:333
char * DoubleToFixedCString(double value, int f)
Definition: conversions.cc:156