LCOV - code coverage report
Current view: top level - src/runtime - runtime-numbers.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 68 81 84.0 %
Date: 2017-10-20 Functions: 10 24 41.7 %

          Line data    Source code
       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/isolate-inl.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15          12 : RUNTIME_FUNCTION(Runtime_IsValidSmi) {
      16             :   SealHandleScope shs(isolate);
      17             :   DCHECK_EQ(1, args.length());
      18             : 
      19          12 :   CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
      20           6 :   return isolate->heap()->ToBoolean(Smi::IsValid(number));
      21             : }
      22             : 
      23             : 
      24     9061472 : RUNTIME_FUNCTION(Runtime_StringToNumber) {
      25     4530736 :   HandleScope handle_scope(isolate);
      26             :   DCHECK_EQ(1, args.length());
      27     9061472 :   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
      28     9061472 :   return *String::ToNumber(subject);
      29             : }
      30             : 
      31             : 
      32             : // ES6 18.2.5 parseInt(string, radix) slow path
      33     2733806 : RUNTIME_FUNCTION(Runtime_StringParseInt) {
      34     1366903 :   HandleScope handle_scope(isolate);
      35             :   DCHECK_EQ(2, args.length());
      36     1366903 :   CONVERT_ARG_HANDLE_CHECKED(Object, string, 0);
      37     1366903 :   CONVERT_ARG_HANDLE_CHECKED(Object, radix, 1);
      38             : 
      39             :   // Convert {string} to a String first, and flatten it.
      40             :   Handle<String> subject;
      41     2733806 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, subject,
      42             :                                      Object::ToString(isolate, string));
      43     1366874 :   subject = String::Flatten(subject);
      44             : 
      45             :   // Convert {radix} to Int32.
      46     1366874 :   if (!radix->IsNumber()) {
      47     2732834 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix, Object::ToNumber(radix));
      48             :   }
      49     1366855 :   int radix32 = DoubleToInt32(radix->Number());
      50     1366855 :   if (radix32 != 0 && (radix32 < 2 || radix32 > 36)) {
      51           9 :     return isolate->heap()->nan_value();
      52             :   }
      53             : 
      54     1366846 :   double result = StringToInt(isolate, subject, radix32);
      55     2733692 :   return *isolate->factory()->NewNumber(result);
      56             : }
      57             : 
      58             : 
      59             : // ES6 18.2.4 parseFloat(string)
      60        1752 : RUNTIME_FUNCTION(Runtime_StringParseFloat) {
      61         584 :   HandleScope shs(isolate);
      62             :   DCHECK_EQ(1, args.length());
      63        1168 :   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
      64             : 
      65             :   double value =
      66             :       StringToDouble(isolate->unicode_cache(), subject, ALLOW_TRAILING_JUNK,
      67        1168 :                      std::numeric_limits<double>::quiet_NaN());
      68             : 
      69        1168 :   return *isolate->factory()->NewNumber(value);
      70             : }
      71             : 
      72             : 
      73    61047022 : RUNTIME_FUNCTION(Runtime_NumberToString) {
      74    30523511 :   HandleScope scope(isolate);
      75             :   DCHECK_EQ(1, args.length());
      76    61047022 :   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
      77             : 
      78    61047022 :   return *isolate->factory()->NumberToString(number);
      79             : }
      80             : 
      81             : 
      82           0 : RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
      83           0 :   HandleScope scope(isolate);
      84             :   DCHECK_EQ(1, args.length());
      85           0 :   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
      86             : 
      87           0 :   return *isolate->factory()->NumberToString(number, false);
      88             : }
      89             : 
      90             : 
      91             : // Converts a Number to a Smi, if possible. Returns NaN if the number is not
      92             : // a small integer.
      93          24 : RUNTIME_FUNCTION(Runtime_NumberToSmi) {
      94             :   SealHandleScope shs(isolate);
      95             :   DCHECK_EQ(1, args.length());
      96          12 :   CONVERT_ARG_CHECKED(Object, obj, 0);
      97          12 :   if (obj->IsSmi()) {
      98             :     return obj;
      99             :   }
     100           0 :   if (obj->IsHeapNumber()) {
     101           0 :     double value = HeapNumber::cast(obj)->value();
     102           0 :     int int_value = FastD2I(value);
     103           0 :     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
     104           0 :       return Smi::FromInt(int_value);
     105             :     }
     106             :   }
     107           0 :   return isolate->heap()->nan_value();
     108             : }
     109             : 
     110             : 
     111             : // Compare two Smis as if they were converted to strings and then
     112             : // compared lexicographically.
     113    54384142 : RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
     114             :   SealHandleScope shs(isolate);
     115             :   DCHECK_EQ(2, args.length());
     116    54384142 :   CONVERT_SMI_ARG_CHECKED(x_value, 0);
     117    54384142 :   CONVERT_SMI_ARG_CHECKED(y_value, 1);
     118             : 
     119             :   // If the integers are equal so are the string representations.
     120    27192071 :   if (x_value == y_value) return Smi::FromInt(EQUAL);
     121             : 
     122             :   // If one of the integers is zero the normal integer order is the
     123             :   // same as the lexicographic order of the string representations.
     124    27183791 :   if (x_value == 0 || y_value == 0)
     125       16940 :     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
     126             : 
     127             :   // If only one of the integers is negative the negative number is
     128             :   // smallest because the char code of '-' is less than the char code
     129             :   // of any digit.  Otherwise, we make both values positive.
     130             : 
     131             :   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
     132             :   // architectures using 32-bit Smis.
     133    27166851 :   uint32_t x_scaled = x_value;
     134    27166851 :   uint32_t y_scaled = y_value;
     135    27166851 :   if (x_value < 0 || y_value < 0) {
     136     5129630 :     if (y_value >= 0) return Smi::FromInt(LESS);
     137     3419810 :     if (x_value >= 0) return Smi::FromInt(GREATER);
     138     1709900 :     x_scaled = -x_value;
     139     1709900 :     y_scaled = -y_value;
     140             :   }
     141             : 
     142             :   static const uint32_t kPowersOf10[] = {
     143             :       1,                 10,                100,         1000,
     144             :       10 * 1000,         100 * 1000,        1000 * 1000, 10 * 1000 * 1000,
     145             :       100 * 1000 * 1000, 1000 * 1000 * 1000};
     146             : 
     147             :   // If the integers have the same number of decimal digits they can be
     148             :   // compared directly as the numeric order is the same as the
     149             :   // lexicographic order.  If one integer has fewer digits, it is scaled
     150             :   // by some power of 10 to have the same number of digits as the longer
     151             :   // integer.  If the scaled integers are equal it means the shorter
     152             :   // integer comes first in the lexicographic order.
     153             : 
     154             :   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
     155    23747121 :   int x_log2 = 31 - base::bits::CountLeadingZeros32(x_scaled);
     156    23747121 :   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
     157    23747121 :   x_log10 -= x_scaled < kPowersOf10[x_log10];
     158             : 
     159    23747121 :   int y_log2 = 31 - base::bits::CountLeadingZeros32(y_scaled);
     160    23747121 :   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
     161    23747121 :   y_log10 -= y_scaled < kPowersOf10[y_log10];
     162             : 
     163             :   int tie = EQUAL;
     164             : 
     165    23747121 :   if (x_log10 < y_log10) {
     166             :     // X has fewer digits.  We would like to simply scale up X but that
     167             :     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
     168             :     // be scaled up to 9_000_000_000. So we scale up by the next
     169             :     // smallest power and scale down Y to drop one digit. It is OK to
     170             :     // drop one digit from the longer integer since the final digit is
     171             :     // past the length of the shorter integer.
     172     3470810 :     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
     173     3470810 :     y_scaled /= 10;
     174             :     tie = LESS;
     175    20276311 :   } else if (y_log10 < x_log10) {
     176     3026010 :     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
     177     3026010 :     x_scaled /= 10;
     178             :     tie = GREATER;
     179             :   }
     180             : 
     181    23747121 :   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
     182    10676565 :   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
     183      494720 :   return Smi::FromInt(tie);
     184             : }
     185             : 
     186             : 
     187         724 : RUNTIME_FUNCTION(Runtime_MaxSmi) {
     188             :   SealHandleScope shs(isolate);
     189             :   DCHECK_EQ(0, args.length());
     190         362 :   return Smi::FromInt(Smi::kMaxValue);
     191             : }
     192             : 
     193             : 
     194           0 : RUNTIME_FUNCTION(Runtime_IsSmi) {
     195             :   SealHandleScope shs(isolate);
     196             :   DCHECK_EQ(1, args.length());
     197           0 :   CONVERT_ARG_CHECKED(Object, obj, 0);
     198           0 :   return isolate->heap()->ToBoolean(obj->IsSmi());
     199             : }
     200             : 
     201             : 
     202          80 : RUNTIME_FUNCTION(Runtime_GetHoleNaNUpper) {
     203          40 :   HandleScope scope(isolate);
     204             :   DCHECK_EQ(0, args.length());
     205          80 :   return *isolate->factory()->NewNumberFromUint(kHoleNanUpper32);
     206             : }
     207             : 
     208             : 
     209          80 : RUNTIME_FUNCTION(Runtime_GetHoleNaNLower) {
     210          40 :   HandleScope scope(isolate);
     211             :   DCHECK_EQ(0, args.length());
     212          80 :   return *isolate->factory()->NewNumberFromUint(kHoleNanLower32);
     213             : }
     214             : 
     215             : 
     216             : }  // namespace internal
     217             : }  // namespace v8

Generated by: LCOV version 1.10