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.
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"
14 #ifndef _STLP_VENDOR_CSTD
15 // STLPort doesn't import fpclassify and isless into the std namespace.
16 using std::fpclassify;
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);
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(
41 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
42 if (std::isnan(value)) {
43 return isolate->heap()->nan_string();
45 if (std::isinf(value)) {
47 return isolate->heap()->minus_infinity_string();
49 return isolate->heap()->infinity_string();
51 char* str = DoubleToRadixCString(value, radix);
52 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
58 RUNTIME_FUNCTION(Runtime_NumberToFixed) {
59 HandleScope scope(isolate);
60 DCHECK(args.length() == 2);
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);
75 RUNTIME_FUNCTION(Runtime_NumberToExponential) {
76 HandleScope scope(isolate);
77 DCHECK(args.length() == 2);
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);
91 RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
92 HandleScope scope(isolate);
93 DCHECK(args.length() == 2);
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);
107 RUNTIME_FUNCTION(Runtime_IsValidSmi) {
108 SealHandleScope shs(isolate);
109 DCHECK(args.length() == 1);
111 CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
112 return isolate->heap()->ToBoolean(Smi::IsValid(number));
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;
125 static int ParseDecimalInteger(const uint8_t* s, int from, int to) {
126 DCHECK(to - from < 10); // Overflow is not possible.
128 int d = s[from] - '0';
130 for (int i = from + 1; i < to; i++) {
131 d = 10 * d + (s[i] - '0');
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);
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);
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);
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 .
161 if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
162 return isolate->heap()->nan_value();
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);
169 if (d == 0) return isolate->heap()->minus_zero_value();
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);
177 subject->Hash(); // Force hash calculation.
178 DCHECK_EQ(static_cast<int>(subject->hash_field()),
179 static_cast<int>(hash));
181 subject->set_hash_field(hash);
183 return Smi::FromInt(d);
188 int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
189 return *isolate->factory()->NewNumber(
190 StringToDouble(isolate->unicode_cache(), subject, flags));
194 RUNTIME_FUNCTION(Runtime_StringParseInt) {
195 HandleScope handle_scope(isolate);
196 DCHECK(args.length() == 2);
197 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
198 CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
199 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
201 subject = String::Flatten(subject);
205 DisallowHeapAllocation no_gc;
206 String::FlatContent flat = subject->GetFlatContent();
208 // ECMA-262 section 15.1.2.3, empty string is NaN
209 if (flat.IsOneByte()) {
211 StringToInt(isolate->unicode_cache(), flat.ToOneByteVector(), radix);
213 value = StringToInt(isolate->unicode_cache(), flat.ToUC16Vector(), radix);
217 return *isolate->factory()->NewNumber(value);
221 RUNTIME_FUNCTION(Runtime_StringParseFloat) {
222 HandleScope shs(isolate);
223 DCHECK(args.length() == 1);
224 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
227 StringToDouble(isolate->unicode_cache(), subject, ALLOW_TRAILING_JUNK,
228 std::numeric_limits<double>::quiet_NaN());
230 return *isolate->factory()->NewNumber(value);
234 RUNTIME_FUNCTION(Runtime_NumberToString) {
235 HandleScope scope(isolate);
236 DCHECK(args.length() == 1);
237 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
239 return *isolate->factory()->NumberToString(number);
243 RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
244 HandleScope scope(isolate);
245 DCHECK(args.length() == 1);
246 CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
248 return *isolate->factory()->NumberToString(number, false);
252 RUNTIME_FUNCTION(Runtime_NumberToInteger) {
253 HandleScope scope(isolate);
254 DCHECK(args.length() == 1);
256 CONVERT_DOUBLE_ARG_CHECKED(number, 0);
257 return *isolate->factory()->NewNumber(DoubleToInteger(number));
261 RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
262 HandleScope scope(isolate);
263 DCHECK(args.length() == 1);
265 CONVERT_DOUBLE_ARG_CHECKED(number, 0);
266 double double_value = DoubleToInteger(number);
267 // Map both -0 and +0 to +0.
268 if (double_value == 0) double_value = 0;
270 return *isolate->factory()->NewNumber(double_value);
274 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
276 RUNTIME_FUNCTION(Runtime_NumberToSmi) {
277 SealHandleScope shs(isolate);
278 DCHECK(args.length() == 1);
279 CONVERT_ARG_CHECKED(Object, obj, 0);
283 if (obj->IsHeapNumber()) {
284 double value = HeapNumber::cast(obj)->value();
285 int int_value = FastD2I(value);
286 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
287 return Smi::FromInt(int_value);
290 return isolate->heap()->nan_value();
294 RUNTIME_FUNCTION(Runtime_NumberAdd) {
295 HandleScope scope(isolate);
296 DCHECK(args.length() == 2);
298 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
299 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
300 return *isolate->factory()->NewNumber(x + y);
304 RUNTIME_FUNCTION(Runtime_NumberSub) {
305 HandleScope scope(isolate);
306 DCHECK(args.length() == 2);
308 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
309 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
310 return *isolate->factory()->NewNumber(x - y);
314 RUNTIME_FUNCTION(Runtime_NumberMul) {
315 HandleScope scope(isolate);
316 DCHECK(args.length() == 2);
318 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
319 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
320 return *isolate->factory()->NewNumber(x * y);
324 RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
325 HandleScope scope(isolate);
326 DCHECK(args.length() == 1);
328 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
329 return *isolate->factory()->NewNumber(-x);
333 RUNTIME_FUNCTION(Runtime_NumberDiv) {
334 HandleScope scope(isolate);
335 DCHECK(args.length() == 2);
337 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
338 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
339 return *isolate->factory()->NewNumber(x / y);
343 RUNTIME_FUNCTION(Runtime_NumberMod) {
344 HandleScope scope(isolate);
345 DCHECK(args.length() == 2);
347 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
348 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
349 return *isolate->factory()->NewNumber(modulo(x, y));
353 RUNTIME_FUNCTION(Runtime_NumberImul) {
354 HandleScope scope(isolate);
355 DCHECK(args.length() == 2);
357 // We rely on implementation-defined behavior below, but at least not on
358 // undefined behavior.
359 CONVERT_NUMBER_CHECKED(uint32_t, x, Int32, args[0]);
360 CONVERT_NUMBER_CHECKED(uint32_t, y, Int32, args[1]);
361 int32_t product = static_cast<int32_t>(x * y);
362 return *isolate->factory()->NewNumberFromInt(product);
366 RUNTIME_FUNCTION(Runtime_NumberOr) {
367 HandleScope scope(isolate);
368 DCHECK(args.length() == 2);
370 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
371 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
372 return *isolate->factory()->NewNumberFromInt(x | y);
376 RUNTIME_FUNCTION(Runtime_NumberAnd) {
377 HandleScope scope(isolate);
378 DCHECK(args.length() == 2);
380 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
381 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
382 return *isolate->factory()->NewNumberFromInt(x & y);
386 RUNTIME_FUNCTION(Runtime_NumberXor) {
387 HandleScope scope(isolate);
388 DCHECK(args.length() == 2);
390 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
391 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
392 return *isolate->factory()->NewNumberFromInt(x ^ y);
396 RUNTIME_FUNCTION(Runtime_NumberShl) {
397 HandleScope scope(isolate);
398 DCHECK(args.length() == 2);
400 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
401 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
402 return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
406 RUNTIME_FUNCTION(Runtime_NumberShr) {
407 HandleScope scope(isolate);
408 DCHECK(args.length() == 2);
410 CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
411 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
412 return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
416 RUNTIME_FUNCTION(Runtime_NumberSar) {
417 HandleScope scope(isolate);
418 DCHECK(args.length() == 2);
420 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
421 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
422 return *isolate->factory()->NewNumberFromInt(
423 ArithmeticShiftRight(x, y & 0x1f));
427 RUNTIME_FUNCTION(Runtime_NumberEquals) {
428 SealHandleScope shs(isolate);
429 DCHECK(args.length() == 2);
431 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
432 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
433 if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
434 if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
435 if (x == y) return Smi::FromInt(EQUAL);
437 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
438 result = Smi::FromInt(EQUAL);
440 result = Smi::FromInt(NOT_EQUAL);
446 RUNTIME_FUNCTION(Runtime_NumberCompare) {
447 SealHandleScope shs(isolate);
448 DCHECK(args.length() == 3);
450 CONVERT_DOUBLE_ARG_CHECKED(x, 0);
451 CONVERT_DOUBLE_ARG_CHECKED(y, 1);
452 CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
453 if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
454 if (x == y) return Smi::FromInt(EQUAL);
455 if (isless(x, y)) return Smi::FromInt(LESS);
456 return Smi::FromInt(GREATER);
460 // Compare two Smis as if they were converted to strings and then
461 // compared lexicographically.
462 RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
463 SealHandleScope shs(isolate);
464 DCHECK(args.length() == 2);
465 CONVERT_SMI_ARG_CHECKED(x_value, 0);
466 CONVERT_SMI_ARG_CHECKED(y_value, 1);
468 // If the integers are equal so are the string representations.
469 if (x_value == y_value) return Smi::FromInt(EQUAL);
471 // If one of the integers is zero the normal integer order is the
472 // same as the lexicographic order of the string representations.
473 if (x_value == 0 || y_value == 0)
474 return Smi::FromInt(x_value < y_value ? LESS : GREATER);
476 // If only one of the integers is negative the negative number is
477 // smallest because the char code of '-' is less than the char code
478 // of any digit. Otherwise, we make both values positive.
480 // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
481 // architectures using 32-bit Smis.
482 uint32_t x_scaled = x_value;
483 uint32_t y_scaled = y_value;
484 if (x_value < 0 || y_value < 0) {
485 if (y_value >= 0) return Smi::FromInt(LESS);
486 if (x_value >= 0) return Smi::FromInt(GREATER);
491 static const uint32_t kPowersOf10[] = {
493 10 * 1000, 100 * 1000, 1000 * 1000, 10 * 1000 * 1000,
494 100 * 1000 * 1000, 1000 * 1000 * 1000};
496 // If the integers have the same number of decimal digits they can be
497 // compared directly as the numeric order is the same as the
498 // lexicographic order. If one integer has fewer digits, it is scaled
499 // by some power of 10 to have the same number of digits as the longer
500 // integer. If the scaled integers are equal it means the shorter
501 // integer comes first in the lexicographic order.
503 // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
504 int x_log2 = 31 - base::bits::CountLeadingZeros32(x_scaled);
505 int x_log10 = ((x_log2 + 1) * 1233) >> 12;
506 x_log10 -= x_scaled < kPowersOf10[x_log10];
508 int y_log2 = 31 - base::bits::CountLeadingZeros32(y_scaled);
509 int y_log10 = ((y_log2 + 1) * 1233) >> 12;
510 y_log10 -= y_scaled < kPowersOf10[y_log10];
514 if (x_log10 < y_log10) {
515 // X has fewer digits. We would like to simply scale up X but that
516 // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
517 // be scaled up to 9_000_000_000. So we scale up by the next
518 // smallest power and scale down Y to drop one digit. It is OK to
519 // drop one digit from the longer integer since the final digit is
520 // past the length of the shorter integer.
521 x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
524 } else if (y_log10 < x_log10) {
525 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
530 if (x_scaled < y_scaled) return Smi::FromInt(LESS);
531 if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
532 return Smi::FromInt(tie);
536 RUNTIME_FUNCTION(Runtime_MaxSmi) {
537 SealHandleScope shs(isolate);
538 DCHECK(args.length() == 0);
539 return Smi::FromInt(Smi::kMaxValue);
543 RUNTIME_FUNCTION(Runtime_IsSmi) {
544 SealHandleScope shs(isolate);
545 DCHECK(args.length() == 1);
546 CONVERT_ARG_CHECKED(Object, obj, 0);
547 return isolate->heap()->ToBoolean(obj->IsSmi());
551 RUNTIME_FUNCTION(Runtime_IsNonNegativeSmi) {
552 SealHandleScope shs(isolate);
553 DCHECK(args.length() == 1);
554 CONVERT_ARG_CHECKED(Object, obj, 0);
555 return isolate->heap()->ToBoolean(obj->IsSmi() &&
556 Smi::cast(obj)->value() >= 0);
560 RUNTIME_FUNCTION(Runtime_GetRootNaN) {
561 SealHandleScope shs(isolate);
562 DCHECK(args.length() == 0);
563 return isolate->heap()->nan_value();
565 } // namespace internal