Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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 #ifndef V8_CONVERSIONS_INL_H_
      6 #define V8_CONVERSIONS_INL_H_
      7 
      8 #include <float.h>         // Required for DBL_MAX and on Win32 for finite()
      9 #include <limits.h>        // Required for INT_MAX etc.
     10 #include <stdarg.h>
     11 #include <cmath>
     12 #include "src/globals.h"       // Required for V8_INFINITY
     13 
     14 // ----------------------------------------------------------------------------
     15 // Extra POSIX/ANSI functions for Win32/MSVC.
     16 
     17 #include "src/base/bits.h"
     18 #include "src/base/platform/platform.h"
     19 #include "src/conversions.h"
     20 #include "src/double.h"
     21 #include "src/objects-inl.h"
     22 
     23 namespace v8 {
     24 namespace internal {
     25 
     26 // The fast double-to-unsigned-int conversion routine does not guarantee
     27 // rounding towards zero, or any reasonable value if the argument is larger
     28 // than what fits in an unsigned 32-bit integer.
     29 inline unsigned int FastD2UI(double x) {
     30   // There is no unsigned version of lrint, so there is no fast path
     31   // in this function as there is in FastD2I. Using lrint doesn't work
     32   // for values of 2^31 and above.
     33 
     34   // Convert "small enough" doubles to uint32_t by fixing the 32
     35   // least significant non-fractional bits in the low 32 bits of the
     36   // double, and reading them from there.
     37   const double k2Pow52 = 4503599627370496.0;
     38   bool negative = x < 0;
     39   if (negative) {
     40     x = -x;
     41   }
     42   if (x < k2Pow52) {
     43     x += k2Pow52;
     44     uint32_t result;
     45 #ifndef V8_TARGET_BIG_ENDIAN
     46     void* mantissa_ptr = reinterpret_cast<void*>(&x);
     47 #else
     48     void* mantissa_ptr =
     49         reinterpret_cast<void*>(reinterpret_cast<Address>(&x) + kInt32Size);
     50 #endif
     51     // Copy least significant 32 bits of mantissa.
     52     memcpy(&result, mantissa_ptr, sizeof(result));
     53     return negative ? ~result + 1 : result;
     54   }
     55   // Large number (outside uint32 range), Infinity or NaN.
     56   return 0x80000000u;  // Return integer indefinite.
     57 }
     58 
     59 
     60 inline float DoubleToFloat32(double x) {
     61   // TODO(yangguo): This static_cast is implementation-defined behaviour in C++,
     62   // so we may need to do the conversion manually instead to match the spec.
     63   volatile float f = static_cast<float>(x);
     64   return f;
     65 }
     66 
     67 
     68 inline double DoubleToInteger(double x) {
     69   if (std::isnan(x)) return 0;
     70   if (!std::isfinite(x) || x == 0) return x;
     71   return (x >= 0) ? std::floor(x) : std::ceil(x);
     72 }
     73 
     74 
     75 int32_t DoubleToInt32(double x) {
     76   if ((std::isfinite(x)) && (x <= INT_MAX) && (x >= INT_MIN)) {
     77     int32_t i = static_cast<int32_t>(x);
     78     if (FastI2D(i) == x) return i;
     79   }
     80   Double d(x);
     81   int exponent = d.Exponent();
     82   if (exponent < 0) {
     83     if (exponent <= -Double::kSignificandSize) return 0;
     84     return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
     85   } else {
     86     if (exponent > 31) return 0;
     87     return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
     88   }
     89 }
     90 
     91 bool DoubleToSmiInteger(double value, int* smi_int_value) {
     92   if (!IsSmiDouble(value)) return false;
     93   *smi_int_value = FastD2I(value);
     94   DCHECK(Smi::IsValid(*smi_int_value));
     95   return true;
     96 }
     97 
     98 bool IsSmiDouble(double value) {
     99   return value >= Smi::kMinValue && value <= Smi::kMaxValue &&
    100          !IsMinusZero(value) && value == FastI2D(FastD2I(value));
    101 }
    102 
    103 
    104 bool IsInt32Double(double value) {
    105   return value >= kMinInt && value <= kMaxInt && !IsMinusZero(value) &&
    106          value == FastI2D(FastD2I(value));
    107 }
    108 
    109 
    110 bool IsUint32Double(double value) {
    111   return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
    112          value == FastUI2D(FastD2UI(value));
    113 }
    114 
    115 bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value) {
    116   const double k2Pow52 = 4503599627370496.0;
    117   const uint32_t kValidTopBits = 0x43300000;
    118   const uint64_t kBottomBitMask = V8_2PART_UINT64_C(0x00000000, FFFFFFFF);
    119 
    120   // Add 2^52 to the double, to place valid uint32 values in the low-significant
    121   // bits of the exponent, by effectively setting the (implicit) top bit of the
    122   // significand. Note that this addition also normalises 0.0 and -0.0.
    123   double shifted_value = value + k2Pow52;
    124 
    125   // At this point, a valid uint32 valued double will be represented as:
    126   //
    127   // sign = 0
    128   // exponent = 52
    129   // significand = 1. 00...00 <value>
    130   //       implicit^          ^^^^^^^ 32 bits
    131   //                  ^^^^^^^^^^^^^^^ 52 bits
    132   //
    133   // Therefore, we can first check the top 32 bits to make sure that the sign,
    134   // exponent and remaining significand bits are valid, and only then check the
    135   // value in the bottom 32 bits.
    136 
    137   uint64_t result = bit_cast<uint64_t>(shifted_value);
    138   if ((result >> 32) == kValidTopBits) {
    139     *uint32_value = result & kBottomBitMask;
    140     return FastUI2D(result & kBottomBitMask) == value;
    141   }
    142   return false;
    143 }
    144 
    145 int32_t NumberToInt32(Object* number) {
    146   if (number->IsSmi()) return Smi::ToInt(number);
    147   return DoubleToInt32(number->Number());
    148 }
    149 
    150 uint32_t NumberToUint32(Object* number) {
    151   if (number->IsSmi()) return Smi::ToInt(number);
    152   return DoubleToUint32(number->Number());
    153 }
    154 
    155 uint32_t PositiveNumberToUint32(Object* number) {
    156   if (number->IsSmi()) {
    157     int value = Smi::ToInt(number);
    158     if (value <= 0) return 0;
    159     return value;
    160   }
    161   DCHECK(number->IsHeapNumber());
    162   double value = number->Number();
    163   // Catch all values smaller than 1 and use the double-negation trick for NANs.
    164   if (!(value >= 1)) return 0;
    165   uint32_t max = std::numeric_limits<uint32_t>::max();
    166   if (value < max) return static_cast<uint32_t>(value);
    167   return max;
    168 }
    169 
    170 int64_t NumberToInt64(Object* number) {
    171   if (number->IsSmi()) return Smi::ToInt(number);
    172   double d = number->Number();
    173   if (std::isnan(d)) return 0;
    174   if (d >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
    175     return std::numeric_limits<int64_t>::max();
    176   }
    177   if (d <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
    178     return std::numeric_limits<int64_t>::min();
    179   }
    180   return static_cast<int64_t>(d);
    181 }
    182 
    183 uint64_t PositiveNumberToUint64(Object* number) {
    184   if (number->IsSmi()) {
    185     int value = Smi::ToInt(number);
    186     if (value <= 0) return 0;
    187     return value;
    188   }
    189   DCHECK(number->IsHeapNumber());
    190   double value = number->Number();
    191   // Catch all values smaller than 1 and use the double-negation trick for NANs.
    192   if (!(value >= 1)) return 0;
    193   uint64_t max = std::numeric_limits<uint64_t>::max();
    194   if (value < max) return static_cast<uint64_t>(value);
    195   return max;
    196 }
    197 
    198 bool TryNumberToSize(Object* number, size_t* result) {
    199   // Do not create handles in this function! Don't use SealHandleScope because
    200   // the function can be used concurrently.
    201   if (number->IsSmi()) {
    202     int value = Smi::ToInt(number);
    203     DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
    204            std::numeric_limits<size_t>::max());
    205     if (value >= 0) {
    206       *result = static_cast<size_t>(value);
    207       return true;
    208     }
    209     return false;
    210   } else {
    211     DCHECK(number->IsHeapNumber());
    212     double value = HeapNumber::cast(number)->value();
    213     // If value is compared directly to the limit, the limit will be
    214     // casted to a double and could end up as limit + 1,
    215     // because a double might not have enough mantissa bits for it.
    216     // So we might as well cast the limit first, and use < instead of <=.
    217     double maxSize = static_cast<double>(std::numeric_limits<size_t>::max());
    218     if (value >= 0 && value < maxSize) {
    219       *result = static_cast<size_t>(value);
    220       return true;
    221     } else {
    222       return false;
    223     }
    224   }
    225 }
    226 
    227 size_t NumberToSize(Object* number) {
    228   size_t result = 0;
    229   bool is_valid = TryNumberToSize(number, &result);
    230   CHECK(is_valid);
    231   return result;
    232 }
    233 
    234 
    235 uint32_t DoubleToUint32(double x) {
    236   return static_cast<uint32_t>(DoubleToInt32(x));
    237 }
    238 
    239 }  // namespace internal
    240 }  // namespace v8
    241 
    242 #endif  // V8_CONVERSIONS_INL_H_
    243