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.
5 #include "src/runtime/runtime-utils.h"
7 #include "src/arguments.h"
8 #include "src/base/bits.h"
9 #include "src/bootstrapper.h"
10 #include "src/codegen.h"
13 #ifndef _STLP_VENDOR_CSTD
14 // STLPort doesn't import fpclassify and isless into the std namespace.
15 using std::fpclassify;
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);
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(
40 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
41 if (std::isnan(value)) {
42 return isolate->heap()->nan_string();
44 if (std::isinf(value)) {
46 return isolate->heap()->minus_infinity_string();
48 return isolate->heap()->infinity_string();
50 char* str = DoubleToRadixCString(value, radix);
51 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
57 RUNTIME_FUNCTION(Runtime_NumberToFixed) {
58 HandleScope scope(isolate);
59 DCHECK(args.length() == 2);
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);
74 RUNTIME_FUNCTION(Runtime_NumberToExponential) {
75 HandleScope scope(isolate);
76 DCHECK(args.length() == 2);
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);
90 RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
91 HandleScope scope(isolate);
92 DCHECK(args.length() == 2);
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);
106 RUNTIME_FUNCTION(Runtime_IsValidSmi) {
107 SealHandleScope shs(isolate);
108 DCHECK(args.length() == 1);
110 CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
111 return isolate->heap()->ToBoolean(Smi::IsValid(number));
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;
124 static int ParseDecimalInteger(const uint8_t* s, int from, int to) {
125 DCHECK(to - from < 10); // Overflow is not possible.
127 int d = s[from] - '0';
129 for (int i = from + 1; i < to; i++) {
130 d = 10 * d + (s[i] - '0');
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);
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);
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);
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 .
160 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
161 return isolate->heap()->nan_value();
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);
168 if (d == 0) return isolate->heap()->minus_zero_value();
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);
176 subject->Hash(); // Force hash calculation.
177 DCHECK_EQ(static_cast<int>(subject->hash_field()),
178 static_cast<int>(hash));
180 subject->set_hash_field(hash);
182 return Smi::FromInt(d);
187 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
188 return *isolate->factory()->NewNumber(
189 StringToDouble(isolate->unicode_cache(), subject, flags));
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));
200 subject = String::Flatten(subject);
204 DisallowHeapAllocation no_gc;
205 String::FlatContent flat = subject->GetFlatContent();
207 // ECMA-262 section 15.1.2.3, empty string is NaN
208 if (flat.IsOneByte()) {
210 StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), radix);
212 value = StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix);
216 return *isolate->factory()->NewNumber(value);
220 RUNTIME_FUNCTION(Runtime_StringParseFloat) {
221 HandleScope shs(isolate);
222 DCHECK(args.length() == 1);
223 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
226 StringToDouble(isolate->unicode_cache(), subject, ALLOW_TRAILING_JUNK,
227 std::numeric_limits<double>::quiet_NaN());
229 return *isolate->factory()->NewNumber(value);
233 RUNTIME_FUNCTION(Runtime_NumberToString) {
234 HandleScope scope(isolate);
235 DCHECK(args.length() == 1);
236 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
238 return *isolate->factory()->NumberToString(number);
242 RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
243 HandleScope scope(isolate);
244 DCHECK(args.length() == 1);
245 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
247 return *isolate->factory()->NumberToString(number, false);
251 RUNTIME_FUNCTION(Runtime_NumberToInteger) {
252 HandleScope scope(isolate);
253 DCHECK(args.length() == 1);
255 CONVERT_DOUBLE_ARG_CHECKED(number, 0);
256 return *isolate->factory()->NewNumber(DoubleToInteger(number));
260 RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
261 HandleScope scope(isolate);
262 DCHECK(args.length() == 1);
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;
269 return *isolate->factory()->NewNumber(double_value);
273 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
275 RUNTIME_FUNCTION(Runtime_NumberToSmi) {
276 SealHandleScope shs(isolate);
277 DCHECK(args.length() == 1);
278 CONVERT_ARG_CHECKED(Object, obj, 0);
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);
289 return isolate->heap()->nan_value();
293 RUNTIME_FUNCTION(Runtime_NumberAdd) {
294 HandleScope scope(isolate);
295 DCHECK(args.length() == 2);
297 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
298 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
299 return *isolate->factory()->NewNumber(x + y);
303 RUNTIME_FUNCTION(Runtime_NumberSub) {
304 HandleScope scope(isolate);
305 DCHECK(args.length() == 2);
307 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
308 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
309 return *isolate->factory()->NewNumber(x - y);
313 RUNTIME_FUNCTION(Runtime_NumberMul) {
314 HandleScope scope(isolate);
315 DCHECK(args.length() == 2);
317 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
318 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
319 return *isolate->factory()->NewNumber(x * y);
323 RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
324 HandleScope scope(isolate);
325 DCHECK(args.length() == 1);
327 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
328 return *isolate->factory()->NewNumber(-x);
332 RUNTIME_FUNCTION(Runtime_NumberDiv) {
333 HandleScope scope(isolate);
334 DCHECK(args.length() == 2);
336 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
337 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
338 return *isolate->factory()->NewNumber(x / y);
342 RUNTIME_FUNCTION(Runtime_NumberMod) {
343 HandleScope scope(isolate);
344 DCHECK(args.length() == 2);
346 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
347 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
348 return *isolate->factory()->NewNumber(modulo(x, y));
352 RUNTIME_FUNCTION(Runtime_NumberImul) {
353 HandleScope scope(isolate);
354 DCHECK(args.length() == 2);
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);
365 RUNTIME_FUNCTION(Runtime_NumberOr) {
366 HandleScope scope(isolate);
367 DCHECK(args.length() == 2);
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);
375 RUNTIME_FUNCTION(Runtime_NumberAnd) {
376 HandleScope scope(isolate);
377 DCHECK(args.length() == 2);
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);
385 RUNTIME_FUNCTION(Runtime_NumberXor) {
386 HandleScope scope(isolate);
387 DCHECK(args.length() == 2);
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);
395 RUNTIME_FUNCTION(Runtime_NumberShl) {
396 HandleScope scope(isolate);
397 DCHECK(args.length() == 2);
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));
405 RUNTIME_FUNCTION(Runtime_NumberShr) {
406 HandleScope scope(isolate);
407 DCHECK(args.length() == 2);
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));
415 RUNTIME_FUNCTION(Runtime_NumberSar) {
416 HandleScope scope(isolate);
417 DCHECK(args.length() == 2);
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));
426 RUNTIME_FUNCTION(Runtime_NumberEquals) {
427 SealHandleScope shs(isolate);
428 DCHECK(args.length() == 2);
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);
436 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
437 result = Smi::FromInt(EQUAL);
439 result = Smi::FromInt(NOT_EQUAL);
445 RUNTIME_FUNCTION(Runtime_NumberCompare) {
446 SealHandleScope shs(isolate);
447 DCHECK(args.length() == 3);
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);
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);
467 // If the integers are equal so are the string representations.
468 if (x_value == y_value) return Smi::FromInt(EQUAL);
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);
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.
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);
490 static const uint32_t kPowersOf10[] = {
492 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000,
493 100 * 1000 * 1000, 1000 * 1000 * 1000};
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.
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];
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];
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];
523 } else if (y_log10 < x_log10) {
524 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
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);
535 RUNTIME_FUNCTION(Runtime_MaxSmi) {
536 SealHandleScope shs(isolate);
537 DCHECK(args.length() == 0);
538 return Smi::FromInt(Smi::kMaxValue);
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());
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);
559 RUNTIME_FUNCTION(Runtime_GetRootNaN) {
560 SealHandleScope shs(isolate);
561 DCHECK(args.length() == 0);
562 return isolate->heap()->nan_value();
564 } // namespace internal