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