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