Line data Source code
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 : #include "src/objects/heap-number-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.
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 120951 : if (negative) {
41 0 : x = -x;
42 : }
43 120951 : if (x < k2Pow52) {
44 120951 : 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 120951 : return negative ? ~result + 1 : result;
55 : }
56 : // Large number (outside uint32 range), Infinity or NaN.
57 : return 0x80000000u; // Return integer indefinite.
58 : }
59 :
60 :
61 : inline float DoubleToFloat32(double x) {
62 : typedef std::numeric_limits<float> limits;
63 107374 : if (x > limits::max()) return limits::infinity();
64 107300 : if (x < limits::lowest()) return -limits::infinity();
65 107248 : return static_cast<float>(x);
66 : }
67 :
68 :
69 634116 : inline double DoubleToInteger(double x) {
70 634116 : if (std::isnan(x)) return 0;
71 629510 : if (!std::isfinite(x) || x == 0) return x;
72 349821 : return (x >= 0) ? std::floor(x) : std::ceil(x);
73 : }
74 :
75 : // Implements most of https://tc39.github.io/ecma262/#sec-toint32.
76 7374830 : int32_t DoubleToInt32(double x) {
77 7374830 : if ((std::isfinite(x)) && (x <= INT_MAX) && (x >= INT_MIN)) {
78 5974370 : int32_t i = static_cast<int32_t>(x);
79 5974370 : if (FastI2D(i) == x) return i;
80 : }
81 : Double d(x);
82 : int exponent = d.Exponent();
83 : uint64_t bits;
84 1589438 : if (exponent < 0) {
85 241380 : if (exponent <= -Double::kSignificandSize) return 0;
86 236973 : bits = d.Significand() >> -exponent;
87 : } else {
88 1348058 : if (exponent > 31) return 0;
89 : // Masking to a 32-bit value ensures that the result of the
90 : // static_cast<int64_t> below is not the minimal int64_t value,
91 : // which would overflow on multiplication with d.Sign().
92 927 : bits = (d.Significand() << exponent) & 0xFFFFFFFFul;
93 : }
94 237900 : return static_cast<int32_t>(d.Sign() * static_cast<int64_t>(bits));
95 : }
96 :
97 : bool DoubleToSmiInteger(double value, int* smi_int_value) {
98 26315082 : if (!IsSmiDouble(value)) return false;
99 : *smi_int_value = FastD2I(value);
100 : DCHECK(Smi::IsValid(*smi_int_value));
101 : return true;
102 : }
103 :
104 : bool IsSmiDouble(double value) {
105 25007191 : return value >= Smi::kMinValue && value <= Smi::kMaxValue &&
106 50652669 : !IsMinusZero(value) && value == FastI2D(FastD2I(value));
107 : }
108 :
109 :
110 : bool IsInt32Double(double value) {
111 2611016 : return value >= kMinInt && value <= kMaxInt && !IsMinusZero(value) &&
112 : value == FastI2D(FastD2I(value));
113 : }
114 :
115 :
116 122573 : bool IsUint32Double(double value) {
117 243107 : return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
118 122573 : value == FastUI2D(FastD2UI(value));
119 : }
120 :
121 : bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value) {
122 : const double k2Pow52 = 4503599627370496.0;
123 : const uint32_t kValidTopBits = 0x43300000;
124 : const uint64_t kBottomBitMask = V8_2PART_UINT64_C(0x00000000, FFFFFFFF);
125 :
126 : // Add 2^52 to the double, to place valid uint32 values in the low-significant
127 : // bits of the exponent, by effectively setting the (implicit) top bit of the
128 : // significand. Note that this addition also normalises 0.0 and -0.0.
129 21275 : double shifted_value = value + k2Pow52;
130 :
131 : // At this point, a valid uint32 valued double will be represented as:
132 : //
133 : // sign = 0
134 : // exponent = 52
135 : // significand = 1. 00...00 <value>
136 : // implicit^ ^^^^^^^ 32 bits
137 : // ^^^^^^^^^^^^^^^ 52 bits
138 : //
139 : // Therefore, we can first check the top 32 bits to make sure that the sign,
140 : // exponent and remaining significand bits are valid, and only then check the
141 : // value in the bottom 32 bits.
142 :
143 : uint64_t result = bit_cast<uint64_t>(shifted_value);
144 21275 : if ((result >> 32) == kValidTopBits) {
145 20437 : *uint32_value = result & kBottomBitMask;
146 20437 : return FastUI2D(result & kBottomBitMask) == value;
147 : }
148 : return false;
149 : }
150 :
151 1106297 : int32_t NumberToInt32(Object number) {
152 2211173 : if (number->IsSmi()) return Smi::ToInt(number);
153 1421 : return DoubleToInt32(number->Number());
154 : }
155 :
156 290846 : uint32_t NumberToUint32(Object number) {
157 543837 : if (number->IsSmi()) return Smi::ToInt(number);
158 37858 : return DoubleToUint32(number->Number());
159 : }
160 :
161 : uint32_t PositiveNumberToUint32(Object number) {
162 3482 : if (number->IsSmi()) {
163 : int value = Smi::ToInt(number);
164 3341 : if (value <= 0) return 0;
165 1944 : return value;
166 : }
167 : DCHECK(number->IsHeapNumber());
168 : double value = number->Number();
169 : // Catch all values smaller than 1 and use the double-negation trick for NANs.
170 141 : if (!(value >= 1)) return 0;
171 : uint32_t max = std::numeric_limits<uint32_t>::max();
172 62 : if (value < max) return static_cast<uint32_t>(value);
173 : return max;
174 : }
175 :
176 : int64_t NumberToInt64(Object number) {
177 5224 : if (number->IsSmi()) return Smi::ToInt(number);
178 : double d = number->Number();
179 126 : if (std::isnan(d)) return 0;
180 126 : if (d >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
181 : return std::numeric_limits<int64_t>::max();
182 : }
183 126 : if (d <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
184 : return std::numeric_limits<int64_t>::min();
185 : }
186 126 : return static_cast<int64_t>(d);
187 : }
188 :
189 : uint64_t PositiveNumberToUint64(Object number) {
190 90 : if (number->IsSmi()) {
191 : int value = Smi::ToInt(number);
192 36 : if (value <= 0) return 0;
193 18 : return value;
194 : }
195 : DCHECK(number->IsHeapNumber());
196 : double value = number->Number();
197 : // Catch all values smaller than 1 and use the double-negation trick for NANs.
198 54 : if (!(value >= 1)) return 0;
199 : uint64_t max = std::numeric_limits<uint64_t>::max();
200 54 : if (value < max) return static_cast<uint64_t>(value);
201 : return max;
202 : }
203 :
204 : bool TryNumberToSize(Object number, size_t* result) {
205 : // Do not create handles in this function! Don't use SealHandleScope because
206 : // the function can be used concurrently.
207 39914815 : if (number->IsSmi()) {
208 : int value = Smi::ToInt(number);
209 : DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
210 : std::numeric_limits<size_t>::max());
211 39905598 : if (value >= 0) {
212 39905593 : *result = static_cast<size_t>(value);
213 : return true;
214 : }
215 : return false;
216 : } else {
217 : DCHECK(number->IsHeapNumber());
218 : double value = HeapNumber::cast(number)->value();
219 : // If value is compared directly to the limit, the limit will be
220 : // casted to a double and could end up as limit + 1,
221 : // because a double might not have enough mantissa bits for it.
222 : // So we might as well cast the limit first, and use < instead of <=.
223 : double maxSize = static_cast<double>(std::numeric_limits<size_t>::max());
224 9217 : if (value >= 0 && value < maxSize) {
225 9207 : *result = static_cast<size_t>(value);
226 : return true;
227 : } else {
228 : return false;
229 : }
230 : }
231 : }
232 :
233 : size_t NumberToSize(Object number) {
234 : size_t result = 0;
235 : bool is_valid = TryNumberToSize(number, &result);
236 : CHECK(is_valid);
237 : return result;
238 : }
239 :
240 : uint32_t DoubleToUint32(double x) {
241 3653601 : return static_cast<uint32_t>(DoubleToInt32(x));
242 : }
243 :
244 : } // namespace internal
245 : } // namespace v8
246 :
247 : #endif // V8_CONVERSIONS_INL_H_
|