49734ba8ddeac904827be4299b216fc1e74e712f
[platform/upstream/v8.git] / src / runtime / runtime-numbers.cc
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/runtime/runtime-utils.h"
6
7 #include "src/arguments.h"
8 #include "src/base/bits.h"
9 #include "src/bootstrapper.h"
10 #include "src/codegen.h"
11
12
13 #ifndef _STLP_VENDOR_CSTD
14 // STLPort doesn't import fpclassify and isless into the std namespace.
15 using std::fpclassify;
16 using std::isless;
17 #endif
18
19 namespace v8 {
20 namespace internal {
21
22 RUNTIME_FUNCTION(Runtime_NumberToRadixString) {
23   HandleScope scope(isolate);
24   DCHECK(args.length() == 2);
25   CONVERT_SMI_ARG_CHECKED(radix, 1);
26   RUNTIME_ASSERT(2 <= radix && radix <= 36);
27
28   // Fast case where the result is a one character string.
29   if (args[0]->IsSmi()) {
30     int value = args.smi_at(0);
31     if (value >= 0 && value < radix) {
32       // Character array used for conversion.
33       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
34       return *isolate->factory()->LookupSingleCharacterStringFromCode(
35           kCharTable[value]);
36     }
37   }
38
39   // Slow case.
40   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
41   if (std::isnan(value)) {
42     return isolate->heap()->nan_string();
43   }
44   if (std::isinf(value)) {
45     if (value < 0) {
46       return isolate->heap()->minus_infinity_string();
47     }
48     return isolate->heap()->infinity_string();
49   }
50   char* str = DoubleToRadixCString(value, radix);
51   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
52   DeleteArray(str);
53   return *result;
54 }
55
56
57 RUNTIME_FUNCTION(Runtime_NumberToFixed) {
58   HandleScope scope(isolate);
59   DCHECK(args.length() == 2);
60
61   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
62   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
63   int f = FastD2IChecked(f_number);
64   // See DoubleToFixedCString for these constants:
65   RUNTIME_ASSERT(f >= 0 && f <= 20);
66   RUNTIME_ASSERT(!Double(value).IsSpecial());
67   char* str = DoubleToFixedCString(value, f);
68   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
69   DeleteArray(str);
70   return *result;
71 }
72
73
74 RUNTIME_FUNCTION(Runtime_NumberToExponential) {
75   HandleScope scope(isolate);
76   DCHECK(args.length() == 2);
77
78   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
79   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
80   int f = FastD2IChecked(f_number);
81   RUNTIME_ASSERT(f >= -1 && f <= 20);
82   RUNTIME_ASSERT(!Double(value).IsSpecial());
83   char* str = DoubleToExponentialCString(value, f);
84   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
85   DeleteArray(str);
86   return *result;
87 }
88
89
90 RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
91   HandleScope scope(isolate);
92   DCHECK(args.length() == 2);
93
94   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
95   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
96   int f = FastD2IChecked(f_number);
97   RUNTIME_ASSERT(f >= 1 && f <= 21);
98   RUNTIME_ASSERT(!Double(value).IsSpecial());
99   char* str = DoubleToPrecisionCString(value, f);
100   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
101   DeleteArray(str);
102   return *result;
103 }
104
105
106 RUNTIME_FUNCTION(Runtime_IsValidSmi) {
107   SealHandleScope shs(isolate);
108   DCHECK(args.length() == 1);
109
110   CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
111   return isolate->heap()->ToBoolean(Smi::IsValid(number));
112 }
113
114
115 static bool AreDigits(const uint8_t* s, int from, int to) {
116   for (int i = from; i < to; i++) {
117     if (s[i] < '0' || s[i] > '9') return false;
118   }
119
120   return true;
121 }
122
123
124 static int ParseDecimalInteger(const uint8_t* s, int from, int to) {
125   DCHECK(to - from < 10);  // Overflow is not possible.
126   DCHECK(from < to);
127   int d = s[from] - '0';
128
129   for (int i = from + 1; i < to; i++) {
130     d = 10 * d + (s[i] - '0');
131   }
132
133   return d;
134 }
135
136
137 RUNTIME_FUNCTION(Runtime_StringToNumber) {
138   HandleScope handle_scope(isolate);
139   DCHECK(args.length() == 1);
140   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
141   subject = String::Flatten(subject);
142
143   // Fast case: short integer or some sorts of junk values.
144   if (subject->IsSeqOneByteString()) {
145     int len = subject->length();
146     if (len == 0) return Smi::FromInt(0);
147
148     DisallowHeapAllocation no_gc;
149     uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
150     bool minus = (data[0] == '-');
151     int start_pos = (minus ? 1 : 0);
152
153     if (start_pos == len) {
154       return isolate->heap()->nan_value();
155     } else if (data[start_pos] > '9') {
156       // Fast check for a junk value. A valid string may start from a
157       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
158       // or the 'I' character ('Infinity'). All of that have codes not greater
159       // than '9' except 'I' and &nbsp;.
160       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
161         return isolate->heap()->nan_value();
162       }
163     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
164       // The maximal/minimal smi has 10 digits. If the string has less digits
165       // we know it will fit into the smi-data type.
166       int d = ParseDecimalInteger(data, start_pos, len);
167       if (minus) {
168         if (d == 0) return isolate->heap()->minus_zero_value();
169         d = -d;
170       } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
171                  (len == 1 || data[0] != '0')) {
172         // String hash is not calculated yet but all the data are present.
173         // Update the hash field to speed up sequential convertions.
174         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
175 #ifdef DEBUG
176         subject->Hash();  // Force hash calculation.
177         DCHECK_EQ(static_cast<int>(subject->hash_field()),
178                   static_cast<int>(hash));
179 #endif
180         subject->set_hash_field(hash);
181       }
182       return Smi::FromInt(d);
183     }
184   }
185
186   // Slower case.
187   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
188   return *isolate->factory()->NewNumber(
189       StringToDouble(isolate->unicode_cache(), subject, flags));
190 }
191
192
193 RUNTIME_FUNCTION(Runtime_StringParseInt) {
194   HandleScope handle_scope(isolate);
195   DCHECK(args.length() == 2);
196   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
197   CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
198   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
199
200   subject = String::Flatten(subject);
201   double value;
202
203   {
204     DisallowHeapAllocation no_gc;
205     String::FlatContent flat = subject->GetFlatContent();
206
207     // ECMA-262 section 15.1.2.3, empty string is NaN
208     if (flat.IsOneByte()) {
209       value =
210           StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), radix);
211     } else {
212       value = StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix);
213     }
214   }
215
216   return *isolate->factory()->NewNumber(value);
217 }
218
219
220 RUNTIME_FUNCTION(Runtime_StringParseFloat) {
221   HandleScope shs(isolate);
222   DCHECK(args.length() == 1);
223   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
224
225   double value =
226       StringToDouble(isolate->unicode_cache(), subject, ALLOW_TRAILING_JUNK,
227                      std::numeric_limits<double>::quiet_NaN());
228
229   return *isolate->factory()->NewNumber(value);
230 }
231
232
233 RUNTIME_FUNCTION(Runtime_NumberToString) {
234   HandleScope scope(isolate);
235   DCHECK(args.length() == 1);
236   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
237
238   return *isolate->factory()->NumberToString(number);
239 }
240
241
242 RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
243   HandleScope scope(isolate);
244   DCHECK(args.length() == 1);
245   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
246
247   return *isolate->factory()->NumberToString(number, false);
248 }
249
250
251 RUNTIME_FUNCTION(Runtime_NumberToInteger) {
252   HandleScope scope(isolate);
253   DCHECK(args.length() == 1);
254
255   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
256   return *isolate->factory()->NewNumber(DoubleToInteger(number));
257 }
258
259
260 RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
261   HandleScope scope(isolate);
262   DCHECK(args.length() == 1);
263
264   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
265   double double_value = DoubleToInteger(number);
266   // Map both -0 and +0 to +0.
267   if (double_value == 0) double_value = 0;
268
269   return *isolate->factory()->NewNumber(double_value);
270 }
271
272
273 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
274 // a small integer.
275 RUNTIME_FUNCTION(Runtime_NumberToSmi) {
276   SealHandleScope shs(isolate);
277   DCHECK(args.length() == 1);
278   CONVERT_ARG_CHECKED(Object, obj, 0);
279   if (obj->IsSmi()) {
280     return obj;
281   }
282   if (obj->IsHeapNumber()) {
283     double value = HeapNumber::cast(obj)->value();
284     int int_value = FastD2I(value);
285     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
286       return Smi::FromInt(int_value);
287     }
288   }
289   return isolate->heap()->nan_value();
290 }
291
292
293 RUNTIME_FUNCTION(Runtime_NumberAdd) {
294   HandleScope scope(isolate);
295   DCHECK(args.length() == 2);
296
297   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
298   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
299   return *isolate->factory()->NewNumber(x + y);
300 }
301
302
303 RUNTIME_FUNCTION(Runtime_NumberSub) {
304   HandleScope scope(isolate);
305   DCHECK(args.length() == 2);
306
307   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
308   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
309   return *isolate->factory()->NewNumber(x - y);
310 }
311
312
313 RUNTIME_FUNCTION(Runtime_NumberMul) {
314   HandleScope scope(isolate);
315   DCHECK(args.length() == 2);
316
317   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
318   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
319   return *isolate->factory()->NewNumber(x * y);
320 }
321
322
323 RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
324   HandleScope scope(isolate);
325   DCHECK(args.length() == 1);
326
327   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
328   return *isolate->factory()->NewNumber(-x);
329 }
330
331
332 RUNTIME_FUNCTION(Runtime_NumberDiv) {
333   HandleScope scope(isolate);
334   DCHECK(args.length() == 2);
335
336   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
337   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
338   return *isolate->factory()->NewNumber(x / y);
339 }
340
341
342 RUNTIME_FUNCTION(Runtime_NumberMod) {
343   HandleScope scope(isolate);
344   DCHECK(args.length() == 2);
345
346   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
347   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
348   return *isolate->factory()->NewNumber(modulo(x, y));
349 }
350
351
352 RUNTIME_FUNCTION(Runtime_NumberImul) {
353   HandleScope scope(isolate);
354   DCHECK(args.length() == 2);
355
356   // We rely on implementation-defined behavior below, but at least not on
357   // undefined behavior.
358   CONVERT_NUMBER_CHECKED(uint32_t, x, Int32, args[0]);
359   CONVERT_NUMBER_CHECKED(uint32_t, y, Int32, args[1]);
360   int32_t product = static_cast<int32_t>(x * y);
361   return *isolate->factory()->NewNumberFromInt(product);
362 }
363
364
365 RUNTIME_FUNCTION(Runtime_NumberOr) {
366   HandleScope scope(isolate);
367   DCHECK(args.length() == 2);
368
369   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
370   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
371   return *isolate->factory()->NewNumberFromInt(x | y);
372 }
373
374
375 RUNTIME_FUNCTION(Runtime_NumberAnd) {
376   HandleScope scope(isolate);
377   DCHECK(args.length() == 2);
378
379   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
380   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
381   return *isolate->factory()->NewNumberFromInt(x & y);
382 }
383
384
385 RUNTIME_FUNCTION(Runtime_NumberXor) {
386   HandleScope scope(isolate);
387   DCHECK(args.length() == 2);
388
389   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
390   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
391   return *isolate->factory()->NewNumberFromInt(x ^ y);
392 }
393
394
395 RUNTIME_FUNCTION(Runtime_NumberShl) {
396   HandleScope scope(isolate);
397   DCHECK(args.length() == 2);
398
399   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
400   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
401   return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
402 }
403
404
405 RUNTIME_FUNCTION(Runtime_NumberShr) {
406   HandleScope scope(isolate);
407   DCHECK(args.length() == 2);
408
409   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
410   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
411   return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
412 }
413
414
415 RUNTIME_FUNCTION(Runtime_NumberSar) {
416   HandleScope scope(isolate);
417   DCHECK(args.length() == 2);
418
419   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
420   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
421   return *isolate->factory()->NewNumberFromInt(
422       ArithmeticShiftRight(x, y & 0x1f));
423 }
424
425
426 RUNTIME_FUNCTION(Runtime_NumberEquals) {
427   SealHandleScope shs(isolate);
428   DCHECK(args.length() == 2);
429
430   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
431   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
432   if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
433   if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
434   if (x == y) return Smi::FromInt(EQUAL);
435   Object* result;
436   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
437     result = Smi::FromInt(EQUAL);
438   } else {
439     result = Smi::FromInt(NOT_EQUAL);
440   }
441   return result;
442 }
443
444
445 RUNTIME_FUNCTION(Runtime_NumberCompare) {
446   SealHandleScope shs(isolate);
447   DCHECK(args.length() == 3);
448
449   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
450   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
451   CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
452   if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
453   if (x == y) return Smi::FromInt(EQUAL);
454   if (isless(x, y)) return Smi::FromInt(LESS);
455   return Smi::FromInt(GREATER);
456 }
457
458
459 // Compare two Smis as if they were converted to strings and then
460 // compared lexicographically.
461 RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
462   SealHandleScope shs(isolate);
463   DCHECK(args.length() == 2);
464   CONVERT_SMI_ARG_CHECKED(x_value, 0);
465   CONVERT_SMI_ARG_CHECKED(y_value, 1);
466
467   // If the integers are equal so are the string representations.
468   if (x_value == y_value) return Smi::FromInt(EQUAL);
469
470   // If one of the integers is zero the normal integer order is the
471   // same as the lexicographic order of the string representations.
472   if (x_value == 0 || y_value == 0)
473     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
474
475   // If only one of the integers is negative the negative number is
476   // smallest because the char code of '-' is less than the char code
477   // of any digit.  Otherwise, we make both values positive.
478
479   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
480   // architectures using 32-bit Smis.
481   uint32_t x_scaled = x_value;
482   uint32_t y_scaled = y_value;
483   if (x_value < 0 || y_value < 0) {
484     if (y_value >= 0) return Smi::FromInt(LESS);
485     if (x_value >= 0) return Smi::FromInt(GREATER);
486     x_scaled = -x_value;
487     y_scaled = -y_value;
488   }
489
490   static const uint32_t kPowersOf10[] = {
491       1,                 10,                100,         1000,
492       10 * 1000,         100 * 1000,        1000 * 1000, 10 * 1000 * 1000,
493       100 * 1000 * 1000, 1000 * 1000 * 1000};
494
495   // If the integers have the same number of decimal digits they can be
496   // compared directly as the numeric order is the same as the
497   // lexicographic order.  If one integer has fewer digits, it is scaled
498   // by some power of 10 to have the same number of digits as the longer
499   // integer.  If the scaled integers are equal it means the shorter
500   // integer comes first in the lexicographic order.
501
502   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
503   int x_log2 = 31 - base::bits::CountLeadingZeros32(x_scaled);
504   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
505   x_log10 -= x_scaled < kPowersOf10[x_log10];
506
507   int y_log2 = 31 - base::bits::CountLeadingZeros32(y_scaled);
508   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
509   y_log10 -= y_scaled < kPowersOf10[y_log10];
510
511   int tie = EQUAL;
512
513   if (x_log10 < y_log10) {
514     // X has fewer digits.  We would like to simply scale up X but that
515     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
516     // be scaled up to 9_000_000_000. So we scale up by the next
517     // smallest power and scale down Y to drop one digit. It is OK to
518     // drop one digit from the longer integer since the final digit is
519     // past the length of the shorter integer.
520     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
521     y_scaled /= 10;
522     tie = LESS;
523   } else if (y_log10 < x_log10) {
524     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
525     x_scaled /= 10;
526     tie = GREATER;
527   }
528
529   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
530   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
531   return Smi::FromInt(tie);
532 }
533
534
535 RUNTIME_FUNCTION(Runtime_MaxSmi) {
536   SealHandleScope shs(isolate);
537   DCHECK(args.length() == 0);
538   return Smi::FromInt(Smi::kMaxValue);
539 }
540
541
542 RUNTIME_FUNCTION(Runtime_IsSmi) {
543   SealHandleScope shs(isolate);
544   DCHECK(args.length() == 1);
545   CONVERT_ARG_CHECKED(Object, obj, 0);
546   return isolate->heap()->ToBoolean(obj->IsSmi());
547 }
548
549
550 RUNTIME_FUNCTION(Runtime_IsNonNegativeSmi) {
551   SealHandleScope shs(isolate);
552   DCHECK(args.length() == 1);
553   CONVERT_ARG_CHECKED(Object, obj, 0);
554   return isolate->heap()->ToBoolean(obj->IsSmi() &&
555                                     Smi::cast(obj)->value() >= 0);
556 }
557
558
559 RUNTIME_FUNCTION(Runtime_GetRootNaN) {
560   SealHandleScope shs(isolate);
561   DCHECK(args.length() == 0);
562   return isolate->heap()->nan_value();
563 }
564 }  // namespace internal
565 }  // namespace v8