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