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