LCOV - code coverage report
Current view: top level - src/runtime - runtime-numbers.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 80 84 95.2 %
Date: 2017-04-26 Functions: 11 24 45.8 %

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

Generated by: LCOV version 1.10